const { useState, useRef, useCallback, useEffect, useMemo } = window.React;

// ── PDF.js chargé dynamiquement depuis cdnjs ───────────────────────────────────
const PDFJS_URL="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.min.js";
const PDFJS_WORKER="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.worker.min.js";
let _pdfjsLib=null;
const loadPdfJs=()=>new Promise((resolve,reject)=>{
  if(_pdfjsLib){resolve(_pdfjsLib);return;}
  if(document.querySelector(`script[src="${PDFJS_URL}"]`)){
    const wait=setInterval(()=>{if(window.pdfjsLib){clearInterval(wait);_pdfjsLib=window.pdfjsLib;_pdfjsLib.GlobalWorkerOptions.workerSrc=PDFJS_WORKER;resolve(_pdfjsLib);}},100);
    return;
  }
  const s=document.createElement("script");
  s.src=PDFJS_URL;
  s.onload=()=>{_pdfjsLib=window.pdfjsLib;_pdfjsLib.GlobalWorkerOptions.workerSrc=PDFJS_WORKER;resolve(_pdfjsLib);};
  s.onerror=reject;
  document.head.appendChild(s);
});

// ── Visionneuse PDF avec PDF.js ────────────────────────────────────────────────
const PdfViewer=({dataUrl})=>{
  const [pages,setPages]=useState([]);
  const [loading,setLoading]=useState(true);
  const [error,setError]=useState(null);
  const [scale,setScale]=useState(1.2);

  useEffect(()=>{
    let cancelled=false;
    setLoading(true);setError(null);setPages([]);
    (async()=>{
      try{
        const lib=await loadPdfJs();
        // Convertir dataUrl en ArrayBuffer
        const base64=dataUrl.split(",")[1];
        const binary=atob(base64);
        const bytes=new Uint8Array(binary.length);
        for(let i=0;i<binary.length;i++)bytes[i]=binary.charCodeAt(i);
        const pdf=await lib.getDocument({data:bytes}).promise;
        const rendered=[];
        for(let i=1;i<=pdf.numPages;i++){
          const page=await pdf.getPage(i);
          const viewport=page.getViewport({scale});
          const canvas=document.createElement("canvas");
          canvas.width=viewport.width;canvas.height=viewport.height;
          await page.render({canvasContext:canvas.getContext("2d"),viewport}).promise;
          rendered.push({num:i,dataUrl:canvas.toDataURL(),w:viewport.width,h:viewport.height});
        }
        if(!cancelled)setPages(rendered);
      }catch(e){if(!cancelled)setError("Impossible d'afficher ce PDF : "+e.message);}
      finally{if(!cancelled)setLoading(false);}
    })();
    return()=>{cancelled=true;};
  },[dataUrl,scale]);

  if(loading)return(
    <div style={{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:40,gap:12}}>
      <div style={{width:36,height:36,border:"3px solid #1e2d45",borderTopColor:"#f0a500",borderRadius:"50%",animation:"spin 0.8s linear infinite"}}/>
      <div style={{color:"#6b7a99",fontSize:13}}>Chargement du PDF…</div>
      <style>{`@keyframes spin{to{transform:rotate(360deg)}}`}</style>
    </div>
  );
  if(error)return(
    <div style={{padding:24,textAlign:"center"}}>
      <div style={{fontSize:40,marginBottom:10}}>⚠️</div>
      <div style={{color:"#ef4444",fontSize:13,marginBottom:16}}>{error}</div>
      <div style={{color:"#6b7a99",fontSize:12}}>Utilisez le bouton ⬇ Télécharger pour ouvrir le fichier.</div>
    </div>
  );

  return(
    <div style={{overflow:"auto",maxHeight:"100%",padding:"8px 0"}}>
      {/* Contrôle zoom */}
      <div style={{display:"flex",alignItems:"center",justifyContent:"center",gap:8,marginBottom:12,position:"sticky",top:0,background:"rgba(0,0,0,0.7)",padding:"6px 12px",borderRadius:8,backdropFilter:"blur(8px)"}}>
        <button onClick={()=>setScale(s=>Math.max(0.5,s-0.2))} style={{background:"rgba(255,255,255,0.1)",border:"none",color:"#fff",borderRadius:6,width:28,height:28,cursor:"pointer",fontSize:16}}>−</button>
        <span style={{color:"#aaa",fontSize:12,minWidth:44,textAlign:"center"}}>{Math.round(scale*100)}%</span>
        <button onClick={()=>setScale(s=>Math.min(3,s+0.2))} style={{background:"rgba(255,255,255,0.1)",border:"none",color:"#fff",borderRadius:6,width:28,height:28,cursor:"pointer",fontSize:16}}>+</button>
        <span style={{color:"#555",fontSize:11,marginLeft:6}}>{pages.length} page{pages.length>1?"s":""}</span>
      </div>
      {pages.map(p=>(
        <div key={p.num} style={{marginBottom:12,display:"flex",flexDirection:"column",alignItems:"center"}}>
          <img src={p.dataUrl} alt={`Page ${p.num}`} style={{maxWidth:"100%",borderRadius:4,boxShadow:"0 2px 20px rgba(0,0,0,0.6)",display:"block"}}/>
          {pages.length>1&&<div style={{fontSize:10,color:"#444",marginTop:4}}>Page {p.num}</div>}
        </div>
      ))}
    </div>
  );
};

// ── Fonts & Reset ─────────────────────────────────────────────────────────────
const FontLink = () => (
  <style>{`
    @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@500;700&family=DM+Sans:wght@300;400;500;600&display=swap');
    *{box-sizing:border-box;margin:0;padding:0}
    ::-webkit-scrollbar{width:5px}::-webkit-scrollbar-track{background:#0d1117}::-webkit-scrollbar-thumb{background:#2a3550;border-radius:3px}
    input[type=date]::-webkit-calendar-picker-indicator{filter:invert(0.5)}
    textarea{resize:vertical}
  `}</style>
);

// ── Theme ─────────────────────────────────────────────────────────────────────
const T = {
  bg:"#0d1117", sidebar:"#0f172a", card:"#1a2235", cardHover:"#1e2840",
  border:"#2a3550", accent:"#f0a500", accentDim:"rgba(240,165,0,0.1)",
  text:"#e2ddd5", muted:"#6b7a99", success:"#22c55e", danger:"#ef4444",
  info:"#38bdf8", warning:"#fb923c", purple:"#a78bfa", pink:"#f472b6",
  font:"'DM Sans',sans-serif", fontD:"'Playfair Display',serif",
};

// ── Helpers ───────────────────────────────────────────────────────────────────
const uid = () => Math.random().toString(36).slice(2,10);
const fmt = d => d ? new Date(d+"T12:00:00").toLocaleDateString("fr-FR") : "—";
const fmtAmt = v => v!=null ? new Intl.NumberFormat("fr-FR",{style:"currency",currency:"EUR"}).format(v) : "—";
const today = () => new Date().toISOString().slice(0,10);
const thisMonth = () => new Date().toISOString().slice(0,7);
const daysFrom = d => d ? Math.round((new Date(d)-new Date())/86400000) : null;
const fmtMois = d => d ? new Date(d+"T12:00:00").toLocaleDateString("fr-FR",{month:"long",year:"numeric"}) : "—";

// ── UI Atoms ──────────────────────────────────────────────────────────────────
const Badge = ({c=T.accent,children}) => (
  <span style={{background:c+"22",color:c,fontSize:11,fontWeight:600,padding:"2px 8px",borderRadius:20,whiteSpace:"nowrap"}}>{children}</span>
);
const Card = ({children,style={},onClick}) => (
  <div onClick={onClick} style={{background:T.card,border:`1px solid ${T.border}`,borderRadius:12,padding:18,
    cursor:onClick?"pointer":undefined,transition:"border-color 0.2s",...style}}
    onMouseEnter={e=>onClick&&(e.currentTarget.style.borderColor=T.accent)}
    onMouseLeave={e=>onClick&&(e.currentTarget.style.borderColor=T.border)}>
    {children}
  </div>
);
const Btn = ({children,onClick,v="primary",sm,disabled,style={}}) => {
  const s = v==="primary"?{background:T.accent,color:"#000",fontWeight:700,border:"none"}
    :v==="ghost"?{background:"transparent",color:T.muted,border:`1px solid ${T.border}`}
    :v==="danger"?{background:"rgba(239,68,68,0.1)",color:T.danger,border:`1px solid rgba(239,68,68,0.3)`}
    :v==="success"?{background:"rgba(34,197,94,0.1)",color:T.success,border:`1px solid rgba(34,197,94,0.3)`}
    :{background:T.accentDim,color:T.accent,border:`1px solid rgba(240,165,0,0.3)`};
  return <button onClick={onClick} disabled={disabled} style={{...s,borderRadius:8,padding:sm?"4px 10px":"8px 16px",
    fontSize:sm?11:13,cursor:disabled?"not-allowed":"pointer",fontFamily:T.font,opacity:disabled?0.5:1,
    transition:"opacity 0.15s",...style}}>{children}</button>;
};
const Inp = ({value,onChange,placeholder,type="text",style={}}) => (
  <input type={type} value={value||""} onChange={e=>onChange(e.target.value)} placeholder={placeholder}
    style={{background:"#0a0e17",border:`1px solid ${T.border}`,borderRadius:8,padding:"8px 12px",
      color:T.text,fontSize:13,fontFamily:T.font,outline:"none",width:"100%",...style}}/>
);
const Sel = ({value,onChange,children,style={}}) => (
  <select value={value||""} onChange={e=>onChange(e.target.value)}
    style={{background:"#0a0e17",border:`1px solid ${T.border}`,borderRadius:8,padding:"8px 12px",
      color:T.text,fontSize:13,fontFamily:T.font,outline:"none",width:"100%",...style}}>
    {children}
  </select>
);
const Txt = ({value,onChange,placeholder,rows=3}) => (
  <textarea value={value||""} onChange={e=>onChange(e.target.value)} rows={rows} placeholder={placeholder}
    style={{background:"#0a0e17",border:`1px solid ${T.border}`,borderRadius:8,padding:"8px 12px",
      color:T.text,fontSize:13,fontFamily:T.font,outline:"none",width:"100%"}}/>
);
const F = ({label,children}) => (
  <div style={{marginBottom:12}}>
    <label style={{fontSize:11,color:T.muted,display:"block",marginBottom:4,textTransform:"uppercase",letterSpacing:"0.05em"}}>{label}</label>
    {children}
  </div>
);
const Divider = ({label}) => (
  <div style={{borderBottom:`1px solid ${T.border}`,marginBottom:14,paddingBottom:3,fontSize:10,
    color:T.muted,textTransform:"uppercase",letterSpacing:"0.1em"}}>{label}</div>
);
const Modal = ({title,onClose,children,width=640}) => (
  <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.85)",zIndex:2000,display:"flex",
    alignItems:"center",justifyContent:"center",padding:16}} onClick={onClose}>
    <div onClick={e=>e.stopPropagation()} style={{background:T.sidebar,border:`1px solid ${T.border}`,
      borderRadius:16,width:"100%",maxWidth:width,maxHeight:"92vh",overflow:"auto",
      boxShadow:"0 30px 80px rgba(0,0,0,0.7)"}}>
      <div style={{padding:"14px 22px",borderBottom:`1px solid ${T.border}`,display:"flex",
        justifyContent:"space-between",alignItems:"center",position:"sticky",top:0,background:T.sidebar,zIndex:1}}>
        <span style={{fontFamily:T.fontD,fontSize:17,color:T.text}}>{title}</span>
        <button onClick={onClose} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:20}}>✕</button>
      </div>
      <div style={{padding:22}}>{children}</div>
    </div>
  </div>
);
const Tabs = ({tabs,active,onChange}) => (
  <div style={{display:"flex",borderBottom:`1px solid ${T.border}`,marginBottom:18,overflowX:"auto",gap:0,flexShrink:0}}>
    {tabs.map(t=>(
      <button key={t.id} onClick={()=>onChange(t.id)} style={{padding:"9px 14px",border:"none",background:"none",
        cursor:"pointer",fontFamily:T.font,fontSize:12,fontWeight:active===t.id?600:400,
        color:active===t.id?T.accent:T.muted,borderBottom:active===t.id?`2px solid ${T.accent}`:"2px solid transparent",
        whiteSpace:"nowrap",transition:"all 0.15s"}}>{t.icon} {t.label}</button>
    ))}
  </div>
);
const StatCard = ({label,value,icon,color=T.accent}) => (
  <Card style={{padding:14}}>
    <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
      <div>
        <div style={{fontSize:9,color:T.muted,textTransform:"uppercase",letterSpacing:"0.1em",marginBottom:4}}>{label}</div>
        <div style={{fontSize:20,fontWeight:700,color,fontFamily:T.fontD}}>{value}</div>
      </div>
      <span style={{fontSize:22,opacity:0.7}}>{icon}</span>
    </div>
  </Card>
);
const EmptyState = ({icon,text}) => (
  <div style={{color:T.muted,textAlign:"center",padding:"40px 20px",fontSize:14}}>
    <div style={{fontSize:36,marginBottom:10}}>{icon}</div>{text}
  </div>
);

// ═══════════════════════════════════════════════════════════════════════════════
// COMPOSANT UNIVERSEL : PIÈCES JOINTES
// Utilisable sur n'importe quel élément (abonnement, CT, travaux, entretien…)
// docs = tableau de {id, nom, url, type, date, taille}
// onChange(newDocs) = callback de mise à jour
// ═══════════════════════════════════════════════════════════════════════════════
const DocAttach=({docs=[],onChange,label="📎 Pièces jointes",compact=false})=>{
  const [preview,setPreview]=useState(null);
  const [dragging,setDragging]=useState(false);
  const [loading,setLoading]=useState(false);
  const ref=useRef();

  // Convertit les fichiers en base64 pour pouvoir les afficher dans l'iframe sandboxée
  const fileToBase64=(file)=>new Promise((resolve,reject)=>{
    const reader=new FileReader();
    reader.onload=e=>resolve(e.target.result); // data:mime;base64,...
    reader.onerror=reject;
    reader.readAsDataURL(file);
  });

  const addFiles=async(files)=>{
    setLoading(true);
    try{
      const newDocs=await Promise.all(Array.from(files).map(async f=>({
        id:uid(),
        nom:f.name,
        dataUrl:await fileToBase64(f),
        type:f.type,
        date:today(),
        taille:f.size>1024*1024?(f.size/(1024*1024)).toFixed(1)+"Mo":(f.size/1024).toFixed(0)+"Ko",
        isPdf:f.type==="application/pdf",
        isImg:f.type.startsWith("image/"),
      })));
      onChange([...docs,...newDocs]);
    }finally{setLoading(false);}
  };

  const del=id=>onChange(docs.filter(d=>d.id!==id));
  const icon=d=>d.isPdf?"📄":d.isImg?"🖼️":d.nom?.endsWith(".xlsx")||d.nom?.endsWith(".xls")?"📊":d.nom?.endsWith(".docx")||d.nom?.endsWith(".doc")?"📝":"📁";

  // Visionneuse plein écran
  const Visionneuse=({doc,onClose})=>(
    <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.97)",zIndex:9999,display:"flex",flexDirection:"column"}} onClick={onClose}>
      {/* Barre titre */}
      <div onClick={e=>e.stopPropagation()} style={{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"10px 20px",background:"#0c1220",borderBottom:"1px solid #1e2d45",flexShrink:0}}>
        <span style={{color:"#e2ddd5",fontWeight:600,fontSize:14}}>{icon(doc)} {doc.nom} {doc.taille&&<span style={{color:"#6b7a99",fontWeight:400,fontSize:12}}>· {doc.taille}</span>}</span>
        <div style={{display:"flex",gap:8}}>
          <a href={doc.dataUrl} download={doc.nom} onClick={e=>e.stopPropagation()} style={{background:"#f0a500",color:"#000",borderRadius:7,padding:"5px 14px",textDecoration:"none",fontSize:12,fontWeight:700}}>⬇ Télécharger</a>
          <button onClick={onClose} style={{background:"rgba(255,255,255,0.07)",border:"1px solid #1e2d45",color:"#fff",borderRadius:7,padding:"5px 14px",cursor:"pointer",fontSize:13}}>✕ Fermer</button>
        </div>
      </div>
      {/* Contenu */}
      <div onClick={e=>e.stopPropagation()} style={{flex:1,overflow:"hidden",display:"flex",flexDirection:"column"}}>
        {doc.isImg?(
          <div style={{flex:1,display:"flex",alignItems:"center",justifyContent:"center",overflow:"auto",padding:20}}>
            <img src={doc.dataUrl} alt={doc.nom} style={{maxWidth:"100%",maxHeight:"100%",objectFit:"contain",borderRadius:8,boxShadow:"0 0 60px rgba(0,0,0,0.8)"}}/>
          </div>
        ):doc.isPdf?(
          <div style={{flex:1,overflow:"hidden"}}>
            <PdfViewer dataUrl={doc.dataUrl}/>
          </div>
        ):(
          <div style={{flex:1,display:"flex",alignItems:"center",justifyContent:"center"}}>
            <div style={{textAlign:"center",color:"#fff"}}>
              <div style={{fontSize:64,marginBottom:16}}>{icon(doc)}</div>
              <div style={{fontSize:18,marginBottom:8}}>{doc.nom}</div>
              <div style={{fontSize:13,color:"#aaa",marginBottom:24}}>{doc.taille}</div>
              <a href={doc.dataUrl} download={doc.nom} style={{background:"#f0a500",color:"#000",borderRadius:9,padding:"10px 28px",textDecoration:"none",fontSize:14,fontWeight:700}}>⬇ Télécharger le fichier</a>
            </div>
          </div>
        )}
      </div>
    </div>
  );

  if(compact){
    return (
      <div style={{display:"flex",flexWrap:"wrap",gap:5,alignItems:"center",marginTop:4}}>
        {docs.map(d=>(
          <div key={d.id} style={{display:"flex",alignItems:"center",gap:4,background:"rgba(240,165,0,0.08)",border:"1px solid rgba(240,165,0,0.2)",borderRadius:6,padding:"2px 8px",fontSize:11}}>
            <span>{icon(d)}</span>
            <span onClick={()=>setPreview(d)} style={{color:T.accent,cursor:"pointer",maxWidth:110,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}} title={d.nom}>{d.nom}</span>
            <button onClick={e=>{e.stopPropagation();del(d.id);}} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,padding:"0 1px",lineHeight:1}}>×</button>
          </div>
        ))}
        <button onClick={e=>{e.stopPropagation();ref.current.click();}} disabled={loading} style={{background:"rgba(240,165,0,0.08)",border:"1px dashed rgba(240,165,0,0.3)",borderRadius:6,padding:"2px 8px",cursor:"pointer",color:T.accent,fontSize:11,fontFamily:T.font}}>
          {loading?"⏳":docs.length===0?"📎 Joindre":"＋"}
        </button>
        <input ref={ref} type="file" accept="image/*,application/pdf,.doc,.docx,.xls,.xlsx,.csv" multiple style={{display:"none"}} onChange={e=>addFiles(e.target.files)}/>
        {preview&&<Visionneuse doc={preview} onClose={()=>setPreview(null)}/>}
      </div>
    );
  }

  // Mode panneau complet
  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:10}}>
        <div style={{fontSize:12,fontWeight:600,color:T.muted,textTransform:"uppercase",letterSpacing:"0.08em"}}>
          {label} {docs.length>0&&<span style={{color:T.accent}}>({docs.length})</span>}
        </div>
        <button onClick={()=>ref.current.click()} disabled={loading} style={{background:"rgba(240,165,0,0.08)",border:"1px solid rgba(240,165,0,0.25)",borderRadius:7,padding:"4px 12px",cursor:"pointer",color:T.accent,fontSize:12,fontFamily:T.font}}>
          {loading?"⏳ Chargement…":"+ Ajouter"}
        </button>
      </div>
      {/* Drop zone */}
      <div
        onDragOver={e=>{e.preventDefault();setDragging(true);}}
        onDragLeave={()=>setDragging(false)}
        onDrop={e=>{e.preventDefault();setDragging(false);addFiles(e.dataTransfer.files);}}
        style={{border:`2px dashed ${dragging?T.accent:T.border}`,borderRadius:10,padding:docs.length===0?"24px 16px":"8px",transition:"border-color 0.15s",background:dragging?"rgba(240,165,0,0.05)":"transparent"}}>
        {docs.length===0&&(
          <div style={{textAlign:"center",color:T.muted,fontSize:12,cursor:"pointer"}} onClick={()=>ref.current.click()}>
            <div style={{fontSize:28,marginBottom:6}}>📎</div>
            <div>Glisser-déposer ou <span style={{color:T.accent}}>cliquer pour ajouter</span></div>
            <div style={{fontSize:10,marginTop:4,color:T.border}}>PDF, images, Word, Excel…</div>
          </div>
        )}
        {docs.length>0&&(
          <div style={{display:"grid",gap:5}}>
            {docs.map(d=>(
              <div key={d.id} style={{display:"flex",alignItems:"center",gap:10,padding:"8px 10px",background:"#060a10",borderRadius:8,cursor:"pointer",transition:"background 0.12s"}}
                onMouseEnter={e=>e.currentTarget.style.background="#0d1420"}
                onMouseLeave={e=>e.currentTarget.style.background="#060a10"}>
                <span style={{fontSize:22,flexShrink:0}}>{icon(d)}</span>
                <div style={{flex:1,minWidth:0}} onClick={()=>setPreview(d)}>
                  <div style={{fontSize:13,color:T.text,fontWeight:500,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{d.nom}</div>
                  <div style={{fontSize:10,color:T.muted}}>{fmt(d.date)}{d.taille&&" · "+d.taille}</div>
                </div>
                <div style={{display:"flex",gap:4,flexShrink:0}}>
                  <button onClick={e=>{e.stopPropagation();setPreview(d);}} style={{background:"rgba(56,189,248,0.1)",border:"1px solid rgba(56,189,248,0.2)",color:T.info,borderRadius:6,padding:"4px 10px",cursor:"pointer",fontSize:11,fontWeight:600}}>👁 Voir</button>
                  <a href={d.dataUrl} download={d.nom} onClick={e=>e.stopPropagation()} style={{background:"rgba(240,165,0,0.1)",border:"1px solid rgba(240,165,0,0.2)",color:T.accent,borderRadius:6,padding:"4px 10px",cursor:"pointer",fontSize:11,textDecoration:"none",fontWeight:600}}>⬇</a>
                  <button onClick={e=>{e.stopPropagation();del(d.id);}} style={{background:"rgba(239,68,68,0.08)",border:"1px solid rgba(239,68,68,0.15)",color:T.danger,borderRadius:6,padding:"4px 8px",cursor:"pointer",fontSize:11}}>🗑</button>
                </div>
              </div>
            ))}
            <div onClick={()=>ref.current.click()} style={{display:"flex",alignItems:"center",gap:8,padding:"7px 10px",border:"1px dashed rgba(240,165,0,0.2)",borderRadius:8,cursor:"pointer",color:T.accent,fontSize:12}}>
              <span>＋</span><span>Ajouter un document</span>
            </div>
          </div>
        )}
      </div>
      <input ref={ref} type="file" accept="image/*,application/pdf,.doc,.docx,.xls,.xlsx,.csv,.txt" multiple style={{display:"none"}} onChange={e=>addFiles(e.target.files)}/>
      {preview&&<Visionneuse doc={preview} onClose={()=>setPreview(null)}/>}
    </div>
  );
};

// ── Data ──────────────────────────────────────────────────────────────────────
const CATS_DOC = [
  {id:"banque",label:"Banque",icon:"🏦",color:"#38bdf8"},
  {id:"impots",label:"Impôts",icon:"🏛️",color:"#a78bfa"},
  {id:"sante",label:"Santé",icon:"🏥",color:"#34d399"},
  {id:"avocat",label:"Juridique",icon:"⚖️",color:"#f87171"},
  {id:"assurance",label:"Assurances",icon:"🛡️",color:"#fbbf24"},
  {id:"immobilier",label:"Immobilier",icon:"🏠",color:"#f0a500"},
  {id:"factures",label:"Factures",icon:"📄",color:"#60a5fa"},
  {id:"contrats",label:"Contrats",icon:"📋",color:"#e879f9"},
  {id:"autres",label:"Autres",icon:"📁",color:"#94a3b8"},
];

// Modules toujours visibles (core)
const MODULES_CORE=new Set(["dashboard","alertes","recherche","guide","wallet"]);

// Tous les modules disponibles avec métadonnée optional
const NAV_GROUPS = [
  { label:"Accueil", items:[
    {id:"dashboard",icon:"⬡",label:"Tableau de bord"},
    {id:"patrimoine",icon:"📊",label:"Mon Patrimoine"},
    {id:"recherche",icon:"🔍",label:"Recherche globale"},
    {id:"guide",icon:"📖",label:"Guide d'utilisation"},
  ]},
  { label:"Mes Biens", items:[
    {id:"docs",icon:"📄",label:"Archivage"},
    {id:"maisons",icon:"🏡",label:"Mes Maisons"},
    {id:"vehicules",icon:"🚗",label:"Véhicules"},
    {id:"locataires",icon:"🏠",label:"Gestion locative"},
    {id:"garanties",icon:"🔧",label:"Garanties & SAV"},
    {id:"projets",icon:"🏗️",label:"Projets & Travaux"},
  ]},
  { label:"Ma Vie", items:[
    {id:"sante",icon:"🏥",label:"Ma Santé"},
    {id:"medicaments",icon:"💊",label:"Médicaments"},
    {id:"impots",icon:"🏛️",label:"Mes Impôts"},
    {id:"banque",icon:"🏦",label:"Ma Banque"},
    {id:"assurances",icon:"🛡️",label:"Assurances"},
    {id:"juridique",icon:"⚖️",label:"Juridique"},
    {id:"travail",icon:"💼",label:"Mon Travail"},
    {id:"retraite",icon:"🧓",label:"Ma Retraite"},
    {id:"abonnements",icon:"🔌",label:"Abonnements"},
    {id:"energie",icon:"⚡",label:"Énergie"},
    {id:"dons",icon:"🤲",label:"Dons & Asso."},
  ]},
  { label:"Loisirs", items:[
    {id:"sports",icon:"⚽",label:"Sports & Passions"},
    {id:"photos",icon:"📸",label:"Photos & Vidéos"},
    {id:"voyages",icon:"✈️",label:"Voyages & Vacances"},
    {id:"bibliotheque",icon:"📚",label:"Ma Bibliothèque"},
    {id:"planificateur",icon:"🗺️",label:"Planif. Séjour"},
  ]},
  { label:"Famille", items:[
    {id:"identite",icon:"🪪",label:"Identité"},
    {id:"viefamille",icon:"👨‍👩‍👧‍👦",label:"Vie de famille"},
    {id:"amis",icon:"👫",label:"Mes Amis"},
    {id:"enfants",icon:"👶",label:"Mes Enfants"},
    {id:"animaux",icon:"🐾",label:"Mes Animaux"},
    {id:"cadeaux",icon:"🎁",label:"Budget Cadeaux"},
    {id:"evenements",icon:"🎉",label:"Événements"},
  ]},
  { label:"Contacts & Suivi", items:[
    {id:"contacts",icon:"👥",label:"Contacts"},
    {id:"alertes",icon:"🔔",label:"Alertes"},
    {id:"courrier",icon:"📝",label:"Modèles courrier"},
    {id:"coffrefort",icon:"🔐",label:"Coffre-fort"},
    {id:"wallet",icon:"💳",label:"Cartes fidélité"},
  ]},
];

// Modules actifs par défaut (tout sauf certains optionnels)
const DEFAULT_VISIBLES=NAV_GROUPS.flatMap(g=>g.items).map(i=>i.id).filter(id=>!["retraite","dons","energie","juridique","bibliotheque","viefamille","animaux","medicaments","cadeaux","evenements","planificateur"].includes(id));
const NAV = NAV_GROUPS.flatMap(g=>g.items);

// ── OCR Simulé ────────────────────────────────────────────────────────────────
const doOCR = name => {
  const n = name.toLowerCase();
  if(n.includes("facture")||n.includes("invoice")) return {type:"Facture",montant:(Math.random()*400+20).toFixed(2),date:today(),fournisseur:"Fournisseur SA",tva:"20%",texte:"FACTURE\nMontant HT: XXX€\nTVA 20%\nTotal TTC: XXX€"};
  if(n.includes("loyer")||n.includes("quittance")) return {type:"Quittance",montant:(Math.random()*800+400).toFixed(2),date:today(),texte:"QUITTANCE DE LOYER\nPériode: XXX\nLoyer+charges: XXX€"};
  if(n.includes("impot")||n.includes("tax")) return {type:"Impôts",date:today(),texte:"AVIS D'IMPOSITION\nRevenu fiscal: XXXXX€\nImpôt net: XXXXX€"};
  if(n.includes("ordonnance")) return {type:"Ordonnance",date:today(),medecin:"Dr. XXXX",texte:"ORDONNANCE\nMédicament 1: XXX\nMédicament 2: XXX"};
  return {type:"Document",date:today(),texte:"Texte extrait par OCR et indexé pour la recherche."};
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: DASHBOARD
// ═══════════════════════════════════════════════════════════════════════════════
const Dashboard = ({docs,locataires,biens,alertes,contacts,sante,impots,assurances}) => {
  const urgentes = alertes.filter(a=>!a.fait&&daysFrom(a.date)<=7).length;
  const loyers = locataires.filter(l=>l.statut==="actif").reduce((s,l)=>s+l.loyer+l.charges,0);
  const prochaines = [...alertes].filter(a=>!a.fait).sort((a,b)=>a.date.localeCompare(b.date)).slice(0,5);
  const recentsDocs = [...docs].sort((a,b)=>(b.uploadedAt||"").localeCompare(a.uploadedAt||"")).slice(0,4);

  return (
    <div>
      <div style={{marginBottom:22}}>
        <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>Tableau de bord</h1>
        <p style={{color:T.muted,marginTop:3,fontSize:13}}>Vue d'ensemble de votre espace personnel</p>
      </div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(160px,1fr))",gap:12,marginBottom:22}}>
        <StatCard label="Documents" value={docs.length} icon="📄" color={T.info}/>
        <StatCard label="Revenus locatifs" value={fmtAmt(loyers)+"/mois"} icon="🏠" color={T.accent}/>
        <StatCard label="Contacts" value={contacts.length} icon="👥" color={T.purple}/>
        <StatCard label="Alertes urgentes" value={urgentes} icon="🔔" color={urgentes>0?T.danger:T.success}/>
        <StatCard label="Dossiers santé" value={sante.rdv.length} icon="🏥" color="#34d399}"/>
        <StatCard label="Assurances actives" value={assurances.filter(a=>a.statut==="actif").length} icon="🛡️" color={T.warning}/>
      </div>
      <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:16}}>
        <Card>
          <div style={{fontWeight:600,color:T.text,marginBottom:12,fontSize:14}}>📄 Documents récents</div>
          {recentsDocs.length===0 ? <EmptyState icon="📂" text="Aucun document"/> :
            recentsDocs.map(d=>{
              const cat=CATS_DOC.find(c=>c.id===d.categorie);
              return (
                <div key={d.id} style={{display:"flex",alignItems:"center",gap:10,padding:"7px 0",borderBottom:`1px solid ${T.border}`}}>
                  <span style={{fontSize:18}}>{cat?.icon||"📄"}</span>
                  <div style={{flex:1,minWidth:0}}>
                    <div style={{fontSize:12,color:T.text,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{d.nom}</div>
                    <div style={{fontSize:11,color:T.muted}}>{cat?.label} · {fmt(d.date)}</div>
                  </div>
                  {d.montant&&<span style={{fontSize:12,color:T.accent,fontWeight:600}}>{fmtAmt(d.montant)}</span>}
                </div>
              );
            })
          }
        </Card>
        <Card>
          <div style={{fontWeight:600,color:T.text,marginBottom:12,fontSize:14}}>🔔 Prochaines échéances</div>
          {prochaines.length===0 ? <EmptyState icon="✅" text="Aucune alerte"/> :
            prochaines.map(a=>{
              const d=daysFrom(a.date);
              const color=d<=0?T.danger:d<=7?T.warning:d<=30?T.info:T.success;
              return (
                <div key={a.id} style={{display:"flex",alignItems:"center",gap:10,padding:"7px 0",borderBottom:`1px solid ${T.border}`}}>
                  <div style={{width:8,height:8,borderRadius:"50%",background:color,flexShrink:0}}/>
                  <div style={{flex:1}}>
                    <div style={{fontSize:12,color:T.text}}>{a.titre}</div>
                    <div style={{fontSize:11,color:T.muted}}>{fmt(a.date)}</div>
                  </div>
                  <Badge c={color}>{d<=0?"Expiré":d===0?"Auj.":d+"j"}</Badge>
                </div>
              );
            })
          }
        </Card>
        <Card>
          <div style={{fontWeight:600,color:T.text,marginBottom:12,fontSize:14}}>🏠 Locataires actifs</div>
          {locataires.filter(l=>l.statut==="actif").map(l=>{
            const b=biens.find(x=>x.id===l.bienId);
            const att=l.paiements.filter(p=>p.statut==="en attente").length;
            return (
              <div key={l.id} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:12}}>
                <div>
                  <span style={{color:T.text,fontWeight:600}}>{l.prenom} {l.nom}</span>
                  <div style={{color:T.muted,fontSize:11}}>{b?.nom}</div>
                </div>
                <div style={{display:"flex",gap:6,alignItems:"center"}}>
                  {att>0&&<Badge c={T.warning}>{att} en att.</Badge>}
                  <span style={{color:T.accent,fontWeight:600}}>{fmtAmt(l.loyer+l.charges)}</span>
                </div>
              </div>
            );
          })}
          {locataires.filter(l=>l.statut==="actif").length===0&&<EmptyState icon="🏠" text="Aucun locataire actif"/>}
        </Card>
        <Card>
          <div style={{fontWeight:600,color:T.text,marginBottom:12,fontSize:14}}>📊 Répartition documents</div>
          {CATS_DOC.filter(c=>docs.some(d=>d.categorie===c.id)).map(cat=>{
            const count=docs.filter(d=>d.categorie===cat.id).length;
            return (
              <div key={cat.id} style={{marginBottom:8}}>
                <div style={{display:"flex",justifyContent:"space-between",marginBottom:2,fontSize:11}}>
                  <span style={{color:T.text}}>{cat.icon} {cat.label}</span>
                  <span style={{color:T.muted}}>{count}</span>
                </div>
                <div style={{background:T.border,borderRadius:4,height:3}}>
                  <div style={{background:cat.color,height:3,borderRadius:4,width:`${Math.min(100,(count/Math.max(docs.length,1))*100)}%`,transition:"width 0.5s"}}/>
                </div>
              </div>
            );
          })}
          {docs.length===0&&<EmptyState icon="📂" text="Aucun document"/>}
        </Card>
      </div>
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: ARCHIVAGE
// ═══════════════════════════════════════════════════════════════════════════════
const Archivage = ({docs,setDocs}) => {
  const [search,setSearch]=useState("");
  const [filterCat,setFilterCat]=useState("all");
  const [preview,setPreview]=useState(null);
  const [showAdd,setShowAdd]=useState(false);
  const [processing,setProcessing]=useState(false);
  const [pendingFile,setPendingFile]=useState(null);
  const [form,setForm]=useState({nom:"",categorie:"factures",date:today(),montant:"",tags:"",note:""});
  const dropRef=useRef();

  const handleFiles = useCallback(async files=>{
    const file=files[0]; if(!file) return;
    const dataUrl=await new Promise(r=>{const fr=new FileReader();fr.onload=e=>r(e.target.result);fr.readAsDataURL(file);});
    const isPdf=file.type==="application/pdf";
    const isImg=file.type.startsWith("image/");
    setPendingFile({file,dataUrl,type:file.type,isPdf,isImg});
    setForm(f=>({...f,nom:file.name.replace(/\.[^.]+$/,""),date:today()}));
    setShowAdd(true); setProcessing(true);
    setTimeout(()=>{
      const ocr=doOCR(file.name);
      setPendingFile(p=>({...p,ocr}));
      setForm(f=>({...f,montant:ocr.montant||f.montant,date:ocr.date||f.date}));
      setProcessing(false);
    },1500);
  },[]);

  const saveDoc = ()=>{
    setDocs(p=>[{id:uid(),nom:form.nom,categorie:form.categorie,date:form.date,
      montant:form.montant?parseFloat(form.montant):null,
      tags:form.tags.split(",").map(t=>t.trim()).filter(Boolean),
      note:form.note,
      dataUrl:pendingFile?.dataUrl||null,
      fileType:pendingFile?.type||null,
      isPdf:pendingFile?.isPdf||false,
      isImg:pendingFile?.isImg||false,
      ocr:pendingFile?.ocr||null,uploadedAt:today()
    },...p]);
    setShowAdd(false); setPendingFile(null);
    setForm({nom:"",categorie:"factures",date:today(),montant:"",tags:"",note:""});
  };

  const filtered=docs.filter(d=>{
    const s=search.toLowerCase();
    return (!s||d.nom.toLowerCase().includes(s)||d.ocr?.texte?.toLowerCase().includes(s)||d.tags?.some(t=>t.toLowerCase().includes(s)))
      &&(filterCat==="all"||d.categorie===filterCat);
  });

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>📄 Archivage</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>{docs.length} documents · OCR + recherche plein texte</p>
        </div>
        <Btn onClick={()=>dropRef.current.click()}>+ Importer</Btn>
      </div>
      <input ref={dropRef} type="file" accept="image/*,application/pdf" style={{display:"none"}} onChange={e=>handleFiles(e.target.files)}/>
      <div onDragOver={e=>{e.preventDefault();e.currentTarget.style.borderColor=T.accent}}
        onDragLeave={e=>e.currentTarget.style.borderColor=T.border}
        onDrop={e=>{e.preventDefault();e.currentTarget.style.borderColor=T.border;handleFiles(e.dataTransfer.files)}}
        onClick={()=>dropRef.current.click()}
        style={{border:`2px dashed ${T.border}`,borderRadius:12,padding:"24px 20px",textAlign:"center",
          cursor:"pointer",marginBottom:18,transition:"border-color 0.2s"}}>
        <div style={{fontSize:28,marginBottom:6}}>📂</div>
        <div style={{color:T.muted,fontSize:13}}>Glissez vos documents · <span style={{color:T.accent}}>PDF, JPG, PNG</span> · OCR automatique</div>
      </div>
      <div style={{display:"flex",gap:10,marginBottom:16}}>
        <Inp value={search} onChange={setSearch} placeholder="🔍 Rechercher (nom, texte OCR, tags)..." style={{flex:1}}/>
        <Sel value={filterCat} onChange={setFilterCat} style={{width:180}}>
          <option value="all">Toutes catégories</option>
          {CATS_DOC.map(c=><option key={c.id} value={c.id}>{c.icon} {c.label}</option>)}
        </Sel>
      </div>
      <div style={{display:"grid",gap:8}}>
        {filtered.length===0&&<EmptyState icon="📂" text="Aucun document trouvé"/>}
        {filtered.map(doc=>{
          const cat=CATS_DOC.find(c=>c.id===doc.categorie);
          return (
            <Card key={doc.id} style={{padding:"12px 16px"}} onClick={()=>setPreview(doc)}>
              <div style={{display:"flex",alignItems:"center",gap:12}}>
                <div style={{width:40,height:40,borderRadius:8,background:cat?.color+"22",display:"flex",alignItems:"center",justifyContent:"center",fontSize:20,flexShrink:0}}>{cat?.icon||"📄"}</div>
                <div style={{flex:1,minWidth:0}}>
                  <div style={{display:"flex",alignItems:"center",gap:6,marginBottom:2,flexWrap:"wrap"}}>
                    <span style={{fontSize:13,fontWeight:600,color:T.text,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",maxWidth:300}}>{doc.nom}</span>
                    <Badge c={cat?.color||T.accent}>{cat?.label}</Badge>
                    {doc.ocr&&<Badge c={T.success}>OCR ✓</Badge>}
                  </div>
                  <div style={{fontSize:11,color:T.muted,display:"flex",gap:10,flexWrap:"wrap"}}>
                    <span>📅 {fmt(doc.date)}</span>
                    {doc.montant&&<span style={{color:T.accent}}>💶 {fmtAmt(doc.montant)}</span>}
                    {doc.tags?.length>0&&<span>🏷 {doc.tags.join(", ")}</span>}
                  </div>
                </div>
                <span style={{fontSize:11,color:T.muted}}>👁 Voir</span>
              </div>
            </Card>
          );
        })}
      </div>
      {showAdd&&(
        <Modal title="📄 Nouveau document" onClose={()=>{setShowAdd(false);setPendingFile(null);}}>
          {processing&&<div style={{background:T.accentDim,border:`1px solid rgba(240,165,0,0.3)`,borderRadius:8,padding:10,marginBottom:14,fontSize:13,color:T.accent}}>⚙️ Analyse OCR en cours...</div>}
          {pendingFile?.ocr&&<div style={{background:"rgba(34,197,94,0.08)",border:"1px solid rgba(34,197,94,0.2)",borderRadius:8,padding:10,marginBottom:14,fontSize:12,color:T.success}}>✅ OCR terminé · {pendingFile.ocr.type} détecté{pendingFile.ocr.montant?" · "+fmtAmt(pendingFile.ocr.montant):""}</div>}
          <div style={{display:"grid",gap:10}}>
            <F label="Nom"><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Nom du document"/></F>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
              <F label="Catégorie"><Sel value={form.categorie} onChange={v=>setForm(f=>({...f,categorie:v}))}>{CATS_DOC.map(c=><option key={c.id} value={c.id}>{c.icon} {c.label}</option>)}</Sel></F>
              <F label="Date"><Inp type="date" value={form.date} onChange={v=>setForm(f=>({...f,date:v}))}/></F>
            </div>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
              <F label="Montant (€)"><Inp type="number" value={form.montant} onChange={v=>setForm(f=>({...f,montant:v}))} placeholder="0.00"/></F>
              <F label="Tags"><Inp value={form.tags} onChange={v=>setForm(f=>({...f,tags:v}))} placeholder="urgent, 2025..."/></F>
            </div>
            <F label="Note"><Inp value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} placeholder="Note libre..."/></F>
            {pendingFile?.ocr?.texte&&<div style={{background:"#0a0e17",borderRadius:8,padding:10,fontSize:11,color:T.muted,fontFamily:"monospace",whiteSpace:"pre-wrap",maxHeight:80,overflow:"auto"}}>{pendingFile.ocr.texte}</div>}
            <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:4}}>
              <Btn v="ghost" onClick={()=>{setShowAdd(false);setPendingFile(null);}}>Annuler</Btn>
              <Btn onClick={saveDoc} disabled={processing}>💾 Enregistrer</Btn>
            </div>
          </div>
        </Modal>
      )}
      {preview&&(
        <Modal title={preview.nom} onClose={()=>setPreview(null)} width={860}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:16}}>
            {/* Visionneuse */}
            <div style={{background:"#060a10",borderRadius:10,minHeight:260,display:"flex",flexDirection:"column",overflow:"hidden"}}>
              {preview.dataUrl?(
                preview.isImg
                  ? <img src={preview.dataUrl} alt={preview.nom} style={{maxWidth:"100%",maxHeight:320,objectFit:"contain",borderRadius:8,margin:"auto",padding:8}}/>
                  : preview.isPdf
                    ? <div style={{flex:1,overflow:"auto",maxHeight:380}}><PdfViewer dataUrl={preview.dataUrl}/></div>
                    : <div style={{display:"flex",alignItems:"center",justifyContent:"center",flex:1,padding:20,textAlign:"center"}}>
                        <div><div style={{fontSize:48,marginBottom:10}}>📄</div><div style={{color:T.muted,fontSize:12}}>Aperçu non disponible</div></div>
                      </div>
              ):(
                <div style={{display:"flex",alignItems:"center",justifyContent:"center",flex:1}}>
                  <div style={{textAlign:"center",color:T.muted}}><div style={{fontSize:48}}>📄</div><div style={{fontSize:12,marginTop:6}}>Aucun fichier joint</div></div>
                </div>
              )}
            </div>
            <div>
              {[["Catégorie",CATS_DOC.find(c=>c.id===preview.categorie)?.label],["Date",fmt(preview.date)],["Montant",preview.montant&&fmtAmt(preview.montant)],["Note",preview.note]].filter(([,v])=>v).map(([l,v])=>(
                <div key={l} style={{marginBottom:10}}>
                  <div style={{fontSize:10,color:T.muted,textTransform:"uppercase",letterSpacing:"0.08em",marginBottom:2}}>{l}</div>
                  <div style={{color:l==="Montant"?T.accent:T.text,fontSize:l==="Montant"?20:13,fontWeight:l==="Montant"?700:400,fontFamily:l==="Montant"?T.fontD:T.font}}>{v}</div>
                </div>
              ))}
              {preview.tags?.length>0&&<div style={{display:"flex",gap:6,flexWrap:"wrap",marginBottom:10}}>{preview.tags.map(t=><Badge key={t}>{t}</Badge>)}</div>}
              {preview.ocr&&<div style={{background:"#0a0e17",borderRadius:8,padding:10,fontSize:11,color:T.muted,fontFamily:"monospace",whiteSpace:"pre-wrap",maxHeight:120,overflow:"auto"}}>{preview.ocr.texte}</div>}
              <div style={{display:"flex",gap:8,marginTop:12}}>
                {preview.dataUrl&&<a href={preview.dataUrl} download={preview.nom} style={{background:T.accentDim,color:T.accent,textDecoration:"none",padding:"6px 12px",borderRadius:8,fontSize:12,fontWeight:600}}>⬇ Télécharger</a>}
                <Btn v="danger" sm onClick={()=>{setDocs(p=>p.filter(d=>d.id!==preview.id));setPreview(null);}}>🗑 Supprimer</Btn>
              </div>
            </div>
          </div>
        </Modal>
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: GESTION LOCATIVE (Rentila-inspired)
// ═══════════════════════════════════════════════════════════════════════════════
const PIECES=["Entrée","Salon","Cuisine","Chambre 1","Chambre 2","Salle de bain","WC","Garage"];
const ETATS_EDL=["Neuf","Très bon état","Bon état","État d'usage","Mauvais état"];
const LETTRES=[
  {id:"retard",titre:"Rappel loyer impayé",corps:"Madame, Monsieur,\n\nNous vous rappelons que le loyer du mois de [MOIS] d'un montant de [MONTANT] n'a pas été réglé.\n\nMerci de procéder à son règlement dans les plus brefs délais.\n\nCordialement,\nLe propriétaire"},
  {id:"revision",titre:"Révision annuelle (IRL)",corps:"Madame, Monsieur,\n\nConformément à votre bail, le loyer est révisé à compter du [DATE].\n\nAncien loyer : [ANCIEN] €\nNouvel IRL : [IRL]\nNouveau loyer : [NOUVEAU] €\n\nCordialement,\nLe propriétaire"},
  {id:"assurance",titre:"Demande attestation assurance",corps:"Madame, Monsieur,\n\nMerci de nous faire parvenir votre attestation d'assurance habitation en cours de validité.\n\nCordialement,\nLe propriétaire"},
  {id:"travaux",titre:"Notification de travaux",corps:"Madame, Monsieur,\n\nNous vous informons que des travaux seront effectués du [DATE_DEBUT] au [DATE_FIN].\n\nCordialement,\nLe propriétaire"},
  {id:"conge",titre:"Congé donné au locataire",corps:"Madame, Monsieur,\n\nNous vous notifions notre décision de mettre fin à votre bail le [DATE_FIN].\n\nCordialement,\nLe propriétaire"},
];

const genQuittance=(loc,bien,mois)=>`QUITTANCE DE LOYER
══════════════════════════════════
Période : ${fmtMois(mois+"-01")}
Locataire : ${loc.prenom} ${loc.nom}
Bien : ${bien?.adresse||""}
──────────────────────────────────
Loyer HC             ${fmtAmt(loc.loyer)}
Charges              ${fmtAmt(loc.charges)}
──────────────────────────────────
TOTAL REÇU           ${fmtAmt(loc.loyer+loc.charges)}
──────────────────────────────────
Fait le ${new Date().toLocaleDateString("fr-FR")}
Signature : ________________`;

const DossierLocataire=({loc,bien,onUpdate,onClose})=>{
  const [tab,setTab]=useState("loyers");
  const [showQ,setShowQ]=useState(null);
  const [showEdl,setShowEdl]=useState(false);
  const [showLettre,setShowLettre]=useState(null);
  const [showRev,setShowRev]=useState(false);
  const [showInter,setShowInter]=useState(false);
  const [newMsg,setNewMsg]=useState("");
  const [irlNouv,setIrlNouv]=useState("145.76");
  const [inter,setInter]=useState({titre:"",date:today(),description:"",statut:"en cours",cout:""});
  const [edlPieces,setEdlPieces]=useState(PIECES.map(p=>({nom:p,etat:"Bon état",commentaire:""})));

  const newLoyer=Math.round(loc.loyer*(parseFloat(irlNouv)/parseFloat(loc.indexEntree||"143.46"))*100)/100;
  const totalEnc=loc.paiements.filter(p=>p.statut==="payé").reduce((s,p)=>s+p.montant,0);
  const att=loc.paiements.filter(p=>p.statut==="en attente").length;
  const jFin=daysFrom(loc.dateFin);
  const assOk=loc.assuranceOk&&daysFrom(loc.assuranceExpiry)>0;

  const TABS=[{id:"loyers",icon:"💶",label:"Loyers"},{id:"edl",icon:"🔍",label:"État des lieux"},
    {id:"interventions",icon:"🔧",label:"Travaux"},{id:"finances",icon:"📊",label:"Finances"},
    {id:"messages",icon:"✉️",label:"Messages"},{id:"lettres",icon:"📝",label:"Courriers"},
    {id:"dossier",icon:"👤",label:"Dossier"}];

  return (
    <div style={{position:"fixed",inset:0,background:T.bg,zIndex:1500,display:"flex",flexDirection:"column",overflow:"hidden"}}>
      <FontLink/>
      <div style={{background:T.sidebar,borderBottom:`1px solid ${T.border}`,padding:"12px 22px",display:"flex",alignItems:"center",gap:14,flexShrink:0}}>
        <Btn v="outline" sm onClick={onClose}>← Retour</Btn>
        <div style={{flex:1}}>
          <div style={{fontFamily:T.fontD,fontSize:19,color:T.text}}>{loc.prenom} {loc.nom}</div>
          <div style={{fontSize:11,color:T.muted}}>🏠 {bien?.nom} · {loc.typeBail} · {fmtAmt(loc.loyer+loc.charges)}/mois</div>
        </div>
        <div style={{display:"flex",gap:6,flexWrap:"wrap"}}>
          {att>0&&<Badge c={T.warning}>{att} loyer{att>1?"s":""} en attente</Badge>}
          {jFin!=null&&jFin<=90&&<Badge c={jFin<=0?T.danger:T.warning}>Bail {jFin<=0?"expiré":jFin+"j"}</Badge>}
          {!assOk&&<Badge c={T.danger}>Assurance !</Badge>}
        </div>
      </div>
      <div style={{flex:1,overflow:"auto",padding:"18px 22px"}}>
        <Tabs tabs={TABS} active={tab} onChange={setTab}/>

        {tab==="loyers"&&(
          <div>
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(150px,1fr))",gap:10,marginBottom:16}}>
              <StatCard label="Total encaissé" value={fmtAmt(totalEnc)} icon="💰" color={T.success}/>
              <StatCard label="Loyer HC" value={fmtAmt(loc.loyer)} icon="💶" color={T.accent}/>
              <StatCard label="Charges" value={fmtAmt(loc.charges)} icon="⚡" color={T.info}/>
              <StatCard label="Dépôt" value={fmtAmt(loc.depot)} icon="🔒" color={T.purple}/>
            </div>
            <div style={{display:"flex",gap:8,marginBottom:14,flexWrap:"wrap"}}>
              <Btn sm onClick={()=>{const m=thisMonth();if(!loc.paiements.find(p=>p.mois===m))onUpdate({...loc,paiements:[...loc.paiements,{id:uid(),mois:m,montant:loc.loyer+loc.charges,date:null,mode:"",statut:"en attente"}]});}}>+ Mois courant</Btn>
              <Btn sm v="outline" onClick={()=>setShowRev(true)}>📈 Révision IRL</Btn>
            </div>
            <div style={{background:T.card,borderRadius:10,border:`1px solid ${T.border}`,overflow:"auto"}}>
              <table style={{width:"100%",borderCollapse:"collapse",fontSize:13}}>
                <thead><tr style={{background:"#0a0e17"}}>{["Mois","Montant","Date","Mode","Statut",""].map(h=><th key={h} style={{padding:"9px 12px",textAlign:"left",color:T.muted,fontSize:11}}>{h}</th>)}</tr></thead>
                <tbody>
                  {[...loc.paiements].reverse().map(p=>(
                    <tr key={p.id} style={{borderTop:`1px solid ${T.border}`}}>
                      <td style={{padding:"9px 12px",fontWeight:600,color:T.text}}>{fmtMois(p.mois+"-01")}</td>
                      <td style={{padding:"9px 12px",color:T.accent,fontWeight:600}}>{fmtAmt(p.montant)}</td>
                      <td style={{padding:"9px 12px",color:T.muted}}>{p.date?fmt(p.date):"—"}</td>
                      <td style={{padding:"9px 12px",color:T.muted}}>{p.mode||"—"}</td>
                      <td style={{padding:"9px 12px"}}><Badge c={p.statut==="payé"?T.success:T.warning}>{p.statut}</Badge></td>
                      <td style={{padding:"9px 12px"}}>
                        <div style={{display:"flex",gap:6}}>
                          {p.statut==="en attente"&&<Btn sm v="success" onClick={()=>onUpdate({...loc,paiements:loc.paiements.map(x=>x.id===p.id?{...x,statut:"payé",date:today(),mode:"virement"}:x)})}>✓</Btn>}
                          <Btn sm v="outline" onClick={()=>setShowQ(p)}>📄</Btn>
                        </div>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        )}

        {tab==="edl"&&(
          <div>
            <div style={{display:"flex",gap:8,marginBottom:16}}>
              <Btn onClick={()=>setShowEdl("entree")}>+ EDL d'entrée</Btn>
              <Btn v="outline" onClick={()=>setShowEdl("sortie")}>+ EDL de sortie</Btn>
            </div>
            {!loc.edlEntree&&!loc.edlSortie&&<EmptyState icon="🔍" text="Aucun état des lieux enregistré."/>}
            {["edlEntree","edlSortie"].map(k=>loc[k]&&(
              <Card key={k} style={{marginBottom:12}}>
                <div style={{fontWeight:700,color:T.text,marginBottom:10}}>📋 EDL d'{k==="edlEntree"?"entrée":"sortie"} — {fmt(loc[k].date)}</div>
                <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(140px,1fr))",gap:8}}>
                  {(loc[k].pieces||[]).map(p=>(
                    <div key={p.nom} style={{background:"#0a0e17",padding:"7px 10px",borderRadius:8}}>
                      <div style={{fontSize:11,fontWeight:600,color:T.text,marginBottom:3}}>{p.nom}</div>
                      <Badge c={p.etat==="Neuf"||p.etat==="Très bon état"?T.success:p.etat==="Bon état"?T.info:T.warning}>{p.etat}</Badge>
                    </div>
                  ))}
                </div>
              </Card>
            ))}
          </div>
        )}

        {tab==="interventions"&&(
          <div>
            <div style={{marginBottom:14}}><Btn onClick={()=>setShowInter(true)}>+ Nouvelle intervention</Btn></div>
            {(loc.interventions||[]).length===0&&<EmptyState icon="🔧" text="Aucune intervention enregistrée."/>}
            {(loc.interventions||[]).map(iv=>(
              <Card key={iv.id} style={{marginBottom:10,padding:"12px 16px"}}>
                <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                  <div>
                    <div style={{fontWeight:600,color:T.text,marginBottom:3}}>{iv.titre}</div>
                    <div style={{fontSize:12,color:T.muted}}>{fmt(iv.date)}{iv.description&&" · "+iv.description}</div>
                  </div>
                  <div style={{display:"flex",gap:8,alignItems:"center"}}>
                    {iv.cout>0&&<span style={{fontWeight:700,color:T.accent,fontSize:13}}>{fmtAmt(iv.cout)}</span>}
                    <Badge c={iv.statut==="résolu"?T.success:T.warning}>{iv.statut}</Badge>
                  </div>
                </div>
              </Card>
            ))}
          </div>
        )}

        {tab==="finances"&&(
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
            <Card>
              <Divider label="Revenus"/>
              {[["Loyers encaissés",fmtAmt(totalEnc),T.success],["En attente",fmtAmt(loc.paiements.filter(p=>p.statut==="en attente").reduce((s,p)=>s+p.montant,0)),T.warning],["Dépôt de garantie",fmtAmt(loc.depot),T.purple]].map(([l,v,c])=>(
                <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                  <span style={{color:T.muted}}>{l}</span><span style={{color:c,fontWeight:600}}>{v}</span>
                </div>
              ))}
            </Card>
            <Card>
              <Divider label="Dépenses & Aide déclaration 2044"/>
              {[["Travaux déductibles",fmtAmt((loc.interventions||[]).reduce((s,i)=>s+i.cout,0)),T.danger]].map(([l,v,c])=>(
                <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                  <span style={{color:T.muted}}>{l}</span><span style={{color:c,fontWeight:600}}>{v}</span>
                </div>
              ))}
              <div style={{marginTop:12,background:T.accentDim,borderRadius:8,padding:10}}>
                <div style={{fontSize:10,color:T.muted,marginBottom:3}}>REVENU FONCIER NET ESTIMÉ</div>
                <div style={{fontSize:22,fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{fmtAmt(totalEnc-(loc.interventions||[]).reduce((s,i)=>s+i.cout,0))}</div>
              </div>
            </Card>
          </div>
        )}

        {tab==="messages"&&(
          <div>
            <div style={{display:"grid",gap:8,marginBottom:14,maxHeight:350,overflow:"auto"}}>
              {(loc.messages||[]).length===0&&<EmptyState icon="✉️" text="Aucun message."/>}
              {(loc.messages||[]).map(m=>(
                <div key={m.id} style={{display:"flex",justifyContent:m.de==="proprietaire"?"flex-end":"flex-start"}}>
                  <div style={{maxWidth:"70%",background:m.de==="proprietaire"?T.accentDim:"#0a0e17",border:`1px solid ${m.de==="proprietaire"?"rgba(240,165,0,0.3)":T.border}`,borderRadius:10,padding:"9px 13px"}}>
                    <div style={{fontSize:10,color:T.muted,marginBottom:3}}>{m.de==="proprietaire"?"Vous":"Locataire"} · {fmt(m.date)}</div>
                    <div style={{fontSize:13,color:T.text}}>{m.texte}</div>
                  </div>
                </div>
              ))}
            </div>
            <div style={{display:"flex",gap:8}}>
              <Txt value={newMsg} onChange={setNewMsg} placeholder="Écrire au locataire..." rows={2}/>
              <Btn onClick={()=>{if(newMsg.trim()){onUpdate({...loc,messages:[...(loc.messages||[]),{id:uid(),de:"proprietaire",texte:newMsg,date:today(),lu:true}]});setNewMsg("");}}} style={{alignSelf:"flex-end",whiteSpace:"nowrap"}}>✉️ Envoyer</Btn>
            </div>
          </div>
        )}

        {tab==="lettres"&&(
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(200px,1fr))",gap:12}}>
            {LETTRES.map(l=>(
              <Card key={l.id} onClick={()=>setShowLettre(l)} style={{cursor:"pointer"}}>
                <div style={{fontSize:13,fontWeight:600,color:T.text,marginBottom:6}}>📝 {l.titre}</div>
                <div style={{fontSize:11,color:T.muted,lineHeight:1.5}}>{l.corps.slice(0,70)}...</div>
                <div style={{marginTop:10}}><Badge c={T.accent}>Utiliser</Badge></div>
              </Card>
            ))}
          </div>
        )}

        {tab==="dossier"&&(
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
            <Card>
              <Divider label="Identité"/>
              {[["Prénom",loc.prenom],["Nom",loc.nom],["Email",loc.email],["Tél",loc.tel],["Profession",loc.profession],["Revenu mensuel",loc.revenuMensuel&&fmtAmt(loc.revenuMensuel)]].map(([l,v])=>v&&(
                <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"6px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                  <span style={{color:T.muted}}>{l}</span><span style={{color:T.text,fontWeight:500}}>{v}</span>
                </div>
              ))}
            </Card>
            <Card>
              <Divider label="Bail"/>
              {[["Type",loc.typeBail],["Entrée",fmt(loc.dateEntree)],["Fin",fmt(loc.dateFin)],["Loyer HC",fmtAmt(loc.loyer)],["Charges",fmtAmt(loc.charges)],["Dépôt",fmtAmt(loc.depot)],["Index IRL entrée",loc.indexEntree]].map(([l,v])=>(
                <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"6px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                  <span style={{color:T.muted}}>{l}</span><span style={{color:T.text,fontWeight:500}}>{v||"—"}</span>
                </div>
              ))}
              <div style={{marginTop:10}}>
                <span style={{color:T.muted,fontSize:13}}>Assurance : </span>
                <Badge c={assOk?T.success:T.danger}>{assOk?"À jour":"Expirée / manquante"}</Badge>
              </div>
            </Card>
          </div>
        )}
      </div>

      {showQ&&<Modal title="📄 Quittance" onClose={()=>setShowQ(null)}>
        <div style={{background:"#fff",color:"#111",borderRadius:8,padding:20,fontFamily:"monospace",fontSize:12,whiteSpace:"pre-wrap",lineHeight:1.8,marginBottom:14}}>{genQuittance(loc,bien,showQ.mois)}</div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
          <Btn v="ghost" onClick={()=>setShowQ(null)}>Fermer</Btn>
          <Btn onClick={()=>{const w=window.open("","_blank");w.document.write(`<pre style="font-family:monospace;padding:40px">${genQuittance(loc,bien,showQ.mois)}</pre>`);w.print();}}>🖨️ Imprimer</Btn>
        </div>
      </Modal>}
      {showEdl&&<Modal title={`📋 État des lieux d'${showEdl}`} onClose={()=>setShowEdl(false)} width={700}>
        <div style={{display:"grid",gap:8,marginBottom:14}}>
          {edlPieces.map((p,i)=>(
            <div key={p.nom} style={{display:"grid",gridTemplateColumns:"1fr 1fr 2fr",gap:8,alignItems:"center",background:"#0a0e17",padding:"8px 10px",borderRadius:8}}>
              <div style={{fontSize:13,fontWeight:600,color:T.text}}>{p.nom}</div>
              <Sel value={p.etat} onChange={v=>setEdlPieces(ps=>ps.map((x,j)=>j===i?{...x,etat:v}:x))}>{ETATS_EDL.map(e=><option key={e}>{e}</option>)}</Sel>
              <Inp value={p.commentaire} onChange={v=>setEdlPieces(ps=>ps.map((x,j)=>j===i?{...x,commentaire:v}:x))} placeholder="Observations..."/>
            </div>
          ))}
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
          <Btn v="ghost" onClick={()=>setShowEdl(false)}>Annuler</Btn>
          <Btn onClick={()=>{onUpdate({...loc,[showEdl==="entree"?"edlEntree":"edlSortie"]:{date:today(),pieces:edlPieces}});setShowEdl(false);}}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
      {showLettre&&<Modal title={showLettre.titre} onClose={()=>setShowLettre(null)}>
        <Txt value={showLettre.corps.replace("[MOIS]",fmtMois(thisMonth()+"-01")).replace("[MONTANT]",fmtAmt(loc.loyer+loc.charges)).replace("[ANCIEN]",String(loc.loyer)).replace("[NOUVEAU]",String(newLoyer)).replace("[IRL]",irlNouv)} onChange={()=>{}} rows={12}/>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowLettre(null)}>Fermer</Btn>
          <Btn onClick={()=>{const w=window.open("","_blank");w.document.write(`<pre style="font-family:Arial;padding:40px;font-size:14px;line-height:1.8">${showLettre.corps}</pre>`);w.print();}}>🖨️ Imprimer</Btn>
        </div>
      </Modal>}
      {showRev&&<Modal title="📈 Révision loyer (IRL)" onClose={()=>setShowRev(false)}>
        <div style={{background:T.accentDim,borderRadius:8,padding:10,marginBottom:14,fontSize:12,color:T.accent}}>Formule : Nouveau loyer = Loyer actuel × (IRL nouveau ÷ IRL référence)</div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10,marginBottom:14}}>
          <F label="IRL référence (entrée)"><Inp value={loc.indexEntree||"143.46"} onChange={()=>{}}/></F>
          <F label="Nouvel IRL"><Inp value={irlNouv} onChange={setIrlNouv}/></F>
        </div>
        <div style={{background:"#0a0e17",borderRadius:8,padding:14,marginBottom:14}}>
          <div style={{display:"flex",justifyContent:"space-between",fontSize:13,marginBottom:6}}><span style={{color:T.muted}}>Loyer actuel</span><span style={{color:T.text}}>{fmtAmt(loc.loyer)}</span></div>
          <div style={{display:"flex",justifyContent:"space-between",fontSize:16,fontWeight:700,paddingTop:8,borderTop:`1px solid ${T.border}`}}><span style={{color:T.text}}>Nouveau loyer</span><span style={{color:T.accent,fontFamily:T.fontD,fontSize:22}}>{fmtAmt(newLoyer)}</span></div>
          <div style={{fontSize:12,color:T.success,marginTop:6}}>+{fmtAmt(newLoyer-loc.loyer)} (+{(((newLoyer-loc.loyer)/loc.loyer)*100).toFixed(2)}%)</div>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
          <Btn v="ghost" onClick={()=>setShowRev(false)}>Annuler</Btn>
          <Btn onClick={()=>{onUpdate({...loc,loyer:newLoyer});setShowRev(false);}}>✅ Appliquer</Btn>
        </div>
      </Modal>}
      {showInter&&<Modal title="🔧 Nouvelle intervention" onClose={()=>setShowInter(false)}>
        <div style={{display:"grid",gap:10}}>
          <F label="Titre"><Inp value={inter.titre} onChange={v=>setInter(x=>({...x,titre:v}))} placeholder="Ex: Fuite robinet..."/></F>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:10}}>
            <F label="Date"><Inp type="date" value={inter.date} onChange={v=>setInter(x=>({...x,date:v}))}/></F>
            <F label="Coût (€)"><Inp type="number" value={inter.cout} onChange={v=>setInter(x=>({...x,cout:v}))}/></F>
            <F label="Statut"><Sel value={inter.statut} onChange={v=>setInter(x=>({...x,statut:v}))}><option value="en cours">En cours</option><option value="résolu">Résolu</option><option value="planifié">Planifié</option></Sel></F>
          </div>
          <F label="Description"><Txt value={inter.description} onChange={v=>setInter(x=>({...x,description:v}))} placeholder="Détails..."/></F>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
            <Btn v="ghost" onClick={()=>setShowInter(false)}>Annuler</Btn>
            <Btn onClick={()=>{onUpdate({...loc,interventions:[...(loc.interventions||[]),{...inter,id:uid(),cout:parseFloat(inter.cout)||0}]});setShowInter(false);}}>💾 Enregistrer</Btn>
          </div>
        </div>
      </Modal>}
    </div>
  );
};

const GestionLocative=({locataires,setLocataires,biens,setBiens})=>{
  const [selected,setSelected]=useState(null);
  const [selectedBien,setSelectedBien]=useState(null);
  const [tabMain,setTabMain]=useState("locataires");
  const [showAddLoc,setShowAddLoc]=useState(false);
  const [showAddBien,setShowAddBien]=useState(false);
  const [formLoc,setFormLoc]=useState({nom:"",prenom:"",email:"",tel:"",bienId:"",typeBail:"Vide",dateEntree:"",dateFin:"",loyer:"",charges:"",depot:"",indexEntree:"145.76",profession:"",revenuMensuel:""});
  const [formBien,setFormBien]=useState({nom:"",type:"Appartement",adresse:"",surface:"",dpe:"C",loyer:"",charges:"",depot:""});

  const sel=locataires.find(l=>l.id===selected);
  const selBien=sel?biens.find(b=>b.id===sel.bienId):null;
  const updateLoc=updated=>setLocataires(p=>p.map(l=>l.id===updated.id?updated:l));
  const totalLoyers=locataires.filter(l=>l.statut==="actif").reduce((s,l)=>s+l.loyer+l.charges,0);

  if(selected&&sel) return <DossierLocataire loc={sel} bien={selBien} onUpdate={updateLoc} onClose={()=>setSelected(null)}/>;

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🏠 Gestion Locative</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>Inspiré de Rentila · {locataires.filter(l=>l.statut==="actif").length} locataires · {biens.length} biens</p>
        </div>
        <div style={{display:"flex",gap:8}}>
          <Btn v="outline" sm onClick={()=>setShowAddBien(true)}>+ Bien</Btn>
          <Btn onClick={()=>setShowAddLoc(true)}>+ Locataire</Btn>
        </div>
      </div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(160px,1fr))",gap:12,marginBottom:20}}>
        <StatCard label="Revenus mensuels" value={fmtAmt(totalLoyers)} icon="💶" color={T.success}/>
        <StatCard label="Revenus annuels" value={fmtAmt(totalLoyers*12)} icon="📈" color={T.accent}/>
        <StatCard label="Dépôts détenus" value={fmtAmt(locataires.reduce((s,l)=>s+l.depot,0))} icon="🔒" color={T.purple}/>
        <StatCard label="Travaux" value={fmtAmt(locataires.reduce((s,l)=>s+(l.interventions||[]).reduce((ss,i)=>ss+i.cout,0),0))} icon="🔧" color={T.danger}/>
      </div>
      <Tabs tabs={[{id:"locataires",icon:"👤",label:`Locataires (${locataires.length})`},{id:"biens",icon:"🏠",label:`Biens (${biens.length})`},{id:"synthese",icon:"📊",label:"Synthèse fiscale"}]} active={tabMain} onChange={setTabMain}/>
      {tabMain==="locataires"&&(
        <div style={{display:"grid",gap:10}}>
          {locataires.length===0&&<EmptyState icon="🏠" text="Aucun locataire. Ajoutez votre premier bien puis votre premier locataire."/>}
          {locataires.map(l=>{
            const b=biens.find(x=>x.id===l.bienId);
            const att=l.paiements.filter(p=>p.statut==="en attente").length;
            const jFin=daysFrom(l.dateFin);
            const msgs=(l.messages||[]).filter(m=>!m.lu&&m.de==="locataire").length;
            return (
              <Card key={l.id} onClick={()=>setSelected(l.id)}>
                <div style={{display:"flex",alignItems:"center",gap:14}}>
                  <div style={{width:44,height:44,borderRadius:22,background:T.accentDim,display:"flex",alignItems:"center",justifyContent:"center",fontSize:16,fontWeight:700,color:T.accent,flexShrink:0}}>{l.prenom[0]}{l.nom[0]}</div>
                  <div style={{flex:1,minWidth:0}}>
                    <div style={{fontWeight:700,color:T.text,fontSize:14,marginBottom:2}}>{l.prenom} {l.nom}</div>
                    <div style={{fontSize:11,color:T.muted,marginBottom:6}}>🏠 {b?.nom||"—"} · {l.typeBail} · Depuis {fmt(l.dateEntree)}</div>
                    <div style={{display:"flex",gap:6,flexWrap:"wrap"}}>
                      <Badge c={T.accent}>{fmtAmt(l.loyer+l.charges)}/mois</Badge>
                      {att>0&&<Badge c={T.warning}>{att} loyer{att>1?"s":""} en att.</Badge>}
                      {jFin!=null&&jFin<=90&&<Badge c={jFin<=0?T.danger:T.warning}>Bail {jFin<=0?"expiré":jFin+"j"}</Badge>}
                      {msgs>0&&<Badge c={T.info}>{msgs} msg</Badge>}
                    </div>
                  </div>
                  <Badge c={T.muted}>→ Dossier</Badge>
                </div>
              </Card>
            );
          })}
        </div>
      )}
      {tabMain==="biens"&&(
        <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(280px,1fr))",gap:12}}>
          {biens.length===0&&<EmptyState icon="🏠" text="Aucun bien enregistré."/>}
          {biens.map(b=>{
            const locs=locataires.filter(l=>l.bienId===b.id&&l.statut==="actif");
            return (
              <Card key={b.id} onClick={()=>setSelectedBien(b.id)} style={{cursor:"pointer",borderColor:selectedBien===b.id?T.accent:T.border}}>
                <div style={{display:"flex",justifyContent:"space-between",marginBottom:8}}>
                  <div style={{fontWeight:700,color:T.text}}>{b.nom}</div>
                  <Badge c={locs.length>0?T.success:T.muted}>{locs.length>0?"Occupé":"Vacant"}</Badge>
                </div>
                <div style={{fontSize:12,color:T.muted,marginBottom:8}}>📍 {b.adresse}</div>
                <div style={{display:"flex",gap:6,flexWrap:"wrap",marginBottom:8}}>
                  {[b.type,b.surface&&b.surface+"m²","DPE "+b.dpe].filter(Boolean).map(v=><Badge key={v} c={T.muted}>{v}</Badge>)}
                </div>
                {locs.map(l=><div key={l.id} style={{fontSize:12,color:T.success}}>👤 {l.prenom} {l.nom} → {fmt(l.dateFin)}</div>)}
                {b.loyer&&<div style={{fontSize:13,fontWeight:700,color:T.accent,marginTop:6}}>{fmtAmt(b.loyer)}/mois HC</div>}
                {(b.docs||[]).length>0&&<div style={{marginTop:6}}><Badge c={T.accent}>📎 {b.docs.length}</Badge></div>}
              </Card>
            );
          })}
        </div>
      )}
      {selectedBien&&(()=>{
        const b=biens.find(x=>x.id===selectedBien);
        if(!b)return null;
        const locs=locataires.filter(l=>l.bienId===b.id&&l.statut==="actif");
        const DPE_COLOR={A:T.success,B:T.success,C:T.info,D:T.warning,E:T.warning,F:T.danger,G:T.danger};
        return <FichePanel
          title={b.nom} icon="🏠"
          badge={locs.length>0?"Occupé":"Vacant"} badgeColor={locs.length>0?T.success:T.muted}
          onClose={()=>setSelectedBien(null)}
          onDelete={()=>{setBiens(p=>p.filter(x=>x.id!==b.id));setSelectedBien(null);}}
          docs={b.docs||[]} echanges={b.echanges||[]}
          onDocsChange={nd=>setBiens(p=>p.map(x=>x.id===b.id?{...x,docs:nd}:x))}
          onEchangesChange={ne=>setBiens(p=>p.map(x=>x.id===b.id?{...x,echanges:ne}:x))}
          docsLabel="Titre de propriété, diagnostics, règlement de copropriété..."
          leftContent={<div>
            <InfoRow label="Type de bien" value={b.type}/>
            <InfoRow label="Adresse" value={b.adresse}/>
            <InfoRow label="Surface" value={b.surface&&b.surface+" m²"}/>
            <InfoRow label="DPE" value={b.dpe} color={DPE_COLOR[b.dpe]||T.muted}/>
            <InfoRow label="Loyer HC" value={b.loyer&&fmtAmt(b.loyer)} color={T.success}/>
            <InfoRow label="Charges" value={b.charges&&fmtAmt(b.charges)}/>
            <InfoRow label="Dépôt de garantie" value={b.depot&&fmtAmt(b.depot)} color={T.accent}/>
            <div style={{marginTop:16}}>
              <Divider label="Locataires actuels"/>
              {locs.length===0&&<div style={{fontSize:12,color:T.muted}}>Aucun locataire actif.</div>}
              {locs.map(l=><div key={l.id} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                <span style={{color:T.text}}>👤 {l.prenom} {l.nom}</span>
                <span style={{color:T.accent}}>{fmtAmt(l.loyer+l.charges)}/mois</span>
              </div>)}
            </div>
          </div>}
        />;
      })()}
      {tabMain==="synthese"&&(
        <Card>
          <div style={{fontFamily:T.fontD,fontSize:17,color:T.text,marginBottom:16}}>📊 Bilan — Aide déclaration 2044</div>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
            <div>
              <Divider label="Revenus locatifs"/>
              {locataires.map(l=>(
                <div key={l.id} style={{display:"flex",justifyContent:"space-between",padding:"6px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                  <span style={{color:T.muted}}>{l.prenom} {l.nom}</span>
                  <span style={{color:T.success,fontWeight:600}}>{fmtAmt(l.paiements.filter(p=>p.statut==="payé").reduce((s,p)=>s+p.montant,0))}</span>
                </div>
              ))}
              <div style={{display:"flex",justifyContent:"space-between",padding:"8px 0",fontWeight:700,fontSize:14}}>
                <span style={{color:T.text}}>Total brut</span>
                <span style={{color:T.success}}>{fmtAmt(locataires.reduce((s,l)=>s+l.paiements.filter(p=>p.statut==="payé").reduce((ss,p)=>ss+p.montant,0),0))}</span>
              </div>
            </div>
            <div>
              <Divider label="Charges déductibles"/>
              {locataires.map(l=>{const dep=(l.interventions||[]).reduce((s,i)=>s+i.cout,0);return dep>0&&(
                <div key={l.id} style={{display:"flex",justifyContent:"space-between",padding:"6px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                  <span style={{color:T.muted}}>{l.prenom} {l.nom}</span><span style={{color:T.danger}}>-{fmtAmt(dep)}</span>
                </div>
              );})}
              <div style={{background:T.accentDim,borderRadius:8,padding:12,marginTop:10}}>
                <div style={{fontSize:10,color:T.muted,marginBottom:3}}>REVENU FONCIER NET ESTIMÉ</div>
                <div style={{fontSize:24,fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{fmtAmt(locataires.reduce((s,l)=>s+l.paiements.filter(p=>p.statut==="payé").reduce((ss,p)=>ss+p.montant,0),0)-locataires.reduce((s,l)=>s+(l.interventions||[]).reduce((ss,i)=>ss+i.cout,0),0))}</div>
              </div>
            </div>
          </div>
        </Card>
      )}
      {showAddLoc&&<Modal title="👤 Nouveau locataire" onClose={()=>setShowAddLoc(false)} width={700}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Prénom *"><Inp value={formLoc.prenom} onChange={v=>setFormLoc(f=>({...f,prenom:v}))} placeholder="Marie"/></F>
          <F label="Nom *"><Inp value={formLoc.nom} onChange={v=>setFormLoc(f=>({...f,nom:v}))} placeholder="Dupont"/></F>
          <F label="Email"><Inp type="email" value={formLoc.email} onChange={v=>setFormLoc(f=>({...f,email:v}))}/></F>
          <F label="Téléphone"><Inp value={formLoc.tel} onChange={v=>setFormLoc(f=>({...f,tel:v}))}/></F>
          <F label="Bien *"><Sel value={formLoc.bienId} onChange={v=>setFormLoc(f=>({...f,bienId:v,...(biens.find(b=>b.id===v)?{loyer:String(biens.find(b=>b.id===v).loyer||""),charges:String(biens.find(b=>b.id===v).charges||""),depot:String(biens.find(b=>b.id===v).depot||"")}:{})}))}><option value="">— Choisir —</option>{biens.map(b=><option key={b.id} value={b.id}>{b.nom}</option>)}</Sel></F>
          <F label="Type de bail"><Sel value={formLoc.typeBail} onChange={v=>setFormLoc(f=>({...f,typeBail:v}))}>{["Vide","Meublé","Commercial","Saisonnier"].map(t=><option key={t}>{t}</option>)}</Sel></F>
          <F label="Date d'entrée"><Inp type="date" value={formLoc.dateEntree} onChange={v=>setFormLoc(f=>({...f,dateEntree:v}))}/></F>
          <F label="Fin de bail"><Inp type="date" value={formLoc.dateFin} onChange={v=>setFormLoc(f=>({...f,dateFin:v}))}/></F>
          <F label="Loyer HC (€)"><Inp type="number" value={formLoc.loyer} onChange={v=>setFormLoc(f=>({...f,loyer:v}))}/></F>
          <F label="Charges (€)"><Inp type="number" value={formLoc.charges} onChange={v=>setFormLoc(f=>({...f,charges:v}))}/></F>
          <F label="Dépôt (€)"><Inp type="number" value={formLoc.depot} onChange={v=>setFormLoc(f=>({...f,depot:v}))}/></F>
          <F label="IRL entrée"><Inp value={formLoc.indexEntree} onChange={v=>setFormLoc(f=>({...f,indexEntree:v}))}/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAddLoc(false)}>Annuler</Btn>
          <Btn onClick={()=>{setLocataires(p=>[...p,{...formLoc,id:uid(),loyer:+formLoc.loyer,charges:+formLoc.charges,depot:+formLoc.depot,revenuMensuel:+formLoc.revenuMensuel,statut:"actif",paiements:[],interventions:[],docs:[],messages:[],caution:{nom:"",tel:""}}]);setShowAddLoc(false);}} disabled={!formLoc.nom||!formLoc.prenom||!formLoc.bienId}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
      {showAddBien&&<Modal title="🏠 Nouveau bien" onClose={()=>setShowAddBien(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Nom *"><Inp value={formBien.nom} onChange={v=>setFormBien(f=>({...f,nom:v}))} placeholder="Apt A - 12 rue des Fleurs"/></F>
          <F label="Type"><Sel value={formBien.type} onChange={v=>setFormBien(f=>({...f,type:v}))}>{["Appartement","Maison","Studio","Garage","Commerce"].map(t=><option key={t}>{t}</option>)}</Sel></F>
        </div>
        <F label="Adresse complète"><Inp value={formBien.adresse} onChange={v=>setFormBien(f=>({...f,adresse:v}))} placeholder="12 rue des Fleurs, 75011 Paris"/></F>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr 1fr",gap:10}}>
          <F label="Surface (m²)"><Inp type="number" value={formBien.surface} onChange={v=>setFormBien(f=>({...f,surface:v}))}/></F>
          <F label="DPE"><Sel value={formBien.dpe} onChange={v=>setFormBien(f=>({...f,dpe:v}))}>{["A","B","C","D","E","F","G"].map(d=><option key={d}>{d}</option>)}</Sel></F>
          <F label="Loyer HC (€)"><Inp type="number" value={formBien.loyer} onChange={v=>setFormBien(f=>({...f,loyer:v}))}/></F>
          <F label="Dépôt (€)"><Inp type="number" value={formBien.depot} onChange={v=>setFormBien(f=>({...f,depot:v}))}/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAddBien(false)}>Annuler</Btn>
          <Btn onClick={()=>{setBiens(p=>[...p,{...formBien,id:uid(),surface:+formBien.surface,loyer:+formBien.loyer,charges:+formBien.charges||0,depot:+formBien.depot}]);setShowAddBien(false);}} disabled={!formBien.nom}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: MA SANTÉ
// ═══════════════════════════════════════════════════════════════════════════════
// ═══════════════════════════════════════════════════════════════════════════════
// SUIVI DES ÉCHANGES — Composant universel (courrier, email, téléphone…)
// ═══════════════════════════════════════════════════════════════════════════════
const TYPES_ECHANGE=[
  {v:"telephone",l:"Téléphone",icon:"📞",color:"#34d399"},
  {v:"email",l:"Email",icon:"📧",color:"#38bdf8"},
  {v:"courrier",l:"Courrier",icon:"✉️",color:"#f0a500"},
  {v:"reunion",l:"Réunion",icon:"🤝",color:"#a78bfa"},
  {v:"sms",l:"SMS",icon:"💬",color:"#fb923c"},
  {v:"autre",l:"Autre",icon:"📋",color:"#94a3b8"},
];
const SENS_ECHANGE=[{v:"entrant",l:"Reçu",icon:"⬇️"},{v:"sortant",l:"Envoyé",icon:"⬆️"},{v:"bilateral",l:"Les deux",icon:"↕️"}];

const SuiviEchanges=({echanges=[],onChange})=>{
  const [showForm,setShowForm]=useState(false);
  const [viewId,setViewId]=useState(null);
  const [form,setForm]=useState({type:"telephone",sens:"entrant",date:today(),heure:"",interlocuteur:"",objet:"",contenu:"",docs:[]});
  const fileRef=useRef();

  const save=()=>{onChange([{...form,id:uid()},...echanges]);setShowForm(false);setForm({type:"telephone",sens:"entrant",date:today(),heure:"",interlocuteur:"",objet:"",contenu:"",docs:[]});};
  const del=id=>onChange(echanges.filter(e=>e.id!==id));
  const sorted=[...echanges].sort((a,b)=>b.date.localeCompare(a.date)||((b.heure||"").localeCompare(a.heure||"")));
  const viewItem=viewId&&echanges.find(e=>e.id===viewId);

  const addDocToForm=async(files)=>{
    const newDocs=await Promise.all([...files].map(async f=>{
      const dataUrl=await new Promise(r=>{const fr=new FileReader();fr.onload=e=>r(e.target.result);fr.readAsDataURL(f);});
      return {id:uid(),nom:f.name,taille:f.size>1024*1024?(f.size/(1024*1024)).toFixed(1)+"Mo":(f.size/1024).toFixed(0)+"Ko",type:f.type,dataUrl,isPdf:f.type==="application/pdf",isImg:f.type.startsWith("image/")};
    }));
    setForm(f=>({...f,docs:[...f.docs,...newDocs]}));
  };

  return (
    <div>
      {/* Header + bouton */}
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:14}}>
        <div style={{fontSize:11,color:T.muted,textTransform:"uppercase",letterSpacing:"0.1em",fontWeight:600}}>
          Suivi des échanges {echanges.length>0&&<span style={{color:T.accent}}>({echanges.length})</span>}
        </div>
        <button onClick={()=>setShowForm(v=>!v)} style={{background:showForm?T.accentDim:"rgba(240,165,0,0.08)",border:`1px solid ${T.accent}44`,color:T.accent,borderRadius:8,padding:"4px 12px",cursor:"pointer",fontSize:12,fontFamily:T.font}}>
          {showForm?"✕ Annuler":"+ Nouvel échange"}
        </button>
      </div>

      {/* Formulaire d'ajout */}
      {showForm&&(
        <div style={{background:"#0a0e17",border:`1px solid ${T.accent}33`,borderRadius:12,padding:16,marginBottom:16}}>
          {/* Type d'échange */}
          <div style={{display:"flex",gap:6,flexWrap:"wrap",marginBottom:12}}>
            {TYPES_ECHANGE.map(t=>(
              <button key={t.v} onClick={()=>setForm(f=>({...f,type:t.v}))} style={{background:form.type===t.v?t.color+"22":"transparent",border:`1px solid ${form.type===t.v?t.color:T.border}`,color:form.type===t.v?t.color:T.muted,borderRadius:8,padding:"5px 10px",cursor:"pointer",fontSize:12,display:"flex",alignItems:"center",gap:4}}>
                {t.icon} {t.l}
              </button>
            ))}
          </div>
          {/* Sens */}
          <div style={{display:"flex",gap:6,marginBottom:12}}>
            {SENS_ECHANGE.map(s=>(
              <button key={s.v} onClick={()=>setForm(f=>({...f,sens:s.v}))} style={{background:form.sens===s.v?T.accentDim:"transparent",border:`1px solid ${form.sens===s.v?T.accent:T.border}`,color:form.sens===s.v?T.accent:T.muted,borderRadius:8,padding:"4px 10px",cursor:"pointer",fontSize:12}}>
                {s.icon} {s.l}
              </button>
            ))}
          </div>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8,marginBottom:8}}>
            <F label="Date"><Inp type="date" value={form.date} onChange={v=>setForm(f=>({...f,date:v}))}/></F>
            <F label="Heure (opt.)"><Inp type="time" value={form.heure} onChange={v=>setForm(f=>({...f,heure:v}))}/></F>
            <F label="Interlocuteur"><Inp value={form.interlocuteur} onChange={v=>setForm(f=>({...f,interlocuteur:v}))} placeholder="Nom, prénom, service…"/></F>
            <F label="Objet / Sujet"><Inp value={form.objet} onChange={v=>setForm(f=>({...f,objet:v}))} placeholder="Remboursement, sinistre, relance…"/></F>
          </div>
          <F label="Compte-rendu / Résumé de l'échange">
            <Txt value={form.contenu} onChange={v=>setForm(f=>({...f,contenu:v}))} rows={4} placeholder="Décrivez ce qui a été dit, les engagements pris, les suites à donner…"/>
          </F>
          {/* Pièces jointes rapides */}
          <div style={{marginTop:8}}>
            <input ref={fileRef} type="file" multiple accept=".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx" style={{display:"none"}} onChange={e=>addDocToForm(e.target.files)}/>
            <div onClick={()=>fileRef.current.click()} style={{border:`1px dashed ${T.accent}44`,borderRadius:8,padding:"8px 12px",cursor:"pointer",fontSize:12,color:T.accent,display:"flex",alignItems:"center",gap:6}}>
              📎 Joindre un fichier (courrier, email, capture…)
            </div>
            {form.docs.length>0&&<div style={{display:"flex",gap:6,flexWrap:"wrap",marginTop:6}}>
              {form.docs.map(d=><Badge key={d.id} c={T.accent}>📎 {d.nom} <span onClick={()=>setForm(f=>({...f,docs:f.docs.filter(x=>x.id!==d.id)}))} style={{cursor:"pointer",marginLeft:4}}>✕</span></Badge>)}
            </div>}
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,marginTop:12}}>
            <button onClick={save} disabled={!form.objet&&!form.contenu} style={{background:T.accent,border:"none",color:"#000",borderRadius:8,padding:"7px 18px",cursor:"pointer",fontSize:13,fontWeight:700,opacity:(!form.objet&&!form.contenu)?0.4:1}}>💾 Enregistrer</button>
          </div>
        </div>
      )}

      {/* Liste des échanges */}
      {echanges.length===0&&!showForm&&(
        <div style={{textAlign:"center",padding:"24px 0",color:T.muted,fontSize:13}}>
          <div style={{fontSize:28,marginBottom:8}}>💬</div>
          Aucun échange enregistré.<br/>
          <span style={{fontSize:12}}>Ajoutez vos appels, emails et courriers pour garder une trace complète.</span>
        </div>
      )}
      <div style={{display:"grid",gap:8}}>
        {sorted.map(e=>{
          const te=TYPES_ECHANGE.find(t=>t.v===e.type)||TYPES_ECHANGE[5];
          const se=SENS_ECHANGE.find(s=>s.v===e.sens)||SENS_ECHANGE[0];
          const isOpen=viewId===e.id;
          return (
            <div key={e.id} style={{background:isOpen?"#0c1828":"#0a0e17",border:`1px solid ${isOpen?T.accent+"66":T.border}`,borderRadius:10,overflow:"hidden",transition:"border-color 0.15s"}}>
              {/* Ligne résumé — cliquer pour ouvrir */}
              <div onClick={()=>setViewId(isOpen?null:e.id)} style={{display:"flex",alignItems:"center",gap:10,padding:"10px 14px",cursor:"pointer"}}>
                <div style={{width:32,height:32,borderRadius:8,background:te.color+"22",display:"flex",alignItems:"center",justifyContent:"center",fontSize:16,flexShrink:0}}>{te.icon}</div>
                <div style={{flex:1,minWidth:0}}>
                  <div style={{display:"flex",gap:6,alignItems:"center",marginBottom:2,flexWrap:"wrap"}}>
                    <span style={{fontWeight:600,color:T.text,fontSize:13}}>{e.objet||"(sans objet)"}</span>
                    <Badge c={te.color}>{te.l}</Badge>
                    <Badge c={T.muted}>{se.icon} {se.l}</Badge>
                    {(e.docs||[]).length>0&&<Badge c={T.accent}>📎 {e.docs.length}</Badge>}
                  </div>
                  <div style={{fontSize:11,color:T.muted,display:"flex",gap:10}}>
                    <span>📅 {fmt(e.date)}{e.heure&&" à "+e.heure}</span>
                    {e.interlocuteur&&<span>👤 {e.interlocuteur}</span>}
                  </div>
                </div>
                <span style={{color:T.muted,fontSize:16,transform:isOpen?"rotate(90deg)":"none",transition:"transform 0.2s"}}>›</span>
              </div>
              {/* Détail déplié */}
              {isOpen&&(
                <div style={{padding:"12px 14px",borderTop:`1px solid ${T.border}`}}>
                  {e.contenu&&(
                    <div style={{background:"#060a10",borderRadius:8,padding:12,fontSize:13,color:T.text,lineHeight:1.7,marginBottom:12,whiteSpace:"pre-wrap",borderLeft:`3px solid ${te.color}`}}>
                      {e.contenu}
                    </div>
                  )}
                  {(e.docs||[]).length>0&&(
                    <div style={{marginBottom:12}}>
                      <div style={{fontSize:11,color:T.muted,marginBottom:6}}>Pièces jointes :</div>
                      <div style={{display:"flex",gap:6,flexWrap:"wrap"}}>
                        {e.docs.map(d=>(
                          <a key={d.id} href={d.dataUrl||d.url} download={d.nom} onClick={e=>e.stopPropagation()} style={{display:"flex",alignItems:"center",gap:4,background:T.accentDim,border:`1px solid ${T.accent}44`,color:T.accent,borderRadius:7,padding:"4px 10px",fontSize:12,textDecoration:"none"}}>
                            📎 {d.nom}
                          </a>
                        ))}
                      </div>
                    </div>
                  )}
                  <div style={{display:"flex",justifyContent:"flex-end"}}>
                    <button onClick={()=>{if(confirm("Supprimer cet échange ?"))del(e.id);setViewId(null);}} style={{background:"rgba(239,68,68,0.1)",border:"1px solid rgba(239,68,68,0.2)",color:T.danger,borderRadius:7,padding:"4px 12px",cursor:"pointer",fontSize:12}}>🗑 Supprimer</button>
                  </div>
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// FICHE PANEL UNIVERSEL — Split gauche (infos) / droite (docs + échanges)
// ═══════════════════════════════════════════════════════════════════════════════
const FichePanel=({title,icon="📄",badge,badgeColor,onClose,onDelete,leftContent,docs=[],onDocsChange,docsLabel="📎 Documents",echanges=[],onEchangesChange})=>{
  const [rightTab,setRightTab]=useState("docs");
  const nbEchanges=echanges.length;
  const nbDocs=docs.length;
  return (
    <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.75)",zIndex:3000,display:"flex",alignItems:"stretch",justifyContent:"flex-end"}} onClick={onClose}>
      <div onClick={e=>e.stopPropagation()} style={{width:"min(96vw,1100px)",background:T.sidebar,display:"flex",flexDirection:"column",borderLeft:`1px solid ${T.border}`,boxShadow:"-20px 0 60px rgba(0,0,0,0.6)",animation:"slideIn .22s ease"}}>
        {/* Header */}
        <div style={{padding:"16px 22px",borderBottom:`1px solid ${T.border}`,display:"flex",justifyContent:"space-between",alignItems:"center",background:"#0c1220",flexShrink:0}}>
          <div style={{display:"flex",gap:12,alignItems:"center"}}>
            <span style={{fontSize:26}}>{icon}</span>
            <div>
              <div style={{fontFamily:T.fontD,fontSize:18,color:T.text,fontWeight:700}}>{title}</div>
              {badge&&<Badge c={badgeColor||T.accent}>{badge}</Badge>}
            </div>
          </div>
          <div style={{display:"flex",gap:8}}>
            {onDelete&&<button onClick={()=>{if(confirm("Supprimer cet élément ?"))onDelete();}} style={{background:"rgba(239,68,68,0.1)",border:"1px solid rgba(239,68,68,0.25)",color:T.danger,borderRadius:7,padding:"5px 12px",cursor:"pointer",fontSize:13}}>🗑 Supprimer</button>}
            <button onClick={onClose} style={{background:"rgba(255,255,255,0.06)",border:`1px solid ${T.border}`,color:T.muted,borderRadius:7,padding:"5px 14px",cursor:"pointer",fontSize:14}}>✕ Fermer</button>
          </div>
        </div>
        {/* Body split 40/60 */}
        <div style={{flex:1,display:"grid",gridTemplateColumns:"2fr 3fr",overflow:"hidden"}}>
          {/* Gauche — informations */}
          <div style={{padding:22,overflowY:"auto",borderRight:`1px solid ${T.border}`}}>
            <div style={{fontSize:10,color:T.muted,textTransform:"uppercase",letterSpacing:"0.12em",marginBottom:14,fontWeight:600}}>Informations</div>
            {leftContent}
          </div>
          {/* Droite — onglets Docs / Échanges */}
          <div style={{display:"flex",flexDirection:"column",overflow:"hidden",background:"#0a0e17"}}>
            {/* Onglets */}
            <div style={{display:"flex",borderBottom:`1px solid ${T.border}`,flexShrink:0}}>
              {[
                {id:"docs",label:"📎 Documents",count:nbDocs},
                {id:"echanges",label:"💬 Échanges",count:nbEchanges},
              ].map(tab=>(
                <button key={tab.id} onClick={()=>setRightTab(tab.id)} style={{flex:1,padding:"12px 8px",background:"none",border:"none",borderBottom:`2px solid ${rightTab===tab.id?T.accent:"transparent"}`,color:rightTab===tab.id?T.accent:T.muted,cursor:"pointer",fontSize:13,fontFamily:T.font,fontWeight:rightTab===tab.id?700:400,display:"flex",alignItems:"center",justifyContent:"center",gap:6,transition:"color 0.15s"}}>
                  {tab.label}
                  {tab.count>0&&<span style={{background:rightTab===tab.id?T.accent:T.border,color:rightTab===tab.id?"#000":T.muted,borderRadius:10,padding:"1px 7px",fontSize:10,fontWeight:700}}>{tab.count}</span>}
                </button>
              ))}
            </div>
            {/* Contenu onglet */}
            <div style={{flex:1,overflowY:"auto",padding:20}}>
              {rightTab==="docs"&&<DocAttach docs={docs} onChange={onDocsChange} label={docsLabel}/>}
              {rightTab==="echanges"&&<SuiviEchanges echanges={echanges} onChange={onEchangesChange||(() =>{})}/>}
            </div>
          </div>
        </div>
      </div>
      <style>{`@keyframes slideIn{from{transform:translateX(40px);opacity:0}to{transform:translateX(0);opacity:1}}`}</style>
    </div>
  );
};

// Ligne d'info réutilisable dans FichePanel
const InfoRow=({label,value,color,mono})=>value?(
  <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"8px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
    <span style={{color:T.muted,minWidth:130,fontSize:12}}>{label}</span>
    <span style={{color:color||T.text,fontWeight:500,textAlign:"right",fontFamily:mono?"monospace":T.font}}>{value}</span>
  </div>
):null;

// ── Boutons Maps / Waze universels ────────────────────────────────────────────
// Helper : construit une adresse complète depuis rue+codePostal+ville ou adresse seule
const adresseFull=(obj)=>{
  if(!obj)return "";
  if(obj.rue||obj.codePostal){
    const cp_ville=[obj.codePostal,obj.ville].filter(Boolean).join(" ");
    return [obj.rue,cp_ville].filter(Boolean).join(", ");
  }
  return obj.adresse||"";
};

const MapsLinks=({adresse,label="Ouvrir dans..."})=>{
  if(!adresse)return null;
  const q=encodeURIComponent(adresse);
  return (
    <div style={{display:"flex",gap:6,marginTop:6,flexWrap:"wrap"}}>
      <a href={`https://www.google.com/maps/search/?api=1&query=${q}`} target="_blank" rel="noreferrer"
        style={{display:"flex",alignItems:"center",gap:5,background:"rgba(66,133,244,0.12)",border:"1px solid rgba(66,133,244,0.25)",color:"#4285F4",borderRadius:7,padding:"5px 11px",textDecoration:"none",fontSize:12,fontWeight:600}}>
        🗺️ Google Maps
      </a>
      <a href={`https://waze.com/ul?q=${q}`} target="_blank" rel="noreferrer"
        style={{display:"flex",alignItems:"center",gap:5,background:"rgba(5,190,255,0.10)",border:"1px solid rgba(5,190,255,0.22)",color:"#05BEFF",borderRadius:7,padding:"5px 11px",textDecoration:"none",fontSize:12,fontWeight:600}}>
        🚗 Waze
      </a>
      <a href={`https://maps.apple.com/?q=${q}`} target="_blank" rel="noreferrer"
        style={{display:"flex",alignItems:"center",gap:5,background:"rgba(52,211,153,0.10)",border:"1px solid rgba(52,211,153,0.22)",color:T.success,borderRadius:7,padding:"5px 11px",textDecoration:"none",fontSize:12,fontWeight:600}}>
        🍎 Apple Maps
      </a>
    </div>
  );
};

// ── Boutons actions contacts universels ───────────────────────────────────────
const ContactActions=({tel,email,adresse})=>(
  <div style={{display:"flex",flexDirection:"column",gap:7,marginTop:16}}>
    {tel&&<a href={`tel:${tel}`} style={{display:"flex",alignItems:"center",gap:8,background:"rgba(56,189,248,0.1)",border:"1px solid rgba(56,189,248,0.2)",color:T.info,textDecoration:"none",padding:"9px 16px",borderRadius:9,fontSize:13,fontWeight:600}}>📞 Appeler — {tel}</a>}
    {email&&<a href={`mailto:${email}`} style={{display:"flex",alignItems:"center",gap:8,background:T.accentDim,border:`1px solid rgba(240,165,0,0.2)`,color:T.accent,textDecoration:"none",padding:"9px 16px",borderRadius:9,fontSize:13,fontWeight:600}}>✉️ Envoyer un email</a>}
    {adresse&&<div><div style={{fontSize:11,color:T.muted,marginBottom:4}}>📍 {adresse}</div><MapsLinks adresse={adresse}/></div>}
  </div>
);

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: MA SANTÉ
// ═══════════════════════════════════════════════════════════════════════════════
const Sante=({sante,setSante})=>{
  const [tab,setTab]=useState("rdv");
  const [showAdd,setShowAdd]=useState(false);
  const [selected,setSelected]=useState(null); // {type, id}
  const [form,setForm]=useState({type:"rdv",titre:"",medecin:"",specialite:"",date:today(),heure:"",adresse:"",note:"",montant:"",rembourse:"",mutuelle:""});

  const save=()=>{setSante(s=>({...s,[form.type]:[...(s[form.type]||[]),{...form,id:uid()}]}));setShowAdd(false);};
  const updDocs=(type,id,nd)=>setSante(s=>({...s,[type]:(s[type]||[]).map(x=>x.id===id?{...x,docs:nd}:x)}));
  const updEchanges=(type,id,ne)=>setSante(s=>({...s,[type]:(s[type]||[]).map(x=>x.id===id?{...x,echanges:ne}:x)}));
  const del=(type,id)=>{setSante(s=>({...s,[type]:(s[type]||[]).filter(x=>x.id!==id)}));setSelected(null);};

  const TABS=[{id:"rdv",icon:"📅",label:"Rendez-vous"},{id:"ordonnances",icon:"💊",label:"Ordonnances"},{id:"remboursements",icon:"💰",label:"Remboursements"},{id:"medecins",icon:"👨‍⚕️",label:"Médecins"},{id:"constantes",icon:"❤️",label:"Constantes"}];
  const totalPaye=sante.remboursements?.reduce((s,r)=>s+(parseFloat(r.montant)||0),0)||0;
  const totalRembourse=sante.remboursements?.reduce((s,r)=>s+(parseFloat(r.rembourse)||0)+(parseFloat(r.mutuelle)||0),0)||0;

  const selItem=selected&&(sante[selected.type]||[]).find(x=>x.id===selected.id);

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div><h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🏥 Ma Santé</h1><p style={{color:T.muted,marginTop:3,fontSize:13}}>Suivi médical · ordonnances · remboursements</p></div>
        <Btn onClick={()=>{setForm(f=>({...f,type:tab}));setShowAdd(true);}}>+ Ajouter</Btn>
      </div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(150px,1fr))",gap:12,marginBottom:20}}>
        <StatCard label="RDV à venir" value={(sante.rdv||[]).filter(r=>daysFrom(r.date)>=0).length} icon="📅" color="#34d399"/>
        <StatCard label="Total dépensé" value={fmtAmt(totalPaye)} icon="💊" color={T.danger}/>
        <StatCard label="Remboursé" value={fmtAmt(totalRembourse)} icon="💰" color={T.success}/>
        <StatCard label="Reste à charge" value={fmtAmt(totalPaye-totalRembourse)} icon="💳" color={T.warning}/>
      </div>
      <Tabs tabs={TABS} active={tab} onChange={setTab}/>

      {tab==="rdv"&&<div style={{display:"grid",gap:10}}>
        {(sante.rdv||[]).length===0&&<EmptyState icon="📅" text="Aucun rendez-vous."/>}
        {[...(sante.rdv||[])].sort((a,b)=>a.date.localeCompare(b.date)).map(r=>{
          const d=daysFrom(r.date);
          return <Card key={r.id} onClick={()=>setSelected({type:"rdv",id:r.id})} style={{padding:"12px 16px",cursor:"pointer"}}>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
              <div>
                <div style={{fontWeight:600,color:T.text,marginBottom:3}}>{r.titre||r.specialite}</div>
                <div style={{fontSize:12,color:T.muted}}>👨‍⚕️ {r.medecin} · {r.specialite}</div>
                {(r.docs||[]).length>0&&<div style={{fontSize:10,color:T.accent,marginTop:3}}>📎 {r.docs.length} document(s)</div>}
              </div>
              <div style={{textAlign:"right"}}>
                <div style={{fontWeight:600,color:T.text,marginBottom:4}}>{fmt(r.date)}{r.heure&&" à "+r.heure}</div>
                <Badge c={d<0?T.muted:d<=7?T.warning:T.success}>{d<0?"Passé":d===0?"Aujourd'hui":d+"j"}</Badge>
              </div>
            </div>
          </Card>;
        })}
      </div>}

      {tab==="ordonnances"&&<div style={{display:"grid",gap:10}}>
        {(sante.ordonnances||[]).length===0&&<EmptyState icon="💊" text="Aucune ordonnance."/>}
        {(sante.ordonnances||[]).map(o=><Card key={o.id} onClick={()=>setSelected({type:"ordonnances",id:o.id})} style={{padding:"12px 16px",cursor:"pointer"}}>
          <div style={{display:"flex",justifyContent:"space-between"}}>
            <div>
              <div style={{fontWeight:600,color:T.text,marginBottom:3}}>{o.titre||"Ordonnance"}</div>
              <div style={{fontSize:12,color:T.muted}}>Dr {o.medecin} · {fmt(o.date)}</div>
              {(o.docs||[]).length>0&&<div style={{fontSize:10,color:T.accent,marginTop:3}}>📎 {o.docs.length} document(s)</div>}
            </div>
            <Badge c="#34d399">💊</Badge>
          </div>
        </Card>)}
      </div>}

      {tab==="remboursements"&&<div style={{display:"grid",gap:10}}>
        {(sante.remboursements||[]).length===0&&<EmptyState icon="💰" text="Aucun remboursement."/>}
        {(sante.remboursements||[]).map(r=><Card key={r.id} onClick={()=>setSelected({type:"remboursements",id:r.id})} style={{padding:"12px 16px",cursor:"pointer"}}>
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}>
            <div>
              <div style={{fontWeight:600,color:T.text,marginBottom:3}}>{r.titre||r.medecin}</div>
              <div style={{fontSize:12,color:T.muted}}>{fmt(r.date)} · Dr {r.medecin}</div>
              {(r.docs||[]).length>0&&<div style={{fontSize:10,color:T.accent,marginTop:3}}>📎 {r.docs.length} document(s)</div>}
            </div>
            <div style={{textAlign:"right"}}>
              <div style={{fontSize:13,color:T.danger}}>Payé: {fmtAmt(r.montant)}</div>
              <div style={{fontSize:11,color:T.success}}>Remb: {fmtAmt((parseFloat(r.rembourse)||0)+(parseFloat(r.mutuelle)||0))}</div>
            </div>
          </div>
        </Card>)}
      </div>}

      {tab==="medecins"&&<div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(250px,1fr))",gap:12}}>
        {(sante.medecins||[]).length===0&&<EmptyState icon="👨‍⚕️" text="Aucun médecin enregistré."/>}
        {(sante.medecins||[]).map(m=><Card key={m.id} onClick={()=>setSelected({type:"medecins",id:m.id})} style={{cursor:"pointer"}}>
          <div style={{fontWeight:700,color:T.text,marginBottom:4}}>{m.nom}</div>
          <div style={{fontSize:12,color:"#34d399",marginBottom:6}}>{m.specialite}</div>
          {m.tel&&<div style={{fontSize:12,color:T.muted}}>📞 {m.tel}</div>}
          {m.email&&<div style={{fontSize:12,color:T.muted}}>📧 {m.email}</div>}
          {(m.docs||[]).length>0&&<div style={{fontSize:10,color:T.accent,marginTop:6}}>📎 {m.docs.length} document(s)</div>}
        </Card>)}
      </div>}

      {tab==="constantes"&&<div>
        <div style={{marginBottom:14}}><Btn onClick={()=>{setForm(f=>({...f,type:"constantes"}));setShowAdd(true);}}>+ Mesure</Btn></div>
        {(sante.constantes||[]).length===0&&<EmptyState icon="❤️" text="Aucune constante enregistrée."/>}
        <div style={{background:T.card,borderRadius:10,border:`1px solid ${T.border}`,overflow:"auto"}}>
          <table style={{width:"100%",borderCollapse:"collapse",fontSize:13}}>
            <thead><tr style={{background:"#0a0e17"}}>{["Date","Type","Valeur","Note"].map(h=><th key={h} style={{padding:"9px 12px",textAlign:"left",color:T.muted,fontSize:11}}>{h}</th>)}</tr></thead>
            <tbody>{(sante.constantes||[]).map(c=>(
              <tr key={c.id} onClick={()=>setSelected({type:"constantes",id:c.id})} style={{borderTop:`1px solid ${T.border}`,cursor:"pointer"}}>
                <td style={{padding:"8px 12px",color:T.muted}}>{fmt(c.date)}</td>
                <td style={{padding:"8px 12px",color:T.text,fontWeight:600}}>{c.titre}</td>
                <td style={{padding:"8px 12px",color:T.accent,fontWeight:700}}>{c.montant} {c.unite}</td>
                <td style={{padding:"8px 12px",color:T.muted,fontSize:11}}>{c.note}</td>
              </tr>
            ))}</tbody>
          </table>
        </div>
      </div>}

      {/* FichePanel */}
      {selItem&&selected&&<FichePanel
        title={selItem.titre||selItem.nom||selItem.medecin||"Fiche"}
        icon={tab==="rdv"?"📅":tab==="ordonnances"?"💊":tab==="remboursements"?"💰":tab==="medecins"?"👨‍⚕️":"❤️"}
        onClose={()=>setSelected(null)}
        onDelete={()=>del(selected.type,selected.id)}
        docs={selItem.docs||[]} echanges={selItem.echanges||[]}
        onDocsChange={nd=>updDocs(selected.type,selected.id,nd)}
        onEchangesChange={ne=>updEchanges(selected.type,selected.id,ne)}
        docsLabel="Ordonnances, remboursements, comptes-rendus..."
        leftContent={<div>
          <InfoRow label="Titre / Motif" value={selItem.titre}/>
          <InfoRow label="Médecin" value={selItem.medecin}/>
          <InfoRow label="Spécialité" value={selItem.specialite}/>
          <InfoRow label="Date" value={fmt(selItem.date)}/>
          <InfoRow label="Heure" value={selItem.heure}/>
          <InfoRow label="Adresse" value={selItem.adresse}/>
          {selItem.montant&&<InfoRow label="Montant payé" value={fmtAmt(selItem.montant)} color={T.danger}/>}
          {selItem.rembourse&&<InfoRow label="Remb. Sécu" value={fmtAmt(selItem.rembourse)} color={T.success}/>}
          {selItem.mutuelle&&<InfoRow label="Remb. Mutuelle" value={fmtAmt(selItem.mutuelle)} color={T.success}/>}
          {selItem.montant&&<InfoRow label="Reste à charge" value={fmtAmt((parseFloat(selItem.montant)||0)-(parseFloat(selItem.rembourse)||0)-(parseFloat(selItem.mutuelle)||0))} color={T.warning}/>}
          <InfoRow label="Email" value={selItem.email}/>
          <InfoRow label="Téléphone" value={selItem.tel}/>
          {selItem.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{selItem.note}</div>}
          <ContactActions tel={selItem.tel} email={selItem.email} adresse={selItem.adresse}/>
        </div>}      />}

      {showAdd&&<Modal title="+ Ajouter" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gap:10}}>
          <F label="Type"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}><option value="rdv">Rendez-vous</option><option value="ordonnances">Ordonnance</option><option value="remboursements">Remboursement</option><option value="medecins">Médecin</option><option value="constantes">Constante</option></Sel></F>
          <F label="Titre / Motif"><Inp value={form.titre} onChange={v=>setForm(f=>({...f,titre:v}))} placeholder="Consultation, Prise de sang..."/></F>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Médecin"><Inp value={form.medecin} onChange={v=>setForm(f=>({...f,medecin:v}))} placeholder="Dr. Martin"/></F>
            <F label="Spécialité"><Inp value={form.specialite} onChange={v=>setForm(f=>({...f,specialite:v}))} placeholder="Généraliste..."/></F>
            <F label="Date"><Inp type="date" value={form.date} onChange={v=>setForm(f=>({...f,date:v}))}/></F>
            <F label="Heure / Valeur"><Inp value={form.heure} onChange={v=>setForm(f=>({...f,heure:v}))} placeholder="09:30"/></F>
          </div>
          {form.type==="remboursements"&&<div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:10}}>
            <F label="Payé (€)"><Inp type="number" value={form.montant} onChange={v=>setForm(f=>({...f,montant:v}))}/></F>
            <F label="Sécu (€)"><Inp type="number" value={form.rembourse} onChange={v=>setForm(f=>({...f,rembourse:v}))}/></F>
            <F label="Mutuelle (€)"><Inp type="number" value={form.mutuelle} onChange={v=>setForm(f=>({...f,mutuelle:v}))}/></F>
          </div>}
          <F label="Adresse / Note"><Inp value={form.note} onChange={v=>setForm(f=>({...f,note:v}))}/></F>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
            <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
            <Btn onClick={save}>💾 Enregistrer</Btn>
          </div>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: MES IMPÔTS
// ═══════════════════════════════════════════════════════════════════════════════
const Impots=({impots,setImpots})=>{
  const [tab,setTab]=useState("declarations");
  const [showAdd,setShowAdd]=useState(false);
  const [selected,setSelected]=useState(null); // {type,id}
  const [form,setForm]=useState({type:"declarations",annee:new Date().getFullYear().toString(),titre:"",montant:"",dateEcheance:"",statut:"en attente",note:""});

  const save=()=>{setImpots(s=>({...s,[form.type]:[...(s[form.type]||[]),{...form,id:uid()}]}));setShowAdd(false);};
  const updDocs=(type,id,nd)=>setImpots(s=>({...s,[type]:(s[type]||[]).map(x=>x.id===id?{...x,docs:nd}:x)}));
  const updEchanges=(type,id,ne)=>setImpots(s=>({...s,[type]:(s[type]||[]).map(x=>x.id===id?{...x,echanges:ne}:x)}));
  const del=(type,id)=>{setImpots(s=>({...s,[type]:(s[type]||[]).filter(x=>x.id!==id)}));setSelected(null);};

  const TABS=[{id:"declarations",icon:"📋",label:"Déclarations"},{id:"avis",icon:"📄",label:"Avis"},{id:"paiements",icon:"💳",label:"Paiements"},{id:"deductions",icon:"➖",label:"Déductions"}];
  const totalImpot=(impots.paiements||[]).reduce((s,p)=>s+(parseFloat(p.montant)||0),0);
  const totalDeduc=(impots.deductions||[]).reduce((s,d)=>s+(parseFloat(d.montant)||0),0);

  const selItem=selected&&(impots[selected.type]||[]).find(x=>x.id===selected.id);
  const tabIcons={declarations:"📋",avis:"📄",paiements:"💳",deductions:"➖"};

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div><h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🏛️ Mes Impôts</h1><p style={{color:T.muted,marginTop:3,fontSize:13}}>Déclarations · avis · paiements · déductions</p></div>
        <Btn onClick={()=>setShowAdd(true)}>+ Ajouter</Btn>
      </div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(160px,1fr))",gap:12,marginBottom:20}}>
        <StatCard label="Total payé" value={fmtAmt(totalImpot)} icon="🏛️" color={T.purple}/>
        <StatCard label="Déductions" value={fmtAmt(totalDeduc)} icon="➖" color={T.success}/>
        <StatCard label="Déclarations" value={(impots.declarations||[]).length} icon="📋" color={T.info}/>
        <StatCard label="Échéances" value={(impots.paiements||[]).filter(p=>daysFrom(p.dateEcheance)>=0).length} icon="📅" color={T.warning}/>
      </div>
      <Tabs tabs={TABS} active={tab} onChange={setTab}/>

      <div style={{display:"grid",gap:10}}>
        {(impots[tab]||[]).length===0&&<EmptyState icon="🏛️" text="Aucun élément. Ajoutez votre premier document fiscal."/>}
        {(impots[tab]||[]).map(item=>{
          const j=daysFrom(item.dateEcheance);
          return <Card key={item.id} onClick={()=>setSelected({type:tab,id:item.id})} style={{padding:"12px 16px",cursor:"pointer"}}>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
              <div style={{flex:1}}>
                <div style={{fontWeight:600,color:T.text,marginBottom:3}}>{item.titre||item.annee}</div>
                <div style={{fontSize:12,color:T.muted}}>Année {item.annee}{item.dateEcheance&&" · Échéance: "+fmt(item.dateEcheance)}</div>
                {item.note&&<div style={{fontSize:11,color:T.muted,fontStyle:"italic",marginTop:2}}>{item.note}</div>}
                {(item.docs||[]).length>0&&<div style={{fontSize:10,color:T.accent,marginTop:3}}>📎 {item.docs.length} document(s)</div>}
              </div>
              <div style={{textAlign:"right",display:"flex",flexDirection:"column",gap:4,alignItems:"flex-end"}}>
                {item.montant&&<span style={{fontWeight:700,color:T.purple,fontFamily:T.fontD,fontSize:16}}>{fmtAmt(item.montant)}</span>}
                {item.statut&&<Badge c={item.statut==="payé"||item.statut==="déposé"?T.success:item.statut==="en attente"?T.warning:T.info}>{item.statut}</Badge>}
                {j!=null&&j<=30&&j>=0&&<Badge c={T.danger}>⚠️ {j}j</Badge>}
              </div>
            </div>
          </Card>;
        })}
      </div>

      {selItem&&selected&&<FichePanel
        title={selItem.titre||selItem.annee||"Fiche fiscale"}
        icon={tabIcons[selected.type]||"🏛️"}
        badge={selItem.statut} badgeColor={selItem.statut==="payé"||selItem.statut==="déposé"?T.success:T.warning}
        onClose={()=>setSelected(null)}
        onDelete={()=>del(selected.type,selected.id)}
        docs={selItem.docs||[]} echanges={selItem.echanges||[]}
        onDocsChange={nd=>updDocs(selected.type,selected.id,nd)}
        onEchangesChange={ne=>updEchanges(selected.type,selected.id,ne)}
        docsLabel="Avis d'imposition, reçus, justificatifs..."
        leftContent={<div>
          <InfoRow label="Titre" value={selItem.titre}/>
          <InfoRow label="Année fiscale" value={selItem.annee}/>
          <InfoRow label="Montant" value={selItem.montant&&fmtAmt(selItem.montant)} color={T.purple}/>
          <InfoRow label="Échéance" value={fmt(selItem.dateEcheance)}/>
          <InfoRow label="Statut" value={selItem.statut}/>
          {selItem.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{selItem.note}</div>}
        </div>}
      />}

      {showAdd&&<Modal title="🏛️ Ajouter" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gap:10}}>
          <F label="Catégorie"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}><option value="declarations">Déclaration</option><option value="avis">Avis d'imposition</option><option value="paiements">Paiement</option><option value="deductions">Déduction</option></Sel></F>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Année"><Inp value={form.annee} onChange={v=>setForm(f=>({...f,annee:v}))} placeholder="2025"/></F>
            <F label="Titre"><Inp value={form.titre} onChange={v=>setForm(f=>({...f,titre:v}))} placeholder="Ex: Taxe foncière..."/></F>
            <F label="Montant (€)"><Inp type="number" value={form.montant} onChange={v=>setForm(f=>({...f,montant:v}))}/></F>
            <F label="Échéance"><Inp type="date" value={form.dateEcheance} onChange={v=>setForm(f=>({...f,dateEcheance:v}))}/></F>
          </div>
          <F label="Statut"><Sel value={form.statut} onChange={v=>setForm(f=>({...f,statut:v}))}><option value="en attente">En attente</option><option value="déposé">Déposé</option><option value="payé">Payé</option><option value="à vérifier">À vérifier</option></Sel></F>
          <F label="Note"><Txt value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} rows={2}/></F>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
            <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
            <Btn onClick={save}>💾 Enregistrer</Btn>
          </div>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: MA BANQUE
// ═══════════════════════════════════════════════════════════════════════════════
// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: MA BANQUE
// ═══════════════════════════════════════════════════════════════════════════════
// ═══════════════════════════════════════════════════════════════════════════════
// BANQUE — Composants graphiques SVG natifs
// ═══════════════════════════════════════════════════════════════════════════════
// ═══════════════════════════════════════════════════════════════════════════════
// SIMULATEUR DE CRÉDIT
// ═══════════════════════════════════════════════════════════════════════════════
const SimulateurCredit=()=>{
  const [sim,setSim]=useState({montant:200000,taux:3.5,duree:20,apport:20000,assurance:0.36,fraisNotaire:8});
  const [mode,setMode]=useState("mensualite"); // mensualite | capacite | duree
  const [capa,setCapa]=useState({mensualiteMax:1200,taux:3.5,duree:20,assurance:0.36});
  const [showAmort,setShowAmort]=useState(false);
  const s=sim;

  // ── Calculs crédit principal ─────────────────────────────────────────────
  const montantEmprunte=s.montant-s.apport;
  const tauxMensuel=(s.taux/100)/12;
  const tauxAssurMensuel=(s.assurance/100)/12;
  const n=s.duree*12;

  const mensualiteHorsAssur=tauxMensuel===0?montantEmprunte/n:
    montantEmprunte*(tauxMensuel*Math.pow(1+tauxMensuel,n))/(Math.pow(1+tauxMensuel,n)-1);
  const mensualiteAssur=montantEmprunte*tauxAssurMensuel;
  const mensualiteTotale=mensualiteHorsAssur+mensualiteAssur;
  const coutTotal=mensualiteTotale*n;
  const coutInterets=mensualiteHorsAssur*n-montantEmprunte;
  const coutAssurance=mensualiteAssur*n;
  const fraisNotaireAmt=s.montant*(s.fraisNotaire/100);
  const coutGlobal=coutTotal+fraisNotaireAmt+s.apport;
  const tauxEffectif=((mensualiteTotale*n/montantEmprunte)-1)/(s.duree)*100;

  // ── Capacité d'emprunt ───────────────────────────────────────────────────
  const tMC=(capa.taux/100)/12;
  const tAC=(capa.assurance/100)/12;
  const nC=capa.duree*12;
  const mensualiteCapHorsAssur=capa.mensualiteMax/(1+(tAC/tMC));
  const capaEmprunt=tMC===0?mensualiteCapHorsAssur*nC:
    mensualiteCapHorsAssur*(Math.pow(1+tMC,nC)-1)/(tMC*Math.pow(1+tMC,nC));

  // ── Tableau d'amortissement (annuel) ────────────────────────────────────
  const amortAnnuel=useMemo(()=>{
    if(montantEmprunte<=0||tauxMensuel<0)return[];
    const rows=[];
    let restant=montantEmprunte;
    for(let annee=1;annee<=s.duree;annee++){
      let intAn=0,capAn=0;
      for(let m=0;m<12;m++){
        const int=restant*tauxMensuel;
        const cap=mensualiteHorsAssur-int;
        intAn+=int;capAn+=cap;restant-=cap;
      }
      rows.push({annee,interets:Math.round(intAn),capital:Math.round(capAn),restant:Math.max(0,Math.round(restant)),mensualite:Math.round(mensualiteTotale)});
    }
    return rows;
  },[montantEmprunte,tauxMensuel,mensualiteHorsAssur,s.duree]);

  // ── Comparatif taux ──────────────────────────────────────────────────────
  const comparatifTaux=[2.5,3.0,3.5,4.0,4.5,5.0].map(t=>{
    const tm=(t/100)/12;
    const m=tm===0?montantEmprunte/n:montantEmprunte*(tm*Math.pow(1+tm,n))/(Math.pow(1+tm,n)-1);
    return {taux:t,mensualite:m,cout:(m*n-montantEmprunte)};
  });

  const slider=(label,key,min,max,step,suffix,obj,setObj)=>(
    <div style={{marginBottom:14}}>
      <div style={{display:"flex",justifyContent:"space-between",marginBottom:5,fontSize:13}}>
        <span style={{color:T.muted}}>{label}</span>
        <span style={{color:T.accent,fontWeight:700,fontFamily:T.fontD}}>{obj[key].toLocaleString("fr-FR")}{suffix}</span>
      </div>
      <input type="range" min={min} max={max} step={step} value={obj[key]}
        onChange={e=>setObj(o=>({...o,[key]:parseFloat(e.target.value)}))}
        style={{width:"100%",accentColor:T.accent}}/>
      <div style={{display:"flex",justifyContent:"space-between",fontSize:9,color:T.border,marginTop:2}}>
        <span>{min.toLocaleString("fr-FR")}{suffix}</span><span>{max.toLocaleString("fr-FR")}{suffix}</span>
      </div>
    </div>
  );

  const kpi=(label,value,color,sub)=>(
    <div style={{background:"#060a10",borderRadius:10,padding:"14px 16px"}}>
      <div style={{fontSize:10,color:T.muted,textTransform:"uppercase",marginBottom:4,letterSpacing:"0.06em"}}>{label}</div>
      <div style={{fontSize:20,fontWeight:700,fontFamily:T.fontD,color:color||T.text}}>{value}</div>
      {sub&&<div style={{fontSize:10,color:T.muted,marginTop:3}}>{sub}</div>}
    </div>
  );

  return (
    <div style={{display:"grid",gap:16}}>
      {/* Mode selector */}
      <div style={{display:"flex",gap:8}}>
        {[{id:"mensualite",l:"💶 Calculer la mensualité",sub:"Je connais le montant"},{id:"capacite",l:"🏠 Capacité d'emprunt",sub:"Combien puis-je emprunter ?"},{id:"duree",l:"📅 Comparatif taux",sub:"Quel taux choisir ?"}].map(m=>(
          <button key={m.id} onClick={()=>setMode(m.id)} style={{flex:1,padding:"10px 12px",borderRadius:10,border:`2px solid ${mode===m.id?T.accent:T.border}`,background:mode===m.id?T.accentDim:"transparent",color:mode===m.id?T.accent:T.muted,fontFamily:T.font,fontSize:12,fontWeight:600,cursor:"pointer",textAlign:"center"}}>
            <div>{m.l}</div><div style={{fontSize:10,marginTop:2,opacity:0.7}}>{m.sub}</div>
          </button>
        ))}
      </div>

      {/* ── MODE : MENSUALITÉ ── */}
      {mode==="mensualite"&&(
        <div style={{display:"grid",gridTemplateColumns:"360px 1fr",gap:16}}>
          {/* Sliders */}
          <Card style={{padding:"18px 20px"}}>
            <Divider label="Paramètres du prêt"/>
            {slider("💰 Prix du bien",    "montant",  50000,1000000,5000," €",sim,setSim)}
            {slider("🏦 Apport personnel","apport",   0,   300000,1000," €",sim,setSim)}
            {slider("📈 Taux d'intérêt",  "taux",     0.5, 8,     0.1," %",sim,setSim)}
            {slider("📅 Durée",           "duree",    5,   30,    1," ans",sim,setSim)}
            {slider("🛡️ Taux assurance",  "assurance","0.10",0.80, 0.01," %",sim,setSim)}
            {slider("🔑 Frais de notaire","fraisNotaire",2,12,0.5," %",sim,setSim)}
          </Card>

          {/* Résultats */}
          <div style={{display:"grid",gap:12}}>
            {/* KPIs principaux */}
            <div style={{background:`linear-gradient(135deg,${T.accentDim},rgba(240,165,0,0.04))`,border:`1px solid rgba(240,165,0,0.3)`,borderRadius:14,padding:"20px 24px"}}>
              <div style={{fontSize:12,color:T.muted,marginBottom:6}}>MENSUALITÉ TOTALE</div>
              <div style={{fontFamily:T.fontD,fontSize:42,fontWeight:700,color:T.accent}}>{fmtAmt(mensualiteTotale)}<span style={{fontSize:18,color:T.muted}}>/mois</span></div>
              <div style={{display:"flex",gap:16,marginTop:8,fontSize:12,color:T.muted}}>
                <span>dont {fmtAmt(mensualiteHorsAssur)} capital+intérêts</span>
                <span>+ {fmtAmt(mensualiteAssur)} assurance</span>
              </div>
            </div>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:10}}>
              {kpi("Montant emprunté",fmtAmt(montantEmprunte),T.info)}
              {kpi("Coût des intérêts",fmtAmt(coutInterets),T.danger,`${((coutInterets/montantEmprunte)*100).toFixed(1)}% du capital`)}
              {kpi("Coût assurance",fmtAmt(coutAssurance),T.warning)}
              {kpi("Frais notaire",fmtAmt(fraisNotaireAmt),T.muted,`${s.fraisNotaire}% du prix`)}
              {kpi("Coût total",fmtAmt(coutGlobal),T.danger,"tout inclus")}
              {kpi("Taux d'endettement",`${((mensualiteTotale/3000)*100).toFixed(1)}%`,mensualiteTotale/3000>0.35?T.danger:T.success,"sur salaire 3 000 €")}
            </div>

            {/* Barre répartition */}
            <Card style={{padding:"14px 18px"}}>
              <Divider label="Répartition du coût total"/>
              <div style={{display:"flex",height:18,borderRadius:9,overflow:"hidden",marginBottom:12}}>
                {[{v:s.apport,c:"#34d399",l:"Apport"},{v:montantEmprunte,c:T.info,l:"Capital"},{v:coutInterets,c:T.danger,l:"Intérêts"},{v:coutAssurance,c:T.warning,l:"Assurance"},{v:fraisNotaireAmt,c:"#94a3b8",l:"Notaire"}].map((b,i)=>(
                  <div key={i} title={`${b.l}: ${fmtAmt(b.v)}`}
                    style={{flex:b.v,background:b.c,transition:"flex 0.5s"}}/>
                ))}
              </div>
              <div style={{display:"flex",gap:12,flexWrap:"wrap"}}>
                {[{v:s.apport,c:"#34d399",l:"Apport"},{v:montantEmprunte,c:T.info,l:"Capital"},{v:coutInterets,c:T.danger,l:"Intérêts"},{v:coutAssurance,c:T.warning,l:"Assurance"},{v:fraisNotaireAmt,c:"#94a3b8",l:"Notaire"}].map((b,i)=>(
                  <div key={i} style={{display:"flex",alignItems:"center",gap:5,fontSize:11}}>
                    <div style={{width:8,height:8,borderRadius:2,background:b.c}}/>
                    <span style={{color:T.muted}}>{b.l}</span>
                    <span style={{color:T.text,fontWeight:600}}>{fmtAmt(b.v)}</span>
                  </div>
                ))}
              </div>
            </Card>

            {/* Tableau amortissement */}
            <div>
              <button onClick={()=>setShowAmort(!showAmort)} style={{background:"none",border:`1px solid ${T.border}`,color:T.muted,borderRadius:8,padding:"6px 14px",cursor:"pointer",fontFamily:T.font,fontSize:12,marginBottom:10}}>
                {showAmort?"▲ Masquer":"▼ Tableau d'amortissement annuel"}
              </button>
              {showAmort&&(
                <div style={{maxHeight:280,overflow:"auto",border:`1px solid ${T.border}`,borderRadius:10}}>
                  <table style={{width:"100%",borderCollapse:"collapse",fontSize:12,fontFamily:T.font}}>
                    <thead><tr style={{background:"#060a10",position:"sticky",top:0}}>
                      {["Année","Mensualité","Capital remb.","Intérêts","Capital restant"].map(h=>(
                        <th key={h} style={{padding:"8px 12px",textAlign:"right",color:T.muted,fontWeight:600,fontSize:10,borderBottom:`1px solid ${T.border}`}}>{h}</th>
                      ))}
                    </tr></thead>
                    <tbody>
                      {amortAnnuel.map((r,i)=>(
                        <tr key={r.annee} style={{background:i%2===0?"transparent":"#060a10"}}>
                          <td style={{padding:"7px 12px",color:T.accent,fontWeight:700,textAlign:"right"}}>{r.annee}</td>
                          <td style={{padding:"7px 12px",color:T.text,textAlign:"right",fontFamily:"monospace"}}>{fmtAmt(r.mensualite)}</td>
                          <td style={{padding:"7px 12px",color:T.success,textAlign:"right",fontFamily:"monospace"}}>{fmtAmt(r.capital)}</td>
                          <td style={{padding:"7px 12px",color:T.danger,textAlign:"right",fontFamily:"monospace"}}>{fmtAmt(r.interets)}</td>
                          <td style={{padding:"7px 12px",color:T.muted,textAlign:"right",fontFamily:"monospace"}}>{fmtAmt(r.restant)}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              )}
            </div>
          </div>
        </div>
      )}

      {/* ── MODE : CAPACITÉ D'EMPRUNT ── */}
      {mode==="capacite"&&(
        <div style={{display:"grid",gridTemplateColumns:"360px 1fr",gap:16}}>
          <Card style={{padding:"18px 20px"}}>
            <Divider label="Votre situation"/>
            {slider("💶 Mensualité max souhaitée","mensualiteMax",300,5000,50," €",capa,setCapa)}
            {slider("📈 Taux d'intérêt","taux",0.5,8,0.1," %",capa,setCapa)}
            {slider("📅 Durée souhaitée","duree",5,30,1," ans",capa,setCapa)}
            {slider("🛡️ Taux assurance","assurance",0.10,0.80,0.01," %",capa,setCapa)}
            <div style={{padding:"12px",background:"rgba(240,165,0,0.07)",borderRadius:9,marginTop:8,fontSize:12,color:T.muted,lineHeight:1.6}}>
              💡 La règle est de ne pas dépasser <strong style={{color:T.warning}}>33% d'endettement</strong> de vos revenus nets.
            </div>
          </Card>
          <div style={{display:"grid",gap:12,alignContent:"start"}}>
            <div style={{background:`linear-gradient(135deg,${T.accentDim},rgba(240,165,0,0.04))`,border:`1px solid rgba(240,165,0,0.3)`,borderRadius:14,padding:"24px 28px",textAlign:"center"}}>
              <div style={{fontSize:12,color:T.muted,marginBottom:8,textTransform:"uppercase"}}>Capacité d'emprunt estimée</div>
              <div style={{fontFamily:T.fontD,fontSize:44,fontWeight:700,color:T.accent}}>{fmtAmt(Math.round(capaEmprunt))}</div>
              <div style={{fontSize:13,color:T.muted,marginTop:8}}>Pour une mensualité de {fmtAmt(capa.mensualiteMax)} / mois</div>
            </div>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
              {kpi("Revenus mensuels conseillés",fmtAmt(capa.mensualiteMax/0.33),T.info,"pour 33% d'endettement")}
              {kpi("Coût total estimé",fmtAmt(capa.mensualiteMax*capa.duree*12),T.danger,"hors notaire et apport")}
              {kpi("Durée",`${capa.duree} ans`,T.muted,`${capa.duree*12} mensualités`)}
              {kpi("Taux appliqué",`${capa.taux} %`,T.warning,"TAEG hors assurance")}
            </div>
            <Card style={{padding:"14px 18px"}}>
              <Divider label="Simulation budget total à prévoir"/>
              {[["Capital emprunté",Math.round(capaEmprunt),T.info],[`Apport conseillé (10%)`,Math.round(capaEmprunt*0.1),T.success],["Frais de notaire (8%)",Math.round(capaEmprunt*0.08),"#94a3b8"],["Coût total du crédit",Math.round(capa.mensualiteMax*capa.duree*12-capaEmprunt),T.danger]].map(([l,v,c])=>(
                <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                  <span style={{color:T.muted}}>{l}</span><span style={{color:c,fontWeight:700,fontFamily:T.fontD}}>{fmtAmt(v)}</span>
                </div>
              ))}
            </Card>
          </div>
        </div>
      )}

      {/* ── MODE : COMPARATIF TAUX ── */}
      {mode==="duree"&&(
        <div style={{display:"grid",gap:14}}>
          <div style={{display:"grid",gridTemplateColumns:"360px 1fr",gap:16}}>
            <Card style={{padding:"18px 20px"}}>
              <Divider label="Votre prêt de référence"/>
              {slider("💰 Montant emprunté","montant",50000,1000000,5000," €",sim,setSim)}
              {slider("📅 Durée","duree",5,30,1," ans",sim,setSim)}
            </Card>
            <Card>
              <Divider label="Comparatif selon le taux d'intérêt"/>
              <div style={{display:"grid",gap:3}}>
                <div style={{display:"grid",gridTemplateColumns:"80px 1fr 1fr 1fr 100px",gap:4,padding:"7px 10px",fontSize:10,color:T.muted,fontWeight:600,textTransform:"uppercase"}}>
                  <span>Taux</span><span>Mensualité</span><span>Coût intérêts</span><span>Coût total</span><span style={{textAlign:"right"}}>vs le meilleur</span>
                </div>
                {comparatifTaux.map((r,i)=>{
                  const best=comparatifTaux[0];
                  const surcoût=r.mensualite-best.mensualite;
                  const isCurrent=Math.abs(r.taux-sim.taux)<0.01;
                  return (
                    <div key={r.taux} style={{display:"grid",gridTemplateColumns:"80px 1fr 1fr 1fr 100px",gap:4,padding:"10px 10px",borderRadius:8,background:isCurrent?T.accentDim:"#060a10",border:isCurrent?`1px solid rgba(240,165,0,0.3)`:"1px solid transparent"}}>
                      <span style={{fontWeight:700,color:isCurrent?T.accent:T.text,fontFamily:T.fontD}}>{r.taux}%</span>
                      <span style={{color:T.text,fontFamily:"monospace",fontSize:13}}>{fmtAmt(r.mensualite)}/mois</span>
                      <span style={{color:T.danger,fontFamily:"monospace",fontSize:13}}>{fmtAmt(r.cout)}</span>
                      <span style={{color:T.muted,fontSize:12}}>{fmtAmt(r.mensualite*sim.duree*12)}</span>
                      <span style={{textAlign:"right",color:i===0?T.success:T.warning,fontSize:12,fontWeight:600}}>{i===0?"✅ Meilleur":`+${fmtAmt(surcoût)}/mois`}</span>
                    </div>
                  );
                })}
              </div>
              <div style={{marginTop:14}}>
                <Divider label="Visualisation mensualités par taux"/>
                <BarChart data={comparatifTaux.map(r=>({label:`${r.taux}%`,value:Math.round(r.mensualite)}))} color={T.accent} height={100}/>
              </div>
            </Card>
          </div>
        </div>
      )}
    </div>
  );
};

const CATS_TX=[
  {id:"salaire",l:"Salaire / Revenus",icon:"💰",color:"#22c55e",type:"credit"},
  {id:"loyer",l:"Loyer / Charges",icon:"🏠",color:"#f87171",type:"debit"},
  {id:"alimentation",l:"Alimentation",icon:"🛒",color:"#fb923c",type:"debit"},
  {id:"restaurant",l:"Restaurant / Bar",icon:"🍽️",color:"#fbbf24",type:"debit"},
  {id:"transport",l:"Transport",icon:"🚗",color:"#38bdf8",type:"debit"},
  {id:"sante",l:"Santé",icon:"🏥",color:"#34d399",type:"debit"},
  {id:"loisirs",l:"Loisirs / Sorties",icon:"🎭",color:"#a78bfa",type:"debit"},
  {id:"shopping",l:"Shopping / Vêtements",icon:"👗",color:"#f472b6",type:"debit"},
  {id:"abonnements",l:"Abonnements",icon:"📱",color:"#60a5fa",type:"debit"},
  {id:"voyages",l:"Voyages / Vacances",icon:"✈️",color:"#34d399",type:"debit"},
  {id:"education",l:"Éducation / Formation",icon:"🎓",color:"#c084fc",type:"debit"},
  {id:"banque",l:"Frais bancaires",icon:"🏦",color:"#94a3b8",type:"debit"},
  {id:"epargne",l:"Épargne / Placement",icon:"🐷",color:"#4ade80",type:"debit"},
  {id:"travaux",l:"Travaux / Maison",icon:"🔨",color:"#d97706",type:"debit"},
  {id:"assurance",l:"Assurances",icon:"🛡️",color:"#fbbf24",type:"debit"},
  {id:"autre",l:"Autre",icon:"📁",color:"#94a3b8",type:"both"},
];

// Donut SVG pur
const DonutChart=({data,size=160,thickness=32})=>{
  const total=data.reduce((s,d)=>s+d.value,0);
  if(total===0)return <div style={{width:size,height:size,borderRadius:size/2,background:T.border,display:"flex",alignItems:"center",justifyContent:"center",color:T.muted,fontSize:12}}>—</div>;
  let cumul=0;
  const cx=size/2,cy=size/2,r=(size-thickness)/2;
  const circumference=2*Math.PI*r;
  const slices=data.filter(d=>d.value>0).map(d=>{
    const pct=d.value/total;
    const offset=circumference*(1-cumul-pct);
    const slice={...d,pct,offset,strokeDash:circumference*pct-2};
    cumul+=pct;
    return slice;
  });
  return (
    <svg width={size} height={size} style={{transform:"rotate(-90deg)"}}>
      {slices.map((s,i)=>(
        <circle key={i} cx={cx} cy={cy} r={r} fill="none"
          stroke={s.color} strokeWidth={thickness}
          strokeDasharray={`${s.strokeDash} ${circumference}`}
          strokeDashoffset={s.offset} style={{transition:"all 0.5s"}}/>
      ))}
    </svg>
  );
};

// Barres SVG
const BarChart=({data,height=120,color=T.accent,negColor=T.danger})=>{
  if(!data.length)return null;
  const vals=data.map(d=>d.value);
  const max=Math.max(...vals.map(Math.abs),1);
  const w=100/data.length;
  return (
    <svg width="100%" height={height} style={{overflow:"visible"}}>
      {data.map((d,i)=>{
        const barH=Math.abs(d.value)/max*(height-22);
        const isNeg=d.value<0;
        const c=isNeg?negColor:color;
        return (
          <g key={i}>
            <rect x={`${i*w+w*0.1}%`} y={height-22-barH} width={`${w*0.8}%`} height={barH}
              fill={c} rx={3} style={{transition:"all 0.4s"}} opacity={0.85}/>
            <text x={`${i*w+w/2}%`} y={height-6} textAnchor="middle" fill={T.muted} fontSize={9} fontFamily={T.font}>{d.label}</text>
            {d.value!==0&&<text x={`${i*w+w/2}%`} y={height-22-barH-4} textAnchor="middle" fill={c} fontSize={9} fontFamily={T.font} fontWeight="600">{Math.abs(d.value)>999?(Math.abs(d.value)/1000).toFixed(1)+"k":Math.abs(d.value).toFixed(0)}</text>}
          </g>
        );
      })}
    </svg>
  );
};

// Sparkline SVG
const Sparkline=({values,color=T.accent,height=32})=>{
  if(values.length<2)return null;
  const mn=Math.min(...values),mx=Math.max(...values);
  const range=mx-mn||1;
  const w=100/(values.length-1);
  const pts=values.map((v,i)=>`${i*w},${((mx-v)/range*(height-4)+2).toFixed(1)}`).join(" ");
  return (
    <svg width="100%" height={height} style={{overflow:"visible"}}>
      <polyline points={pts} fill="none" stroke={color} strokeWidth="1.5" strokeLinejoin="round" style={{transition:"all 0.4s"}}/>
      <circle cx={`${(values.length-1)*w}%`} cy={((mx-values[values.length-1])/range*(height-4)+2).toFixed(1)} r={3} fill={color}/>
    </svg>
  );
};

// ─── MODULE BANQUE ────────────────────────────────────────────────────────────
const Banque=({banque,setBanque})=>{
  const [tab,setTab]=useState("dashboard");
  const [showAdd,setShowAdd]=useState(false);
  const [showAddTx,setShowAddTx]=useState(false);
  const [selectedCompte,setSelectedCompte]=useState(null);
  const [txFilter,setTxFilter]=useState({cat:"all",compte:"all",sens:"all",mois:"",search:""});
  const [sortTx,setSortTx]=useState("date");
  const [showBudget,setShowBudget]=useState(false);
  const [form,setForm]=useState({type:"comptes",nom:"",banqueNom:"",iban:"",solde:"",type2:"courant",note:""});
  const [formTx,setFormTx]=useState({compteId:"",libelle:"",montant:"",sens:"debit",categorie:"alimentation",date:today(),note:"",tags:""});

  const transactions=banque.transactions||[];
  const comptes=banque.comptes||[];
  const epargne=banque.epargne||[];
  const credits=banque.credits||[];
  const budgets=banque.budgets||{};

  // ── Totaux ──────────────────────────────────────────────────────────────────
  const totalSolde=comptes.reduce((s,c)=>s+c.solde,0);
  const totalEpargne=epargne.reduce((s,e)=>s+e.solde,0);
  const totalCredits=credits.reduce((s,c)=>s+(c.solde||0),0);
  const totalPatrimoine=totalSolde+totalEpargne-totalCredits;

  // ── Transactions filtrées ───────────────────────────────────────────────────
  const txFiltered=useMemo(()=>{
    return transactions.filter(tx=>{
      if(txFilter.cat!=="all"&&tx.categorie!==txFilter.cat)return false;
      if(txFilter.compte!=="all"&&tx.compteId!==txFilter.compte)return false;
      if(txFilter.sens!=="all"&&tx.sens!==txFilter.sens)return false;
      if(txFilter.mois&&!tx.date.startsWith(txFilter.mois))return false;
      if(txFilter.search&&!tx.libelle.toLowerCase().includes(txFilter.search.toLowerCase()))return false;
      return true;
    }).sort((a,b)=>b.date.localeCompare(a.date));
  },[transactions,txFilter]);

  // ── Analyse par catégorie ───────────────────────────────────────────────────
  const moisDisponibles=useMemo(()=>{
    const s=new Set(transactions.map(t=>t.date.slice(0,7)));
    return [...s].sort().reverse();
  },[transactions]);

  const moisCourant=txFilter.mois||(moisDisponibles[0]||today().slice(0,7));

  const txMois=useMemo(()=>transactions.filter(t=>t.date.startsWith(moisCourant)),[transactions,moisCourant]);
  const depenseMois=txMois.filter(t=>t.sens==="debit").reduce((s,t)=>s+t.montant,0);
  const revenuMois=txMois.filter(t=>t.sens==="credit").reduce((s,t)=>s+t.montant,0);
  const balanceMois=revenuMois-depenseMois;

  const depenseParCat=useMemo(()=>{
    const map={};
    txMois.filter(t=>t.sens==="debit").forEach(t=>{
      map[t.categorie]=(map[t.categorie]||0)+t.montant;
    });
    return Object.entries(map).map(([id,value])=>{
      const cat=CATS_TX.find(c=>c.id===id)||{l:id,color:"#94a3b8",icon:"📁"};
      return {id,value,label:cat.l,color:cat.color,icon:cat.icon};
    }).sort((a,b)=>b.value-a.value);
  },[txMois]);

  // ── Évolution 6 derniers mois ───────────────────────────────────────────────
  const evol6mois=useMemo(()=>{
    const mois=[];
    for(let i=5;i>=0;i--){
      const d=new Date();d.setMonth(d.getMonth()-i);
      const m=d.toISOString().slice(0,7);
      const dep=transactions.filter(t=>t.date.startsWith(m)&&t.sens==="debit").reduce((s,t)=>s+t.montant,0);
      const rev=transactions.filter(t=>t.date.startsWith(m)&&t.sens==="credit").reduce((s,t)=>s+t.montant,0);
      mois.push({label:fmtMois(m).slice(0,3),dep,rev,balance:rev-dep,mois:m});
    }
    return mois;
  },[transactions]);

  // ── Actions ─────────────────────────────────────────────────────────────────
  const addCompte=()=>{setBanque(s=>({...s,[form.type]:[...(s[form.type]||[]),{...form,id:uid(),solde:parseFloat(form.solde)||0}]}));setShowAdd(false);};
  const addTx=()=>{
    const tx={...formTx,id:uid(),montant:parseFloat(formTx.montant)||0,tags:formTx.tags.split(",").map(t=>t.trim()).filter(Boolean)};
    setBanque(s=>({...s,transactions:[tx,...(s.transactions||[])]}));
    // Mettre à jour le solde du compte
    if(tx.compteId){
      setBanque(s=>({...s,comptes:(s.comptes||[]).map(c=>c.id===tx.compteId?{...c,solde:c.solde+(tx.sens==="credit"?tx.montant:-tx.montant)}:c)}));
    }
    setShowAddTx(false);
    setFormTx({compteId:comptes[0]?.id||"",libelle:"",montant:"",sens:"debit",categorie:"alimentation",date:today(),note:"",tags:""});
  };
  const delTx=id=>setBanque(s=>({...s,transactions:(s.transactions||[]).filter(t=>t.id!==id)}));
  const delCompte=(type,id)=>setBanque(s=>({...s,[type]:(s[type]||[]).filter(x=>x.id!==id)}));
  const setBudget=(cat,val)=>setBanque(s=>({...s,budgets:{...(s.budgets||{}),[cat]:parseFloat(val)||0}}));

  const TABS=[{id:"dashboard",icon:"📊",label:"Tableau de bord"},{id:"comptes",icon:"🏦",label:"Comptes"},{id:"transactions",icon:"↔️",label:"Transactions"},{id:"analyse",icon:"🔍",label:"Analyse"},{id:"budget",icon:"🎯",label:"Budget"},{id:"simulateur",icon:"🧮",label:"Simulateur"}];

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div><h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🏦 Ma Banque</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>Patrimoine total : <span style={{color:T.accent,fontWeight:700,fontFamily:T.fontD}}>{fmtAmt(totalPatrimoine)}</span></p>
        </div>
        <div style={{display:"flex",gap:8}}>
          <Btn v="ghost" onClick={()=>setShowAddTx(true)}>+ Transaction</Btn>
          <Btn onClick={()=>setShowAdd(true)}>+ Compte</Btn>
        </div>
      </div>

      <Tabs tabs={TABS} active={tab} onChange={setTab}/>

      {/* ── DASHBOARD ── */}
      {tab==="dashboard"&&(
        <div style={{display:"grid",gap:16}}>
          {/* KPIs */}
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(150px,1fr))",gap:12}}>
            <StatCard label="Solde comptes" value={fmtAmt(totalSolde)} icon="💰" color={totalSolde>=0?T.success:T.danger}/>
            <StatCard label="Épargne totale" value={fmtAmt(totalEpargne)} icon="🐷" color={T.success}/>
            <StatCard label="Crédits restants" value={fmtAmt(totalCredits)} icon="💳" color={T.danger}/>
            <StatCard label="Patrimoine net" value={fmtAmt(totalPatrimoine)} icon="📈" color={T.accent}/>
            <StatCard label={`Revenus ${fmtMois(moisCourant).slice(0,3)}`} value={fmtAmt(revenuMois)} icon="⬆️" color={T.success}/>
            <StatCard label={`Dépenses ${fmtMois(moisCourant).slice(0,3)}`} value={fmtAmt(depenseMois)} icon="⬇️" color={T.danger}/>
          </div>

          {/* Évolution 6 mois + répartition */}
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
            <Card>
              <Divider label="Évolution 6 mois — Dépenses vs Revenus"/>
              {transactions.length===0?<EmptyState icon="📊" text="Ajoutez des transactions"/>:(
                <div>
                  <div style={{display:"flex",gap:16,marginBottom:12}}>
                    <div style={{display:"flex",alignItems:"center",gap:5,fontSize:11}}><div style={{width:10,height:10,borderRadius:2,background:T.danger}}/><span style={{color:T.muted}}>Dépenses</span></div>
                    <div style={{display:"flex",alignItems:"center",gap:5,fontSize:11}}><div style={{width:10,height:10,borderRadius:2,background:T.success}}/><span style={{color:T.muted}}>Revenus</span></div>
                  </div>
                  <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
                    <div>
                      <div style={{fontSize:10,color:T.muted,marginBottom:4}}>DÉPENSES</div>
                      <BarChart data={evol6mois.map(m=>({label:m.label,value:m.dep}))} color={T.danger} height={100}/>
                    </div>
                    <div>
                      <div style={{fontSize:10,color:T.muted,marginBottom:4}}>REVENUS</div>
                      <BarChart data={evol6mois.map(m=>({label:m.label,value:m.rev}))} color={T.success} height={100}/>
                    </div>
                  </div>
                  <div style={{marginTop:14,borderTop:`1px solid ${T.border}`,paddingTop:10}}>
                    <div style={{fontSize:10,color:T.muted,marginBottom:4}}>SOLDE MENSUEL (revenus − dépenses)</div>
                    <BarChart data={evol6mois.map(m=>({label:m.label,value:m.balance}))} color={T.success} negColor={T.danger} height={70}/>
                  </div>
                </div>
              )}
            </Card>

            <Card>
              <Divider label={`Répartition dépenses — ${fmtMois(moisCourant)}`}/>
              {depenseParCat.length===0?<EmptyState icon="🍩" text="Aucune dépense ce mois"/>:(
                <div style={{display:"flex",gap:16,alignItems:"center"}}>
                  <div style={{flexShrink:0,position:"relative"}}>
                    <DonutChart data={depenseParCat} size={140} thickness={28}/>
                    <div style={{position:"absolute",inset:0,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center"}}>
                      <div style={{fontSize:14,fontWeight:700,color:T.text,fontFamily:T.fontD}}>{fmtAmt(depenseMois)}</div>
                      <div style={{fontSize:9,color:T.muted}}>dépenses</div>
                    </div>
                  </div>
                  <div style={{flex:1,display:"grid",gap:4}}>
                    {depenseParCat.slice(0,6).map(c=>(
                      <div key={c.id} style={{display:"flex",alignItems:"center",gap:6}}>
                        <div style={{width:8,height:8,borderRadius:2,background:c.color,flexShrink:0}}/>
                        <span style={{fontSize:11,color:T.muted,flex:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{c.icon} {c.label}</span>
                        <span style={{fontSize:11,fontWeight:700,color:T.text,flexShrink:0}}>{fmtAmt(c.value)}</span>
                        <span style={{fontSize:9,color:T.muted,flexShrink:0}}>{Math.round(c.value/depenseMois*100)}%</span>
                      </div>
                    ))}
                    {depenseParCat.length>6&&<div style={{fontSize:10,color:T.muted}}>+{depenseParCat.length-6} autres catégories</div>}
                  </div>
                </div>
              )}
            </Card>
          </div>

          {/* Comptes résumé + dernières transactions */}
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
            <Card>
              <Divider label="Mes comptes"/>
              {comptes.map(c=>(
                <div key={c.id} style={{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"8px 0",borderBottom:`1px solid ${T.border}`}}>
                  <div>
                    <div style={{fontSize:13,fontWeight:600,color:T.text}}>{c.nom}</div>
                    <div style={{fontSize:10,color:T.muted}}>{c.banqueNom}</div>
                  </div>
                  <div style={{textAlign:"right"}}>
                    <div style={{fontSize:15,fontWeight:700,fontFamily:T.fontD,color:c.solde>=0?T.success:T.danger}}>{fmtAmt(c.solde)}</div>
                    <div style={{width:60}}><Sparkline values={transactions.filter(t=>t.compteId===c.id).slice(0,12).reverse().reduce((acc,t)=>[...acc,(acc[acc.length-1]||c.solde)+(t.sens==="credit"?t.montant:-t.montant)],[c.solde])} color={c.solde>=0?T.success:T.danger}/></div>
                  </div>
                </div>
              ))}
              <div style={{marginTop:10,padding:"8px 0",borderTop:`1px solid ${T.border}`,display:"flex",justifyContent:"space-between"}}>
                <span style={{color:T.muted,fontSize:12}}>Total comptes</span>
                <span style={{fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{fmtAmt(totalSolde)}</span>
              </div>
            </Card>
            <Card>
              <Divider label="Dernières transactions"/>
              {transactions.length===0&&<EmptyState icon="↔️" text="Aucune transaction"/>}
              {transactions.slice(0,8).map(tx=>{
                const cat=CATS_TX.find(c=>c.id===tx.categorie)||{icon:"📁",color:"#94a3b8"};
                return (
                  <div key={tx.id} style={{display:"flex",alignItems:"center",gap:8,padding:"7px 0",borderBottom:`1px solid ${T.border}`}}>
                    <span style={{fontSize:16,flexShrink:0}}>{cat.icon}</span>
                    <div style={{flex:1,minWidth:0}}>
                      <div style={{fontSize:12,fontWeight:600,color:T.text,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{tx.libelle}</div>
                      <div style={{fontSize:10,color:T.muted}}>{fmt(tx.date)}</div>
                    </div>
                    <span style={{fontWeight:700,fontFamily:T.fontD,fontSize:13,color:tx.sens==="credit"?T.success:T.danger,flexShrink:0}}>{tx.sens==="credit"?"+":"-"}{fmtAmt(tx.montant)}</span>
                  </div>
                );
              })}
              {transactions.length>8&&<div style={{fontSize:11,color:T.accent,marginTop:8,cursor:"pointer",textAlign:"center"}} onClick={()=>setTab("transactions")}>Voir toutes les transactions →</div>}
            </Card>
          </div>
        </div>
      )}

      {/* ── COMPTES ── */}
      {tab==="comptes"&&(
        <div style={{display:"grid",gap:16}}>
          {/* Comptes courants */}
          <div>
            <Divider label="💳 Comptes courants"/>
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(300px,1fr))",gap:12}}>
              {comptes.length===0&&<EmptyState icon="🏦" text="Ajoutez un compte courant"/>}
              {comptes.map(c=>{
                const txCompte=transactions.filter(t=>t.compteId===c.id);
                const depCeMois=txCompte.filter(t=>t.date.startsWith(moisCourant)&&t.sens==="debit").reduce((s,t)=>s+t.montant,0);
                const revCeMois=txCompte.filter(t=>t.date.startsWith(moisCourant)&&t.sens==="credit").reduce((s,t)=>s+t.montant,0);
                return (
                  <Card key={c.id} style={{padding:0,overflow:"hidden",cursor:"pointer",borderColor:selectedCompte===c.id?T.accent:T.border}} onClick={()=>setSelectedCompte(selectedCompte===c.id?null:c.id)}>
                    <div style={{background:"linear-gradient(135deg,rgba(56,189,248,0.08),transparent)",padding:"16px 18px",borderBottom:`1px solid ${T.border}`}}>
                      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                        <div>
                          <div style={{fontFamily:T.fontD,fontSize:16,fontWeight:700,color:T.text}}>{c.nom}</div>
                          <div style={{fontSize:11,color:T.muted}}>{c.banqueNom} · {c.type2}</div>
                        </div>
                        <button onClick={e=>{e.stopPropagation();if(confirm("Supprimer ?"))delCompte("comptes",c.id)}} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:13}}>🗑</button>
                      </div>
                      <div style={{marginTop:12}}>
                        <div style={{fontSize:9,color:T.muted,marginBottom:2}}>SOLDE ACTUEL</div>
                        <div style={{fontSize:28,fontWeight:700,fontFamily:T.fontD,color:c.solde>=0?T.success:T.danger}}>{fmtAmt(c.solde)}</div>
                      </div>
                      {c.iban&&<div style={{fontSize:10,color:T.muted,marginTop:8,fontFamily:"monospace"}}>{c.iban}</div>}
                    </div>
                    <div style={{padding:"10px 18px",display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
                      <div><div style={{fontSize:9,color:T.muted}}>DÉPENSES CE MOIS</div><div style={{fontSize:14,fontWeight:700,color:T.danger,fontFamily:T.fontD}}>{fmtAmt(depCeMois)}</div></div>
                      <div><div style={{fontSize:9,color:T.muted}}>REVENUS CE MOIS</div><div style={{fontSize:14,fontWeight:700,color:T.success,fontFamily:T.fontD}}>{fmtAmt(revCeMois)}</div></div>
                    </div>
                    {txCompte.length>0&&<div style={{padding:"0 18px 12px"}}><Sparkline values={txCompte.slice(-15).map((_,i,arr)=>arr.slice(0,i+1).reduce((s,t)=>s+(t.sens==="credit"?t.montant:-t.montant),c.solde-txCompte.reduce((s,t)=>s+(t.sens==="credit"?t.montant:-t.montant),0)))} color={c.solde>=0?T.success:T.danger} height={28}/></div>}
                  </Card>
                );
              })}
            </div>
          </div>

          {/* Épargne */}
          <div>
            <Divider label="🐷 Épargne & Placements"/>
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(280px,1fr))",gap:12}}>
              {epargne.length===0&&<EmptyState icon="🐷" text="Ajoutez vos comptes épargne"/>}
              {epargne.map(e=>(
                <Card key={e.id} style={{padding:0,overflow:"hidden"}}>
                  <div style={{background:"linear-gradient(135deg,rgba(74,222,128,0.08),transparent)",padding:"16px 18px"}}>
                    <div style={{display:"flex",justifyContent:"space-between"}}>
                      <div><div style={{fontFamily:T.fontD,fontSize:15,fontWeight:700,color:T.text}}>{e.nom}</div><div style={{fontSize:11,color:T.muted}}>{e.banqueNom} · {e.type2}</div></div>
                      <button onClick={()=>delCompte("epargne",e.id)} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:13}}>🗑</button>
                    </div>
                    <div style={{marginTop:12,fontSize:26,fontWeight:700,fontFamily:T.fontD,color:T.success}}>{fmtAmt(e.solde)}</div>
                  </div>
                </Card>
              ))}
            </div>
          </div>

          {/* Crédits */}
          <div>
            <Divider label="💳 Crédits & Prêts"/>
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(280px,1fr))",gap:12}}>
              {credits.length===0&&<EmptyState icon="💳" text="Ajoutez vos crédits"/>}
              {credits.map(c=>(
                <Card key={c.id} style={{padding:0,overflow:"hidden"}}>
                  <div style={{background:"linear-gradient(135deg,rgba(248,113,113,0.07),transparent)",padding:"16px 18px"}}>
                    <div style={{display:"flex",justifyContent:"space-between"}}>
                      <div><div style={{fontFamily:T.fontD,fontSize:15,fontWeight:700,color:T.text}}>{c.nom}</div><div style={{fontSize:11,color:T.muted}}>{c.banqueNom}</div></div>
                      <Badge c={c.statut==="actif"?T.success:T.muted}>{c.statut}</Badge>
                    </div>
                    <div style={{marginTop:12,fontSize:26,fontWeight:700,fontFamily:T.fontD,color:T.danger}}>{fmtAmt(c.solde)}</div>
                    {c.note&&<div style={{fontSize:11,color:T.muted,marginTop:6,fontStyle:"italic"}}>{c.note}</div>}
                  </div>
                </Card>
              ))}
            </div>
          </div>
        </div>
      )}

      {/* ── TRANSACTIONS ── */}
      {tab==="transactions"&&(
        <div>
          {/* Filtres */}
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr 1fr auto",gap:8,marginBottom:14,background:"#060a10",borderRadius:10,padding:"12px 14px"}}>
            <F label="Recherche"><Inp value={txFilter.search} onChange={v=>setTxFilter(f=>({...f,search:v}))} placeholder="Libellé..."/></F>
            <F label="Catégorie"><Sel value={txFilter.cat} onChange={v=>setTxFilter(f=>({...f,cat:v}))}><option value="all">Toutes</option>{CATS_TX.map(c=><option key={c.id} value={c.id}>{c.icon} {c.l}</option>)}</Sel></F>
            <F label="Sens"><Sel value={txFilter.sens} onChange={v=>setTxFilter(f=>({...f,sens:v}))}><option value="all">Tous</option><option value="debit">Dépenses</option><option value="credit">Revenus</option></Sel></F>
            <F label="Mois"><Sel value={txFilter.mois} onChange={v=>setTxFilter(f=>({...f,mois:v}))}><option value="">Tous</option>{moisDisponibles.map(m=><option key={m} value={m}>{fmtMois(m)}</option>)}</Sel></F>
            <div style={{display:"flex",alignItems:"flex-end"}}><Btn sm v="ghost" onClick={()=>setTxFilter({cat:"all",compte:"all",sens:"all",mois:"",search:""})}>↺</Btn></div>
          </div>

          {/* Stats du filtre */}
          <div style={{display:"grid",gridTemplateColumns:"repeat(4,1fr)",gap:10,marginBottom:14}}>
            <div style={{background:"#060a10",borderRadius:8,padding:"10px 14px"}}>
              <div style={{fontSize:9,color:T.muted,textTransform:"uppercase",marginBottom:3}}>Transactions</div>
              <div style={{fontSize:18,fontWeight:700,color:T.text,fontFamily:T.fontD}}>{txFiltered.length}</div>
            </div>
            <div style={{background:"#060a10",borderRadius:8,padding:"10px 14px"}}>
              <div style={{fontSize:9,color:T.muted,textTransform:"uppercase",marginBottom:3}}>Dépenses</div>
              <div style={{fontSize:18,fontWeight:700,color:T.danger,fontFamily:T.fontD}}>{fmtAmt(txFiltered.filter(t=>t.sens==="debit").reduce((s,t)=>s+t.montant,0))}</div>
            </div>
            <div style={{background:"#060a10",borderRadius:8,padding:"10px 14px"}}>
              <div style={{fontSize:9,color:T.muted,textTransform:"uppercase",marginBottom:3}}>Revenus</div>
              <div style={{fontSize:18,fontWeight:700,color:T.success,fontFamily:T.fontD}}>{fmtAmt(txFiltered.filter(t=>t.sens==="credit").reduce((s,t)=>s+t.montant,0))}</div>
            </div>
            <div style={{background:"#060a10",borderRadius:8,padding:"10px 14px"}}>
              <div style={{fontSize:9,color:T.muted,textTransform:"uppercase",marginBottom:3}}>Solde</div>
              <div style={{fontSize:18,fontWeight:700,fontFamily:T.fontD,color:(()=>{const b=txFiltered.filter(t=>t.sens==="credit").reduce((s,t)=>s+t.montant,0)-txFiltered.filter(t=>t.sens==="debit").reduce((s,t)=>s+t.montant,0);return b>=0?T.success:T.danger;})()}}>{(()=>{const b=txFiltered.filter(t=>t.sens==="credit").reduce((s,t)=>s+t.montant,0)-txFiltered.filter(t=>t.sens==="debit").reduce((s,t)=>s+t.montant,0);return(b>=0?"+":"")+fmtAmt(b);})()}</div>
            </div>
          </div>

          {/* Liste transactions */}
          {txFiltered.length===0&&<EmptyState icon="↔️" text="Aucune transaction. Cliquez sur + Transaction pour commencer."/>}
          <div style={{display:"grid",gap:3}}>
            {txFiltered.map(tx=>{
              const cat=CATS_TX.find(c=>c.id===tx.categorie)||{icon:"📁",color:"#94a3b8",l:"Autre"};
              const compte=comptes.find(c=>c.id===tx.compteId);
              return (
                <div key={tx.id} style={{display:"flex",alignItems:"center",gap:10,padding:"10px 14px",background:"#060a10",borderRadius:9,transition:"background 0.12s"}}
                  onMouseEnter={e=>e.currentTarget.style.background="#0d1420"}
                  onMouseLeave={e=>e.currentTarget.style.background="#060a10"}>
                  <div style={{width:36,height:36,borderRadius:18,background:cat.color+"22",display:"flex",alignItems:"center",justifyContent:"center",fontSize:18,flexShrink:0}}>{cat.icon}</div>
                  <div style={{flex:1,minWidth:0}}>
                    <div style={{fontSize:13,fontWeight:600,color:T.text,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{tx.libelle}</div>
                    <div style={{fontSize:10,color:T.muted,display:"flex",gap:8,marginTop:2}}>
                      <span>{fmt(tx.date)}</span>
                      <span style={{color:cat.color}}>{cat.icon} {cat.l}</span>
                      {compte&&<span>🏦 {compte.nom}</span>}
                    </div>
                    {(tx.tags||[]).length>0&&<div style={{display:"flex",gap:4,marginTop:3}}>{tx.tags.map(t=><span key={t} style={{fontSize:9,background:T.accentDim,color:T.accent,borderRadius:4,padding:"1px 5px"}}>{t}</span>)}</div>}
                  </div>
                  <div style={{textAlign:"right",flexShrink:0}}>
                    <div style={{fontSize:15,fontWeight:700,fontFamily:T.fontD,color:tx.sens==="credit"?T.success:T.danger}}>{tx.sens==="credit"?"+":"-"}{fmtAmt(tx.montant)}</div>
                    {tx.note&&<div style={{fontSize:9,color:T.muted,maxWidth:100,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{tx.note}</div>}
                  </div>
                  <button onClick={()=>delTx(tx.id)} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:13,opacity:0.5,flexShrink:0}}>🗑</button>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {/* ── ANALYSE ── */}
      {tab==="analyse"&&(
        <div style={{display:"grid",gap:14}}>
          {/* Sélecteur mois */}
          <div style={{display:"flex",alignItems:"center",gap:12}}>
            <F label="Mois analysé" style={{minWidth:180}}>
              <Sel value={txFilter.mois} onChange={v=>setTxFilter(f=>({...f,mois:v}))}><option value="">Ce mois-ci</option>{moisDisponibles.map(m=><option key={m} value={m}>{fmtMois(m)}</option>)}</Sel>
            </F>
            <div style={{padding:"8px 14px",background:T.accentDim,borderRadius:8,fontSize:13,color:T.accent}}>
              Balance : <strong style={{fontFamily:T.fontD}}>{balanceMois>=0?"+":""}{fmtAmt(balanceMois)}</strong>
            </div>
          </div>

          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
            {/* Donut + détail catégories */}
            <Card>
              <Divider label="Dépenses par catégorie"/>
              {depenseParCat.length===0?<EmptyState icon="🍩" text="Aucune dépense ce mois"/>:(
                <div>
                  <div style={{display:"flex",justifyContent:"center",marginBottom:16,position:"relative"}}>
                    <DonutChart data={depenseParCat} size={180} thickness={36}/>
                    <div style={{position:"absolute",inset:0,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",pointerEvents:"none"}}>
                      <div style={{fontSize:18,fontWeight:700,fontFamily:T.fontD,color:T.text}}>{fmtAmt(depenseMois)}</div>
                      <div style={{fontSize:10,color:T.muted}}>total dépenses</div>
                    </div>
                  </div>
                  <div style={{display:"grid",gap:6}}>
                    {depenseParCat.map(c=>{
                      const bgt=budgets[c.id];
                      const pctBgt=bgt?Math.min(100,c.value/bgt*100):null;
                      return (
                        <div key={c.id} style={{padding:"8px 10px",background:"#060a10",borderRadius:8}}>
                          <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:bgt?4:0}}>
                            <div style={{display:"flex",alignItems:"center",gap:7}}>
                              <div style={{width:10,height:10,borderRadius:3,background:c.color,flexShrink:0}}/>
                              <span style={{fontSize:12,color:T.text}}>{c.icon} {c.label}</span>
                            </div>
                            <div style={{display:"flex",gap:8,alignItems:"center"}}>
                              <span style={{fontWeight:700,fontFamily:T.fontD,fontSize:13,color:c.color}}>{fmtAmt(c.value)}</span>
                              <span style={{fontSize:10,color:T.muted}}>{Math.round(c.value/depenseMois*100)}%</span>
                            </div>
                          </div>
                          {bgt&&<div style={{background:T.border,borderRadius:3,height:3}}><div style={{background:pctBgt>90?T.danger:pctBgt>70?T.warning:c.color,height:3,borderRadius:3,width:`${pctBgt}%`,transition:"width 0.5s"}}/></div>}
                          {bgt&&<div style={{fontSize:9,color:pctBgt>90?T.danger:T.muted,marginTop:2}}>Budget: {fmtAmt(bgt)} · Restant: {fmtAmt(bgt-c.value)}</div>}
                        </div>
                      );
                    })}
                  </div>
                </div>
              )}
            </Card>

            {/* Comparaison mois */}
            <div style={{display:"grid",gap:14}}>
              <Card>
                <Divider label="Dépenses par mois"/>
                <BarChart data={evol6mois.map(m=>({label:m.label,value:m.dep}))} color={T.danger} height={110}/>
              </Card>
              <Card>
                <Divider label="Top dépenses du mois"/>
                {txMois.filter(t=>t.sens==="debit").sort((a,b)=>b.montant-a.montant).slice(0,6).map(tx=>{
                  const cat=CATS_TX.find(c=>c.id===tx.categorie)||{icon:"📁"};
                  return (
                    <div key={tx.id} style={{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                      <div style={{display:"flex",alignItems:"center",gap:7}}>
                        <span>{cat.icon}</span>
                        <span style={{color:T.text,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",maxWidth:160}}>{tx.libelle}</span>
                      </div>
                      <span style={{fontWeight:700,color:T.danger,fontFamily:T.fontD,flexShrink:0}}>{fmtAmt(tx.montant)}</span>
                    </div>
                  );
                })}
                {txMois.filter(t=>t.sens==="debit").length===0&&<EmptyState icon="💸" text="Aucune dépense"/>}
              </Card>
            </div>
          </div>
        </div>
      )}

      {/* ── BUDGET ── */}
      {tab==="budget"&&(
        <div>
          <div style={{background:"rgba(240,165,0,0.07)",border:"1px solid rgba(240,165,0,0.2)",borderRadius:10,padding:"12px 16px",marginBottom:18,fontSize:13,color:T.muted}}>
            🎯 Définissez un budget mensuel par catégorie. Les barres de progression s'affichent dans l'analyse dès qu'une limite est fixée.
          </div>
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(260px,1fr))",gap:10}}>
            {CATS_TX.filter(c=>c.type==="debit"||c.type==="both").map(cat=>{
              const bgt=budgets[cat.id]||0;
              const depense=depenseMois>0?depenseParCat.find(d=>d.id===cat.id)?.value||0:0;
              const pct=bgt>0?Math.min(100,depense/bgt*100):0;
              return (
                <Card key={cat.id} style={{padding:"12px 14px"}}>
                  <div style={{display:"flex",alignItems:"center",gap:8,marginBottom:10}}>
                    <span style={{fontSize:20}}>{cat.icon}</span>
                    <div style={{flex:1}}>
                      <div style={{fontSize:12,fontWeight:700,color:T.text}}>{cat.l}</div>
                      {bgt>0&&depense>0&&<div style={{fontSize:10,color:pct>90?T.danger:T.muted}}>{fmtAmt(depense)} / {fmtAmt(bgt)}</div>}
                    </div>
                    {bgt>0&&depense>0&&<Badge c={pct>90?T.danger:pct>70?T.warning:T.success}>{Math.round(pct)}%</Badge>}
                  </div>
                  {bgt>0&&<div style={{background:T.border,borderRadius:4,height:4,marginBottom:8}}><div style={{background:pct>90?T.danger:pct>70?T.warning:cat.color,height:4,borderRadius:4,width:`${pct}%`,transition:"width 0.5s"}}/></div>}
                  <div style={{display:"flex",alignItems:"center",gap:6}}>
                    <span style={{fontSize:10,color:T.muted,width:48}}>Budget</span>
                    <input type="number" value={bgt||""} onChange={e=>setBudget(cat.id,e.target.value)} placeholder="0 €" min="0"
                      style={{flex:1,background:"#060a10",border:`1px solid ${T.border}`,borderRadius:6,padding:"5px 8px",color:T.accent,fontFamily:T.fontD,fontSize:13,fontWeight:700,outline:"none",textAlign:"right"}}/>
                    <span style={{fontSize:10,color:T.muted}}>€/mois</span>
                  </div>
                </Card>
              );
            })}
          </div>
        </div>
      )}

      {/* ── SIMULATEUR DE CRÉDIT ── */}
      {tab==="simulateur"&&<SimulateurCredit/>}

      {/* ── MODALE AJOUT COMPTE ── */}
      {showAdd&&<Modal title="🏦 Ajouter un compte" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gap:10}}>
          <F label="Type"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}><option value="comptes">💳 Compte courant</option><option value="epargne">🐷 Épargne / Placement</option><option value="credits">💸 Crédit / Prêt</option></Sel></F>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Nom *"><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Compte principal"/></F>
            <F label="Banque"><Inp value={form.banqueNom} onChange={v=>setForm(f=>({...f,banqueNom:v}))} placeholder="BNP, Crédit Agricole..."/></F>
            <F label="Solde actuel (€)"><Inp type="number" value={form.solde} onChange={v=>setForm(f=>({...f,solde:v}))}/></F>
            <F label="Type de compte"><Inp value={form.type2} onChange={v=>setForm(f=>({...f,type2:v}))} placeholder="Courant, PEL, Livret A..."/></F>
            <F label="IBAN" style={{gridColumn:"1/-1"}}><Inp value={form.iban} onChange={v=>setForm(f=>({...f,iban:v}))} placeholder="FR76..." mono/></F>
          </div>
          <F label="Note"><Inp value={form.note} onChange={v=>setForm(f=>({...f,note:v}))}/></F>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
            <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
            <Btn onClick={addCompte} disabled={!form.nom}>💾 Enregistrer</Btn>
          </div>
        </div>
      </Modal>}

      {/* ── MODALE TRANSACTION ── */}
      {showAddTx&&<Modal title="↔️ Nouvelle transaction" onClose={()=>setShowAddTx(false)} width={600}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Sens" style={{gridColumn:"1/-1"}}>
            <div style={{display:"flex",gap:8}}>
              {[{v:"debit",l:"💸 Dépense",c:T.danger},{v:"credit",l:"💰 Revenu",c:T.success}].map(s=>(
                <button key={s.v} onClick={()=>setFormTx(f=>({...f,sens:s.v}))} style={{flex:1,padding:"8px",borderRadius:8,border:`2px solid ${formTx.sens===s.v?s.c:T.border}`,background:formTx.sens===s.v?s.c+"22":"transparent",color:formTx.sens===s.v?s.c:T.muted,fontFamily:T.font,fontSize:13,fontWeight:600,cursor:"pointer"}}>{s.l}</button>
              ))}
            </div>
          </F>
          <F label="Libellé *"><Inp value={formTx.libelle} onChange={v=>setFormTx(f=>({...f,libelle:v}))} placeholder="Courses Leclerc, Salaire..."/></F>
          <F label="Montant (€) *"><Inp type="number" value={formTx.montant} onChange={v=>setFormTx(f=>({...f,montant:v}))} placeholder="0.00"/></F>
          <F label="Catégorie"><Sel value={formTx.categorie} onChange={v=>setFormTx(f=>({...f,categorie:v}))}>{CATS_TX.filter(c=>c.type==="both"||(formTx.sens==="debit"?c.type==="debit":c.type==="credit")).map(c=><option key={c.id} value={c.id}>{c.icon} {c.l}</option>)}</Sel></F>
          <F label="Compte"><Sel value={formTx.compteId} onChange={v=>setFormTx(f=>({...f,compteId:v}))}><option value="">— Aucun —</option>{comptes.map(c=><option key={c.id} value={c.id}>{c.nom}</option>)}</Sel></F>
          <F label="Date"><Inp type="date" value={formTx.date} onChange={v=>setFormTx(f=>({...f,date:v}))}/></F>
          <F label="Tags (virgule)" style={{gridColumn:"1/-1"}}><Inp value={formTx.tags} onChange={v=>setFormTx(f=>({...f,tags:v}))} placeholder="abonnement, récurrent..."/></F>
          <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={formTx.note} onChange={v=>setFormTx(f=>({...f,note:v}))}/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAddTx(false)}>Annuler</Btn>
          <Btn onClick={addTx} disabled={!formTx.libelle||!formTx.montant}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: ASSURANCES
// ═══════════════════════════════════════════════════════════════════════════════
const Assurances=({assurances,setAssurances})=>{
  const [showAdd,setShowAdd]=useState(false);
  const [selected,setSelected]=useState(null);
  const [form,setForm]=useState({nom:"",assureur:"",type:"habitation",numero:"",prime:"",dateDebut:"",dateEcheance:"",statut:"actif",note:""});
  const TYPES_ASS=[{v:"habitation",l:"Habitation",icon:"🏠"},{v:"auto",l:"Auto",icon:"🚗"},{v:"vie",l:"Vie",icon:"❤️"},{v:"sante",l:"Santé / Mutuelle",icon:"🏥"},{v:"pno",l:"PNO (Bailleur)",icon:"🏢"},{v:"prevoyance",l:"Prévoyance",icon:"🛡️"},{v:"autre",l:"Autre",icon:"📋"}];

  const save=()=>{setAssurances(p=>[...p,{...form,id:uid(),prime:parseFloat(form.prime)||0}]);setShowAdd(false);setForm({nom:"",assureur:"",type:"habitation",numero:"",prime:"",dateDebut:"",dateEcheance:"",statut:"actif",note:""});};
  const totalPrimes=assurances.filter(a=>a.statut==="actif").reduce((s,a)=>s+a.prime,0);
  const selItem=selected&&assurances.find(a=>a.id===selected);
  const selTypeInfo=selItem&&TYPES_ASS.find(t=>t.v===selItem.type);

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div><h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🛡️ Assurances</h1><p style={{color:T.muted,marginTop:3,fontSize:13}}>{assurances.filter(a=>a.statut==="actif").length} contrats actifs</p></div>
        <Btn onClick={()=>setShowAdd(true)}>+ Contrat</Btn>
      </div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(160px,1fr))",gap:12,marginBottom:20}}>
        <StatCard label="Contrats actifs" value={assurances.filter(a=>a.statut==="actif").length} icon="🛡️" color={T.warning}/>
        <StatCard label="Primes annuelles" value={fmtAmt(totalPrimes*12)} icon="💶" color={T.danger}/>
        <StatCard label="Primes mensuelles" value={fmtAmt(totalPrimes)} icon="📅" color={T.warning}/>
        <StatCard label="Expirent bientôt" value={assurances.filter(a=>a.statut==="actif"&&daysFrom(a.dateEcheance)!=null&&daysFrom(a.dateEcheance)<=30).length} icon="⚠️" color={T.danger}/>
      </div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(280px,1fr))",gap:12}}>
        {assurances.length===0&&<EmptyState icon="🛡️" text="Aucun contrat d'assurance enregistré."/>}
        {assurances.map(a=>{
          const typeInfo=TYPES_ASS.find(t=>t.v===a.type);
          const jEch=daysFrom(a.dateEcheance);
          return (
            <Card key={a.id} onClick={()=>setSelected(a.id)} style={{cursor:"pointer",borderColor:selected===a.id?T.accent:T.border}}>
              <div style={{display:"flex",justifyContent:"space-between",marginBottom:8,alignItems:"flex-start"}}>
                <div style={{display:"flex",gap:8,alignItems:"center"}}>
                  <span style={{fontSize:20}}>{typeInfo?.icon||"🛡️"}</span>
                  <div>
                    <div style={{fontWeight:700,color:T.text,fontSize:14}}>{a.nom}</div>
                    <div style={{fontSize:11,color:T.muted}}>{a.assureur}</div>
                  </div>
                </div>
                <Badge c={a.statut==="actif"?T.success:T.muted}>{a.statut}</Badge>
              </div>
              <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:6,marginBottom:8}}>
                <div style={{background:"#0a0e17",borderRadius:6,padding:"6px 8px"}}>
                  <div style={{fontSize:9,color:T.muted}}>PRIME/MOIS</div>
                  <div style={{fontSize:14,fontWeight:700,color:T.warning}}>{fmtAmt(a.prime)}</div>
                </div>
                <div style={{background:"#0a0e17",borderRadius:6,padding:"6px 8px"}}>
                  <div style={{fontSize:9,color:T.muted}}>ÉCHÉANCE</div>
                  <div style={{fontSize:12,fontWeight:600,color:jEch!=null&&jEch<=30?T.danger:T.text}}>{fmt(a.dateEcheance)||"—"}</div>
                </div>
              </div>
              {a.numero&&<div style={{fontSize:11,color:T.muted}}>N° {a.numero}</div>}
              {jEch!=null&&jEch<=30&&jEch>=0&&<Badge c={T.danger}>⚠️ Expire dans {jEch}j</Badge>}
              {(a.docs||[]).length>0&&<div style={{fontSize:10,color:T.accent,marginTop:6}}>📎 {a.docs.length} document(s)</div>}
            </Card>
          );
        })}
      </div>

      {selItem&&<FichePanel
        title={selItem.nom}
        icon={selTypeInfo?.icon||"🛡️"}
        badge={selItem.statut} badgeColor={selItem.statut==="actif"?T.success:T.muted}
        onClose={()=>setSelected(null)}
        onDelete={()=>{setAssurances(p=>p.filter(a=>a.id!==selItem.id));setSelected(null);}}
        docs={selItem.docs||[]} echanges={selItem.echanges||[]}
        onDocsChange={nd=>setAssurances(p=>p.map(a=>a.id===selItem.id?{...a,docs:nd}:a))}
        onEchangesChange={ne=>setAssurances(p=>p.map(a=>a.id===selItem.id?{...a,echanges:ne}:a))}
        docsLabel="Contrat, attestation, conditions générales..."
        leftContent={<div>
          <InfoRow label="Type de contrat" value={selTypeInfo?.l||selItem.type}/>
          <InfoRow label="Assureur" value={selItem.assureur}/>
          <InfoRow label="N° de contrat" value={selItem.numero} mono/>
          <InfoRow label="Prime mensuelle" value={fmtAmt(selItem.prime)} color={T.warning}/>
          <InfoRow label="Prime annuelle" value={fmtAmt(selItem.prime*12)} color={T.danger}/>
          <InfoRow label="Date de début" value={fmt(selItem.dateDebut)}/>
          <InfoRow label="Date d'échéance" value={fmt(selItem.dateEcheance)} color={daysFrom(selItem.dateEcheance)!=null&&daysFrom(selItem.dateEcheance)<=30?T.danger:T.text}/>
          <InfoRow label="Statut" value={selItem.statut}/>
          {selItem.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{selItem.note}</div>}
        </div>}
      />}

      {showAdd&&<Modal title="🛡️ Nouveau contrat" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gap:10}}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Nom du contrat"><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Assurance habitation Apt A"/></F>
            <F label="Assureur"><Inp value={form.assureur} onChange={v=>setForm(f=>({...f,assureur:v}))} placeholder="AXA, MAAF..."/></F>
            <F label="Type"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}>{TYPES_ASS.map(t=><option key={t.v} value={t.v}>{t.icon} {t.l}</option>)}</Sel></F>
            <F label="N° de contrat"><Inp value={form.numero} onChange={v=>setForm(f=>({...f,numero:v}))}/></F>
            <F label="Prime mensuelle (€)"><Inp type="number" value={form.prime} onChange={v=>setForm(f=>({...f,prime:v}))}/></F>
            <F label="Statut"><Sel value={form.statut} onChange={v=>setForm(f=>({...f,statut:v}))}><option value="actif">Actif</option><option value="résilié">Résilié</option></Sel></F>
            <F label="Date début"><Inp type="date" value={form.dateDebut} onChange={v=>setForm(f=>({...f,dateDebut:v}))}/></F>
            <F label="Date d'échéance"><Inp type="date" value={form.dateEcheance} onChange={v=>setForm(f=>({...f,dateEcheance:v}))}/></F>
          </div>
          <F label="Note"><Inp value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} placeholder="Garanties, franchise..."/></F>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
            <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
            <Btn onClick={save} disabled={!form.nom}>💾 Enregistrer</Btn>
          </div>
        </div>
      </Modal>}
    </div>
  );
};


// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: JURIDIQUE
// ═══════════════════════════════════════════════════════════════════════════════
const Juridique=({juridique,setJuridique})=>{
  const [tab,setTab]=useState("contrats");
  const [showAdd,setShowAdd]=useState(false);
  const [selected,setSelected]=useState(null);
  const [form,setForm]=useState({type:"contrats",titre:"",parties:"",dateSignature:"",dateFin:"",montant:"",statut:"en cours",note:""});

  const save=()=>{setJuridique(s=>({...s,[form.type]:[...(s[form.type]||[]),{...form,id:uid()}]}));setShowAdd(false);};
  const updDocs=(type,id,nd)=>setJuridique(s=>({...s,[type]:(s[type]||[]).map(x=>x.id===id?{...x,docs:nd}:x)}));
  const updEchanges=(type,id,ne)=>setJuridique(s=>({...s,[type]:(s[type]||[]).map(x=>x.id===id?{...x,echanges:ne}:x)}));
  const del=(type,id)=>{setJuridique(s=>({...s,[type]:(s[type]||[]).filter(x=>x.id!==id)}));setSelected(null);};
  const TABS=[{id:"contrats",icon:"📋",label:"Contrats"},{id:"procedures",icon:"⚖️",label:"Procédures"},{id:"correspondances",icon:"📬",label:"Correspondances"}];
  const tabIcons={contrats:"📋",procedures:"⚖️",correspondances:"📬"};
  const selItem=selected&&(juridique[selected.type]||[]).find(x=>x.id===selected.id);

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div><h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>⚖️ Juridique</h1><p style={{color:T.muted,marginTop:3,fontSize:13}}>Contrats · procédures · correspondances</p></div>
        <Btn onClick={()=>setShowAdd(true)}>+ Ajouter</Btn>
      </div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(160px,1fr))",gap:12,marginBottom:20}}>
        <StatCard label="Contrats" value={(juridique.contrats||[]).length} icon="📋" color={T.pink}/>
        <StatCard label="Procédures" value={(juridique.procedures||[]).filter(p=>p.statut==="en cours").length} icon="⚖️" color={T.danger}/>
        <StatCard label="Correspondances" value={(juridique.correspondances||[]).length} icon="📬" color={T.info}/>
      </div>
      <Tabs tabs={TABS} active={tab} onChange={setTab}/>
      <div style={{display:"grid",gap:10}}>
        {(juridique[tab]||[]).length===0&&<EmptyState icon="⚖️" text="Aucun élément juridique."/>}
        {(juridique[tab]||[]).map(item=>(
          <Card key={item.id} onClick={()=>setSelected({type:tab,id:item.id})} style={{padding:"12px 16px",cursor:"pointer"}}>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
              <div style={{flex:1}}>
                <div style={{fontWeight:600,color:T.text,marginBottom:3}}>{item.titre}</div>
                {item.parties&&<div style={{fontSize:12,color:T.muted}}>👥 {item.parties}</div>}
                {item.dateSignature&&<div style={{fontSize:12,color:T.muted}}>📅 {fmt(item.dateSignature)}{item.dateFin&&" → "+fmt(item.dateFin)}</div>}
                {(item.docs||[]).length>0&&<div style={{fontSize:10,color:T.accent,marginTop:3}}>📎 {item.docs.length} document(s)</div>}
              </div>
              <div style={{display:"flex",flexDirection:"column",gap:4,alignItems:"flex-end"}}>
                {item.montant&&<span style={{fontWeight:700,color:T.pink,fontSize:14}}>{fmtAmt(item.montant)}</span>}
                {item.statut&&<Badge c={item.statut==="terminé"?T.success:item.statut==="en cours"?T.warning:T.muted}>{item.statut}</Badge>}
              </div>
            </div>
          </Card>
        ))}
      </div>

      {selItem&&selected&&<FichePanel
        title={selItem.titre}
        icon={tabIcons[selected.type]||"⚖️"}
        badge={selItem.statut} badgeColor={selItem.statut==="terminé"?T.success:T.warning}
        onClose={()=>setSelected(null)}
        onDelete={()=>del(selected.type,selected.id)}
        docs={selItem.docs||[]} echanges={selItem.echanges||[]}
        onDocsChange={nd=>updDocs(selected.type,selected.id,nd)}
        onEchangesChange={ne=>updEchanges(selected.type,selected.id,ne)}
        docsLabel="Contrats signés, courriers, PV, jugements..."
        leftContent={<div>
          <InfoRow label="Titre / Objet" value={selItem.titre}/>
          <InfoRow label="Parties" value={selItem.parties}/>
          <InfoRow label="Date signature" value={fmt(selItem.dateSignature)}/>
          <InfoRow label="Date fin / échéance" value={fmt(selItem.dateFin)}/>
          <InfoRow label="Montant" value={selItem.montant&&fmtAmt(selItem.montant)} color={T.pink}/>
          <InfoRow label="Statut" value={selItem.statut}/>
          {selItem.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{selItem.note}</div>}
        </div>}
      />}

      {showAdd&&<Modal title="⚖️ Ajouter" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gap:10}}>
          <F label="Catégorie"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}><option value="contrats">Contrat</option><option value="procedures">Procédure</option><option value="correspondances">Correspondance</option></Sel></F>
          <F label="Titre / Objet"><Inp value={form.titre} onChange={v=>setForm(f=>({...f,titre:v}))} placeholder="Compromis, Divorce, Lettre recommandée..."/></F>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Parties"><Inp value={form.parties} onChange={v=>setForm(f=>({...f,parties:v}))} placeholder="Moi / Dupont SARL..."/></F>
            <F label="Montant (€)"><Inp type="number" value={form.montant} onChange={v=>setForm(f=>({...f,montant:v}))}/></F>
            <F label="Date signature"><Inp type="date" value={form.dateSignature} onChange={v=>setForm(f=>({...f,dateSignature:v}))}/></F>
            <F label="Date fin"><Inp type="date" value={form.dateFin} onChange={v=>setForm(f=>({...f,dateFin:v}))}/></F>
          </div>
          <F label="Statut"><Sel value={form.statut} onChange={v=>setForm(f=>({...f,statut:v}))}><option value="en cours">En cours</option><option value="terminé">Terminé</option><option value="suspendu">Suspendu</option></Sel></F>
          <F label="Note"><Txt value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} rows={2}/></F>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
            <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
            <Btn onClick={save} disabled={!form.titre}>💾 Enregistrer</Btn>
          </div>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: CONTACTS
// ═══════════════════════════════════════════════════════════════════════════════
const TYPES_CONTACT=[{v:"avocat",l:"Avocat",c:"#f87171"},{v:"banque",l:"Banque",c:"#38bdf8"},{v:"medecin",l:"Médecin",c:"#34d399"},{v:"notaire",l:"Notaire",c:"#a78bfa"},{v:"assurance",l:"Assurance",c:"#fbbf24"},{v:"comptable",l:"Comptable",c:"#fb923c"},{v:"autre",l:"Autre",c:"#94a3b8"}];
const Contacts=({contacts,setContacts})=>{
  const [selected,setSelected]=useState(null);
  const [showAdd,setShowAdd]=useState(false);
  const EMPTY_FORM={nom:"",type:"autre",email:"",tel:"",societe:"",rue:"",codePostal:"",ville:"",note:""};
  const [form,setForm]=useState({...EMPTY_FORM});

  const save=()=>{const tc=TYPES_CONTACT.find(t=>t.v===form.type);setContacts(p=>[...p,{...form,id:uid(),color:tc?.c||"#94a3b8"}]);setShowAdd(false);setForm({...EMPTY_FORM});};
  const selItem=selected&&contacts.find(c=>c.id===selected);
  const selTC=selItem&&TYPES_CONTACT.find(t=>t.v===selItem.type);

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div><h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>👥 Contacts</h1><p style={{color:T.muted,marginTop:3,fontSize:13}}>{contacts.length} contacts enregistrés</p></div>
        <Btn onClick={()=>setShowAdd(true)}>+ Contact</Btn>
      </div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(250px,1fr))",gap:12}}>
        {contacts.length===0&&<EmptyState icon="👥" text="Aucun contact."/>}
        {contacts.map(c=>{
          const tc=TYPES_CONTACT.find(t=>t.v===c.type);
          const adr=adresseFull(c);
          return (
            <Card key={c.id} onClick={()=>setSelected(c.id)} style={{cursor:"pointer",borderColor:selected===c.id?T.accent:T.border}}>
              <div style={{display:"flex",gap:10,alignItems:"flex-start"}}>
                <div style={{width:40,height:40,borderRadius:20,background:c.color+"33",display:"flex",alignItems:"center",justifyContent:"center",fontSize:16,fontWeight:700,color:c.color,flexShrink:0}}>{c.nom[0]}</div>
                <div style={{flex:1,minWidth:0}}>
                  <div style={{fontSize:14,fontWeight:700,color:T.text,marginBottom:2}}>{c.nom}</div>
                  {c.societe&&<div style={{fontSize:11,color:T.muted,marginBottom:4}}>{c.societe}</div>}
                  <Badge c={c.color}>{tc?.l||c.type}</Badge>
                  {c.tel&&<div style={{fontSize:11,color:T.muted,marginTop:4}}>📞 {c.tel}</div>}
                  {adr&&<div style={{fontSize:11,color:T.muted,marginTop:2}}>📍 {adr}</div>}
                  {(c.docs||[]).length>0&&<div style={{fontSize:10,color:T.accent,marginTop:4}}>📎 {c.docs.length} document(s)</div>}
                </div>
              </div>
            </Card>
          );
        })}
      </div>

      {selItem&&<FichePanel
        title={selItem.nom}
        icon="👤"
        badge={selTC?.l||selItem.type} badgeColor={selItem.color}
        onClose={()=>setSelected(null)}
        onDelete={()=>{setContacts(p=>p.filter(c=>c.id!==selItem.id));setSelected(null);}}
        docs={selItem.docs||[]} echanges={selItem.echanges||[]}
        onDocsChange={nd=>setContacts(p=>p.map(c=>c.id===selItem.id?{...c,docs:nd}:c))}
        onEchangesChange={ne=>setContacts(p=>p.map(c=>c.id===selItem.id?{...c,echanges:ne}:c))}
        docsLabel="Mandats, contrats, correspondances..."
        leftContent={<div>
          <InfoRow label="Nom" value={selItem.nom}/>
          <InfoRow label="Société" value={selItem.societe}/>
          <InfoRow label="Type" value={selTC?.l||selItem.type}/>
          <InfoRow label="Email" value={selItem.email}/>
          <InfoRow label="Téléphone" value={selItem.tel}/>
          <InfoRow label="Rue" value={selItem.rue||selItem.adresse}/>
          <InfoRow label="Code postal" value={selItem.codePostal}/>
          <InfoRow label="Ville" value={selItem.ville}/>
          {adresseFull(selItem)&&<InfoRow label="Adresse complète" value={adresseFull(selItem)}/>}
          {selItem.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{selItem.note}</div>}
          <ContactActions tel={selItem.tel} email={selItem.email} adresse={adresseFull(selItem)}/>
        </div>}
      />}

      {showAdd&&<Modal title="👤 Nouveau contact" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Nom *"><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Maître Dubois"/></F>
          <F label="Société"><Inp value={form.societe} onChange={v=>setForm(f=>({...f,societe:v}))} placeholder="Cabinet Dubois"/></F>
          <F label="Type"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}>{TYPES_CONTACT.map(t=><option key={t.v} value={t.v}>{t.l}</option>)}</Sel></F>
          <F label="Email"><Inp type="email" value={form.email} onChange={v=>setForm(f=>({...f,email:v}))}/></F>
          <F label="Téléphone"><Inp value={form.tel} onChange={v=>setForm(f=>({...f,tel:v}))}/></F>
        </div>
        <div style={{display:"grid",gridTemplateColumns:"1fr auto auto",gap:10,marginTop:4}}>
          <F label="Rue / N° et voie"><Inp value={form.rue} onChange={v=>setForm(f=>({...f,rue:v}))} placeholder="15 rue de la Justice"/></F>
          <F label="Code postal"><Inp value={form.codePostal} onChange={v=>setForm(f=>({...f,codePostal:v}))} placeholder="75001" style={{width:90}}/></F>
          <F label="Ville"><Inp value={form.ville} onChange={v=>setForm(f=>({...f,ville:v}))} placeholder="Paris"/></F>
        </div>
        <F label="Note"><Inp value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} placeholder="Spécialité, note..."/></F>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={save} disabled={!form.nom}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: ALERTES
// ═══════════════════════════════════════════════════════════════════════════════
const Alertes=({alertes,setAlertes})=>{
  const [showAdd,setShowAdd]=useState(false);
  const [form,setForm]=useState({titre:"",date:"",priorite:"moyenne",categorie:"autres",note:"",recurrence:"aucune"});
  const save=()=>{setAlertes(p=>[...p,{...form,id:uid(),fait:false}]);setShowAdd(false);setForm({titre:"",date:"",priorite:"moyenne",categorie:"autres",note:"",recurrence:"aucune"});};
  const sorted=[...alertes].sort((a,b)=>a.date.localeCompare(b.date));
  const actives=sorted.filter(a=>!a.fait);
  const faites=sorted.filter(a=>a.fait);

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🔔 Alertes & Rappels</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>{actives.length} en cours · {faites.length} terminées</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Alerte</Btn>
      </div>
      <div style={{display:"grid",gap:8}}>
        {actives.length===0&&<EmptyState icon="✅" text="Aucune alerte en cours. Bravo !"/>}
        {actives.map(a=>{
          const d=daysFrom(a.date);
          const color=d<0?T.danger:d<=7?T.warning:d<=30?T.info:T.success;
          const cat=CATS_DOC.find(c=>c.id===a.categorie);
          return (
            <Card key={a.id} style={{padding:"12px 16px"}}>
              <div style={{display:"flex",alignItems:"center",gap:12}}>
                <div style={{width:10,height:10,borderRadius:"50%",background:color,flexShrink:0}}/>
                <div style={{flex:1}}>
                  <div style={{fontSize:14,fontWeight:600,color:T.text,marginBottom:2}}>{a.titre}</div>
                  <div style={{fontSize:11,color:T.muted,display:"flex",gap:10}}>
                    <span>📅 {fmt(a.date)}</span>
                    {cat&&<span>{cat.icon} {cat.label}</span>}
                    {a.note&&<span>· {a.note}</span>}
                  </div>
                </div>
                <div style={{display:"flex",gap:6,alignItems:"center",flexWrap:"wrap"}}>
                  <Badge c={color}>{d<0?"Expiré":d===0?"Auj.":d+"j"}</Badge>
                  <Badge c={a.priorite==="haute"?T.danger:a.priorite==="moyenne"?T.warning:T.muted}>{a.priorite}</Badge>
                  <Btn sm v="success" onClick={()=>setAlertes(p=>p.map(x=>x.id===a.id?{...x,fait:true}:x))}>✓</Btn>
                  <Btn sm v="danger" onClick={()=>setAlertes(p=>p.filter(x=>x.id!==a.id))}>🗑</Btn>
                </div>
              </div>
            </Card>
          );
        })}
        {faites.length>0&&<div style={{marginTop:16,fontSize:12,color:T.muted,fontWeight:600,paddingBottom:6,borderBottom:`1px solid ${T.border}`}}>✅ Terminées ({faites.length})</div>}
        {faites.slice(-3).map(a=>(
          <Card key={a.id} style={{padding:"10px 16px",opacity:0.5}}>
            <div style={{display:"flex",alignItems:"center",gap:10}}>
              <span style={{fontSize:14}}>✅</span>
              <div style={{flex:1,fontSize:13,color:T.muted,textDecoration:"line-through"}}>{a.titre}</div>
              <Btn sm v="ghost" onClick={()=>setAlertes(p=>p.map(x=>x.id===a.id?{...x,fait:false}:x))}>↩</Btn>
            </div>
          </Card>
        ))}
      </div>
      {showAdd&&<Modal title="🔔 Nouvelle alerte" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gap:10}}>
          <F label="Titre *"><Inp value={form.titre} onChange={v=>setForm(f=>({...f,titre:v}))} placeholder="Ex: Déclaration impôts, Renouvellement bail..."/></F>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Date"><Inp type="date" value={form.date} onChange={v=>setForm(f=>({...f,date:v}))}/></F>
            <F label="Priorité"><Sel value={form.priorite} onChange={v=>setForm(f=>({...f,priorite:v}))}><option value="basse">Basse</option><option value="moyenne">Moyenne</option><option value="haute">Haute</option></Sel></F>
            <F label="Catégorie"><Sel value={form.categorie} onChange={v=>setForm(f=>({...f,categorie:v}))}>{CATS_DOC.map(c=><option key={c.id} value={c.id}>{c.icon} {c.label}</option>)}</Sel></F>
            <F label="Récurrence"><Sel value={form.recurrence} onChange={v=>setForm(f=>({...f,recurrence:v}))}><option value="aucune">Aucune</option><option value="mensuelle">Mensuelle</option><option value="annuelle">Annuelle</option></Sel></F>
          </div>
          <F label="Note"><Inp value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} placeholder="Détails..."/></F>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
            <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
            <Btn onClick={save} disabled={!form.titre||!form.date}>💾 Enregistrer</Btn>
          </div>
        </div>
      </Modal>}
    </div>
  );
};


// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: MES MAISONS (principale + secondaire)
// ═══════════════════════════════════════════════════════════════════════════════
const PIECES_MAISON=["Entrée","Salon","Cuisine","Chambre principale","Chambre 2","Chambre 3","Salle de bain","WC","Bureau","Cave","Garage","Jardin","Terrasse","Grenier"];
const TYPES_TRAVAUX=["Peinture","Plomberie","Électricité","Menuiserie","Toiture","Isolation","Chauffage","Cuisine","Salle de bain","Jardinage","Autre"];

// Abonnement categories with icons and colors
const ABONNEMENT_CATS=[
  {id:"electricite",label:"Électricité",icon:"⚡",color:"#fbbf24"},
  {id:"gaz",label:"Gaz",icon:"🔥",color:"#fb923c"},
  {id:"eau",label:"Eau",icon:"💧",color:"#38bdf8"},
  {id:"internet",label:"Internet",icon:"📡",color:"#818cf8"},
  {id:"telephone",label:"Téléphone fixe",icon:"☎️",color:"#a78bfa"},
  {id:"streaming",label:"Streaming",icon:"📺",color:"#ec4899"},
  {id:"alarme",label:"Alarme / Sécurité",icon:"🔒",color:"#ef4444"},
  {id:"entretien",label:"Contrat entretien",icon:"🔧",color:"#34d399"},
  {id:"ordures",label:"Ordures ménagères",icon:"🗑️",color:"#6b7a99"},
  {id:"copropriete",label:"Charges copropriété",icon:"🏢",color:"#60a5fa"},
  {id:"autre",label:"Autre",icon:"📋",color:"#9ca3af"},
];

const MaisonDetail=({maison,onUpdate,onClose,assurances=[],impots={},setPage})=>{
  const [tab,setTab]=useState("resume");
  const [showAddAbonnement,setShowAddAbonnement]=useState(false);
  const [showAddTravaux,setShowAddTravaux]=useState(false);
  const [showAddEquip,setShowAddEquip]=useState(false);
  const [selectedAbo,setSelectedAbo]=useState(null);
  const [selectedTravail,setSelectedTravail]=useState(null);
  const [selectedEquip,setSelectedEquip]=useState(null);
  const [selectedAssurMaison,setSelectedAssurMaison]=useState(null);
  const [selectedFiscalMaison,setSelectedFiscalMaison]=useState(null);
  const [formAbo,setFormAbo]=useState({categorie:"electricite",fournisseur:"",reference:"",montantMensuel:"",dateDebut:"",dateEcheance:"",prelevement:"mensuel",iban:"",note:"",statut:"actif"});
  const [formT,setFormT]=useState({titre:"",type:"Peinture",date:today(),cout:"",artisan:"",statut:"terminé",note:"",garantie:""});
  const [formE,setFormE]=useState({nom:"",piece:"Salon",marque:"",modele:"",dateAchat:"",garantieJusqu:"",cout:"",note:""});
  const fileRef=useRef();

  const TABS=[
    {id:"resume",icon:"📋",label:"Résumé"},
    {id:"abonnements",icon:"💡",label:"Abonnements"},
    {id:"assurances",icon:"🛡️",label:"Assurances"},
    {id:"fiscal",icon:"🏛️",label:"Fiscal"},
    {id:"travaux",icon:"🔨",label:"Travaux"},
    {id:"equipements",icon:"⚙️",label:"Équipements"},
    {id:"energie",icon:"⚡",label:"Énergie"},
    {id:"pieces",icon:"🚪",label:"Pièces"},
    {id:"docs",icon:"📄",label:"Documents"},
    {id:"infos",icon:"ℹ️",label:"Infos"},
  ];
  const totalTravaux=(maison.travaux||[]).reduce((s,t)=>s+(parseFloat(t.cout)||0),0);
  const totalEquip=(maison.equipements||[]).reduce((s,e)=>s+(parseFloat(e.cout)||0),0);
  const abonnements=maison.abonnements||[];
  const totalAboMensuel=abonnements.filter(a=>a.statut==="actif").reduce((s,a)=>{
    const m=parseFloat(a.montantMensuel)||0;
    return s+(a.prelevement==="annuel"?m/12:a.prelevement==="trimestriel"?m/3:m);
  },0);
  // Passerelle assurances — filtre par nom/type lié à cette maison
  const assurancesLiees=assurances.filter(a=>
    a.type==="habitation"||a.type==="pno"||a.type==="mre"||
    (a.nom||"").toLowerCase().includes((maison.nom||"").toLowerCase().slice(0,6))||
    (a.note||"").toLowerCase().includes("maison")||(a.note||"").toLowerCase().includes("résidence")
  );
  // Passerelle impôts — taxe foncière + taxe d'habitation
  const impotsMaison=[...(impots.paiements||[]),...(impots.avis||[])].filter(i=>
    (i.titre||"").toLowerCase().includes("foncière")||
    (i.titre||"").toLowerCase().includes("habitation")||
    (i.note||"").toLowerCase().includes("maison")||
    (i.note||"").toLowerCase().includes((maison.adresse||"").slice(0,10).toLowerCase())
  );

  return (
    <div style={{position:"fixed",inset:0,background:T.bg,zIndex:1500,display:"flex",flexDirection:"column",overflow:"hidden"}}>
      <FontLink/>
      <div style={{background:T.sidebar,borderBottom:`1px solid ${T.border}`,padding:"12px 22px",display:"flex",alignItems:"center",gap:14,flexShrink:0}}>
        <Btn v="outline" sm onClick={onClose}>← Retour</Btn>
        <div style={{flex:1}}>
          <div style={{fontFamily:T.fontD,fontSize:19,color:T.text}}>{maison.icon} {maison.nom}</div>
          <div style={{fontSize:11,color:T.muted}}>📍 {maison.adresse} · {maison.surface}m² · DPE {maison.dpe}</div>
        </div>
        <div style={{display:"flex",gap:16}}>
          <div style={{textAlign:"right"}}>
            <div style={{fontSize:10,color:T.muted}}>Charges/mois</div>
            <div style={{fontSize:16,fontWeight:700,color:T.info}}>{fmtAmt(totalAboMensuel)}</div>
          </div>
          <div style={{textAlign:"right"}}>
            <div style={{fontSize:10,color:T.muted}}>Travaux total</div>
            <div style={{fontSize:16,fontWeight:700,color:T.warning}}>{fmtAmt(totalTravaux)}</div>
          </div>
          <div style={{textAlign:"right"}}>
            <div style={{fontSize:10,color:T.muted}}>Valeur estimée</div>
            <div style={{fontSize:16,fontWeight:700,color:T.success}}>{maison.valeur?fmtAmt(maison.valeur):"—"}</div>
          </div>
        </div>
      </div>
      <div style={{flex:1,overflow:"auto",padding:"18px 22px"}}>
        <Tabs tabs={TABS} active={tab} onChange={setTab}/>


        {/* ── RÉSUMÉ ── */}
        {tab==="resume"&&(
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:14}}>
            {/* Charges mensuelles */}
            <Card style={{gridColumn:"1/-1",padding:0,overflow:"hidden"}}>
              <div style={{background:"linear-gradient(135deg,#0f172a,#1e2840)",padding:"16px 20px",borderBottom:`1px solid ${T.border}`}}>
                <div style={{fontWeight:700,color:T.text,fontSize:15,marginBottom:2}}>💰 Budget mensuel de la maison</div>
                <div style={{fontSize:11,color:T.muted}}>Charges récurrentes · abonnements actifs</div>
              </div>
              <div style={{padding:"14px 20px"}}>
                <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(180px,1fr))",gap:10}}>
                  {ABONNEMENT_CATS.map(cat=>{
                    const catAbos=abonnements.filter(a=>a.categorie===cat.id&&a.statut==="actif");
                    if(catAbos.length===0)return null;
                    const total=catAbos.reduce((s,a)=>{const m=parseFloat(a.montantMensuel)||0;return s+(a.prelevement==="annuel"?m/12:a.prelevement==="trimestriel"?m/3:m);},0);
                    return (
                      <div key={cat.id} style={{background:"#0a0e17",borderRadius:8,padding:"10px 12px",display:"flex",alignItems:"center",gap:10,cursor:"pointer"}} onClick={()=>setTab("abonnements")}>
                        <span style={{fontSize:20}}>{cat.icon}</span>
                        <div style={{flex:1}}>
                          <div style={{fontSize:12,color:T.muted}}>{cat.label}</div>
                          <div style={{fontSize:14,fontWeight:700,color:cat.color}}>{fmtAmt(total)}<span style={{fontSize:10,color:T.muted}}>/mois</span></div>
                        </div>
                      </div>
                    );
                  }).filter(Boolean)}
                  {abonnements.filter(a=>a.statut==="actif").length===0&&(
                    <div style={{color:T.muted,fontSize:13,padding:8,gridColumn:"1/-1"}}>
                      Aucun abonnement. <button onClick={()=>setTab("abonnements")} style={{color:T.accent,background:"none",border:"none",cursor:"pointer",fontFamily:T.font,fontSize:13}}>→ Ajouter vos charges</button>
                    </div>
                  )}
                </div>
                {abonnements.filter(a=>a.statut==="actif").length>0&&(
                  <div style={{marginTop:12,paddingTop:12,borderTop:`1px solid ${T.border}`,display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                    <span style={{color:T.muted,fontSize:13}}>Total mensuel</span>
                    <span style={{fontSize:22,fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{fmtAmt(totalAboMensuel)}<span style={{fontSize:12,color:T.muted,fontWeight:400}}>/mois = {fmtAmt(totalAboMensuel*12)}/an</span></span>
                  </div>
                )}
              </div>
            </Card>
            {/* Passerelle assurances */}
            <Card style={{padding:0,overflow:"hidden"}}>
              <div style={{padding:"12px 16px",background:"rgba(239,68,68,0.08)",borderBottom:`1px solid ${T.border}`,display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                <div style={{fontWeight:600,color:T.text,fontSize:14}}>🛡️ Assurances liées</div>
                <Badge c={T.danger}>{assurancesLiees.length}</Badge>
              </div>
              <div style={{padding:14}}>
                {assurancesLiees.length===0&&<div style={{color:T.muted,fontSize:12}}>Aucune assurance détectée. <button onClick={()=>setTab("assurances")} style={{color:T.accent,background:"none",border:"none",cursor:"pointer",fontFamily:T.font,fontSize:12}}>→ Lier une assurance</button></div>}
                {assurancesLiees.map(a=>{
                  const j=daysFrom(a.dateEcheance);
                  return <div key={a.id} style={{padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:12}}>
                    <div style={{fontWeight:600,color:T.text}}>{a.nom}</div>
                    <div style={{color:T.muted}}>{a.assureur} · {fmtAmt(a.prime)}/mois</div>
                    {j!=null&&<Badge c={j<=30?T.danger:j<=90?T.warning:T.success}>Échéance: {j<=0?"Expirée":j+"j"}</Badge>}
                  </div>;
                })}
                <button onClick={()=>setTab("assurances")} style={{marginTop:8,fontSize:11,color:T.accent,background:"none",border:"none",cursor:"pointer",fontFamily:T.font}}>→ Voir tout</button>
              </div>
            </Card>
            {/* Passerelle fiscal */}
            <Card style={{padding:0,overflow:"hidden"}}>
              <div style={{padding:"12px 16px",background:"rgba(167,139,250,0.08)",borderBottom:`1px solid ${T.border}`,display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                <div style={{fontWeight:600,color:T.text,fontSize:14}}>🏛️ Fiscal & Impôts</div>
                <Badge c={T.purple}>{impotsMaison.length}</Badge>
              </div>
              <div style={{padding:14}}>
                {impotsMaison.length===0&&<div style={{color:T.muted,fontSize:12}}>Taxe foncière non renseignée. <button onClick={()=>setTab("fiscal")} style={{color:T.accent,background:"none",border:"none",cursor:"pointer",fontFamily:T.font,fontSize:12}}>→ Voir</button></div>}
                {impotsMaison.map(i=>(
                  <div key={i.id} style={{padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:12}}>
                    <div style={{fontWeight:600,color:T.text}}>{i.titre}</div>
                    <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginTop:2}}>
                      <span style={{color:T.muted}}>{i.annee||""}</span>
                      {i.montant&&<span style={{color:T.accent,fontWeight:700}}>{fmtAmt(i.montant)}</span>}
                    </div>
                    {i.dateEcheance&&<Badge c={daysFrom(i.dateEcheance)<=30?T.warning:T.muted}>Échéance: {fmt(i.dateEcheance)}</Badge>}
                  </div>
                ))}
                <button onClick={()=>setTab("fiscal")} style={{marginTop:8,fontSize:11,color:T.accent,background:"none",border:"none",cursor:"pointer",fontFamily:T.font}}>→ Voir tout</button>
              </div>
            </Card>
            {/* Travaux récents */}
            <Card>
              <Divider label="🔨 Travaux récents"/>
              {(maison.travaux||[]).length===0&&<div style={{color:T.muted,fontSize:12}}>Aucun travail.</div>}
              {[...(maison.travaux||[])].sort((a,b)=>b.date.localeCompare(a.date)).slice(0,3).map(t=>(
                <div key={t.id} style={{padding:"6px 0",borderBottom:`1px solid ${T.border}`,fontSize:12}}>
                  <div style={{fontWeight:600,color:T.text}}>{t.titre}</div>
                  <div style={{display:"flex",justifyContent:"space-between"}}><span style={{color:T.muted}}>{fmt(t.date)}</span><span style={{color:T.accent,fontWeight:700}}>{t.cout&&fmtAmt(t.cout)}</span></div>
                </div>
              ))}
              <button onClick={()=>setTab("travaux")} style={{marginTop:8,fontSize:11,color:T.accent,background:"none",border:"none",cursor:"pointer",fontFamily:T.font}}>→ Tous les travaux · {fmtAmt(totalTravaux)} total</button>
            </Card>
          </div>
        )}

        {/* ── ABONNEMENTS ── */}
        {tab==="abonnements"&&(
          <div>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:16}}>
              <div>
                <div style={{fontWeight:700,color:T.text,fontSize:16}}>Abonnements & Charges récurrentes</div>
                <div style={{fontSize:12,color:T.muted,marginTop:2}}>Total : <strong style={{color:T.accent}}>{fmtAmt(totalAboMensuel)}/mois</strong> · {fmtAmt(totalAboMensuel*12)}/an</div>
              </div>
              <Btn onClick={()=>setShowAddAbonnement(true)}>+ Abonnement</Btn>
            </div>
            {/* Barre catégories */}
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(130px,1fr))",gap:8,marginBottom:20}}>
              {ABONNEMENT_CATS.map(cat=>{
                const catAbos=abonnements.filter(a=>a.categorie===cat.id&&a.statut==="actif");
                if(catAbos.length===0)return null;
                const total=catAbos.reduce((s,a)=>{const m=parseFloat(a.montantMensuel)||0;return s+(a.prelevement==="annuel"?m/12:a.prelevement==="trimestriel"?m/3:m);},0);
                return (
                  <div key={cat.id} style={{background:"#0a0e17",borderRadius:8,padding:"10px 12px",textAlign:"center",border:`1px solid ${cat.color}33`}}>
                    <div style={{fontSize:22,marginBottom:3}}>{cat.icon}</div>
                    <div style={{fontSize:10,color:T.muted,marginBottom:2}}>{cat.label}</div>
                    <div style={{fontSize:14,fontWeight:700,color:cat.color}}>{fmtAmt(total)}</div>
                    <div style={{fontSize:9,color:T.muted}}>/mois</div>
                  </div>
                );
              }).filter(Boolean)}
            </div>
            {abonnements.length===0&&<EmptyState icon="💡" text="Ajoutez vos abonnements : électricité, eau, gaz, internet, streaming, alarme..."/>}
            <div style={{display:"grid",gap:10}}>
              {[...(abonnements)].sort((a,b)=>{
                const mo={electricite:0,gaz:1,eau:2,internet:3,telephone:4,streaming:5,alarme:6,entretien:7,ordures:8,copropriete:9,autre:10};
                return (mo[a.categorie]||99)-(mo[b.categorie]||99);
              }).map(abo=>{
                const cat=ABONNEMENT_CATS.find(c=>c.id===abo.categorie)||ABONNEMENT_CATS[ABONNEMENT_CATS.length-1];
                const j=daysFrom(abo.dateEcheance);
                const mensuel=parseFloat(abo.montantMensuel)||0;
                const mensuelNorm=abo.prelevement==="annuel"?mensuel/12:abo.prelevement==="trimestriel"?mensuel/3:mensuel;
                return (
                  <Card key={abo.id} onClick={()=>setSelectedAbo(abo.id)} style={{padding:"12px 16px",cursor:"pointer",borderColor:selectedAbo===abo.id?T.accent:T.border}}>
                    <div style={{display:"flex",alignItems:"center",gap:12}}>
                      <div style={{width:42,height:42,borderRadius:10,background:cat.color+"22",border:`1px solid ${cat.color}44`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:20,flexShrink:0}}>{cat.icon}</div>
                      <div style={{flex:1,minWidth:0}}>
                        <div style={{display:"flex",alignItems:"center",gap:8,marginBottom:2}}>
                          <span style={{fontWeight:700,color:T.text,fontSize:14}}>{abo.fournisseur||cat.label}</span>
                          <Badge c={abo.statut==="actif"?T.success:T.muted}>{abo.statut}</Badge>
                          {(abo.docs||[]).length>0&&<Badge c={T.accent}>📎 {abo.docs.length}</Badge>}
                        </div>
                        <div style={{fontSize:11,color:T.muted}}>
                          {cat.label}{abo.reference&&" · Réf: "+abo.reference}
                          {abo.iban&&" · 🏦 Prélèvement auto"}
                        </div>
                        {abo.dateEcheance&&<div style={{marginTop:3}}><Badge c={j!=null&&j<=30?T.warning:T.muted}>Échéance: {fmt(abo.dateEcheance)}{j!=null&&j<=90?" ("+j+"j)":""}</Badge></div>}
                      </div>
                      <div style={{textAlign:"right",flexShrink:0}}>
                        <div style={{fontSize:18,fontWeight:700,color:cat.color,fontFamily:T.fontD}}>{fmtAmt(mensuelNorm)}<span style={{fontSize:10,color:T.muted,fontWeight:400}}>/mois</span></div>
                        {abo.prelevement!=="mensuel"&&<div style={{fontSize:11,color:T.muted}}>{fmtAmt(mensuel)}/{abo.prelevement==="annuel"?"an":"trim."}</div>}
                        <div style={{fontSize:11,color:T.muted,marginTop:2}}>= {fmtAmt(mensuelNorm*12)}/an</div>
                      </div>
                    </div>
                  </Card>
                );
              })}
            </div>
          </div>
        )}

        {/* ── FichePanel ABONNEMENT ── */}
        {selectedAbo&&(()=>{
          const abo=abonnements.find(a=>a.id===selectedAbo);
          if(!abo)return null;
          const cat=ABONNEMENT_CATS.find(c=>c.id===abo.categorie)||ABONNEMENT_CATS[ABONNEMENT_CATS.length-1];
          const mensuel=parseFloat(abo.montantMensuel)||0;
          const mensuelNorm=abo.prelevement==="annuel"?mensuel/12:abo.prelevement==="trimestriel"?mensuel/3:mensuel;
          const j=daysFrom(abo.dateEcheance);
          return <FichePanel
            title={abo.fournisseur||cat.label}
            icon={cat.icon}
            badge={abo.statut} badgeColor={abo.statut==="actif"?T.success:T.muted}
            onClose={()=>setSelectedAbo(null)}
            onDelete={()=>{onUpdate({...maison,abonnements:(maison.abonnements||[]).filter(a=>a.id!==abo.id)});setSelectedAbo(null);}}
            docs={abo.docs||[]} echanges={abo.echanges||[]}
            onDocsChange={nd=>onUpdate({...maison,abonnements:(maison.abonnements||[]).map(a=>a.id===abo.id?{...a,docs:nd}:a)})}
            onEchangesChange={ne=>onUpdate({...maison,abonnements:(maison.abonnements||[]).map(a=>a.id===abo.id?{...a,echanges:ne}:a)})}
            docsLabel="Factures, contrat, CGV..."
            leftContent={<div>
              <InfoRow label="Catégorie" value={cat.label}/>
              <InfoRow label="Fournisseur" value={abo.fournisseur}/>
              <InfoRow label="Référence contrat" value={abo.reference} mono/>
              <InfoRow label="Montant" value={`${fmtAmt(mensuel)} / ${abo.prelevement}`} color={cat.color}/>
              <InfoRow label="Équivalent mensuel" value={fmtAmt(mensuelNorm)} color={cat.color}/>
              <InfoRow label="Coût annuel" value={fmtAmt(mensuelNorm*12)} color={T.warning}/>
              <InfoRow label="Prélèvement auto" value={abo.iban||"Non renseigné"} mono/>
              <InfoRow label="Date début" value={fmt(abo.dateDebut)}/>
              <InfoRow label="Échéance" value={fmt(abo.dateEcheance)} color={j!=null&&j<=30?T.danger:T.text}/>
              <InfoRow label="Statut" value={abo.statut}/>
              {abo.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{abo.note}</div>}
            </div>}
          />;
        })()}

        {/* ── ASSURANCES (passerelle) ── */}
        {tab==="assurances"&&(
          <div>
            <div style={{marginBottom:16}}>
              <div style={{fontWeight:700,color:T.text,fontSize:16,marginBottom:4}}>🛡️ Assurances de cette maison</div>
              <div style={{fontSize:12,color:T.muted}}>Données issues du module Assurances · <button onClick={()=>setPage&&setPage("assurances")} style={{color:T.accent,background:"none",border:"none",cursor:"pointer",fontFamily:T.font,fontSize:12}}>→ Ouvrir le module Assurances</button></div>
            </div>
            {assurancesLiees.length===0&&(
              <div style={{background:"rgba(240,165,0,0.06)",border:`1px dashed ${T.accent}`,borderRadius:12,padding:24,textAlign:"center"}}>
                <div style={{fontSize:32,marginBottom:8}}>🛡️</div>
                <div style={{color:T.text,fontWeight:600,marginBottom:4}}>Aucune assurance liée</div>
                <div style={{color:T.muted,fontSize:13,marginBottom:12}}>Les assurances de type Habitation / MRE / PNO associées à "{maison.nom}" apparaîtront automatiquement ici.</div>
                <Btn onClick={()=>setPage&&setPage("assurances")}>→ Aller dans Assurances</Btn>
              </div>
            )}
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(300px,1fr))",gap:14}}>
              {assurancesLiees.map(a=>{
                const j=daysFrom(a.dateEcheance);
                return (
                  <Card key={a.id} onClick={()=>setSelectedAssurMaison(a.id)} style={{cursor:"pointer",borderColor:selectedAssurMaison===a.id?T.accent:j!=null&&j<=30?T.danger:T.border}}>
                    <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:8}}>
                      <div>
                        <div style={{fontWeight:700,color:T.text,fontSize:14}}>{a.nom}</div>
                        <div style={{fontSize:12,color:T.muted}}>{a.assureur}{a.numero&&" · N°"+a.numero}</div>
                      </div>
                      <div style={{textAlign:"right"}}>
                        <div style={{fontSize:18,fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{fmtAmt(a.prime)}<span style={{fontSize:11,fontWeight:400,color:T.muted}}>/mois</span></div>
                        <Badge c={a.statut==="actif"?T.success:T.muted}>{a.statut}</Badge>
                      </div>
                    </div>
                    <div style={{display:"flex",justifyContent:"space-between",fontSize:12,color:T.muted}}>
                      <span>Début: {fmt(a.dateDebut)}</span>
                      <Badge c={j!=null&&j<=0?T.danger:j!=null&&j<=90?T.warning:T.muted}>Échéance: {fmt(a.dateEcheance)}{j!=null&&j>=0?" ("+j+"j)":j!=null?" (expirée)":""}</Badge>
                    </div>
                    {(a.docs||[]).length>0&&<div style={{marginTop:6}}><Badge c={T.accent}>📎 {a.docs.length} document(s)</Badge></div>}
                  </Card>
                );
              })}
            </div>
            {selectedAssurMaison&&(()=>{
              const a=assurancesLiees.find(x=>x.id===selectedAssurMaison);
              if(!a)return null;
              const j=daysFrom(a.dateEcheance);
              return <FichePanel
                title={a.nom} icon="🛡️"
                badge={a.statut} badgeColor={a.statut==="actif"?T.success:T.muted}
                onClose={()=>setSelectedAssurMaison(null)}
                docs={a.docs||[]} echanges={a.echanges||[]}
                onDocsChange={()=>{}}
                docsLabel="Contrat, attestation, conditions générales..."
                leftContent={<div>
                  <div style={{padding:"10px 12px",background:"rgba(240,165,0,0.07)",borderRadius:8,marginBottom:14,fontSize:12,color:T.accent}}>💡 Pour modifier cette assurance, ouvrez le module Assurances.</div>
                  <InfoRow label="Assureur" value={a.assureur}/>
                  <InfoRow label="N° contrat" value={a.numero} mono/>
                  <InfoRow label="Type" value={a.type}/>
                  <InfoRow label="Prime mensuelle" value={fmtAmt(a.prime)} color={T.accent}/>
                  <InfoRow label="Prime annuelle" value={fmtAmt((a.prime||0)*12)} color={T.warning}/>
                  <InfoRow label="Date début" value={fmt(a.dateDebut)}/>
                  <InfoRow label="Échéance" value={fmt(a.dateEcheance)} color={j!=null&&j<=30?T.danger:T.text}/>
                  <InfoRow label="Statut" value={a.statut}/>
                  {j!=null&&j<=90&&j>=0&&<div style={{marginTop:12,padding:10,background:"rgba(251,146,60,0.1)",borderRadius:8,fontSize:12,color:T.warning}}>⚠️ Renouvellement dans {j} jours</div>}
                  {a.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{a.note}</div>}
                </div>}
              />;
            })()}
            <div style={{marginTop:20,background:`${T.card}`,border:`1px solid ${T.border}`,borderRadius:12,padding:16}}>
              <div style={{fontWeight:600,color:T.text,marginBottom:6,fontSize:13}}>💡 Comment lier une assurance ?</div>
              <div style={{fontSize:12,color:T.muted,lineHeight:1.7}}>Dans le module <strong style={{color:T.text}}>Assurances</strong>, créez ou modifiez une assurance en choisissant le type <em>Habitation / MRE</em> et mentionnez "{maison.nom}" dans le nom ou la note. Elle apparaîtra automatiquement ici.</div>
            </div>
          </div>
        )}

        {/* ── FISCAL (passerelle) ── */}
        {tab==="fiscal"&&(
          <div>
            <div style={{marginBottom:16}}>
              <div style={{fontWeight:700,color:T.text,fontSize:16,marginBottom:4}}>🏛️ Taxes & Impôts liés</div>
              <div style={{fontSize:12,color:T.muted}}>Données issues du module Impôts · <button onClick={()=>setPage&&setPage("impots")} style={{color:T.accent,background:"none",border:"none",cursor:"pointer",fontFamily:T.font,fontSize:12}}>→ Ouvrir le module Impôts</button></div>
            </div>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14,marginBottom:20}}>
              {[{l:"Taxe foncière",icon:"🏠",cat:"foncière"},{l:"Taxe d'habitation",icon:"🏡",cat:"habitation"}].map(tx=>{
                const items=[...(impots.paiements||[]),...(impots.avis||[])].filter(i=>(i.titre||"").toLowerCase().includes(tx.cat));
                const dernierMontant=items[0]?.montant;
                return (
                  <Card key={tx.cat} style={{padding:16,borderLeft:`3px solid ${T.purple}`}}>
                    <div style={{fontSize:28,marginBottom:6}}>{tx.icon}</div>
                    <div style={{fontWeight:700,color:T.text,fontSize:14,marginBottom:4}}>{tx.l}</div>
                    {dernierMontant?<div style={{fontSize:22,fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{fmtAmt(dernierMontant)}</div>:<div style={{color:T.muted,fontSize:13}}>Non renseigné</div>}
                    {items[0]?.dateEcheance&&<div style={{marginTop:6}}><Badge c={daysFrom(items[0].dateEcheance)<=30?T.warning:T.muted}>Échéance: {fmt(items[0].dateEcheance)}</Badge></div>}
                    {items[0]?.statut&&<div style={{marginTop:4}}><Badge c={items[0].statut==="payé"?T.success:T.warning}>{items[0].statut}</Badge></div>}
                  </Card>
                );
              })}
            </div>
            {impotsMaison.length===0&&(
              <div style={{background:"rgba(167,139,250,0.06)",border:`1px dashed ${T.purple}`,borderRadius:12,padding:24,textAlign:"center"}}>
                <div style={{fontSize:32,marginBottom:8}}>🏛️</div>
                <div style={{color:T.text,fontWeight:600,marginBottom:4}}>Aucune donnée fiscale trouvée</div>
                <div style={{color:T.muted,fontSize:13,marginBottom:12}}>Ajoutez vos taxes foncières et d'habitation dans le module Impôts avec le mot-clé "foncière" ou "habitation" dans le titre.</div>
                <Btn onClick={()=>setPage&&setPage("impots")}>→ Aller dans Mes Impôts</Btn>
              </div>
            )}
            {impotsMaison.length>0&&(
              <Card>
                <Divider label="Historique fiscal — cliquez pour voir le détail"/>
                {impotsMaison.map(i=>(
                  <div key={i.id} onClick={()=>setSelectedFiscalMaison(i.id)} style={{display:"flex",justifyContent:"space-between",padding:"10px 8px",borderBottom:`1px solid ${T.border}`,fontSize:13,alignItems:"center",cursor:"pointer",borderRadius:6,background:selectedFiscalMaison===i.id?T.accentDim:"transparent"}}>
                    <div>
                      <div style={{fontWeight:600,color:T.text}}>{i.titre}</div>
                      <div style={{fontSize:11,color:T.muted}}>{i.annee||""}{i.dateEcheance&&" · Échéance: "+fmt(i.dateEcheance)}</div>
                    </div>
                    <div style={{textAlign:"right",display:"flex",flexDirection:"column",gap:3,alignItems:"flex-end"}}>
                      {i.montant&&<div style={{fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{fmtAmt(i.montant)}</div>}
                      {i.statut&&<Badge c={i.statut==="payé"?T.success:T.warning}>{i.statut}</Badge>}
                      {(i.docs||[]).length>0&&<Badge c={T.accent}>📎 {i.docs.length}</Badge>}
                    </div>
                  </div>
                ))}
              </Card>
            )}
            {selectedFiscalMaison&&(()=>{
              const i=impotsMaison.find(x=>x.id===selectedFiscalMaison);
              if(!i)return null;
              const j=daysFrom(i.dateEcheance);
              return <FichePanel
                title={i.titre||i.annee||"Fiche fiscale"} icon="🏛️"
                badge={i.statut} badgeColor={i.statut==="payé"?T.success:T.warning}
                onClose={()=>setSelectedFiscalMaison(null)}
                docs={i.docs||[]} echanges={i.echanges||[]}
                onDocsChange={()=>{}}
                docsLabel="Avis d'imposition, reçus, justificatifs..."
                leftContent={<div>
                  <div style={{padding:"10px 12px",background:"rgba(167,139,250,0.07)",borderRadius:8,marginBottom:14,fontSize:12,color:T.purple}}>💡 Pour modifier, ouvrez le module Impôts.</div>
                  <InfoRow label="Titre" value={i.titre}/>
                  <InfoRow label="Année fiscale" value={i.annee}/>
                  <InfoRow label="Montant" value={i.montant&&fmtAmt(i.montant)} color={T.accent}/>
                  <InfoRow label="Échéance" value={fmt(i.dateEcheance)} color={j!=null&&j<=30?T.danger:T.text}/>
                  <InfoRow label="Statut" value={i.statut}/>
                  {j!=null&&j>=0&&j<=30&&<div style={{marginTop:12,padding:10,background:"rgba(239,68,68,0.1)",borderRadius:8,fontSize:12,color:T.danger}}>⚠️ Échéance dans {j} jours !</div>}
                  {i.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{i.note}</div>}
                </div>}
              />;
            })()}
            {/* Déductions travaux */}
            {(impots.deductions||[]).length>0&&(
              <Card style={{marginTop:14}}>
                <Divider label="Déductions fiscales liées aux travaux"/>
                {(impots.deductions||[]).map(d=>(
                  <div key={d.id} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:12,alignItems:"center"}}>
                    <div><div style={{fontWeight:600,color:T.text}}>{d.titre}</div><div style={{fontSize:11,color:T.muted}}>{d.note}</div></div>
                    <div style={{textAlign:"right"}}>
                      {d.montant&&<div style={{fontWeight:700,color:T.success}}>{fmtAmt(d.montant)}</div>}
                      <Badge c={d.statut==="validé"?T.success:T.warning}>{d.statut}</Badge>
                    </div>
                  </div>
                ))}
              </Card>
            )}
          </div>
        )}

        {tab==="pieces"&&(
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(160px,1fr))",gap:12}}>
            {(maison.pieces||PIECES_MAISON.slice(0,8).map(p=>({id:uid(),nom:p,superficie:"",etat:"Bon état",note:""}))).map(p=>(
              <Card key={p.id||p.nom} style={{padding:14}}>
                <div style={{fontSize:28,marginBottom:6,textAlign:"center"}}>
                  {p.nom==="Cuisine"?"🍳":p.nom==="Salon"?"🛋️":p.nom==="Chambre principale"?"🛏️":p.nom==="Salle de bain"?"🚿":p.nom==="WC"?"🚽":p.nom==="Garage"?"🏎️":p.nom==="Jardin"?"🌿":p.nom==="Bureau"?"💻":"🚪"}
                </div>
                <div style={{fontWeight:600,color:T.text,fontSize:13,textAlign:"center",marginBottom:4}}>{p.nom}</div>
                {p.superficie&&<div style={{fontSize:11,color:T.muted,textAlign:"center"}}>{p.superficie}m²</div>}
                {p.etat&&<div style={{marginTop:6,textAlign:"center"}}><Badge c={p.etat==="Neuf"||p.etat==="Très bon état"?T.success:p.etat==="Bon état"?T.info:T.warning}>{p.etat}</Badge></div>}
                {p.note&&<div style={{fontSize:10,color:T.muted,marginTop:4,textAlign:"center",fontStyle:"italic"}}>{p.note}</div>}
              </Card>
            ))}
          </div>
        )}

        {tab==="travaux"&&(
          <div>
            <div style={{display:"flex",gap:10,marginBottom:16}}>
              <Btn onClick={()=>setShowAddTravaux(true)}>+ Nouveau travail</Btn>
              <StatCard label="Total travaux" value={fmtAmt(totalTravaux)} icon="🔨" color={T.warning}/>
            </div>
            {(maison.travaux||[]).length===0&&<EmptyState icon="🔨" text="Aucun travail enregistré. Gardez une trace de tous vos travaux !"/>}
            <div style={{display:"grid",gap:10}}>
              {[...(maison.travaux||[])].sort((a,b)=>b.date.localeCompare(a.date)).map(t=>(
                <Card key={t.id} onClick={()=>setSelectedTravail(t.id)} style={{padding:"12px 16px",cursor:"pointer",borderColor:selectedTravail===t.id?T.accent:T.border}}>
                  <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                    <div>
                      <div style={{fontWeight:600,color:T.text,marginBottom:3}}>{t.titre}</div>
                      <div style={{fontSize:12,color:T.muted}}>🗓️ {fmt(t.date)}{t.artisan&&" · 👷 "+t.artisan}</div>
                      {t.garantie&&<div style={{fontSize:11,color:T.success,marginTop:2}}>🛡️ Garantie jusqu'au {fmt(t.garantie)}</div>}
                    </div>
                    <div style={{textAlign:"right",display:"flex",flexDirection:"column",gap:4,alignItems:"flex-end"}}>
                      {t.cout&&<span style={{fontWeight:700,color:T.accent,fontFamily:T.fontD,fontSize:16}}>{fmtAmt(t.cout)}</span>}
                      <Badge c={t.statut==="terminé"?T.success:t.statut==="en cours"?T.warning:T.info}>{t.statut}</Badge>
                      <Badge c={T.muted}>{t.type}</Badge>
                      {(t.docs||[]).length>0&&<Badge c={T.accent}>📎 {t.docs.length}</Badge>}
                    </div>
                  </div>
                </Card>
              ))}
            </div>
          </div>
        )}

        {/* ── FichePanel TRAVAUX ── */}
        {selectedTravail&&(()=>{
          const t=(maison.travaux||[]).find(x=>x.id===selectedTravail);
          if(!t)return null;
          return <FichePanel
            title={t.titre}
            icon="🔨"
            badge={t.statut} badgeColor={t.statut==="terminé"?T.success:t.statut==="en cours"?T.warning:T.info}
            onClose={()=>setSelectedTravail(null)}
            onDelete={()=>{onUpdate({...maison,travaux:(maison.travaux||[]).filter(x=>x.id!==t.id)});setSelectedTravail(null);}}
            docs={t.docs||[]} echanges={t.echanges||[]}
            onDocsChange={nd=>onUpdate({...maison,travaux:(maison.travaux||[]).map(x=>x.id===t.id?{...x,docs:nd}:x)})}
            onEchangesChange={ne=>onUpdate({...maison,travaux:(maison.travaux||[]).map(x=>x.id===t.id?{...x,echanges:ne}:x)})}
            docsLabel="Devis, factures, photos avant/après..."
            leftContent={<div>
              <InfoRow label="Titre" value={t.titre}/>
              <InfoRow label="Type de travaux" value={t.type}/>
              <InfoRow label="Statut" value={t.statut}/>
              <InfoRow label="Date" value={fmt(t.date)}/>
              <InfoRow label="Artisan / Entreprise" value={t.artisan}/>
              <InfoRow label="Coût" value={t.cout&&fmtAmt(t.cout)} color={T.accent}/>
              <InfoRow label="Garantie jusqu'au" value={fmt(t.garantie)} color={daysFrom(t.garantie)!=null&&daysFrom(t.garantie)>0?T.success:T.danger}/>
              {t.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{t.note}</div>}
            </div>}
          />;
        })()}

        {tab==="equipements"&&(
          <div>
            <div style={{marginBottom:14}}><Btn onClick={()=>setShowAddEquip(true)}>+ Équipement</Btn></div>
            {(maison.equipements||[]).length===0&&<EmptyState icon="⚙️" text="Aucun équipement. Enregistrez vos appareils, garanties, dates d'achat..."/>}
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(280px,1fr))",gap:12}}>
              {(maison.equipements||[]).map(e=>{
                const jGar=daysFrom(e.garantieJusqu);
                return (
                  <Card key={e.id} onClick={()=>setSelectedEquip(e.id)} style={{cursor:"pointer",borderColor:selectedEquip===e.id?T.accent:T.border}}>
                    <div style={{fontWeight:700,color:T.text,marginBottom:3}}>{e.nom}</div>
                    <div style={{fontSize:11,color:T.muted,marginBottom:8}}>📍 {e.piece}{e.marque&&" · "+e.marque}{e.modele&&" "+e.modele}</div>
                    <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:6}}>
                      {e.dateAchat&&<div style={{background:"#0a0e17",borderRadius:6,padding:"5px 8px",fontSize:11}}><div style={{color:T.muted}}>Achat</div><div style={{color:T.text}}>{fmt(e.dateAchat)}</div></div>}
                      {e.cout&&<div style={{background:"#0a0e17",borderRadius:6,padding:"5px 8px",fontSize:11}}><div style={{color:T.muted}}>Prix</div><div style={{color:T.accent,fontWeight:700}}>{fmtAmt(e.cout)}</div></div>}
                    </div>
                    {e.garantieJusqu&&<div style={{marginTop:8}}><Badge c={jGar!=null&&jGar>0?T.success:T.danger}>🛡️ Garantie {jGar!=null&&jGar>0?"jusqu'au "+fmt(e.garantieJusqu):"expirée"}</Badge></div>}
                    {(e.docs||[]).length>0&&<div style={{marginTop:6}}><Badge c={T.accent}>📎 {e.docs.length} document(s)</Badge></div>}
                  </Card>
                );
              })}
            </div>
          </div>
        )}

        {/* ── FichePanel ÉQUIPEMENT ── */}
        {selectedEquip&&(()=>{
          const e=(maison.equipements||[]).find(x=>x.id===selectedEquip);
          if(!e)return null;
          const jGar=daysFrom(e.garantieJusqu);
          return <FichePanel
            title={e.nom}
            icon="⚙️"
            badge={e.piece} badgeColor={T.info}
            onClose={()=>setSelectedEquip(null)}
            onDelete={()=>{onUpdate({...maison,equipements:(maison.equipements||[]).filter(x=>x.id!==e.id)});setSelectedEquip(null);}}
            docs={e.docs||[]} echanges={e.echanges||[]}
            onDocsChange={nd=>onUpdate({...maison,equipements:(maison.equipements||[]).map(x=>x.id===e.id?{...x,docs:nd}:x)})}
            onEchangesChange={ne=>onUpdate({...maison,equipements:(maison.equipements||[]).map(x=>x.id===e.id?{...x,echanges:ne}:x)})}
            docsLabel="Facture d'achat, notice, certificat de garantie..."
            leftContent={<div>
              <InfoRow label="Appareil" value={e.nom}/>
              <InfoRow label="Pièce" value={e.piece}/>
              <InfoRow label="Marque" value={e.marque}/>
              <InfoRow label="Modèle" value={e.modele}/>
              <InfoRow label="Date d'achat" value={fmt(e.dateAchat)}/>
              <InfoRow label="Prix" value={e.cout&&fmtAmt(e.cout)} color={T.accent}/>
              <InfoRow label="Garantie jusqu'au" value={fmt(e.garantieJusqu)} color={jGar!=null&&jGar>0?T.success:T.danger}/>
              {jGar!=null&&jGar>0&&<div style={{marginTop:10,padding:10,background:"rgba(34,197,94,0.08)",borderRadius:8,fontSize:12,color:T.success}}>✅ Garantie valide encore {jGar} jours</div>}
              {jGar!=null&&jGar<=0&&<div style={{marginTop:10,padding:10,background:"rgba(239,68,68,0.08)",borderRadius:8,fontSize:12,color:T.danger}}>⚠️ Garantie expirée</div>}
              {e.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{e.note}</div>}
            </div>}
          />;
        })()}

        {tab==="energie"&&(
          <div>
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(200px,1fr))",gap:14,marginBottom:20}}>
              {[{l:"DPE",v:maison.dpe,icon:"⚡",c:{"A":T.success,"B":T.success,"C":T.info,"D":T.warning,"E":T.warning,"F":T.danger,"G":T.danger}[maison.dpe]||T.muted},
                {l:"Surface",v:maison.surface+"m²",icon:"📐",c:T.info},
                {l:"Année construction",v:maison.anneeConstruction,icon:"🏗️",c:T.muted},
                {l:"Chauffage",v:maison.chauffage||"Non renseigné",icon:"🔥",c:T.warning},
              ].map(s=><StatCard key={s.l} label={s.l} value={s.v||"—"} icon={s.icon} color={s.c}/>)}
            </div>
            <Card>
              <Divider label="Relevés de compteurs"/>
              {(maison.relevesCpt||[]).length===0&&<EmptyState icon="📊" text="Ajoutez vos relevés de compteurs pour suivre votre consommation."/>}
              <div style={{display:"grid",gap:8}}>
                {(maison.relevesCpt||[]).map(r=>(
                  <div key={r.id} style={{display:"flex",justifyContent:"space-between",padding:"8px 12px",background:"#0a0e17",borderRadius:8,fontSize:13}}>
                    <span style={{color:T.muted}}>{fmt(r.date)}</span>
                    <span style={{color:T.text}}>{r.type}</span>
                    <span style={{color:T.accent,fontWeight:600}}>{r.valeur} {r.unite}</span>
                  </div>
                ))}
              </div>
              <div style={{marginTop:12}}>
                <Btn sm onClick={()=>onUpdate({...maison,relevesCpt:[...(maison.relevesCpt||[]),{id:uid(),type:"Électricité",valeur:prompt("Index électricité (kWh):"),unite:"kWh",date:today()}]})}>+ Relevé compteur</Btn>
              </div>
            </Card>
          </div>
        )}

        {tab==="docs"&&(
          <div>
            <div style={{marginBottom:14}}><Btn onClick={()=>fileRef.current.click()}>+ Document</Btn></div>
            <input ref={fileRef} type="file" accept="image/*,application/pdf" style={{display:"none"}} onChange={async e=>{const f=e.target.files[0];if(!f)return;const dataUrl=await new Promise(r=>{const fr=new FileReader();fr.onload=ev=>r(ev.target.result);fr.readAsDataURL(f);});onUpdate({...maison,documents:[...(maison.documents||[]),{id:uid(),nom:f.name,dataUrl,isPdf:f.type==="application/pdf",isImg:f.type.startsWith("image/"),type:f.type,date:today()}]});}}/>            {(maison.documents||[]).length===0&&<EmptyState icon="📄" text="Aucun document. Ajoutez acte de propriété, diagnostics, plans..."/>}
            <div style={{display:"grid",gap:8}}>
              {(maison.documents||[]).map(d=>(
                <Card key={d.id} style={{padding:"10px 14px"}}>
                  <div style={{display:"flex",alignItems:"center",gap:10}}>
                    <span style={{fontSize:22}}>📄</span>
                    <div style={{flex:1}}>
                      <div style={{fontSize:13,fontWeight:600,color:T.text}}>{d.nom}</div>
                      <div style={{fontSize:11,color:T.muted}}>{fmt(d.date)}</div>
                    </div>
                    {(d.url||d.dataUrl)&&<a href={d.dataUrl||d.url} download={d.nom} style={{color:T.accent,fontSize:12}}>⬇️</a>}
                  </div>
                </Card>
              ))}
            </div>
          </div>
        )}

        {tab==="infos"&&(
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
            <Card>
              <Divider label="Caractéristiques"/>
              {[["Adresse",maison.adresse],["Surface",maison.surface&&maison.surface+"m²"],["Nb pièces",maison.nbPieces],["Étage",maison.etage],["Année construction",maison.anneeConstruction],["DPE",maison.dpe],["Chauffage",maison.chauffage],["ECS",maison.ecs]].filter(([,v])=>v).map(([l,v])=>(
                <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                  <span style={{color:T.muted}}>{l}</span><span style={{color:T.text,fontWeight:500}}>{v}</span>
                </div>
              ))}
              {maison.adresse&&<div style={{marginTop:10}}><MapsLinks adresse={maison.adresse}/></div>}
            </Card>
            <Card>
              <Divider label="Financier"/>
              {[["Valeur estimée",maison.valeur&&fmtAmt(maison.valeur)],["Prix d'achat",maison.prixAchat&&fmtAmt(maison.prixAchat)],["Date d'achat",fmt(maison.dateAchat)],["Notaire",maison.notaire],["Total travaux",fmtAmt(totalTravaux)],["Total équipements",fmtAmt(totalEquip)]].filter(([,v])=>v&&v!=="—").map(([l,v])=>(
                <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                  <span style={{color:T.muted}}>{l}</span><span style={{color:l.includes("Total")?T.accent:T.text,fontWeight:l.includes("Total")?700:500}}>{v}</span>
                </div>
              ))}
              <div style={{background:T.accentDim,borderRadius:8,padding:10,marginTop:10}}>
                <div style={{fontSize:10,color:T.muted}}>INVESTISSEMENT TOTAL</div>
                <div style={{fontSize:22,fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{fmtAmt((parseFloat(maison.prixAchat)||0)+totalTravaux+totalEquip)}</div>
              </div>
            </Card>
          </div>
        )}
      </div>

      {showAddAbonnement&&<Modal title="💡 Nouvel abonnement / charge" onClose={()=>setShowAddAbonnement(false)} width={700}>
        <div style={{marginBottom:12}}>
          <div style={{fontSize:11,color:T.muted,marginBottom:8,textTransform:"uppercase",letterSpacing:"0.08em"}}>Catégorie</div>
          <div style={{display:"flex",gap:6,flexWrap:"wrap"}}>
            {ABONNEMENT_CATS.map(cat=>(
              <button key={cat.id} onClick={()=>setFormAbo(f=>({...f,categorie:cat.id}))} style={{background:formAbo.categorie===cat.id?cat.color+"22":"transparent",border:`2px solid ${formAbo.categorie===cat.id?cat.color:T.border}`,borderRadius:8,padding:"6px 10px",cursor:"pointer",fontSize:12,color:formAbo.categorie===cat.id?cat.color:T.muted,fontFamily:T.font,display:"flex",alignItems:"center",gap:5}}>
                <span>{cat.icon}</span><span>{cat.label}</span>
              </button>
            ))}
          </div>
        </div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Fournisseur *"><Inp value={formAbo.fournisseur} onChange={v=>setFormAbo(f=>({...f,fournisseur:v}))} placeholder="EDF, Engie, Orange..."/></F>
          <F label="Référence contrat"><Inp value={formAbo.reference} onChange={v=>setFormAbo(f=>({...f,reference:v}))} placeholder="N° client, référence..."/></F>
          <F label="Montant"><Inp type="number" value={formAbo.montantMensuel} onChange={v=>setFormAbo(f=>({...f,montantMensuel:v}))} placeholder="0.00"/></F>
          <F label="Périodicité"><Sel value={formAbo.prelevement} onChange={v=>setFormAbo(f=>({...f,prelevement:v}))}><option value="mensuel">Mensuel</option><option value="trimestriel">Trimestriel</option><option value="annuel">Annuel</option></Sel></F>
          <F label="Date début"><Inp type="date" value={formAbo.dateDebut} onChange={v=>setFormAbo(f=>({...f,dateDebut:v}))}/></F>
          <F label="Date échéance / fin"><Inp type="date" value={formAbo.dateEcheance} onChange={v=>setFormAbo(f=>({...f,dateEcheance:v}))}/></F>
          <F label="IBAN prélèvement"><Inp value={formAbo.iban} onChange={v=>setFormAbo(f=>({...f,iban:v}))} placeholder="FR76..."/></F>
          <F label="Statut"><Sel value={formAbo.statut} onChange={v=>setFormAbo(f=>({...f,statut:v}))}><option value="actif">Actif</option><option value="résilié">Résilié</option><option value="en attente">En attente</option></Sel></F>
        </div>
        <F label="Note"><Inp value={formAbo.note} onChange={v=>setFormAbo(f=>({...f,note:v}))} placeholder="Offre, particularités..."/></F>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAddAbonnement(false)}>Annuler</Btn>
          <Btn onClick={()=>{onUpdate({...maison,abonnements:[...(maison.abonnements||[]),{...formAbo,id:uid()}]});setShowAddAbonnement(false);setFormAbo({categorie:"electricite",fournisseur:"",reference:"",montantMensuel:"",dateDebut:"",dateEcheance:"",prelevement:"mensuel",iban:"",note:"",statut:"actif"});}} disabled={!formAbo.fournisseur}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
      {showAddTravaux&&<Modal title="🔨 Nouveau travail" onClose={()=>setShowAddTravaux(false)}>
        <div style={{display:"grid",gap:10}}>
          <F label="Titre *"><Inp value={formT.titre} onChange={v=>setFormT(f=>({...f,titre:v}))} placeholder="Ex: Peinture salon, Remplacement chaudière..."/></F>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Type"><Sel value={formT.type} onChange={v=>setFormT(f=>({...f,type:v}))}>{TYPES_TRAVAUX.map(t=><option key={t}>{t}</option>)}</Sel></F>
            <F label="Statut"><Sel value={formT.statut} onChange={v=>setFormT(f=>({...f,statut:v}))}><option value="terminé">Terminé</option><option value="en cours">En cours</option><option value="planifié">Planifié</option><option value="devis">Devis en attente</option></Sel></F>
            <F label="Date"><Inp type="date" value={formT.date} onChange={v=>setFormT(f=>({...f,date:v}))}/></F>
            <F label="Coût (€)"><Inp type="number" value={formT.cout} onChange={v=>setFormT(f=>({...f,cout:v}))}/></F>
            <F label="Artisan / Entreprise"><Inp value={formT.artisan} onChange={v=>setFormT(f=>({...f,artisan:v}))} placeholder="Plombier Martin..."/></F>
            <F label="Garantie jusqu'au"><Inp type="date" value={formT.garantie} onChange={v=>setFormT(f=>({...f,garantie:v}))}/></F>
          </div>
          <F label="Note"><Inp value={formT.note} onChange={v=>setFormT(f=>({...f,note:v}))} placeholder="Détails, références, couleurs..."/></F>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
            <Btn v="ghost" onClick={()=>setShowAddTravaux(false)}>Annuler</Btn>
            <Btn onClick={()=>{onUpdate({...maison,travaux:[...(maison.travaux||[]),{...formT,id:uid(),cout:parseFloat(formT.cout)||0}]});setShowAddTravaux(false);}} disabled={!formT.titre}>💾 Enregistrer</Btn>
          </div>
        </div>
      </Modal>}
      {showAddEquip&&<Modal title="⚙️ Nouvel équipement" onClose={()=>setShowAddEquip(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Nom *"><Inp value={formE.nom} onChange={v=>setFormE(f=>({...f,nom:v}))} placeholder="Lave-linge, Chaudière..."/></F>
          <F label="Pièce"><Sel value={formE.piece} onChange={v=>setFormE(f=>({...f,piece:v}))}>{PIECES_MAISON.map(p=><option key={p}>{p}</option>)}</Sel></F>
          <F label="Marque"><Inp value={formE.marque} onChange={v=>setFormE(f=>({...f,marque:v}))} placeholder="Samsung, Bosch..."/></F>
          <F label="Modèle"><Inp value={formE.modele} onChange={v=>setFormE(f=>({...f,modele:v}))}/></F>
          <F label="Date d'achat"><Inp type="date" value={formE.dateAchat} onChange={v=>setFormE(f=>({...f,dateAchat:v}))}/></F>
          <F label="Prix (€)"><Inp type="number" value={formE.cout} onChange={v=>setFormE(f=>({...f,cout:v}))}/></F>
          <F label="Garantie jusqu'au"><Inp type="date" value={formE.garantieJusqu} onChange={v=>setFormE(f=>({...f,garantieJusqu:v}))}/></F>
          <F label="Note"><Inp value={formE.note} onChange={v=>setFormE(f=>({...f,note:v}))} placeholder="Numéro de série, note..."/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
          <Btn v="ghost" onClick={()=>setShowAddEquip(false)}>Annuler</Btn>
          <Btn onClick={()=>{onUpdate({...maison,equipements:[...(maison.equipements||[]),{...formE,id:uid(),cout:parseFloat(formE.cout)||0}]});setShowAddEquip(false);}} disabled={!formE.nom}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

const Maisons=({maisons,setMaisons,assurances=[],impots={},setPage})=>{
  const [selected,setSelected]=useState(null);
  const [showAdd,setShowAdd]=useState(false);
  const [form,setForm]=useState({nom:"",type:"principale",icon:"🏠",adresse:"",surface:"",nbPieces:"",anneeConstruction:"",dpe:"C",chauffage:"Gaz",ecs:"Chauffe-eau",valeur:"",prixAchat:"",dateAchat:"",notaire:"",note:""});

  const sel=maisons.find(m=>m.id===selected);
  const updateM=updated=>setMaisons(p=>p.map(m=>m.id===updated.id?updated:m));
  const ICONS=["🏠","🏡","🏘️","🏰","🏗️","🌴","⛰️","🌊"];

  if(selected&&sel) return <MaisonDetail maison={sel} onUpdate={updateM} onClose={()=>setSelected(null)} assurances={assurances} impots={impots} setPage={setPage}/>;

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🏡 Mes Maisons</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>Résidence principale, secondaire · travaux, équipements, documents</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Ajouter un bien</Btn>
      </div>

      {maisons.length===0&&<EmptyState icon="🏡" text="Ajoutez votre résidence principale pour commencer."/>}
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(320px,1fr))",gap:16}}>
        {maisons.map(m=>{
          const trav=(m.travaux||[]);
          const equip=(m.equipements||[]);
          const totalT=trav.reduce((s,t)=>s+(parseFloat(t.cout)||0),0);
          const travEnCours=trav.filter(t=>t.statut==="en cours").length;
          const aboActifs=(m.abonnements||[]).filter(a=>a.statut==="actif");
          const totalAbo=aboActifs.reduce((s,a)=>{const mo=parseFloat(a.montantMensuel)||0;return s+(a.prelevement==="annuel"?mo/12:a.prelevement==="trimestriel"?mo/3:mo);},0);
          return (
            <Card key={m.id} onClick={()=>setSelected(m.id)} style={{padding:0,overflow:"hidden"}}>
              <div style={{background:`linear-gradient(135deg, #1e2840 0%, #2a3550 100%)`,padding:"20px 18px",borderBottom:`1px solid ${T.border}`}}>
                <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                  <div>
                    <div style={{fontSize:32,marginBottom:6}}>{m.icon||"🏠"}</div>
                    <div style={{fontFamily:T.fontD,fontSize:18,color:T.text,marginBottom:2}}>{m.nom}</div>
                    <div style={{fontSize:11,color:T.muted}}>📍 {m.adresse}</div>
                  </div>
                  <Badge c={m.type==="principale"?T.accent:T.info}>{m.type==="principale"?"Principale":"Secondaire"}</Badge>
                </div>
              </div>
              <div style={{padding:16}}>
                <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:8,marginBottom:12}}>
                  {[[m.surface&&m.surface+"m²","📐"],[m.nbPieces&&m.nbPieces+" pièces","🚪"],["DPE "+m.dpe,"⚡"]].filter(([v])=>v).map(([v,i])=>(
                    <div key={v} style={{background:"#0a0e17",borderRadius:6,padding:"5px 8px",fontSize:11,textAlign:"center"}}>
                      <div>{i}</div><div style={{color:T.text,fontWeight:600}}>{v}</div>
                    </div>
                  ))}
                </div>
                <div style={{display:"flex",gap:6,flexWrap:"wrap"}}>
                  {totalAbo>0&&<Badge c={T.info}>💡 {fmtAmt(totalAbo)}/mois</Badge>}
                  {trav.length>0&&<Badge c={T.warning}>{trav.length} travaux · {fmtAmt(totalT)}</Badge>}
                  {travEnCours>0&&<Badge c={T.danger}>{travEnCours} en cours</Badge>}
                  {equip.length>0&&<Badge c={T.purple}>{equip.length} équip.</Badge>}
                  {m.valeur&&<Badge c={T.success}>≈ {fmtAmt(m.valeur)}</Badge>}
                </div>
                <div style={{marginTop:10,fontSize:12,color:T.accent,fontWeight:600}}>→ Ouvrir le dossier</div>
              </div>
            </Card>
          );
        })}
      </div>

      {showAdd&&<Modal title="🏡 Nouveau bien immobilier" onClose={()=>setShowAdd(false)} width={700}>
        <div style={{display:"flex",gap:8,marginBottom:14,flexWrap:"wrap"}}>
          {ICONS.map(ic=><button key={ic} onClick={()=>setForm(f=>({...f,icon:ic}))} style={{fontSize:24,background:form.icon===ic?T.accentDim:"transparent",border:`2px solid ${form.icon===ic?T.accent:T.border}`,borderRadius:8,padding:6,cursor:"pointer"}}>{ic}</button>)}
        </div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Nom *"><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Ma Maison, Chalet des Alpes..."/></F>
          <F label="Type"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}><option value="principale">Résidence principale</option><option value="secondaire">Résidence secondaire</option></Sel></F>
        </div>
        <F label="Adresse complète"><Inp value={form.adresse} onChange={v=>setForm(f=>({...f,adresse:v}))} placeholder="12 rue des Lilas, 33410 Langon"/></F>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr 1fr",gap:10}}>
          <F label="Surface (m²)"><Inp type="number" value={form.surface} onChange={v=>setForm(f=>({...f,surface:v}))}/></F>
          <F label="Nb pièces"><Inp type="number" value={form.nbPieces} onChange={v=>setForm(f=>({...f,nbPieces:v}))}/></F>
          <F label="Année const."><Inp type="number" value={form.anneeConstruction} onChange={v=>setForm(f=>({...f,anneeConstruction:v}))} placeholder="1985"/></F>
          <F label="DPE"><Sel value={form.dpe} onChange={v=>setForm(f=>({...f,dpe:v}))}>{["A","B","C","D","E","F","G"].map(d=><option key={d}>{d}</option>)}</Sel></F>
        </div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Chauffage"><Sel value={form.chauffage} onChange={v=>setForm(f=>({...f,chauffage:v}))}>{["Gaz","Électrique","Pompe à chaleur","Fioul","Bois","Pellets","Géothermie"].map(c=><option key={c}>{c}</option>)}</Sel></F>
          <F label="Eau chaude"><Sel value={form.ecs} onChange={v=>setForm(f=>({...f,ecs:v}))}>{["Chauffe-eau","Chaudière","Solaire","Thermodynamique"].map(e=><option key={e}>{e}</option>)}</Sel></F>
          <F label="Valeur estimée (€)"><Inp type="number" value={form.valeur} onChange={v=>setForm(f=>({...f,valeur:v}))}/></F>
          <F label="Prix d'achat (€)"><Inp type="number" value={form.prixAchat} onChange={v=>setForm(f=>({...f,prixAchat:v}))}/></F>
          <F label="Date d'achat"><Inp type="date" value={form.dateAchat} onChange={v=>setForm(f=>({...f,dateAchat:v}))}/></F>
          <F label="Notaire"><Inp value={form.notaire} onChange={v=>setForm(f=>({...f,notaire:v}))} placeholder="Maître..."/></F>
        </div>
        <F label="Note"><Inp value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} placeholder="Informations complémentaires..."/></F>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={()=>{setMaisons(p=>[...p,{...form,id:uid(),surface:+form.surface||0,nbPieces:+form.nbPieces||0,valeur:+form.valeur||0,prixAchat:+form.prixAchat||0,travaux:[],equipements:[],documents:[],relevesCpt:[]}]);setShowAdd(false);}} disabled={!form.nom}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: VÉHICULES — avec CT, assurance passerelle, coûts
// ═══════════════════════════════════════════════════════════════════════════════
const VehiculeDetail=({veh,onUpdate,onClose,assurances=[],setPage})=>{
  const [tab,setTab]=useState("resume");
  const [showEnt,setShowEnt]=useState(false);
  const [showCT,setShowCT]=useState(false);
  const [selectedCT,setSelectedCT]=useState(null);
  const [selectedEnt,setSelectedEnt]=useState(null);
  const [selectedAssurVeh,setSelectedAssurVeh]=useState(false);
  const [formE,setFormE]=useState({type:"Vidange",date:today(),kilometrage:"",cout:"",garage:"",note:""});
  const [formCT,setFormCT]=useState({date:today(),resultat:"Favorable",prochainCT:"",centre:"",cout:"",note:"",defauts:""});

  const TYPES_VEH=[{v:"voiture",l:"Voiture",i:"🚗"},{v:"moto",l:"Moto",i:"🏍️"},{v:"velo",l:"Vélo / VAE",i:"🚲"},{v:"camping",l:"Camping-car",i:"🚐"},{v:"bateau",l:"Bateau",i:"⛵"}];
  const ENTRETIENS_TYPES=["Vidange","Révision","Freins","Pneus","Courroie de distribution","Batterie","Climatisation","Filtre habitacle","Filtre à air","Pare-brise","Carrosserie","Autre"];
  const ti=TYPES_VEH.find(t=>t.v===veh.type);
  const entretiens=veh.entretiens||[];
  const histoCT=veh.histoCT||[];
  const totalEnt=entretiens.reduce((s,e)=>s+(parseFloat(e.cout)||0),0);
  const totalCT=histoCT.reduce((s,c)=>s+(parseFloat(c.cout)||0),0);
  const prochainCT=daysFrom(veh.dateCT);
  // Assurance liée
  const assuranceLiee=assurances.find(a=>
    a.type==="auto"||a.type==="moto"||a.type==="vehicule"||
    (a.nom||"").toLowerCase().includes(veh.marque?.toLowerCase()||"")||
    (a.nom||"").toLowerCase().includes(veh.immat?.toLowerCase().slice(0,4)||"")||
    (a.note||"").toLowerCase().includes(veh.immat?.toLowerCase()||"")
  );

  const TABS=[
    {id:"resume",icon:"📋",label:"Résumé"},
    {id:"ct",icon:"🔍",label:"Contrôle Tech."},
    {id:"assurance",icon:"🛡️",label:"Assurance"},
    {id:"entretiens",icon:"🔧",label:"Entretiens"},
    {id:"couts",icon:"💰",label:"Coûts"},
    {id:"infos",icon:"ℹ️",label:"Fiche"},
  ];

  return (
    <div style={{position:"fixed",inset:0,background:T.bg,zIndex:1500,display:"flex",flexDirection:"column",overflow:"hidden"}}>
      <FontLink/>
      <div style={{background:T.sidebar,borderBottom:`1px solid ${T.border}`,padding:"12px 22px",display:"flex",alignItems:"center",gap:14,flexShrink:0}}>
        <Btn v="outline" sm onClick={onClose}>← Retour</Btn>
        <div style={{flex:1}}>
          <div style={{fontFamily:T.fontD,fontSize:19,color:T.text}}>{ti?.i||"🚗"} {veh.marque} {veh.modele}</div>
          <div style={{fontSize:11,color:T.muted}}>{veh.immat&&"🪪 "+veh.immat+" · "}{veh.annee&&"📅 "+veh.annee+" · "}{veh.couleur&&veh.couleur+" · "}⛽ {veh.energie}</div>
        </div>
        <div style={{display:"flex",gap:16}}>
          <div style={{textAlign:"right"}}>
            <div style={{fontSize:10,color:T.muted}}>Kilométrage</div>
            <div style={{fontSize:14,fontWeight:700,color:T.text}}>{veh.kilometrage?Number(veh.kilometrage).toLocaleString("fr-FR")+" km":"—"}</div>
          </div>
          <div style={{textAlign:"right"}}>
            <div style={{fontSize:10,color:T.muted}}>Coût entretien</div>
            <div style={{fontSize:14,fontWeight:700,color:T.warning}}>{fmtAmt(totalEnt+totalCT)}</div>
          </div>
          {veh.dateCT&&<div style={{textAlign:"right"}}>
            <div style={{fontSize:10,color:T.muted}}>Prochain CT</div>
            <div style={{fontSize:14,fontWeight:700,color:prochainCT!=null&&prochainCT<=90?T.danger:T.success}}>{fmt(veh.dateCT)}</div>
          </div>}
        </div>
      </div>
      <div style={{flex:1,overflow:"auto",padding:"18px 22px"}}>
        <Tabs tabs={TABS} active={tab} onChange={setTab}/>

        {/* ── RÉSUMÉ ── */}
        {tab==="resume"&&(
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:14}}>
            {/* CT countdown */}
            <Card style={{padding:20,textAlign:"center",borderLeft:`4px solid ${prochainCT!=null&&prochainCT<=0?T.danger:prochainCT!=null&&prochainCT<=90?T.warning:T.success}`,gridColumn:"span 1"}}>
              <div style={{fontSize:28,marginBottom:6}}>🔍</div>
              <div style={{fontSize:12,color:T.muted,marginBottom:4}}>Prochain CT</div>
              {veh.dateCT?(
                <>
                  <div style={{fontFamily:T.fontD,fontSize:22,fontWeight:700,color:prochainCT!=null&&prochainCT<=0?T.danger:prochainCT!=null&&prochainCT<=90?T.warning:T.success}}>{prochainCT!=null&&prochainCT>=0?prochainCT+"j":"EXPIRÉ"}</div>
                  <div style={{fontSize:12,color:T.muted,marginTop:2}}>{fmt(veh.dateCT)}</div>
                  {prochainCT!=null&&prochainCT<=90&&<div style={{marginTop:8}}><Badge c={prochainCT<=0?T.danger:T.warning}>{prochainCT<=0?"À renouveler d'urgence":"À planifier"}</Badge></div>}
                </>
              ):<div style={{color:T.muted,fontSize:13}}>Non renseigné<br/><button onClick={()=>setTab("ct")} style={{color:T.accent,background:"none",border:"none",cursor:"pointer",fontFamily:T.font,fontSize:12}}>+ Ajouter</button></div>}
            </Card>
            {/* Assurance */}
            <Card style={{padding:20,borderLeft:`4px solid ${assuranceLiee?T.success:T.muted}`}}>
              <div style={{fontSize:28,marginBottom:6}}>🛡️</div>
              <div style={{fontSize:12,color:T.muted,marginBottom:4}}>Assurance</div>
              {assuranceLiee?(
                <>
                  <div style={{fontWeight:700,color:T.text,marginBottom:2}}>{assuranceLiee.nom}</div>
                  <div style={{fontSize:12,color:T.muted}}>{assuranceLiee.assureur}</div>
                  <div style={{fontSize:16,fontWeight:700,color:T.accent,marginTop:4}}>{fmtAmt(assuranceLiee.prime)}<span style={{fontSize:11,fontWeight:400,color:T.muted}}>/mois</span></div>
                  {assuranceLiee.dateEcheance&&<Badge c={daysFrom(assuranceLiee.dateEcheance)<=30?T.warning:T.success}>Ech. {fmt(assuranceLiee.dateEcheance)}</Badge>}
                </>
              ):<div style={{color:T.muted,fontSize:13}}>Non liée<br/><button onClick={()=>setTab("assurance")} style={{color:T.accent,background:"none",border:"none",cursor:"pointer",fontFamily:T.font,fontSize:12}}>→ Associer</button></div>}
            </Card>
            {/* Stats */}
            <Card style={{padding:20}}>
              <div style={{fontSize:28,marginBottom:6}}>📊</div>
              <div style={{fontSize:12,color:T.muted,marginBottom:8}}>Statistiques</div>
              {[["Entretiens",entretiens.length+" opérations"],["Total entretiens",fmtAmt(totalEnt)],["CTs effectués",histoCT.length],["Total CT",fmtAmt(totalCT)],["Coût total",fmtAmt(totalEnt+totalCT+(parseFloat(veh.prixAchat)||0))]].map(([l,v])=>(
                <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"4px 0",fontSize:12,borderBottom:`1px solid ${T.border}`}}>
                  <span style={{color:T.muted}}>{l}</span><span style={{color:T.text,fontWeight:600}}>{v}</span>
                </div>
              ))}
            </Card>
            {/* Derniers entretiens */}
            <Card style={{gridColumn:"1/-1"}}>
              <Divider label="Dernières opérations"/>
              <div style={{display:"grid",gap:6}}>
                {[...entretiens,...histoCT.map(c=>({...c,type:"Contrôle technique"}))].sort((a,b)=>b.date.localeCompare(a.date)).slice(0,5).map(e=>(
                  <div key={e.id} style={{display:"flex",justifyContent:"space-between",padding:"7px 10px",background:"#0a0e17",borderRadius:8,fontSize:12,alignItems:"center"}}>
                    <span style={{color:T.muted}}>{fmt(e.date)}</span>
                    <span style={{fontWeight:600,color:T.text,flex:1,marginLeft:12}}>{e.type}</span>
                    {e.resultat&&<Badge c={e.resultat==="Favorable"?T.success:e.resultat==="Défavorable"?T.danger:T.warning}>{e.resultat}</Badge>}
                    {e.cout>0&&<span style={{color:T.accent,fontWeight:700,marginLeft:10}}>{fmtAmt(e.cout)}</span>}
                  </div>
                ))}
                {entretiens.length===0&&histoCT.length===0&&<div style={{color:T.muted,fontSize:12,padding:8}}>Aucune opération enregistrée.</div>}
              </div>
            </Card>
          </div>
        )}

        {/* ── CONTRÔLE TECHNIQUE ── */}
        {tab==="ct"&&(
          <div>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:16}}>
              <div style={{fontWeight:700,color:T.text,fontSize:16}}>Historique des contrôles techniques</div>
              <Btn onClick={()=>setShowCT(true)}>+ Contrôle technique</Btn>
            </div>
            {/* Prochain CT — carte principale */}
            <Card style={{marginBottom:18,padding:0,overflow:"hidden",borderColor:prochainCT!=null&&prochainCT<=0?T.danger:prochainCT!=null&&prochainCT<=90?T.warning:T.border}}>
              <div style={{display:"flex",alignItems:"center",gap:0}}>
                <div style={{width:160,background:prochainCT!=null&&prochainCT<=0?"rgba(239,68,68,0.15)":prochainCT!=null&&prochainCT<=90?"rgba(251,146,60,0.15)":"rgba(34,197,94,0.12)",padding:20,textAlign:"center",flexShrink:0,borderRight:`1px solid ${T.border}`}}>
                  <div style={{fontSize:11,color:T.muted,textTransform:"uppercase",letterSpacing:"0.1em",marginBottom:4}}>Prochain CT</div>
                  {veh.dateCT?(
                    <>
                      <div style={{fontFamily:T.fontD,fontSize:36,fontWeight:700,color:prochainCT!=null&&prochainCT<=0?T.danger:prochainCT!=null&&prochainCT<=90?T.warning:T.success,lineHeight:1}}>{prochainCT!=null&&prochainCT>=0?prochainCT:"!"}</div>
                      <div style={{fontSize:10,color:T.muted,marginTop:2}}>{prochainCT!=null&&prochainCT>=0?"jours restants":"EXPIRÉ"}</div>
                      <div style={{fontSize:13,color:T.text,marginTop:6,fontWeight:600}}>{fmt(veh.dateCT)}</div>
                    </>
                  ):<div style={{color:T.muted,fontSize:13}}>Non défini</div>}
                </div>
                <div style={{flex:1,padding:"16px 20px"}}>
                  <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:10}}>
                    {[["Contrôles effectués",histoCT.length],["Dernier résultat",histoCT[0]?.resultat||"—"],["Coût total",fmtAmt(totalCT)]].map(([l,v])=>(
                      <div key={l} style={{background:"#0a0e17",borderRadius:8,padding:"8px 12px"}}>
                        <div style={{fontSize:10,color:T.muted,marginBottom:2}}>{l}</div>
                        <div style={{fontSize:14,fontWeight:700,color:T.text}}>{v}</div>
                      </div>
                    ))}
                  </div>
                  {prochainCT!=null&&prochainCT<=90&&(
                    <div style={{marginTop:10,padding:"8px 12px",background:prochainCT<=0?"rgba(239,68,68,0.1)":"rgba(251,146,60,0.1)",borderRadius:8,fontSize:13,color:prochainCT<=0?T.danger:T.warning}}>
                      ⚠️ {prochainCT<=0?"Contrôle technique expiré ! Votre véhicule n'est plus en règle.":"Contrôle technique à planifier dans moins de 3 mois."}
                    </div>
                  )}
                </div>
              </div>
            </Card>
            {histoCT.length===0&&<EmptyState icon="🔍" text="Aucun CT enregistré. Ajoutez votre historique."/>}
            <div style={{display:"grid",gap:10}}>
              {[...histoCT].sort((a,b)=>b.date.localeCompare(a.date)).map(ct=>(
                <Card key={ct.id} onClick={()=>setSelectedCT(ct.id)} style={{padding:"12px 16px",cursor:"pointer",borderColor:selectedCT===ct.id?T.accent:ct.resultat==="Favorable"?T.border:ct.resultat==="Défavorable"?T.danger:T.warning}}>
                  <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                    <div style={{flex:1}}>
                      <div style={{display:"flex",gap:8,alignItems:"center",marginBottom:4}}>
                        <span style={{fontWeight:700,color:T.text,fontSize:14}}>Contrôle du {fmt(ct.date)}</span>
                        <Badge c={ct.resultat==="Favorable"?T.success:ct.resultat==="Défavorable"?T.danger:T.warning}>{ct.resultat}</Badge>
                        {(ct.docs||[]).length>0&&<Badge c={T.accent}>📎 {ct.docs.length}</Badge>}
                      </div>
                      {ct.centre&&<div style={{fontSize:12,color:T.muted}}>🏢 {ct.centre}</div>}
                      {ct.prochainCT&&<div style={{fontSize:12,color:T.info}}>→ Prochain CT: {fmt(ct.prochainCT)}</div>}
                      {ct.defauts&&<div style={{marginTop:6,padding:"5px 10px",background:"rgba(239,68,68,0.08)",borderRadius:6,fontSize:12,color:T.danger}}>⚠️ {ct.defauts}</div>}
                    </div>
                    {ct.cout>0&&<div style={{fontWeight:700,color:T.accent,fontFamily:T.fontD,fontSize:16,flexShrink:0}}>{fmtAmt(ct.cout)}</div>}
                  </div>
                </Card>
              ))}
            </div>
            {selectedCT&&(()=>{
              const ct=histoCT.find(x=>x.id===selectedCT);
              if(!ct)return null;
              return <FichePanel
                title={"CT du "+fmt(ct.date)} icon="🔍"
                badge={ct.resultat} badgeColor={ct.resultat==="Favorable"?T.success:ct.resultat==="Défavorable"?T.danger:T.warning}
                onClose={()=>setSelectedCT(null)}
                onDelete={()=>{onUpdate({...veh,histoCT:(veh.histoCT||[]).filter(c=>c.id!==ct.id)});setSelectedCT(null);}}
                docs={ct.docs||[]} echanges={ct.echanges||[]}
                onDocsChange={nd=>onUpdate({...veh,histoCT:(veh.histoCT||[]).map(c=>c.id===ct.id?{...c,docs:nd}:c)})}
                onEchangesChange={ne=>onUpdate({...veh,histoCT:(veh.histoCT||[]).map(c=>c.id===ct.id?{...c,echanges:ne}:c)})}
                docsLabel="PV de contrôle technique..."
                leftContent={<div>
                  <InfoRow label="Date du contrôle" value={fmt(ct.date)}/>
                  <InfoRow label="Résultat" value={ct.resultat} color={ct.resultat==="Favorable"?T.success:ct.resultat==="Défavorable"?T.danger:T.warning}/>
                  <InfoRow label="Centre de contrôle" value={ct.centre}/>
                  <InfoRow label="Coût" value={ct.cout&&fmtAmt(ct.cout)} color={T.accent}/>
                  <InfoRow label="Prochain CT" value={fmt(ct.prochainCT)}/>
                  {ct.defauts&&<div style={{marginTop:12,padding:12,background:"rgba(239,68,68,0.08)",borderRadius:8,fontSize:12,color:T.danger}}>⚠️ Défauts : {ct.defauts}</div>}
                  {ct.note&&<div style={{marginTop:12,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{ct.note}</div>}
                </div>}
              />;
            })()}
          </div>
        )}

        {/* ── ASSURANCE (passerelle) ── */}
        {tab==="assurance"&&(
          <div>
            <div style={{marginBottom:16}}>
              <div style={{fontWeight:700,color:T.text,fontSize:16,marginBottom:4}}>🛡️ Assurance du véhicule</div>
              <div style={{fontSize:12,color:T.muted}}>Données issues du module Assurances · <button onClick={()=>setPage&&setPage("assurances")} style={{color:T.accent,background:"none",border:"none",cursor:"pointer",fontFamily:T.font,fontSize:12}}>→ Ouvrir le module Assurances</button></div>
            </div>
            {assuranceLiee?(
              <Card onClick={()=>setSelectedAssurVeh(true)} style={{padding:0,overflow:"hidden",borderColor:selectedAssurVeh?T.accent:T.success,cursor:"pointer"}}>
                <div style={{background:"rgba(34,197,94,0.08)",padding:"14px 18px",borderBottom:`1px solid ${T.border}`,display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                  <div style={{fontWeight:700,color:T.text,fontSize:15}}>✅ {assuranceLiee.nom}</div>
                  <div style={{fontSize:22,fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{fmtAmt(assuranceLiee.prime)}<span style={{fontSize:12,fontWeight:400,color:T.muted}}>/mois</span></div>
                </div>
                <div style={{padding:"14px 18px"}}>
                  <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:10,marginBottom:12}}>
                    {[["Assureur",assuranceLiee.assureur],["N° contrat",assuranceLiee.numero||"—"],["Type",assuranceLiee.type],["Début",fmt(assuranceLiee.dateDebut)],["Échéance",fmt(assuranceLiee.dateEcheance)],["Prime/an",fmtAmt((assuranceLiee.prime||0)*12)]].map(([l,v])=>(
                      <div key={l} style={{background:"#0a0e17",borderRadius:8,padding:"8px 10px"}}>
                        <div style={{fontSize:10,color:T.muted,marginBottom:1}}>{l}</div>
                        <div style={{fontSize:13,fontWeight:600,color:T.text}}>{v}</div>
                      </div>
                    ))}
                  </div>
                  {assuranceLiee.dateEcheance&&(()=>{const j=daysFrom(assuranceLiee.dateEcheance);return j!=null&&j<=90&&<div style={{padding:"8px 12px",background:j<=0?"rgba(239,68,68,0.1)":"rgba(251,146,60,0.1)",borderRadius:8,fontSize:13,color:j<=0?T.danger:T.warning}}>⚠️ {j<=0?"Assurance expirée !":"Assurance à renouveler dans "+j+" jours"}</div>;})()}
                  <div style={{marginTop:10,fontSize:11,color:T.accent,textAlign:"center"}}>👆 Cliquez pour voir la fiche complète et les documents</div>
                </div>
              </Card>
            ):(
              <div style={{background:"rgba(240,165,0,0.06)",border:`1px dashed ${T.accent}`,borderRadius:12,padding:28,textAlign:"center"}}>
                <div style={{fontSize:40,marginBottom:10}}>🛡️</div>
                <div style={{color:T.text,fontWeight:600,fontSize:15,marginBottom:6}}>Aucune assurance liée automatiquement</div>
                <div style={{color:T.muted,fontSize:13,marginBottom:16,maxWidth:400,margin:"0 auto 16px"}}>Les assurances de type Auto, Moto ou contenant "{veh.marque}" ou "{veh.immat}" apparaîtront automatiquement ici.</div>
                <Btn onClick={()=>setPage&&setPage("assurances")}>→ Ajouter dans Assurances</Btn>
              </div>
            )}
            {selectedAssurVeh&&assuranceLiee&&(()=>{
              const a=assuranceLiee;
              const j=daysFrom(a.dateEcheance);
              return <FichePanel
                title={a.nom} icon="🛡️"
                badge={a.statut} badgeColor={a.statut==="actif"?T.success:T.muted}
                onClose={()=>setSelectedAssurVeh(false)}
                docs={a.docs||[]} echanges={a.echanges||[]}
                onDocsChange={()=>{}}
                docsLabel="Carte verte, contrat, conditions générales..."
                leftContent={<div>
                  <div style={{padding:"10px 12px",background:"rgba(240,165,0,0.07)",borderRadius:8,marginBottom:14,fontSize:12,color:T.accent}}>💡 Pour modifier, ouvrez le module Assurances.</div>
                  <InfoRow label="Assureur" value={a.assureur}/>
                  <InfoRow label="N° contrat" value={a.numero} mono/>
                  <InfoRow label="Type" value={a.type}/>
                  <InfoRow label="Prime mensuelle" value={fmtAmt(a.prime)} color={T.accent}/>
                  <InfoRow label="Prime annuelle" value={fmtAmt((a.prime||0)*12)} color={T.warning}/>
                  <InfoRow label="Date début" value={fmt(a.dateDebut)}/>
                  <InfoRow label="Échéance" value={fmt(a.dateEcheance)} color={j!=null&&j<=30?T.danger:T.text}/>
                  <InfoRow label="Statut" value={a.statut}/>
                  {j!=null&&j<=90&&j>=0&&<div style={{marginTop:12,padding:10,background:"rgba(251,146,60,0.1)",borderRadius:8,fontSize:12,color:T.warning}}>⚠️ Renouvellement dans {j} jours</div>}
                  {a.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{a.note}</div>}
                </div>}
              />;
            })()}
            {/* Infos utiles */}
            <Card style={{marginTop:16}}>
              <Divider label="Documents d'assurance à garder"/>
              <div style={{display:"grid",gap:6}}>
                {["Carte verte (attestation d'assurance)","Conditions générales du contrat","Relevé d'informations (bonus/malus)","Certificat de non-sinistre"].map(d=>(
                  <div key={d} style={{display:"flex",alignItems:"center",gap:8,padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                    <span style={{color:T.success}}>📄</span>
                    <span style={{color:T.text}}>{d}</span>
                  </div>
                ))}
              </div>
            </Card>
          </div>
        )}

        {/* ── ENTRETIENS ── */}
        {tab==="entretiens"&&(
          <div>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:14}}>
              <div style={{fontWeight:700,color:T.text,fontSize:16}}>Carnet d'entretien <span style={{fontSize:13,color:T.muted,fontWeight:400}}>· {fmtAmt(totalEnt)} total</span></div>
              <Btn onClick={()=>setShowEnt(true)}>+ Entretien</Btn>
            </div>
            {entretiens.length===0&&<EmptyState icon="🔧" text="Aucun entretien. Gardez une trace de tous vos passages en garage."/>}
            <div style={{display:"grid",gap:10}}>
              {[...entretiens].sort((a,b)=>b.date.localeCompare(a.date)).map(e=>(
                <Card key={e.id} onClick={()=>setSelectedEnt(e.id)} style={{padding:"12px 16px",cursor:"pointer",borderColor:selectedEnt===e.id?T.accent:T.border}}>
                  <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                    <div style={{flex:1}}>
                      <div style={{display:"flex",gap:8,alignItems:"center",marginBottom:4}}>
                        <span style={{fontWeight:700,color:T.text,fontSize:14}}>🔧 {e.type}</span>
                        <span style={{fontSize:11,color:T.muted}}>{fmt(e.date)}</span>
                        {e.kilometrage&&<Badge c={T.muted}>{Number(e.kilometrage).toLocaleString("fr-FR")} km</Badge>}
                        {(e.docs||[]).length>0&&<Badge c={T.accent}>📎 {e.docs.length}</Badge>}
                      </div>
                      {e.garage&&<div style={{fontSize:12,color:T.muted}}>🏢 {e.garage}</div>}
                    </div>
                    {e.cout>0&&<div style={{fontWeight:700,color:T.accent,fontFamily:T.fontD,fontSize:16,flexShrink:0}}>{fmtAmt(e.cout)}</div>}
                  </div>
                </Card>
              ))}
            </div>
            {selectedEnt&&(()=>{
              const e=entretiens.find(x=>x.id===selectedEnt);
              if(!e)return null;
              return <FichePanel
                title={e.type} icon="🔧"
                badge={fmt(e.date)} badgeColor={T.muted}
                onClose={()=>setSelectedEnt(null)}
                onDelete={()=>{onUpdate({...veh,entretiens:(veh.entretiens||[]).filter(x=>x.id!==e.id)});setSelectedEnt(null);}}
                docs={e.docs||[]} echanges={e.echanges||[]}
                onDocsChange={nd=>onUpdate({...veh,entretiens:(veh.entretiens||[]).map(x=>x.id===e.id?{...x,docs:nd}:x)})}
                onEchangesChange={ne=>onUpdate({...veh,entretiens:(veh.entretiens||[]).map(x=>x.id===e.id?{...x,echanges:ne}:x)})}
                docsLabel="Facture garage, bon de travail..."
                leftContent={<div>
                  <InfoRow label="Type d'entretien" value={e.type}/>
                  <InfoRow label="Date" value={fmt(e.date)}/>
                  <InfoRow label="Kilométrage" value={e.kilometrage&&Number(e.kilometrage).toLocaleString("fr-FR")+" km"}/>
                  <InfoRow label="Garage / Centre" value={e.garage}/>
                  <InfoRow label="Coût" value={e.cout&&fmtAmt(e.cout)} color={T.accent}/>
                  {e.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{e.note}</div>}
                </div>}
              />;
            })()}
          </div>
        )}

        {/* ── COÛTS ── */}
        {tab==="couts"&&(
          <div>
            <div style={{fontWeight:700,color:T.text,fontSize:16,marginBottom:16}}>💰 Coût total de possession</div>
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(180px,1fr))",gap:12,marginBottom:20}}>
              {[
                {l:"Prix d'achat",v:fmtAmt(veh.prixAchat||0),c:T.accent,icon:"🚗"},
                {l:"Entretiens",v:fmtAmt(totalEnt),c:T.warning,icon:"🔧"},
                {l:"Contrôles techniques",v:fmtAmt(totalCT),c:T.info,icon:"🔍"},
                {l:"Assurance/an",v:fmtAmt((assuranceLiee?.prime||0)*12),c:T.danger,icon:"🛡️"},
                {l:"TOTAL POSSESSION",v:fmtAmt((veh.prixAchat||0)+totalEnt+totalCT),c:T.success,icon:"💰"},
              ].map(s=>(
                <div key={s.l} style={{background:T.card,border:`1px solid ${T.border}`,borderRadius:10,padding:"14px 16px",borderLeft:`3px solid ${s.c}`}}>
                  <div style={{fontSize:20,marginBottom:4}}>{s.icon}</div>
                  <div style={{fontSize:11,color:T.muted,marginBottom:3}}>{s.l}</div>
                  <div style={{fontSize:18,fontWeight:700,color:s.c,fontFamily:T.fontD}}>{s.v}</div>
                </div>
              ))}
            </div>
            {veh.prixAchat>0&&veh.kilometrage>0&&(
              <Card>
                <Divider label="Coût au kilomètre"/>
                <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:10}}>
                  {[
                    ["Achat seul",fmtAmt((veh.prixAchat||0)/Math.max(1,veh.kilometrage))+"/km"],
                    ["Avec entretiens",fmtAmt(((veh.prixAchat||0)+totalEnt+totalCT)/Math.max(1,veh.kilometrage))+"/km"],
                    ["Kilométrage actuel",Number(veh.kilometrage).toLocaleString("fr-FR")+" km"],
                  ].map(([l,v])=>(
                    <div key={l} style={{background:"#0a0e17",borderRadius:8,padding:"10px 12px",textAlign:"center"}}>
                      <div style={{fontSize:11,color:T.muted,marginBottom:3}}>{l}</div>
                      <div style={{fontSize:15,fontWeight:700,color:T.text}}>{v}</div>
                    </div>
                  ))}
                </div>
              </Card>
            )}
          </div>
        )}

        {/* ── FICHE ── */}
        {tab==="infos"&&(
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
            <Card><Divider label="Caractéristiques"/>
              {[["Marque",veh.marque],["Modèle",veh.modele],["Immatriculation",veh.immat],["Année",veh.annee],["Couleur",veh.couleur],["Énergie",veh.energie],["Kilométrage",veh.kilometrage&&Number(veh.kilometrage).toLocaleString("fr-FR")+" km"],["Financement",veh.financement]].filter(([,v])=>v).map(([l,v])=>(
                <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                  <span style={{color:T.muted}}>{l}</span><span style={{color:T.text,fontWeight:500}}>{v}</span>
                </div>
              ))}
            </Card>
            <Card><Divider label="Financier & Échéances"/>
              {[["Prix d'achat",veh.prixAchat&&fmtAmt(veh.prixAchat)],["Date d'achat",fmt(veh.dateAchat)],["Prochain CT",fmt(veh.dateCT)],["Assurance expire",fmt(veh.dateAssurance)],["Crit'Air",fmt(veh.dateCritair)]].filter(([,v])=>v&&v!=="—").map(([l,v])=>(
                <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                  <span style={{color:T.muted}}>{l}</span><span style={{color:T.text,fontWeight:500}}>{v}</span>
                </div>
              ))}
              {veh.note&&<div style={{marginTop:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{veh.note}</div>}
            </Card>
          </div>
        )}
      </div>

      {showCT&&<Modal title="🔍 Contrôle Technique" onClose={()=>setShowCT(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Date du CT *"><Inp type="date" value={formCT.date} onChange={v=>setFormCT(f=>({...f,date:v}))}/></F>
          <F label="Résultat"><Sel value={formCT.resultat} onChange={v=>setFormCT(f=>({...f,resultat:v}))}><option>Favorable</option><option>Défavorable</option><option>Contre-visite</option></Sel></F>
          <F label="Centre de contrôle"><Inp value={formCT.centre} onChange={v=>setFormCT(f=>({...f,centre:v}))} placeholder="Autovision, Bureau Veritas..."/></F>
          <F label="Coût (€)"><Inp type="number" value={formCT.cout} onChange={v=>setFormCT(f=>({...f,cout:v}))}/></F>
          <F label="Prochain CT (date)"><Inp type="date" value={formCT.prochainCT} onChange={v=>setFormCT(f=>({...f,prochainCT:v}))}/></F>
          <F label="Note"><Inp value={formCT.note} onChange={v=>setFormCT(f=>({...f,note:v}))}/></F>
        </div>
        <F label="Défauts constatés"><Inp value={formCT.defauts} onChange={v=>setFormCT(f=>({...f,defauts:v}))} placeholder="Feux arrière gauche, amortisseurs..."/></F>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
          <Btn v="ghost" onClick={()=>setShowCT(false)}>Annuler</Btn>
          <Btn onClick={()=>{
            const updated={...veh,histoCT:[...(veh.histoCT||[]),{...formCT,id:uid(),cout:parseFloat(formCT.cout)||0}]};
            if(formCT.prochainCT)updated.dateCT=formCT.prochainCT;
            onUpdate(updated);setShowCT(false);
          }}>💾 Enregistrer</Btn>
        </div>
      </Modal>}

      {showEnt&&<Modal title="🔧 Entretien / Réparation" onClose={()=>setShowEnt(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Type *"><Sel value={formE.type} onChange={v=>setFormE(f=>({...f,type:v}))}>{ENTRETIENS_TYPES.map(t=><option key={t}>{t}</option>)}</Sel></F>
          <F label="Date"><Inp type="date" value={formE.date} onChange={v=>setFormE(f=>({...f,date:v}))}/></F>
          <F label="Kilométrage"><Inp type="number" value={formE.kilometrage} onChange={v=>setFormE(f=>({...f,kilometrage:v}))}/></F>
          <F label="Coût (€)"><Inp type="number" value={formE.cout} onChange={v=>setFormE(f=>({...f,cout:v}))}/></F>
          <F label="Garage / Artisan"><Inp value={formE.garage} onChange={v=>setFormE(f=>({...f,garage:v}))} placeholder="Garage Central..."/></F>
          <F label="Note"><Inp value={formE.note} onChange={v=>setFormE(f=>({...f,note:v}))}/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
          <Btn v="ghost" onClick={()=>setShowEnt(false)}>Annuler</Btn>
          <Btn onClick={()=>{onUpdate({...veh,entretiens:[...(veh.entretiens||[]),{...formE,id:uid(),cout:parseFloat(formE.cout)||0}]});setShowEnt(false);}}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

const Vehicules=({vehicules,setVehicules,assurances=[],setPage})=>{
  const [selected,setSelected]=useState(null);
  const [showAdd,setShowAdd]=useState(false);
  const [formV,setFormV]=useState({type:"voiture",marque:"",modele:"",annee:"",immat:"",couleur:"",energie:"Essence",kilometrage:"",prixAchat:"",dateAchat:"",dateCT:"",dateAssurance:"",financement:"",note:""});

  const sel=vehicules.find(v=>v.id===selected);
  const TYPES_VEH=[{v:"voiture",l:"Voiture",i:"🚗"},{v:"moto",l:"Moto",i:"🏍️"},{v:"velo",l:"Vélo / VAE",i:"🚲"},{v:"camping",l:"Camping-car",i:"🚐"},{v:"bateau",l:"Bateau",i:"⛵"}];

  if(selected&&sel) return <VehiculeDetail veh={sel} onUpdate={upd=>setVehicules(p=>p.map(v=>v.id===upd.id?upd:v))} onClose={()=>setSelected(null)} assurances={assurances} setPage={setPage}/>;

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🚗 Véhicules</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>{vehicules.length} véhicule{vehicules.length!==1?"s":""} · entretien · CT · assurance</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Véhicule</Btn>
      </div>
      {vehicules.length===0&&<EmptyState icon="🚗" text="Aucun véhicule. Ajoutez votre voiture, moto, vélo..."/>}
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(320px,1fr))",gap:16}}>
        {vehicules.map(v=>{
          const ti=TYPES_VEH.find(t=>t.v===v.type);
          const entretiens=v.entretiens||[];
          const totalEnt=entretiens.reduce((s,e)=>s+(parseFloat(e.cout)||0),0);
          const totalCT=(v.histoCT||[]).reduce((s,c)=>s+(parseFloat(c.cout)||0),0);
          const prochainCT=daysFrom(v.dateCT);
          const prochainAssur=daysFrom(v.dateAssurance);
          const assurLiee=assurances.find(a=>a.type==="auto"||a.type==="moto"||(a.nom||"").toLowerCase().includes((v.marque||"").toLowerCase())||(a.nom||"").toLowerCase().includes((v.immat||"").toLowerCase().slice(0,4)));
          return (
            <Card key={v.id} onClick={()=>setSelected(v.id)} style={{padding:0,overflow:"hidden",cursor:"pointer"}}
              onMouseEnter={e=>e.currentTarget.style.borderColor=T.accent} onMouseLeave={e=>e.currentTarget.style.borderColor=T.border}>
              <div style={{background:"linear-gradient(135deg,#1a2235,#2a3550)",padding:"18px 16px",borderBottom:`1px solid ${T.border}`}}>
                <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                  <div>
                    <div style={{fontSize:30,marginBottom:4}}>{ti?.i||"🚗"}</div>
                    <div style={{fontFamily:T.fontD,fontSize:17,color:T.text}}>{v.marque} {v.modele}</div>
                    <div style={{fontSize:11,color:T.muted}}>{v.immat&&"🪪 "+v.immat+" · "}{v.annee&&"📅 "+v.annee}{v.couleur&&" · "+v.couleur}</div>
                  </div>
                  <div style={{textAlign:"right"}}>
                    <Badge c={T.info}>{ti?.l||v.type}</Badge>
                    {v.energie&&<div style={{fontSize:11,color:T.muted,marginTop:4}}>⛽ {v.energie}</div>}
                  </div>
                </div>
              </div>
              <div style={{padding:14}}>
                <div style={{display:"grid",gridTemplateColumns:"repeat(4,1fr)",gap:6,marginBottom:10}}>
                  <div style={{background:"#0a0e17",borderRadius:6,padding:"6px",textAlign:"center"}}>
                    <div style={{fontSize:8,color:T.muted}}>KM</div>
                    <div style={{fontSize:11,fontWeight:700,color:T.text}}>{v.kilometrage?Math.round(v.kilometrage/1000)+"k":"—"}</div>
                  </div>
                  <div style={{background:"#0a0e17",borderRadius:6,padding:"6px",textAlign:"center"}}>
                    <div style={{fontSize:8,color:T.muted}}>CT dans</div>
                    <div style={{fontSize:11,fontWeight:700,color:prochainCT!=null&&prochainCT<=90?T.danger:T.success}}>{v.dateCT?(prochainCT!=null&&prochainCT>=0?prochainCT+"j":"EXP!"):"—"}</div>
                  </div>
                  <div style={{background:"#0a0e17",borderRadius:6,padding:"6px",textAlign:"center"}}>
                    <div style={{fontSize:8,color:T.muted}}>Entretiens</div>
                    <div style={{fontSize:11,fontWeight:700,color:T.accent}}>{entretiens.length+(v.histoCT||[]).length}</div>
                  </div>
                  <div style={{background:"#0a0e17",borderRadius:6,padding:"6px",textAlign:"center"}}>
                    <div style={{fontSize:8,color:T.muted}}>Assurance</div>
                    <div style={{fontSize:11,fontWeight:700,color:assurLiee?T.success:T.muted}}>{assurLiee?"✓":"—"}</div>
                  </div>
                </div>
                <div style={{display:"flex",gap:5,flexWrap:"wrap"}}>
                  {prochainCT!=null&&prochainCT<=90&&<Badge c={prochainCT<=0?T.danger:T.warning}>CT {prochainCT<=0?"expiré":prochainCT+"j"}</Badge>}
                  {prochainAssur!=null&&prochainAssur<=30&&<Badge c={T.danger}>Assur. {prochainAssur<=0?"expirée":prochainAssur+"j"}</Badge>}
                  {(totalEnt+totalCT)>0&&<Badge c={T.muted}>{fmtAmt(totalEnt+totalCT)} entretien</Badge>}
                </div>
                <div style={{marginTop:10,fontSize:12,color:T.accent,fontWeight:600}}>→ Ouvrir le dossier</div>
              </div>
            </Card>
          );
        })}
      </div>

      {showAdd&&<Modal title="🚗 Nouveau véhicule" onClose={()=>setShowAdd(false)} width={700}>
        <div style={{display:"flex",gap:10,marginBottom:12,flexWrap:"wrap"}}>
          {TYPES_VEH.map(t=><button key={t.v} onClick={()=>setFormV(f=>({...f,type:t.v}))} style={{background:formV.type===t.v?T.accentDim:"transparent",border:`2px solid ${formV.type===t.v?T.accent:T.border}`,borderRadius:8,padding:"8px 12px",cursor:"pointer",fontSize:13,color:formV.type===t.v?T.accent:T.muted,fontFamily:T.font}}>{t.i} {t.l}</button>)}
        </div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Marque *"><Inp value={formV.marque} onChange={v=>setFormV(f=>({...f,marque:v}))} placeholder="Renault, Peugeot..."/></F>
          <F label="Modèle *"><Inp value={formV.modele} onChange={v=>setFormV(f=>({...f,modele:v}))} placeholder="Clio, 308..."/></F>
          <F label="Immatriculation"><Inp value={formV.immat} onChange={v=>setFormV(f=>({...f,immat:v}))} placeholder="AB-123-CD"/></F>
          <F label="Année"><Inp type="number" value={formV.annee} onChange={v=>setFormV(f=>({...f,annee:v}))} placeholder="2020"/></F>
          <F label="Énergie"><Sel value={formV.energie} onChange={v=>setFormV(f=>({...f,energie:v}))}>{["Essence","Diesel","Hybride","Électrique","GPL"].map(e=><option key={e}>{e}</option>)}</Sel></F>
          <F label="Couleur"><Inp value={formV.couleur} onChange={v=>setFormV(f=>({...f,couleur:v}))} placeholder="Blanc, Noir..."/></F>
          <F label="Kilométrage actuel"><Inp type="number" value={formV.kilometrage} onChange={v=>setFormV(f=>({...f,kilometrage:v}))}/></F>
          <F label="Prix d'achat (€)"><Inp type="number" value={formV.prixAchat} onChange={v=>setFormV(f=>({...f,prixAchat:v}))}/></F>
          <F label="Prochain CT"><Inp type="date" value={formV.dateCT} onChange={v=>setFormV(f=>({...f,dateCT:v}))}/></F>
          <F label="Assurance expire"><Inp type="date" value={formV.dateAssurance} onChange={v=>setFormV(f=>({...f,dateAssurance:v}))}/></F>
        </div>
        <F label="Note"><Inp value={formV.note} onChange={v=>setFormV(f=>({...f,note:v}))}/></F>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={()=>{setVehicules(p=>[...p,{...formV,id:uid(),kilometrage:+formV.kilometrage||0,prixAchat:+formV.prixAchat||0,entretiens:[],histoCT:[]}]);setShowAdd(false);}} disabled={!formV.marque}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};
// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: SPORTS & PASSIONS
// ═══════════════════════════════════════════════════════════════════════════════
const Sports=({sports,setSports})=>{
  const [selected,setSelected]=useState(null);
  const [showAdd,setShowAdd]=useState(false);
  const [showSeance,setShowSeance]=useState(false);
  const [formS,setFormS]=useState({nom:"",icon:"⚽",categorie:"Sport",niveau:"Débutant",pratiqueSince:"",frequence:"",club:"",licence:"",licenceExpiry:"",note:""});
  const [formSe,setFormSe]=useState({date:today(),duree:"",distance:"",calories:"",note:""});

  const sel=sports.find(s=>s.id===selected);
  const ICONS_SPORTS=["⚽","🏀","🎾","🏊","🚴","🏃","⛷️","🧘","🥊","🎸","🎨","📚","🌿","🎮","✈️","🎭","🍳","📷","🐕","🎯","🏋️","🤸","🏄","⛳","🎻","🎺","🎲","🪴"];
  const CATS=["Sport","Musique","Art","Lecture","Nature","Voyage","Cuisine","Photo","Animaux","Jeux","Autre"];

  const totalSeances=(sel?.seances||[]).length;
  const totalTemps=(sel?.seances||[]).reduce((s,se)=>s+(parseFloat(se.duree)||0),0);
  const totalDist=(sel?.seances||[]).reduce((s,se)=>s+(parseFloat(se.distance)||0),0);

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>⚽ Sports & Passions</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>{sports.length} activité{sports.length!==1?"s":" enregistrée"} · suivi, équipements, objectifs</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Activité</Btn>
      </div>

      {sports.length===0&&<EmptyState icon="⚽" text="Ajoutez vos sports et passions pour en garder la trace !"/>}
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(260px,1fr))",gap:14}}>
        {sports.map(s=>{
          const seances=s.seances||[];
          const licJ=daysFrom(s.licenceExpiry);
          const lastSeance=seances.length>0?[...seances].sort((a,b)=>b.date.localeCompare(a.date))[0]:null;
          return (
            <Card key={s.id} onClick={()=>setSelected(s.id)} style={{cursor:"pointer",borderColor:selected===s.id?T.accent:T.border}}>
              <div style={{display:"flex",alignItems:"flex-start",gap:12}}>
                <div style={{width:52,height:52,borderRadius:12,background:T.accentDim,display:"flex",alignItems:"center",justifyContent:"center",fontSize:26,flexShrink:0}}>{s.icon}</div>
                <div style={{flex:1,minWidth:0}}>
                  <div style={{fontWeight:700,color:T.text,fontSize:15,marginBottom:2}}>{s.nom}</div>
                  <div style={{fontSize:11,color:T.muted,marginBottom:6}}>{s.categorie}{s.club&&" · "+s.club}{s.niveau&&" · "+s.niveau}</div>
                  <div style={{display:"flex",gap:6,flexWrap:"wrap"}}>
                    {seances.length>0&&<Badge c={T.success}>{seances.length} séances</Badge>}
                    {(s.equipements||[]).length>0&&<Badge c={T.info}>{(s.equipements||[]).length} équip.</Badge>}
                    {licJ!=null&&licJ<=60&&<Badge c={licJ<=0?T.danger:T.warning}>Licence {licJ<=0?"expirée":licJ+"j"}</Badge>}
                    {(s.docs||[]).length>0&&<Badge c={T.accent}>📎 {s.docs.length}</Badge>}
                  </div>
                  {lastSeance&&<div style={{fontSize:11,color:T.muted,marginTop:4}}>Dernière: {fmt(lastSeance.date)}</div>}
                </div>
              </div>
            </Card>
          );
        })}
      </div>

      {sel&&selected&&<FichePanel
        title={sel.nom}
        icon={sel.icon}
        badge={sel.categorie} badgeColor={T.accent}
        onClose={()=>setSelected(null)}
        onDelete={()=>{setSports(p=>p.filter(s=>s.id!==sel.id));setSelected(null);}}
        docs={sel.docs||[]} echanges={sel.echanges||[]}
        onDocsChange={nd=>setSports(p=>p.map(s=>s.id===sel.id?{...s,docs:nd}:s))}
        onEchangesChange={ne=>setSports(p=>p.map(s=>s.id===sel.id?{...s,echanges:ne}:s))}
        docsLabel="Licence, certificat médical, palmarès, photos..."
        leftContent={<div>
          <InfoRow label="Activité" value={sel.nom}/>
          <InfoRow label="Catégorie" value={sel.categorie}/>
          <InfoRow label="Niveau" value={sel.niveau}/>
          <InfoRow label="Club / Salle" value={sel.club}/>
          <InfoRow label="Fréquence" value={sel.frequence}/>
          <InfoRow label="Pratique depuis" value={fmt(sel.pratiqueSince)}/>
          <InfoRow label="Licence expire" value={fmt(sel.licenceExpiry)} color={daysFrom(sel.licenceExpiry)!=null&&daysFrom(sel.licenceExpiry)<=30?T.danger:T.text}/>
          <div style={{marginTop:16}}>
            <Divider label="Statistiques"/>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
              <div style={{background:"#0a0e17",borderRadius:8,padding:"8px 12px",textAlign:"center"}}>
                <div style={{fontSize:9,color:T.muted,textTransform:"uppercase"}}>Séances</div>
                <div style={{fontSize:22,fontWeight:700,color:T.success,fontFamily:T.fontD}}>{totalSeances}</div>
              </div>
              <div style={{background:"#0a0e17",borderRadius:8,padding:"8px 12px",textAlign:"center"}}>
                <div style={{fontSize:9,color:T.muted,textTransform:"uppercase"}}>Temps total</div>
                <div style={{fontSize:22,fontWeight:700,color:T.info,fontFamily:T.fontD}}>{totalTemps>0?Math.round(totalTemps/60)+"h":"—"}</div>
              </div>
              {totalDist>0&&<div style={{background:"#0a0e17",borderRadius:8,padding:"8px 12px",textAlign:"center",gridColumn:"1/-1"}}>
                <div style={{fontSize:9,color:T.muted,textTransform:"uppercase"}}>Distance totale</div>
                <div style={{fontSize:18,fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{totalDist} km</div>
              </div>}
            </div>
          </div>
          <div style={{marginTop:14}}>
            <Divider label="Dernières séances"/>
            {(sel.seances||[]).length===0&&<div style={{fontSize:12,color:T.muted}}>Aucune séance enregistrée.</div>}
            <div style={{display:"grid",gap:6,maxHeight:200,overflowY:"auto"}}>
              {[...(sel.seances||[])].sort((a,b)=>b.date.localeCompare(a.date)).slice(0,8).map(se=>(
                <div key={se.id} style={{display:"flex",justifyContent:"space-between",padding:"7px 10px",background:"#0a0e17",borderRadius:7,fontSize:12}}>
                  <span style={{color:T.muted}}>{fmt(se.date)}</span>
                  <div style={{display:"flex",gap:10}}>
                    {se.duree&&<span style={{color:T.info}}>{se.duree>60?Math.round(se.duree/60)+"h":se.duree+"min"}</span>}
                    {se.distance&&<span style={{color:T.accent}}>{se.distance}km</span>}
                    {se.calories&&<span style={{color:T.success}}>{se.calories}kcal</span>}
                  </div>
                </div>
              ))}
            </div>
            <div style={{marginTop:10}}>
              <Btn sm onClick={()=>setShowSeance(true)}>+ Ajouter une séance</Btn>
            </div>
          </div>
          {(sel.equipements||[]).length>0&&<div style={{marginTop:14}}>
            <Divider label="Équipements"/>
            <div style={{display:"flex",gap:6,flexWrap:"wrap"}}>
              {(sel.equipements||[]).map(e=><Badge key={e.id} c={T.muted}>{e.nom}{e.marque&&" · "+e.marque}</Badge>)}
            </div>
          </div>}
          {sel.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{sel.note}</div>}
        </div>}
      />}

      {showAdd&&<Modal title="⚽ Nouvelle activité" onClose={()=>setShowAdd(false)}>
        <div style={{display:"flex",gap:6,flexWrap:"wrap",marginBottom:14}}>
          {ICONS_SPORTS.map(ic=><button key={ic} onClick={()=>setFormS(f=>({...f,icon:ic}))} style={{fontSize:20,background:formS.icon===ic?T.accentDim:"transparent",border:`2px solid ${formS.icon===ic?T.accent:"transparent"}`,borderRadius:8,padding:4,cursor:"pointer"}}>{ic}</button>)}
        </div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Nom *"><Inp value={formS.nom} onChange={v=>setFormS(f=>({...f,nom:v}))} placeholder="Tennis, Guitare, Randonnée..."/></F>
          <F label="Catégorie"><Sel value={formS.categorie} onChange={v=>setFormS(f=>({...f,categorie:v}))}>{CATS.map(c=><option key={c}>{c}</option>)}</Sel></F>
          <F label="Niveau"><Sel value={formS.niveau} onChange={v=>setFormS(f=>({...f,niveau:v}))}><option>Débutant</option><option>Intermédiaire</option><option>Confirmé</option><option>Expert</option></Sel></F>
          <F label="Fréquence"><Inp value={formS.frequence} onChange={v=>setFormS(f=>({...f,frequence:v}))} placeholder="2x/semaine..."/></F>
          <F label="Club / Salle"><Inp value={formS.club} onChange={v=>setFormS(f=>({...f,club:v}))} placeholder="Club de Tennis de Langon..."/></F>
          <F label="Licence expire"><Inp type="date" value={formS.licenceExpiry} onChange={v=>setFormS(f=>({...f,licenceExpiry:v}))}/></F>
        </div>
        <F label="Note"><Inp value={formS.note} onChange={v=>setFormS(f=>({...f,note:v}))} placeholder="Objectifs, infos..."/></F>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={()=>{setSports(p=>[...p,{...formS,id:uid(),seances:[],equipements:[],objectifs:[]}]);setShowAdd(false);}} disabled={!formS.nom}>💾 Enregistrer</Btn>
        </div>
      </Modal>}

      {showSeance&&sel&&<Modal title={`${sel.icon} Nouvelle séance — ${sel.nom}`} onClose={()=>setShowSeance(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Date"><Inp type="date" value={formSe.date} onChange={v=>setFormSe(f=>({...f,date:v}))}/></F>
          <F label="Durée (minutes)"><Inp type="number" value={formSe.duree} onChange={v=>setFormSe(f=>({...f,duree:v}))} placeholder="60"/></F>
          <F label="Distance (km)"><Inp type="number" value={formSe.distance} onChange={v=>setFormSe(f=>({...f,distance:v}))} placeholder="10"/></F>
          <F label="Calories brûlées"><Inp type="number" value={formSe.calories} onChange={v=>setFormSe(f=>({...f,calories:v}))} placeholder="300"/></F>
        </div>
        <F label="Note / Ressenti"><Txt value={formSe.note} onChange={v=>setFormSe(f=>({...f,note:v}))} rows={2} placeholder="Belle séance, jambes lourdes..."/></F>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
          <Btn v="ghost" onClick={()=>setShowSeance(false)}>Annuler</Btn>
          <Btn onClick={()=>{setSports(p=>p.map(s=>s.id===sel.id?{...s,seances:[...(s.seances||[]),{...formSe,id:uid()}]}:s));setShowSeance(false);}}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: PHOTOS & VIDÉOS — Pro (galerie, éditeur, montage, reconnaissance faciale)
// ═══════════════════════════════════════════════════════════════════════════════

// Palettes démo
const DEMO_PALETTES=[
  {title:"Coucher de soleil",palette:["#ff6b35","#f7931e","#1a0a00"],date:"2024-08-15",album:"Vacances 2024",tags:["nature","soleil"],loc:"Côte d'Azur",faces:["f1","f2"]},
  {title:"Plage",palette:["#0077b6","#00b4d8","#90e0ef"],date:"2024-08-16",album:"Vacances 2024",tags:["mer"],loc:"Nice",faces:["f1"]},
  {title:"Soirée famille",palette:["#2d1b69","#7b2d8b","#c44569"],date:"2024-08-17",album:"Vacances 2024",tags:["famille"],loc:"Nice",faces:["f1","f2","f3"]},
  {title:"Montagne",palette:["#134e5e","#71b280","#c8f5c8"],date:"2024-12-22",album:"Chalet Megève",tags:["montagne"],loc:"Megève",faces:["f1","f2"]},
  {title:"Ski",palette:["#e0f4ff","#4facfe","#00f2fe"],date:"2024-12-23",album:"Chalet Megève",tags:["sport"],loc:"Megève",faces:["f2"]},
  {title:"Noël en famille",palette:["#1a472a","#c41e3a","#ffd700"],date:"2024-12-25",album:"Noël 2024",tags:["famille","noël"],loc:"Langon",faces:["f1","f2","f3","f4"]},
  {title:"Match Tennis",palette:["#2ecc71","#27ae60","#0a3d0a"],date:"2025-01-12",album:"Tennis 2025",tags:["sport"],loc:"TC Langon",faces:["f1"]},
  {title:"Running",palette:["#ff7043","#ff5722","#110800"],date:"2025-02-05",album:"Running 2025",tags:["sport"],loc:"Langon",faces:["f1"]},
  {title:"Jardin",palette:["#56ab2f","#a8e063","#023b00"],date:"2025-03-01",album:"Maison",tags:["jardin"],loc:"Langon",faces:[]},
  {title:"Chalet intérieur",palette:["#8B4513","#D2691E","#3a1c02"],date:"2024-12-24",album:"Chalet Megève",tags:["maison"],loc:"Megève",faces:["f1","f2","f4"]},
  {title:"Cuisine rénovée",palette:["#bdc3c7","#95a5a6","#2c3e50"],date:"2025-01-20",album:"Travaux 2025",tags:["maison"],loc:"Langon",faces:[]},
  {title:"Nuit étoilée",palette:["#0f0c29","#302b63","#24243e"],date:"2025-02-14",album:"Nature",tags:["nuit"],loc:"Langon",faces:[]},
];

const DEMO_FACES=[
  {id:"f1",nom:"Moi",initiales:"M",color:"#f0a500",nbPhotos:8},
  {id:"f2",nom:"Marie",initiales:"Ma",color:"#34d399",nbPhotos:6},
  {id:"f3",nom:"Pierre",initiales:"Pi",color:"#38bdf8",nbPhotos:3},
  {id:"f4",nom:"Inconnu",initiales:"?",color:"#6b7a99",nbPhotos:3},
];

const makeDemoImg=(title,palette,w=600,h=400)=>{
  try{
    const c=document.createElement("canvas");c.width=w;c.height=h;
    const ctx=c.getContext("2d");
    const g=ctx.createLinearGradient(0,0,w,h);
    g.addColorStop(0,palette[0]);g.addColorStop(0.5,palette[1]||palette[0]);g.addColorStop(1,palette[2]||"#000");
    ctx.fillStyle=g;ctx.fillRect(0,0,w,h);
    const r=ctx.createRadialGradient(w*0.3,h*0.25,0,w*0.3,h*0.25,w*0.45);
    r.addColorStop(0,"rgba(255,255,255,0.18)");r.addColorStop(1,"rgba(0,0,0,0)");
    ctx.fillStyle=r;ctx.fillRect(0,0,w,h);
    for(let i=0;i<2000;i++){ctx.fillStyle=`rgba(255,255,255,${Math.random()*0.025})`;ctx.fillRect(Math.random()*w,Math.random()*h,1,1);}
    ctx.fillStyle="rgba(255,255,255,0.88)";ctx.font=`bold ${Math.min(w/9,52)}px sans-serif`;ctx.textAlign="center";ctx.textBaseline="middle";
    ctx.fillText(title,w/2,h/2);
    return c.toDataURL("image/jpeg",0.82);
  }catch{return null;}
};

const PHOTO_PRESETS=[
  {id:"normal",label:"Normal",filter:""},
  {id:"vivid",label:"Vivid",filter:"saturate(165%) contrast(115%)"},
  {id:"cool",label:"Cool",filter:"hue-rotate(20deg) saturate(88%) brightness(106%)"},
  {id:"warm",label:"Chaud",filter:"sepia(28%) saturate(128%) brightness(106%)"},
  {id:"fade",label:"Fade",filter:"brightness(114%) contrast(76%) saturate(80%)"},
  {id:"noir",label:"Noir",filter:"grayscale(100%) contrast(128%)"},
  {id:"drama",label:"Drama",filter:"contrast(152%) saturate(72%) brightness(86%)"},
  {id:"vintage",label:"Vintage",filter:"sepia(58%) contrast(86%) brightness(110%) saturate(62%)"},
  {id:"matte",label:"Matte",filter:"contrast(83%) saturate(88%) brightness(110%)"},
];

const buildFilterStr=(adj,presetFilter)=>{
  const b=`brightness(${adj.brightness}%) contrast(${adj.contrast}%) saturate(${adj.saturation}%) hue-rotate(${adj.hue}deg) blur(${adj.blur}px)`;
  return presetFilter?b+" "+presetFilter:b;
};
const initAdj=()=>({brightness:100,contrast:100,saturation:100,hue:0,blur:0,vignette:0});
const initEditState=()=>({adj:initAdj(),preset:"normal",rotation:0,flipH:false,flipV:false});

// ── Photo Editor ──────────────────────────────────────────────────────────────
const PhotoEditor=({photo,onClose,onSave})=>{
  const [edit,setEdit]=useState(photo.editState||initEditState());
  const [panel,setPanel]=useState("filters");
  const canvasRef=useRef();
  const filterStr=buildFilterStr(edit.adj,PHOTO_PRESETS.find(p=>p.id===edit.preset)?.filter||"");
  const transformStr=`rotate(${edit.rotation}deg) scaleX(${edit.flipH?-1:1}) scaleY(${edit.flipV?-1:1})`;
  const setAdj=(k,v)=>setEdit(e=>({...e,adj:{...e.adj,[k]:v}}));

  const photoSrc=photo.url||photo.dataUrl||null;

  const handleSave=()=>{
    if(!photoSrc){onSave({...photo,editState:edit});return;}
    const img=new Image();
    img.crossOrigin="anonymous";
    img.onload=()=>{
      const cv=canvasRef.current||document.createElement("canvas");
      cv.width=img.width;cv.height=img.height;
      const ctx=cv.getContext("2d");
      ctx.filter=filterStr;
      ctx.save();ctx.translate(img.width/2,img.height/2);ctx.rotate(edit.rotation*Math.PI/180);ctx.scale(edit.flipH?-1:1,edit.flipV?-1:1);ctx.drawImage(img,-img.width/2,-img.height/2);ctx.restore();
      if(edit.adj.vignette>0){const vg=ctx.createRadialGradient(img.width/2,img.height/2,img.width*0.28,img.width/2,img.height/2,img.width*0.82);vg.addColorStop(0,"rgba(0,0,0,0)");vg.addColorStop(1,`rgba(0,0,0,${edit.adj.vignette/100})`);ctx.filter="none";ctx.fillStyle=vg;ctx.fillRect(0,0,img.width,img.height);}
      onSave({...photo,dataUrl:cv.toDataURL("image/jpeg",0.92),url:null,editState:edit});
    };
    img.src=photoSrc;
  };

  return (
    <div style={{position:"fixed",inset:0,background:"#000",zIndex:3000,display:"flex",flexDirection:"column",fontFamily:T.font}}>
      <div style={{height:50,background:"#0a0a0a",borderBottom:"1px solid #222",display:"flex",alignItems:"center",padding:"0 14px",gap:10,flexShrink:0}}>
        <button onClick={onClose} style={{background:"rgba(255,255,255,0.08)",border:"1px solid #333",color:"#e2ddd5",borderRadius:7,padding:"5px 12px",cursor:"pointer",fontFamily:T.font,fontSize:12}}>✕ Fermer</button>
        <div style={{flex:1,textAlign:"center",fontFamily:T.fontD,fontSize:15,color:"#e2ddd5"}}>{photo.title}</div>
        <button onClick={()=>setEdit(initEditState())} style={{background:"rgba(255,255,255,0.06)",border:"1px solid #333",color:"#6b7a99",borderRadius:7,padding:"5px 12px",cursor:"pointer",fontFamily:T.font,fontSize:12}}>↺ Réinit.</button>
        <button onClick={handleSave} style={{background:T.accent,border:"none",color:"#000",borderRadius:7,padding:"6px 16px",cursor:"pointer",fontFamily:T.font,fontSize:12,fontWeight:700}}>💾 Enregistrer</button>
      </div>
      <div style={{flex:1,display:"flex",overflow:"hidden"}}>
        <div style={{flex:1,display:"flex",alignItems:"center",justifyContent:"center",background:"#050505",position:"relative"}}>
          {photoSrc&&<img src={photoSrc} alt="" style={{maxWidth:"86%",maxHeight:"86%",objectFit:"contain",filter:filterStr,transform:transformStr,transition:"filter 0.15s,transform 0.2s",borderRadius:3}}/>}
          {edit.adj.vignette>0&&<div style={{position:"absolute",inset:0,background:`radial-gradient(ellipse at center,transparent 28%,rgba(0,0,0,${edit.adj.vignette/115}) 100%)`,pointerEvents:"none"}}/>}
          <canvas ref={canvasRef} style={{display:"none"}}/>
          <div style={{position:"absolute",bottom:14,left:"50%",transform:"translateX(-50%)",display:"flex",gap:6}}>
            {[["⟳",()=>setEdit(e=>({...e,rotation:(e.rotation+90)%360}))],["⟲",()=>setEdit(e=>({...e,rotation:(e.rotation-90+360)%360}))],["↔",()=>setEdit(e=>({...e,flipH:!e.flipH}))],["↕",()=>setEdit(e=>({...e,flipV:!e.flipV}))]].map(([l,fn])=>(
              <button key={l} onClick={fn} style={{width:38,height:38,borderRadius:19,background:"rgba(0,0,0,0.75)",border:"1px solid #333",color:"#fff",cursor:"pointer",fontSize:16,display:"flex",alignItems:"center",justifyContent:"center"}}>{l}</button>
            ))}
          </div>
        </div>
        <div style={{width:272,background:"#111",borderLeft:"1px solid #222",display:"flex",flexDirection:"column"}}>
          <div style={{display:"flex",borderBottom:"1px solid #222"}}>
            {[{id:"filters",l:"🎨 Filtres"},{id:"adjust",l:"⚡ Réglages"},{id:"transform",l:"↻ Rotation"}].map(p=>(
              <button key={p.id} onClick={()=>setPanel(p.id)} style={{flex:1,padding:"9px 4px",border:"none",background:panel===p.id?"rgba(240,165,0,0.1)":"transparent",color:panel===p.id?T.accent:"#6b7a99",cursor:"pointer",fontFamily:T.font,fontSize:10,borderBottom:panel===p.id?`2px solid ${T.accent}`:"2px solid transparent"}}>{p.l}</button>
            ))}
          </div>
          <div style={{flex:1,overflow:"auto",padding:13}}>
            {panel==="filters"&&(
              <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:6}}>
                {PHOTO_PRESETS.map(p=>(
                  <div key={p.id} onClick={()=>setEdit(e=>({...e,preset:p.id}))} style={{cursor:"pointer",borderRadius:7,overflow:"hidden",border:`2px solid ${edit.preset===p.id?T.accent:"transparent"}`,transition:"border 0.12s"}}>
                    {photoSrc?<div style={{height:54,overflow:"hidden"}}><img src={photoSrc} alt="" style={{width:"100%",height:"100%",objectFit:"cover",filter:p.filter}}/></div>:<div style={{height:54,background:"#1a1a1a"}}/>}
                    <div style={{background:"#0d0d0d",padding:"3px 0",textAlign:"center",fontSize:9,color:edit.preset===p.id?T.accent:"#666"}}>{p.label}</div>
                  </div>
                ))}
              </div>
            )}
            {panel==="adjust"&&[["Luminosité","brightness",50,200],["Contraste","contrast",50,200],["Saturation","saturation",0,300],["Teinte","hue",-180,180],["Vignette","vignette",0,100],["Flou","blur",0,10,0.5]].map(([l,k,mn,mx,st=1])=>(
              <div key={k} style={{marginBottom:11}}>
                <div style={{display:"flex",justifyContent:"space-between",marginBottom:4,fontSize:11}}><span style={{color:"#6b7a99"}}>{l}</span><span style={{color:T.accent,fontWeight:600}}>{edit.adj[k]}{l==="Flou"?"px":"%"}</span></div>
                <input type="range" min={mn} max={mx} step={st} value={edit.adj[k]} onChange={e=>setAdj(k,+e.target.value)} style={{width:"100%",accentColor:T.accent,height:3,cursor:"pointer"}}/>
              </div>
            ))}
            {panel==="transform"&&(
              <div>
                <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:7,marginBottom:12}}>
                  {[["⟳ 90°",()=>setEdit(e=>({...e,rotation:(e.rotation+90)%360}))],["⟲ -90°",()=>setEdit(e=>({...e,rotation:(e.rotation-90+360)%360}))],["↔ Miroir H",()=>setEdit(e=>({...e,flipH:!e.flipH}))],["↕ Miroir V",()=>setEdit(e=>({...e,flipV:!e.flipV}))]].map(([l,fn])=>(
                    <button key={l} onClick={fn} style={{padding:"8px 4px",background:"rgba(255,255,255,0.06)",border:"1px solid #2a2a2a",color:"#e2ddd5",borderRadius:7,cursor:"pointer",fontFamily:T.font,fontSize:11}}>{l}</button>
                  ))}
                </div>
                <div style={{fontSize:11,color:"#6b7a99"}}>Rotation: {edit.rotation}°{edit.flipH?" · H:✓":""}{ edit.flipV?" · V:✓":""}</div>
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

// ── Slideshow/Montage ─────────────────────────────────────────────────────────
const SlideshowPlayer=({mediaList,onClose})=>{
  const [idx,setIdx]=useState(0);const [playing,setPlaying]=useState(false);const [dur,setDur]=useState(3);const [trans,setTrans]=useState("fade");
  const ref=useRef();
  useEffect(()=>{if(playing&&mediaList.length>0){ref.current=setInterval(()=>setIdx(i=>(i+1)%mediaList.length),dur*1000);}return()=>clearInterval(ref.current);},[playing,dur,mediaList.length]);
  const cur=mediaList[idx];
  return (
    <div style={{position:"fixed",inset:0,background:"#000",zIndex:3000,display:"flex",flexDirection:"column",fontFamily:T.font}}>
      <div style={{height:48,background:"rgba(0,0,0,0.9)",borderBottom:"1px solid #1a1a1a",display:"flex",alignItems:"center",padding:"0 14px",gap:10,flexShrink:0}}>
        <button onClick={onClose} style={{background:"rgba(255,255,255,0.08)",border:"1px solid #333",color:"#e2ddd5",borderRadius:7,padding:"4px 12px",cursor:"pointer",fontFamily:T.font,fontSize:12}}>← Retour</button>
        <div style={{fontFamily:T.fontD,fontSize:14,color:T.accent,flex:1,textAlign:"center"}}>🎬 Diaporama — {mediaList.length} photos</div>
        <select value={trans} onChange={e=>setTrans(e.target.value)} style={{background:"#111",border:"1px solid #333",color:"#e2ddd5",borderRadius:7,padding:"4px 8px",fontFamily:T.font,fontSize:12}}>
          {[["fade","Fondu"],["slide","Glissement"],["zoom","Zoom"]].map(([v,l])=><option key={v} value={v}>{l}</option>)}
        </select>
        <div style={{display:"flex",alignItems:"center",gap:6,fontSize:11,color:"#6b7a99"}}>⏱ <input type="range" min={1} max={8} value={dur} onChange={e=>setDur(+e.target.value)} style={{width:70,accentColor:T.accent}}/> {dur}s</div>
      </div>
      <style>{`@keyframes pFade{from{opacity:0}to{opacity:1}}@keyframes pSlide{from{transform:translateX(80%);opacity:0}to{transform:translateX(0);opacity:1}}@keyframes pZoom{from{transform:scale(1.14);opacity:0}to{transform:scale(1);opacity:1}}`}</style>
      <div style={{flex:1,display:"flex",alignItems:"center",justifyContent:"center",position:"relative",overflow:"hidden"}}>
        {(cur?.url||cur?.dataUrl)&&<img key={idx+trans} src={cur.url||cur.dataUrl} alt={cur.title} style={{maxWidth:"88%",maxHeight:"84%",objectFit:"contain",animation:`${trans==="slide"?"pSlide":trans==="zoom"?"pZoom":"pFade"} ${Math.min(0.6,dur*0.22)}s ease-out`}}/>}
        {!cur?.url&&!cur?.dataUrl&&<div style={{color:"#666",fontSize:14}}>Aucune image</div>}
        {playing&&<div style={{position:"absolute",bottom:0,left:0,right:0,height:2,background:"#1a1a1a"}}><div style={{height:2,background:T.accent,width:`${((idx+1)/mediaList.length)*100}%`,transition:`width ${dur*0.88}s linear`}}/></div>}
        <div style={{position:"absolute",top:10,right:12,background:"rgba(0,0,0,0.6)",padding:"2px 10px",borderRadius:10,fontSize:11,color:"#fff"}}>{idx+1}/{mediaList.length}</div>
        <button onClick={()=>{setIdx(i=>Math.max(0,i-1));setPlaying(false)}} style={{position:"absolute",left:14,width:42,height:42,borderRadius:21,background:"rgba(0,0,0,0.7)",border:"1px solid #333",color:"#fff",cursor:"pointer",fontSize:20}}>‹</button>
        <button onClick={()=>{setIdx(i=>Math.min(mediaList.length-1,i+1));setPlaying(false)}} style={{position:"absolute",right:14,width:42,height:42,borderRadius:21,background:"rgba(0,0,0,0.7)",border:"1px solid #333",color:"#fff",cursor:"pointer",fontSize:20}}>›</button>
      </div>
      <div style={{height:56,background:"rgba(0,0,0,0.85)",borderTop:"1px solid #1a1a1a",display:"flex",alignItems:"center",justifyContent:"center",gap:16,flexShrink:0}}>
        <button onClick={()=>{setIdx(0);setPlaying(false)}} style={{background:"none",border:"none",color:"#6b7a99",cursor:"pointer",fontSize:20}}>⏮</button>
        <button onClick={()=>setPlaying(p=>!p)} style={{width:44,height:44,borderRadius:22,background:T.accent,border:"none",color:"#000",cursor:"pointer",fontSize:18,fontWeight:700,display:"flex",alignItems:"center",justifyContent:"center"}}>{playing?"⏸":"▶"}</button>
        <button onClick={()=>{setIdx(mediaList.length-1);setPlaying(false)}} style={{background:"none",border:"none",color:"#6b7a99",cursor:"pointer",fontSize:20}}>⏭</button>
      </div>
      {/* Film strip */}
      <div style={{height:72,background:"#080808",borderTop:"1px solid #111",display:"flex",alignItems:"center",gap:3,padding:"0 10px",overflow:"auto",flexShrink:0}}>
        {mediaList.map((p,i)=>(
          <div key={p.id} onClick={()=>{setIdx(i);setPlaying(false)}} style={{width:64,height:52,borderRadius:3,overflow:"hidden",flexShrink:0,cursor:"pointer",border:`2px solid ${i===idx?T.accent:"transparent"}`,transition:"border 0.12s"}}>
            {(p.url||p.dataUrl)?<img src={p.url||p.dataUrl} alt="" style={{width:"100%",height:"100%",objectFit:"cover"}}/>:<div style={{width:"100%",height:"100%",background:"#1a1a1a"}}/>}
          </div>
        ))}
      </div>
    </div>
  );
};

// ── Face Recognition UI ───────────────────────────────────────────────────────
const FaceRecognition=({mediaList,faces,setFaces,onClose})=>{
  const [mode,setMode]=useState("personnes"); // personnes | tagger | galerie
  const [selectedFaceId,setSelectedFaceId]=useState(null);
  const [tagPhotoId,setTagPhotoId]=useState(null); // photo en cours de tag
  const [renamingId,setRenamingId]=useState(null);
  const [renameVal,setRenameVal]=useState("");
  const [showAddPerson,setShowAddPerson]=useState(false);
  const [newPersonName,setNewPersonName]=useState("");
  const FACE_COLORS=["#f0a500","#34d399","#38bdf8","#a78bfa","#f472b6","#fb923c","#22c55e","#ef4444","#fbbf24","#60a5fa"];

  // Photos avec dataUrl uniquement (= uploadées)
  const photosAvecImg=mediaList.filter(p=>p.url||p.dataUrl);

  // Groupe photos → personnes
  const photosDeFace=faceId=>photosAvecImg.filter(p=>(p.faces||[]).includes(faceId));
  const facesDePhoto=photo=>(photo.faces||[]).map(fid=>faces.find(f=>f.id===fid)).filter(Boolean);

  const rename=(id,nom)=>{
    const initiales=nom.split(" ").map(w=>w[0]||"").join("").toUpperCase().slice(0,2)||"?";
    setFaces(fs=>fs.map(f=>f.id===id?{...f,nom,initiales}:f));
    setRenamingId(null);
  };

  const addPerson=()=>{
    if(!newPersonName.trim())return;
    const nom=newPersonName.trim();
    const initiales=nom.split(" ").map(w=>w[0]||"").join("").toUpperCase().slice(0,2)||"?";
    const color=FACE_COLORS[faces.length%FACE_COLORS.length];
    setFaces(fs=>[...fs,{id:uid(),nom,initiales,color,nbPhotos:0}]);
    setNewPersonName("");setShowAddPerson(false);
  };

  const toggleTag=(photo,faceId)=>{
    // Ajouter/retirer faceId des faces de la photo
    const hasFace=(photo.faces||[]).includes(faceId);
    const newFaces=hasFace?(photo.faces||[]).filter(f=>f!==faceId):[...(photo.faces||[]),faceId];
    // Mettre à jour via setFaces qui va passer par setPhotos
    // On a besoin d'un callback pour mettre à jour la photo — on utilise une astuce :
    // setFaces est en fait setPhotos dans le composant parent
    // On doit plutôt patcher directement via un prop updatePhoto
    // → On utilise setFaces avec un mapping complet
    const updatedMedia=mediaList.map(p=>p.id===photo.id?{...p,faces:newFaces}:p);
    // On a pas accès direct à setPhotos — on doit patcher via le parent
    // Le parent Photos utilise : setFaces=newFaces=>setPhotos(p=>({...p,faces:...}))
    // Mais ici on veut changer les medias, pas les faces de l'album
    // Solution : on expose un callback via un second prop → on va tricher
    // en appelant setFaces avec un objet spécial reconnu en haut
    setFaces({__mediaUpdate__:true,medias:updatedMedia,faces:faces});
  };

  const selFace=selectedFaceId&&faces.find(f=>f.id===selectedFaceId);
  const photosFiltrees=selectedFaceId?photosDeFace(selectedFaceId):photosAvecImg;

  return (
    <div style={{position:"fixed",inset:0,background:"#050508",zIndex:3000,display:"flex",flexDirection:"column",fontFamily:T.font}}>
      {/* Header */}
      <div style={{height:52,background:"#0a0a0f",borderBottom:"1px solid #1a1a2a",display:"flex",alignItems:"center",padding:"0 16px",gap:12,flexShrink:0}}>
        <button onClick={onClose} style={{background:"rgba(255,255,255,0.07)",border:"1px solid #222",color:"#e2ddd5",borderRadius:7,padding:"5px 12px",cursor:"pointer",fontFamily:T.font,fontSize:12}}>← Retour</button>
        <div style={{fontFamily:T.fontD,fontSize:16,color:"#e2ddd5",flex:1}}>👥 Personnes & Albums</div>
        {/* Tabs mode */}
        <div style={{display:"flex",gap:4}}>
          {[{id:"personnes",l:"👥 Personnes"},{id:"tagger",l:"🏷️ Tagger les photos"},{id:"galerie",l:"🖼️ Galerie"}].map(m=>(
            <button key={m.id} onClick={()=>setMode(m.id)} style={{padding:"5px 12px",borderRadius:7,border:`1px solid ${mode===m.id?"#a78bfa":"#1a1a2a"}`,background:mode===m.id?"rgba(167,139,250,0.15)":"transparent",color:mode===m.id?"#a78bfa":"#6b7a99",fontFamily:T.font,fontSize:12,cursor:"pointer"}}>{m.l}</button>
          ))}
        </div>
        <button onClick={()=>setShowAddPerson(true)} style={{background:"#a78bfa",border:"none",color:"#fff",borderRadius:8,padding:"6px 14px",cursor:"pointer",fontFamily:T.font,fontSize:12,fontWeight:700}}>+ Personne</button>
      </div>

      {/* Bandeau info */}
      <div style={{background:"rgba(167,139,250,0.07)",borderBottom:"1px solid rgba(167,139,250,0.15)",padding:"8px 18px",display:"flex",alignItems:"center",gap:8,fontSize:12,color:"#a78bfa"}}>
        <span>💡</span>
        <span>
          {mode==="personnes"&&"Gérez vos albums par personne. Cliquez sur une personne pour voir ses photos."}
          {mode==="tagger"&&"Cliquez sur une photo puis sélectionnez les personnes présentes pour les associer. L'IA de reconnaissance faciale n'est pas disponible dans le navigateur — le tag manuel garantit une précision parfaite."}
          {mode==="galerie"&&"Filtrez les photos par personne. Sélectionnez une personne dans la liste à gauche."}
        </span>
      </div>

      {/* ── MODE PERSONNES ── */}
      {mode==="personnes"&&(
        <div style={{flex:1,overflow:"auto",padding:20}}>
          {faces.length===0&&(
            <div style={{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",gap:16}}>
              <div style={{fontSize:56}}>👥</div>
              <div style={{fontFamily:T.fontD,fontSize:20,color:"#e2ddd5"}}>Aucune personne enregistrée</div>
              <div style={{fontSize:13,color:"#6b7a99",textAlign:"center",maxWidth:400,lineHeight:1.7}}>Créez des fiches pour chaque personne, puis allez dans <strong style={{color:"#a78bfa"}}>Tagger les photos</strong> pour associer les personnes à vos photos.</div>
              <button onClick={()=>setShowAddPerson(true)} style={{background:"#a78bfa",border:"none",color:"#fff",borderRadius:10,padding:"10px 24px",cursor:"pointer",fontFamily:T.font,fontSize:14,fontWeight:700}}>+ Ajouter une première personne</button>
            </div>
          )}
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(240px,1fr))",gap:14}}>
            {faces.map(face=>{
              const photos=photosDeFace(face.id);
              return (
                <div key={face.id} style={{background:"#0f0f18",border:"1px solid #1a1a2a",borderRadius:12,overflow:"hidden",cursor:"pointer"}}
                  onClick={()=>{setSelectedFaceId(face.id);setMode("galerie");}}>
                  {/* Mosaïque de 4 photos */}
                  <div style={{height:110,display:"grid",gridTemplateColumns:"1fr 1fr",gridTemplateRows:"1fr 1fr",gap:2,background:"#1a1a2a"}}>
                    {photos.slice(0,4).map((p,i)=>(
                      <div key={p.id} style={{overflow:"hidden",background:"#0a0a12"}}>
                        {(p.url||p.dataUrl)?<img src={p.url||p.dataUrl} alt="" style={{width:"100%",height:"100%",objectFit:"cover"}}/>:<div style={{width:"100%",height:"100%",display:"flex",alignItems:"center",justifyContent:"center",fontSize:18}}>📸</div>}
                      </div>
                    ))}
                    {photos.length===0&&<div style={{gridColumn:"1/-1",gridRow:"1/-1",display:"flex",alignItems:"center",justifyContent:"center",flexDirection:"column",gap:6}}>
                      <span style={{fontSize:32}}>👤</span><span style={{fontSize:11,color:"#444"}}>Aucune photo</span>
                    </div>}
                    {photos.length===1&&[1,2,3].map(i=><div key={i} style={{background:"#0a0a12"}}/>)}
                    {photos.length===2&&[1,2].map(i=><div key={i} style={{background:"#0a0a12"}}/>)}
                    {photos.length===3&&<div style={{background:"#0a0a12"}}/>}
                  </div>
                  <div style={{padding:"12px 14px",display:"flex",alignItems:"center",gap:10}}>
                    <div style={{width:40,height:40,borderRadius:20,background:face.color+"28",border:`2px solid ${face.color}`,display:"flex",alignItems:"center",justifyContent:"center",fontWeight:700,fontSize:15,color:face.color,flexShrink:0}}>{face.initiales}</div>
                    <div style={{flex:1,minWidth:0}}>
                      {renamingId===face.id?(
                        <div style={{display:"flex",gap:6}} onClick={e=>e.stopPropagation()}>
                          <input value={renameVal} onChange={e=>setRenameVal(e.target.value)} autoFocus style={{flex:1,background:"#0a0a12",border:"1px solid #a78bfa",borderRadius:6,padding:"3px 8px",color:"#e2ddd5",fontFamily:T.font,fontSize:13}} onKeyDown={e=>{if(e.key==="Enter")rename(face.id,renameVal);if(e.key==="Escape")setRenamingId(null);}}/>
                          <button onClick={()=>rename(face.id,renameVal)} style={{background:"#a78bfa",border:"none",color:"#fff",borderRadius:6,padding:"3px 8px",cursor:"pointer",fontSize:12}}>✓</button>
                        </div>
                      ):(
                        <div style={{fontWeight:700,color:"#e2ddd5",fontSize:14,display:"flex",alignItems:"center",gap:6}}>
                          {face.nom}
                          <span onClick={e=>{e.stopPropagation();setRenamingId(face.id);setRenameVal(face.nom);}} style={{fontSize:11,color:"#6b7a99",cursor:"pointer"}}>✏️</span>
                        </div>
                      )}
                      <div style={{fontSize:11,color:"#6b7a99",marginTop:2}}>{photos.length} photo{photos.length!==1?"s":""}</div>
                    </div>
                    <button onClick={e=>{e.stopPropagation();if(confirm(`Supprimer ${face.nom} ?`))setFaces(fs=>fs.filter(f=>f.id!==face.id));}} style={{background:"none",border:"none",color:"#333",cursor:"pointer",fontSize:14}}>🗑</button>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {/* ── MODE TAGGER ── */}
      {mode==="tagger"&&(
        <div style={{flex:1,display:"grid",gridTemplateColumns:"1fr 280px",overflow:"hidden"}}>
          {/* Grille photos */}
          <div style={{overflow:"auto",padding:16}}>
            {photosAvecImg.length===0&&<EmptyState icon="📸" text="Importez des photos dans le module Photos pour pouvoir les tagger"/>}
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(130px,1fr))",gap:6}}>
              {photosAvecImg.map(p=>{
                const tagged=facesDePhoto(p);
                const isTagging=tagPhotoId===p.id;
                return (
                  <div key={p.id} onClick={()=>setTagPhotoId(isTagging?null:p.id)}
                    style={{position:"relative",borderRadius:10,overflow:"hidden",cursor:"pointer",border:`2px solid ${isTagging?"#a78bfa":tagged.length>0?"rgba(167,139,250,0.4)":"transparent"}`,transition:"border 0.15s"}}>
                    {(p.url||p.dataUrl)?<img src={p.url||p.dataUrl} alt="" style={{width:"100%",aspectRatio:"1",objectFit:"cover",display:"block"}}/>:<div style={{width:"100%",aspectRatio:"1",background:"#1a1a2a",display:"flex",alignItems:"center",justifyContent:"center",fontSize:24}}>📸</div>}
                    {/* Badges personnes */}
                    {tagged.length>0&&(
                      <div style={{position:"absolute",bottom:4,left:4,right:4,display:"flex",flexWrap:"wrap",gap:2}}>
                        {tagged.map(f=>(
                          <div key={f.id} style={{background:f.color,borderRadius:10,padding:"1px 6px",fontSize:9,fontWeight:700,color:"#000",maxWidth:80,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{f.nom}</div>
                        ))}
                      </div>
                    )}
                    {isTagging&&<div style={{position:"absolute",inset:0,background:"rgba(167,139,250,0.18)",border:"2px solid #a78bfa",pointerEvents:"none"}}/>}
                    {/* Compteur */}
                    {tagged.length===0&&<div style={{position:"absolute",top:4,right:4,background:"rgba(0,0,0,0.6)",borderRadius:6,padding:"1px 5px",fontSize:9,color:"#666"}}>0 👤</div>}
                  </div>
                );
              })}
            </div>
          </div>
          {/* Panneau droite : sélection personnes */}
          <div style={{borderLeft:"1px solid #1a1a2a",display:"flex",flexDirection:"column",overflow:"hidden"}}>
            <div style={{padding:"14px 16px",borderBottom:"1px solid #1a1a2a"}}>
              <div style={{fontFamily:T.fontD,fontSize:14,color:"#e2ddd5",marginBottom:4}}>
                {tagPhotoId?"🏷️ Qui est sur cette photo ?":"← Sélectionnez une photo"}
              </div>
              {tagPhotoId&&<div style={{fontSize:11,color:"#6b7a99"}}>Cochez les personnes présentes</div>}
            </div>
            <div style={{flex:1,overflow:"auto",padding:"12px 14px"}}>
              {!tagPhotoId&&(
                <div style={{color:"#444",fontSize:12,textAlign:"center",marginTop:30,lineHeight:1.8}}>Cliquez sur une photo pour sélectionner les personnes qui y apparaissent.</div>
              )}
              {tagPhotoId&&faces.length===0&&(
                <div style={{color:"#6b7a99",fontSize:12,textAlign:"center",marginTop:20}}>Créez d'abord des personnes avec le bouton <strong style={{color:"#a78bfa"}}>+ Personne</strong></div>
              )}
              {tagPhotoId&&faces.map(face=>{
                const photo=photosAvecImg.find(p=>p.id===tagPhotoId);
                if(!photo)return null;
                const hasTag=(photo.faces||[]).includes(face.id);
                return (
                  <div key={face.id} onClick={()=>toggleTag(photo,face.id)}
                    style={{display:"flex",alignItems:"center",gap:10,padding:"10px 12px",borderRadius:9,marginBottom:6,cursor:"pointer",background:hasTag?"rgba(167,139,250,0.15)":"#0a0a12",border:`1px solid ${hasTag?"#a78bfa":"#1a1a2a"}`,transition:"all 0.15s"}}>
                    <div style={{width:36,height:36,borderRadius:18,background:face.color+"28",border:`2px solid ${face.color}`,display:"flex",alignItems:"center",justifyContent:"center",fontWeight:700,fontSize:13,color:face.color,flexShrink:0}}>{face.initiales}</div>
                    <div style={{flex:1}}>
                      <div style={{fontSize:13,fontWeight:600,color:"#e2ddd5"}}>{face.nom}</div>
                      <div style={{fontSize:10,color:"#6b7a99"}}>{photosDeFace(face.id).length} photo{photosDeFace(face.id).length!==1?"s":""}</div>
                    </div>
                    <div style={{width:22,height:22,borderRadius:11,background:hasTag?"#a78bfa":"#1a1a2a",display:"flex",alignItems:"center",justifyContent:"center",fontSize:13,flexShrink:0}}>{hasTag?"✓":""}</div>
                  </div>
                );
              })}
            </div>
            {tagPhotoId&&(
              <div style={{padding:"12px 14px",borderTop:"1px solid #1a1a2a"}}>
                <div style={{fontSize:11,color:"#6b7a99",marginBottom:8}}>Photo sélectionnée :</div>
                {(()=>{const p=photosAvecImg.find(ph=>ph.id===tagPhotoId);return p&&(p.url||p.dataUrl)?<img src={p.url||p.dataUrl} alt="" style={{width:"100%",height:100,objectFit:"cover",borderRadius:8}}/>:null;})()}
              </div>
            )}
          </div>
        </div>
      )}

      {/* ── MODE GALERIE ── */}
      {mode==="galerie"&&(
        <div style={{flex:1,display:"grid",gridTemplateColumns:"200px 1fr",overflow:"hidden"}}>
          {/* Sidebar personnes */}
          <div style={{borderRight:"1px solid #1a1a2a",overflow:"auto"}}>
            <div onClick={()=>setSelectedFaceId(null)} style={{padding:"10px 14px",cursor:"pointer",background:!selectedFaceId?"rgba(167,139,250,0.12)":"transparent",borderBottom:"1px solid #1a1a2a"}}>
              <span style={{color:!selectedFaceId?"#a78bfa":"#6b7a99",fontSize:13,fontWeight:600}}>Toutes les photos ({photosAvecImg.length})</span>
            </div>
            {faces.map(f=>(
              <div key={f.id} onClick={()=>setSelectedFaceId(f.id)} style={{display:"flex",alignItems:"center",gap:8,padding:"9px 14px",cursor:"pointer",background:selectedFaceId===f.id?"rgba(167,139,250,0.12)":"transparent",borderBottom:"1px solid #1a1a2a"}}>
                <div style={{width:28,height:28,borderRadius:14,background:f.color+"28",border:`2px solid ${f.color}`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:11,fontWeight:700,color:f.color,flexShrink:0}}>{f.initiales}</div>
                <div style={{flex:1,minWidth:0}}>
                  <div style={{fontSize:12,fontWeight:600,color:selectedFaceId===f.id?"#a78bfa":"#e2ddd5",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{f.nom}</div>
                  <div style={{fontSize:10,color:"#6b7a99"}}>{photosDeFace(f.id).length} photo{photosDeFace(f.id).length!==1?"s":""}</div>
                </div>
              </div>
            ))}
          </div>
          {/* Grille photos filtrées */}
          <div style={{overflow:"auto",padding:16}}>
            <div style={{fontFamily:T.fontD,fontSize:15,color:"#e2ddd5",marginBottom:12}}>
              {selFace?`📸 Photos de ${selFace.nom}`:"📸 Toutes les photos"}
              <span style={{fontSize:12,color:"#6b7a99",fontFamily:T.font,marginLeft:8}}>{photosFiltrees.length} photo{photosFiltrees.length!==1?"s":""}</span>
            </div>
            {photosFiltrees.length===0&&<EmptyState icon="📸" text={selFace?`Aucune photo taguée pour ${selFace.nom}. Allez dans Tagger les photos.`:"Importez des photos dans le module Photos."}/>}
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(150px,1fr))",gap:6}}>
              {photosFiltrees.map(p=>{
                const tagged=facesDePhoto(p);
                return (
                  <div key={p.id} style={{position:"relative",borderRadius:10,overflow:"hidden"}}>
                    {(p.url||p.dataUrl)?<img src={p.url||p.dataUrl} alt="" style={{width:"100%",aspectRatio:"1",objectFit:"cover",display:"block"}}/>:<div style={{width:"100%",aspectRatio:"1",background:"#1a1a2a",display:"flex",alignItems:"center",justifyContent:"center",fontSize:24}}>📸</div>}
                    {tagged.length>0&&(
                      <div style={{position:"absolute",bottom:4,left:4,right:4,display:"flex",flexWrap:"wrap",gap:2}}>
                        {tagged.map(f=><div key={f.id} style={{background:f.color,borderRadius:10,padding:"1px 6px",fontSize:9,fontWeight:700,color:"#000"}}>{f.nom}</div>)}
                      </div>
                    )}
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      )}

      {/* Modale ajout personne */}
      {showAddPerson&&(
        <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.7)",zIndex:4000,display:"flex",alignItems:"center",justifyContent:"center"}}>
          <div style={{background:"#0f0f18",border:"1px solid #1a1a2a",borderRadius:14,padding:"24px 28px",width:340,fontFamily:T.font}}>
            <div style={{fontFamily:T.fontD,fontSize:16,color:"#e2ddd5",marginBottom:16}}>👤 Nouvelle personne</div>
            <input value={newPersonName} onChange={e=>setNewPersonName(e.target.value)} autoFocus placeholder="Prénom Nom (ex: Marie Dupont)" onKeyDown={e=>{if(e.key==="Enter")addPerson();if(e.key==="Escape")setShowAddPerson(false);}}
              style={{width:"100%",background:"#0a0a12",border:"1px solid #a78bfa",borderRadius:8,padding:"10px 14px",color:"#e2ddd5",fontFamily:T.font,fontSize:14,outline:"none",boxSizing:"border-box",marginBottom:16}}/>
            <div style={{display:"flex",gap:8,justifyContent:"flex-end"}}>
              <button onClick={()=>setShowAddPerson(false)} style={{background:"transparent",border:"1px solid #1a1a2a",color:"#6b7a99",borderRadius:8,padding:"8px 16px",cursor:"pointer",fontFamily:T.font}}>Annuler</button>
              <button onClick={addPerson} disabled={!newPersonName.trim()} style={{background:"#a78bfa",border:"none",color:"#fff",borderRadius:8,padding:"8px 18px",cursor:newPersonName.trim()?"pointer":"not-allowed",fontFamily:T.font,fontWeight:700,opacity:newPersonName.trim()?1:0.5}}>✓ Créer</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

// ── Main Photos Component ─────────────────────────────────────────────────────
const Photos=({photos,setPhotos})=>{
  const [view,setView]=useState("timeline");
  const [filterAlbum,setFilterAlbum]=useState(null);
  const [lightbox,setLightbox]=useState(null);
  const [editing,setEditing]=useState(null);
  const [slideshow,setSlideshow]=useState(false);
  const [faceRecog,setFaceRecog]=useState(false);
  const [selMode,setSelMode]=useState(false);
  const [selection,setSelection]=useState([]);
  const [search,setSearch]=useState("");
  const [showAddAlbum,setShowAddAlbum]=useState(false);
  const [formAlbum,setFormAlbum]=useState({nom:"",icon:"📸",description:"",date:today(),tags:""});
  const fileRef=useRef();
  const ALBUM_ICONS=["📸","🏠","🏖️","⛷️","🎉","👨‍👩‍👧","🌿","🚗","🐕","✈️","🎄","❤️","🎓","🎾","🏃","🌸","🍂","🌙"];

  // Init media list from state
  const mediaList=useMemo(()=>photos.medias||[],[photos.medias]);
  const albums=useMemo(()=>photos.albums||[],[photos.albums]);
  const faces=photos.faces||DEMO_FACES;
  const setFaces=newFaces=>{
    if(newFaces&&newFaces.__mediaUpdate__){
      // Mise à jour des medias (tags photo) + faces simultanément
      setPhotos(p=>({...p,medias:newFaces.medias,faces:newFaces.faces}));
    } else {
      setPhotos(p=>({...p,faces:typeof newFaces==="function"?newFaces(p.faces||DEMO_FACES):newFaces}));
    }
  };

  // Generate demo URLs on mount
  useEffect(()=>{
    if(mediaList.length===0){
      const demos=DEMO_PALETTES.map((d,i)=>({
        id:"dp"+i,...d,url:null,favorite:i<3,width:600,height:400,
      }));
      const demoAlbums=[...new Set(DEMO_PALETTES.map(d=>d.album))].map((name,i)=>({
        id:"dal"+i,nom:name,icon:ALBUM_ICONS[i%ALBUM_ICONS.length]||"📸",description:"",date:DEMO_PALETTES.find(d=>d.album===name)?.date||today(),tags:""
      }));
      setPhotos(p=>({...p,medias:demos,albums:[...p.albums||[],...demoAlbums.filter(a=>!(p.albums||[]).some(x=>x.nom===a.nom))],faces:DEMO_FACES}));
    }
  },[]);

  // Lazy generate URLs for demo photos
  useEffect(()=>{
    const todo=mediaList.filter(m=>!m.url&&!m.dataUrl&&m.palette);
    if(todo.length===0)return;
    const batch=todo.slice(0,4);
    batch.forEach(m=>{
      const url=makeDemoImg(m.title,m.palette,m.width||600,m.height||400);
      if(url)setPhotos(p=>({...p,medias:(p.medias||[]).map(x=>x.id===m.id?{...x,url}:x)}));
    });
  },[mediaList.filter(m=>!m.url&&!m.dataUrl).length]);

  const filteredMedia=useMemo(()=>{
    let list=mediaList;
    if(filterAlbum)list=list.filter(m=>m.album===filterAlbum);
    if(view==="favorites")list=list.filter(m=>m.favorite);
    if(view==="faces"&&photos.activeFace)list=list.filter(m=>(m.faces||[]).includes(photos.activeFace));
    if(search)list=list.filter(m=>m.title?.toLowerCase().includes(search)||m.tags?.some(t=>t.includes(search))||m.loc?.toLowerCase().includes(search)||m.album?.toLowerCase().includes(search));
    return list;
  },[mediaList,filterAlbum,view,search,photos.activeFace]);

  const grouped=useMemo(()=>{
    const map={};
    [...filteredMedia].sort((a,b)=>(b.date||"").localeCompare(a.date||"")).forEach(p=>{
      const k=p.date?.slice(0,7)||"—";if(!map[k])map[k]=[];map[k].push(p);
    });
    return Object.entries(map).sort((a,b)=>b[0].localeCompare(a[0]));
  },[filteredMedia]);

  const handleFiles=async files=>{
    const newM=await Promise.all(Array.from(files).map(async f=>{
      const dataUrl=await new Promise(r=>{const fr=new FileReader();fr.onload=e=>r(e.target.result);fr.readAsDataURL(f);});
      return {
        id:uid(),title:f.name.replace(/\.[^.]+$/,""),
        dataUrl,  // base64 — fonctionne dans tous les environnements
        type:f.type.startsWith("video/")?"video":"photo",
        date:today(),album:filterAlbum||"Sans album",
        tags:[],favorite:false,faces:[],url:null,palette:null,
      };
    }));
    setPhotos(p=>({...p,medias:[...newM,...(p.medias||[])]}));
  };

  const toggleFav=id=>setPhotos(p=>({...p,medias:(p.medias||[]).map(m=>m.id===id?{...m,favorite:!m.favorite}:m)}));
  const saveEdit=updated=>setPhotos(p=>({...p,medias:(p.medias||[]).map(m=>m.id===updated.id?updated:m)}));
  const delSelected=()=>{setPhotos(p=>({...p,medias:(p.medias||[]).filter(m=>!selection.includes(m.id))}));setSelection([]);setSelMode(false);};

  const lbPhoto=lightbox?mediaList.find(m=>m.id===lightbox):null;
  const lbIdx=lbPhoto?filteredMedia.findIndex(m=>m.id===lightbox):-1;
  const navLb=dir=>{const ni=lbIdx+dir;if(ni>=0&&ni<filteredMedia.length)setLightbox(filteredMedia[ni].id);};
  const fmtMonth=d=>{try{return new Date(d+"-01T12:00").toLocaleDateString("fr-FR",{month:"long",year:"numeric"});}catch{return d;}};

  if(editing)return <PhotoEditor photo={editing} onClose={()=>setEditing(null)} onSave={saved=>{saveEdit(saved);setEditing(null);}}/>;
  if(slideshow)return <SlideshowPlayer mediaList={filteredMedia.filter(m=>m.url||m.dataUrl)} onClose={()=>setSlideshow(false)}/>;
  if(faceRecog)return <FaceRecognition mediaList={mediaList} faces={faces} setFaces={setFaces} onClose={()=>setFaceRecog(false)}/>;

  return (
    <div style={{display:"flex",height:"calc(100vh - 44px)",margin:"-22px",overflow:"hidden",background:"#0a0a0a"}}>
      {/* Left sidebar */}
      <div style={{width:198,background:"#0d0d0d",borderRight:"1px solid #1a1a1a",display:"flex",flexDirection:"column",flexShrink:0,fontFamily:T.font}}>
        <div style={{padding:"14px 12px",borderBottom:"1px solid #1a1a1a"}}>
          <div style={{fontFamily:T.fontD,fontSize:15,color:"#e2ddd5",marginBottom:1}}>📸 Médiathèque</div>
          <div style={{fontSize:10,color:"#6b7a99"}}>{mediaList.length} médias · {faces.length} personnes</div>
        </div>
        <nav style={{flex:1,padding:"8px 6px",overflow:"auto"}}>
          {[{id:"timeline",icon:"⏱️",l:"Chronologie"},{id:"albums",icon:"📁",l:"Albums"},{id:"favorites",icon:"⭐",l:"Favoris"}].map(n=>(
            <button key={n.id} onClick={()=>{setView(n.id);setFilterAlbum(null);}} style={{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"7px 9px",borderRadius:7,border:"none",background:(view===n.id&&!filterAlbum)?"rgba(240,165,0,0.1)":"transparent",color:(view===n.id&&!filterAlbum)?T.accent:"#6b7a99",cursor:"pointer",fontFamily:T.font,fontSize:12,marginBottom:1}}><span>{n.icon}</span><span>{n.l}</span></button>
          ))}
          <div style={{fontSize:9,color:"#444",padding:"8px 9px 3px",textTransform:"uppercase",letterSpacing:"0.1em"}}>Personnes</div>
          <button onClick={()=>{setFaceRecog(true);}} style={{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"7px 9px",borderRadius:7,border:"none",background:"transparent",color:"#6b7a99",cursor:"pointer",fontFamily:T.font,fontSize:12,marginBottom:1}}>
            <span>🧠</span><span>Reconna. faciale</span>
          </button>
          {faces.filter(f=>f.nom!=="Inconnu"||true).map(face=>(
            <button key={face.id} onClick={()=>{setPhotos(p=>({...p,activeFace:face.id}));setView("faces");setFilterAlbum(null);}} style={{display:"flex",alignItems:"center",gap:7,width:"100%",padding:"6px 9px",borderRadius:7,border:"none",background:(view==="faces"&&photos.activeFace===face.id)?"rgba(240,165,0,0.1)":"transparent",color:(view==="faces"&&photos.activeFace===face.id)?T.accent:"#6b7a99",cursor:"pointer",fontFamily:T.font,fontSize:12,marginBottom:1}}>
              <div style={{width:20,height:20,borderRadius:10,background:face.color+"33",border:`1px solid ${face.color}`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:9,fontWeight:700,color:face.color,flexShrink:0}}>{face.initiales}</div>
              <span style={{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",flex:1}}>{face.nom}</span>
              <span style={{fontSize:10,color:"#444"}}>{(mediaList.filter(m=>(m.faces||[]).includes(face.id)).length)||face.nbPhotos}</span>
            </button>
          ))}
          <div style={{fontSize:9,color:"#444",padding:"8px 9px 3px",textTransform:"uppercase",letterSpacing:"0.1em"}}>Albums</div>
          {albums.map(a=>(
            <button key={a.id} onClick={()=>{setFilterAlbum(a.nom);setView("album");}} style={{display:"flex",alignItems:"center",gap:7,width:"100%",padding:"6px 9px",borderRadius:7,border:"none",background:filterAlbum===a.nom?"rgba(240,165,0,0.1)":"transparent",color:filterAlbum===a.nom?T.accent:"#6b7a99",cursor:"pointer",fontFamily:T.font,fontSize:12,marginBottom:1}}>
              <span style={{fontSize:13}}>{a.icon||"📁"}</span>
              <span style={{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",flex:1}}>{a.nom}</span>
              <span style={{fontSize:10,color:"#444"}}>{mediaList.filter(m=>m.album===a.nom).length}</span>
            </button>
          ))}
        </nav>
        <div style={{padding:8,borderTop:"1px solid #1a1a1a"}}>
          <button onClick={()=>fileRef.current.click()} style={{width:"100%",padding:"8px",background:"rgba(240,165,0,0.1)",border:"1px solid rgba(240,165,0,0.25)",borderRadius:8,color:T.accent,cursor:"pointer",fontFamily:T.font,fontSize:12,fontWeight:600}}>+ Importer</button>
          <input ref={fileRef} type="file" accept="image/*,video/*" multiple style={{display:"none"}} onChange={e=>handleFiles(e.target.files)}/>
        </div>
      </div>

      {/* Main area */}
      <div style={{flex:1,display:"flex",flexDirection:"column",overflow:"hidden",minWidth:0,background:"#0a0a0a",fontFamily:T.font}}>
        {/* Topbar */}
        <div style={{height:50,borderBottom:"1px solid #1a1a1a",display:"flex",alignItems:"center",padding:"0 14px",gap:8,flexShrink:0,background:"rgba(10,10,10,0.95)"}}>
          <div style={{position:"relative",flex:1,maxWidth:300}}>
            <span style={{position:"absolute",left:10,top:"50%",transform:"translateY(-50%)",fontSize:12,color:"#444"}}>🔍</span>
            <input value={search} onChange={e=>setSearch(e.target.value.toLowerCase())} placeholder="Rechercher..." style={{width:"100%",background:"rgba(255,255,255,0.06)",border:"1px solid #1a1a1a",borderRadius:18,padding:"5px 10px 5px 30px",color:"#e2ddd5",fontFamily:T.font,fontSize:12,outline:"none"}}/>
          </div>
          <div style={{flex:1}}/>
          {selMode&&selection.length>0&&<>
            <span style={{fontSize:12,color:T.accent}}>{selection.length} sélect.</span>
            <button onClick={()=>setSlideshow(true)} style={{background:"rgba(240,165,0,0.1)",border:"1px solid rgba(240,165,0,0.25)",color:T.accent,borderRadius:7,padding:"5px 10px",cursor:"pointer",fontFamily:T.font,fontSize:11}}>🎬 Diaporama</button>
            <button onClick={delSelected} style={{background:"rgba(239,68,68,0.1)",border:"1px solid rgba(239,68,68,0.25)",color:"#ef4444",borderRadius:7,padding:"5px 10px",cursor:"pointer",fontFamily:T.font,fontSize:11}}>🗑</button>
          </>}
          <button onClick={()=>{setSelMode(s=>!s);setSelection([]);}} style={{background:selMode?"rgba(240,165,0,0.1)":"rgba(255,255,255,0.06)",border:`1px solid ${selMode?T.accent:"#1a1a1a"}`,color:selMode?T.accent:"#6b7a99",borderRadius:7,padding:"5px 10px",cursor:"pointer",fontFamily:T.font,fontSize:11}}>{selMode?"✓ Terminé":"☑ Sélect."}</button>
          <button onClick={()=>setSlideshow(true)} style={{background:"rgba(255,255,255,0.06)",border:"1px solid #1a1a1a",color:"#6b7a99",borderRadius:7,padding:"5px 10px",cursor:"pointer",fontFamily:T.font,fontSize:11}}>🎬 Diaporama</button>
          <button onClick={()=>setShowAddAlbum(true)} style={{background:"rgba(255,255,255,0.06)",border:"1px solid #1a1a1a",color:"#6b7a99",borderRadius:7,padding:"5px 10px",cursor:"pointer",fontFamily:T.font,fontSize:11}}>📁 + Album</button>
          <button onClick={()=>setFaceRecog(true)} style={{background:"rgba(240,165,0,0.08)",border:"1px solid rgba(240,165,0,0.2)",color:T.accent,borderRadius:7,padding:"5px 10px",cursor:"pointer",fontFamily:T.font,fontSize:11,fontWeight:600}}>🧠 Visages</button>
        </div>

        {/* Content */}
        <div onDragOver={e=>{e.preventDefault();e.currentTarget.style.outline=`2px dashed ${T.accent}`;}} onDragLeave={e=>e.currentTarget.style.outline="none"} onDrop={e=>{e.preventDefault();e.currentTarget.style.outline="none";handleFiles(e.dataTransfer.files);}} style={{flex:1,overflow:"auto",padding:"16px 14px"}}>

          {/* Album grid view */}
          {view==="albums"&&!filterAlbum&&(
            <div>
              <div style={{fontFamily:T.fontD,fontSize:20,color:"#e2ddd5",marginBottom:16}}>Albums</div>
              <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(180px,1fr))",gap:12}}>
                {albums.map(a=>{
                  const cover=mediaList.find(m=>m.album===a.nom&&(m.url||m.dataUrl));
                  const cnt=mediaList.filter(m=>m.album===a.nom).length;
                  return (
                    <div key={a.id} onClick={()=>{setFilterAlbum(a.nom);setView("album");}} style={{cursor:"pointer",borderRadius:10,overflow:"hidden",border:"1px solid #1a1a1a",transition:"transform 0.15s,border-color 0.15s"}} onMouseEnter={e=>{e.currentTarget.style.borderColor=T.accent;e.currentTarget.style.transform="translateY(-2px)";}} onMouseLeave={e=>{e.currentTarget.style.borderColor="#1a1a1a";e.currentTarget.style.transform="none";}}>
                      <div style={{height:120,background:"linear-gradient(135deg,#1a1a2a,#2a2a3a)",overflow:"hidden",display:"flex",alignItems:"center",justifyContent:"center"}}>
                        {(cover?.url||cover?.dataUrl)?<img src={cover.url||cover.dataUrl} alt="" style={{width:"100%",height:"100%",objectFit:"cover"}}/>:<div style={{fontSize:38}}>{a.icon||"📸"}</div>}
                      </div>
                      <div style={{padding:"9px 12px",background:"#0f0f0f"}}>
                        <div style={{fontSize:13,fontWeight:600,color:"#e2ddd5"}}>{a.nom}</div>
                        <div style={{fontSize:11,color:"#6b7a99"}}>{cnt} photo{cnt!==1?"s":""}</div>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          )}

          {/* Timeline / filtered view */}
          {(view!=="albums"||filterAlbum)&&(
            <div>
              {(filterAlbum||view==="favorites"||view==="faces")&&(
                <div style={{display:"flex",alignItems:"center",gap:10,marginBottom:16}}>
                  {filterAlbum&&<button onClick={()=>{setFilterAlbum(null);setView("albums");}} style={{background:"none",border:"none",color:"#6b7a99",cursor:"pointer",fontSize:13}}>← Albums</button>}
                  <div style={{fontFamily:T.fontD,fontSize:19,color:"#e2ddd5"}}>
                    {filterAlbum||view==="favorites"?"⭐ Favoris":view==="faces"?("👤 "+(faces.find(f=>f.id===photos.activeFace)?.nom||"Personne")):""}
                    {filterAlbum}
                  </div>
                  <span style={{fontSize:12,color:"#6b7a99"}}>({filteredMedia.length})</span>
                </div>
              )}
              {grouped.length===0&&(
                <div style={{textAlign:"center",padding:"50px 20px",color:"#6b7a99"}}>
                  <div style={{fontSize:48,marginBottom:10}}>📸</div>
                  <div style={{fontSize:14}}>{search?"Aucun résultat":"Déposez vos photos ici"}</div>
                </div>
              )}
              {grouped.map(([month,mPhotos])=>(
                <div key={month} style={{marginBottom:26}}>
                  <div style={{display:"flex",alignItems:"center",gap:10,marginBottom:10}}>
                    <div style={{fontFamily:T.fontD,fontSize:15,color:"#e2ddd5",textTransform:"capitalize"}}>{fmtMonth(month)}</div>
                    <div style={{fontSize:11,color:"#6b7a99"}}>{mPhotos.length} photo{mPhotos.length!==1?"s":""}</div>
                  </div>
                  <div style={{display:"flex",flexWrap:"wrap",gap:3}}>
                    {mPhotos.map(p=>{
                      const pUrl=p.url||p.dataUrl;
                      const sel=selection.includes(p.id);
                      const editF=p.editState?buildFilterStr(p.editState.adj,PHOTO_PRESETS.find(x=>x.id===p.editState.preset)?.filter||""):"";
                      const editTr=p.editState?`rotate(${p.editState.rotation}deg) scaleX(${p.editState.flipH?-1:1}) scaleY(${p.editState.flipV?-1:1})`:"";
                      const pFaces=(p.faces||[]).map(fid=>faces.find(f=>f.id===fid)).filter(Boolean);
                      return (
                        <div key={p.id} style={{position:"relative",width:155,height:155,flexShrink:0}}
                          onMouseEnter={e=>{const o=e.currentTarget.querySelector(".ph-overlay");if(o)o.style.opacity="1";}}
                          onMouseLeave={e=>{const o=e.currentTarget.querySelector(".ph-overlay");if(o)o.style.opacity="0";}}>
                          <div onClick={()=>selMode?setSelection(s=>s.includes(p.id)?s.filter(x=>x!==p.id):[...s,p.id]):setLightbox(p.id)} style={{width:"100%",height:"100%",borderRadius:3,overflow:"hidden",cursor:"pointer",border:`2px solid ${sel?T.accent:"transparent"}`}}>
                            {pUrl?<img src={pUrl} alt={p.title} style={{width:"100%",height:"100%",objectFit:"cover",filter:editF,transform:editTr,transition:"filter 0.12s"}}/>:<div style={{width:"100%",height:"100%",background:"#1a1a1a",display:"flex",alignItems:"center",justifyContent:"center",fontSize:24}}>🖼️</div>}
                          </div>
                          {p.favorite&&<div style={{position:"absolute",top:5,right:5,fontSize:13,filter:"drop-shadow(0 1px 2px rgba(0,0,0,0.8))"}}>⭐</div>}
                          {sel&&<div style={{position:"absolute",inset:0,background:"rgba(240,165,0,0.22)",borderRadius:3,display:"flex",alignItems:"center",justifyContent:"center"}}><div style={{width:22,height:22,borderRadius:11,background:T.accent,display:"flex",alignItems:"center",justifyContent:"center",color:"#000",fontWeight:700,fontSize:13}}>✓</div></div>}
                          {pFaces.length>0&&<div style={{position:"absolute",bottom:5,left:5,display:"flex",gap:2}}>{pFaces.slice(0,3).map(f=><div key={f.id} style={{width:18,height:18,borderRadius:9,background:f.color,border:"1px solid #000",display:"flex",alignItems:"center",justifyContent:"center",fontSize:8,fontWeight:700,color:"#000"}}>{f.initiales[0]}</div>)}</div>}
                          <div className="ph-overlay" style={{position:"absolute",top:5,right:p.favorite?24:5,display:"flex",gap:3,opacity:0,transition:"opacity 0.15s"}}>
                            <button onClick={e=>{e.stopPropagation();toggleFav(p.id);}} style={{width:26,height:26,borderRadius:13,background:"rgba(0,0,0,0.72)",border:"none",color:p.favorite?T.accent:"#fff",cursor:"pointer",fontSize:12}}>⭐</button>
                            <button onClick={e=>{e.stopPropagation();setEditing(p);}} style={{width:26,height:26,borderRadius:13,background:"rgba(0,0,0,0.72)",border:"none",color:"#fff",cursor:"pointer",fontSize:12}}>✏️</button>
                          </div>
                        </div>
                      );
                    })}
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>

      {/* Lightbox */}
      {lightbox&&lbPhoto&&(
        <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.96)",zIndex:2000,display:"flex",flexDirection:"column"}} onClick={()=>setLightbox(null)}>
          <div style={{height:50,display:"flex",alignItems:"center",padding:"0 14px",gap:10,flexShrink:0}} onClick={e=>e.stopPropagation()}>
            <button onClick={()=>setLightbox(null)} style={{background:"rgba(255,255,255,0.07)",border:"1px solid #222",color:"#e2ddd5",borderRadius:7,padding:"4px 12px",cursor:"pointer",fontFamily:T.font,fontSize:12}}>✕</button>
            <div style={{flex:1,fontFamily:T.fontD,fontSize:15,color:"#e2ddd5",textAlign:"center"}}>{lbPhoto.title}</div>
            <button onClick={()=>toggleFav(lightbox)} style={{background:"rgba(255,255,255,0.07)",border:"1px solid #222",color:lbPhoto.favorite?T.accent:"#6b7a99",borderRadius:7,padding:"4px 12px",cursor:"pointer",fontFamily:T.font,fontSize:12}}>{lbPhoto.favorite?"⭐":"☆"}</button>
            <button onClick={()=>{setEditing(lbPhoto);setLightbox(null);}} style={{background:T.accent,border:"none",color:"#000",borderRadius:7,padding:"5px 14px",cursor:"pointer",fontFamily:T.font,fontSize:12,fontWeight:700}}>✏️ Éditer</button>
          </div>
          <div style={{flex:1,display:"flex",alignItems:"center",justifyContent:"center",position:"relative",overflow:"hidden"}} onClick={()=>setLightbox(null)}>
            {(lbPhoto.url||lbPhoto.dataUrl)&&<img src={lbPhoto.url||lbPhoto.dataUrl} alt={lbPhoto.title} style={{maxWidth:"88vw",maxHeight:"80vh",objectFit:"contain",borderRadius:4,filter:lbPhoto.editState?buildFilterStr(lbPhoto.editState.adj,PHOTO_PRESETS.find(p=>p.id===lbPhoto.editState?.preset)?.filter||""):"",transform:lbPhoto.editState?`rotate(${lbPhoto.editState.rotation}deg) scaleX(${lbPhoto.editState.flipH?-1:1}) scaleY(${lbPhoto.editState.flipV?-1:1})`:""}} onClick={e=>e.stopPropagation()}/>}
            {lbIdx>0&&<button onClick={e=>{e.stopPropagation();navLb(-1);}} style={{position:"absolute",left:12,width:42,height:42,borderRadius:21,background:"rgba(0,0,0,0.72)",border:"1px solid #333",color:"#fff",cursor:"pointer",fontSize:20}}>‹</button>}
            {lbIdx<filteredMedia.length-1&&<button onClick={e=>{e.stopPropagation();navLb(1);}} style={{position:"absolute",right:12,width:42,height:42,borderRadius:21,background:"rgba(0,0,0,0.72)",border:"1px solid #333",color:"#fff",cursor:"pointer",fontSize:20}}>›</button>}
          </div>
          <div style={{height:50,display:"flex",alignItems:"center",justifyContent:"center",gap:16,flexShrink:0}} onClick={e=>e.stopPropagation()}>
            {lbPhoto.date&&<span style={{fontSize:12,color:"#6b7a99"}}>📅 {fmt(lbPhoto.date)}</span>}
            {lbPhoto.loc&&<span style={{fontSize:12,color:"#6b7a99"}}>📍 {lbPhoto.loc}</span>}
            {lbPhoto.tags?.length>0&&<span style={{fontSize:12,color:"#6b7a99"}}>🏷 {lbPhoto.tags.join(", ")}</span>}
            {(lbPhoto.faces||[]).length>0&&<span style={{fontSize:12,color:"#6b7a99"}}>👤 {(lbPhoto.faces||[]).map(fid=>faces.find(f=>f.id===fid)?.nom).filter(Boolean).join(", ")}</span>}
            <span style={{fontSize:12,color:"#6b7a99"}}>{lbIdx+1}/{filteredMedia.length}</span>
          </div>
        </div>
      )}

      {showAddAlbum&&(
        <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.85)",zIndex:2000,display:"flex",alignItems:"center",justifyContent:"center"}}>
          <div style={{background:"#111",border:"1px solid #222",borderRadius:14,width:460,padding:22,fontFamily:T.font}}>
            <div style={{fontFamily:T.fontD,fontSize:17,color:"#e2ddd5",marginBottom:16}}>📁 Nouvel album</div>
            <div style={{display:"flex",gap:5,flexWrap:"wrap",marginBottom:14}}>
              {ALBUM_ICONS.map(ic=><button key={ic} onClick={()=>setFormAlbum(f=>({...f,icon:ic}))} style={{fontSize:20,background:formAlbum.icon===ic?"rgba(240,165,0,0.12)":"transparent",border:`2px solid ${formAlbum.icon===ic?T.accent:"transparent"}`,borderRadius:7,padding:5,cursor:"pointer"}}>{ic}</button>)}
            </div>
            <div style={{marginBottom:10}}>
              <label style={{fontSize:11,color:"#6b7a99",display:"block",marginBottom:4}}>NOM *</label>
              <input value={formAlbum.nom} onChange={e=>setFormAlbum(f=>({...f,nom:e.target.value}))} placeholder="Vacances été 2025..." style={{width:"100%",background:"#0a0a0a",border:"1px solid #222",borderRadius:8,padding:"8px 12px",color:"#e2ddd5",fontFamily:T.font,fontSize:13,outline:"none"}}/>
            </div>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10,marginBottom:14}}>
              <div><label style={{fontSize:11,color:"#6b7a99",display:"block",marginBottom:4}}>DATE</label><input type="date" value={formAlbum.date} onChange={e=>setFormAlbum(f=>({...f,date:e.target.value}))} style={{width:"100%",background:"#0a0a0a",border:"1px solid #222",borderRadius:8,padding:"8px 10px",color:"#e2ddd5",fontFamily:T.font,fontSize:12,outline:"none"}}/></div>
              <div><label style={{fontSize:11,color:"#6b7a99",display:"block",marginBottom:4}}>TAGS</label><input value={formAlbum.tags} onChange={e=>setFormAlbum(f=>({...f,tags:e.target.value}))} placeholder="famille, voyage..." style={{width:"100%",background:"#0a0a0a",border:"1px solid #222",borderRadius:8,padding:"8px 10px",color:"#e2ddd5",fontFamily:T.font,fontSize:12,outline:"none"}}/></div>
            </div>
            <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
              <button onClick={()=>setShowAddAlbum(false)} style={{background:"rgba(255,255,255,0.06)",border:"1px solid #222",color:"#6b7a99",borderRadius:8,padding:"7px 14px",cursor:"pointer",fontFamily:T.font,fontSize:13}}>Annuler</button>
              <button onClick={()=>{if(!formAlbum.nom)return;setPhotos(p=>({...p,albums:[...(p.albums||[]),{...formAlbum,id:uid()}]}));setShowAddAlbum(false);setFormAlbum({nom:"",icon:"📸",description:"",date:today(),tags:""});}} disabled={!formAlbum.nom} style={{background:T.accent,border:"none",color:"#000",borderRadius:8,padding:"7px 16px",cursor:"pointer",fontFamily:T.font,fontSize:13,fontWeight:700,opacity:formAlbum.nom?1:0.5}}>💾 Créer</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};


// ═══════════════════════════════════════════════════════════════════════════════
// SYSTÈME DE SAUVEGARDE UNIVERSEL
// ═══════════════════════════════════════════════════════════════════════════════

// Convertit une blob URL en base64 pour sauvegarde persistante
const blobToBase64=async(url)=>{
  if(!url||!url.startsWith("blob:"))return url;
  try{
    const r=await fetch(url);
    const b=await r.blob();
    return new Promise(res=>{const fr=new FileReader();fr.onload=()=>res(fr.result);fr.readAsDataURL(b);});
  }catch{return null;}
};

// Convertit base64 → blob URL à la restauration
const base64ToBlobUrl=(b64)=>{
  if(!b64||b64.startsWith("blob:"))return b64;
  try{
    const arr=b64.split(","),mime=arr[0].match(/:(.*?);/)[1],bstr=atob(arr[1]);
    let n=bstr.length,u8=new Uint8Array(n);
    while(n--)u8[n]=bstr.charCodeAt(n);
    return URL.createObjectURL(new Blob([u8],{type:mime}));
  }catch{return b64;}
};

// Parcourt récursivement l'état pour convertir les blob URLs en base64
const serializeState=async(obj)=>{
  if(Array.isArray(obj))return Promise.all(obj.map(serializeState));
  if(obj&&typeof obj==="object"){
    const out={};
    for(const k of Object.keys(obj)){
      if(k==="url"&&typeof obj[k]==="string"){out[k]=await blobToBase64(obj[k]);}
      else{out[k]=await serializeState(obj[k]);}
    }
    return out;
  }
  return obj;
};

// Restaure les blob URLs après chargement depuis base64
const deserializeState=(obj)=>{
  if(Array.isArray(obj))return obj.map(deserializeState);
  if(obj&&typeof obj==="object"){
    const out={};
    for(const k of Object.keys(obj)){
      if(k==="url"&&typeof obj[k]==="string"&&obj[k].startsWith("data:")){out[k]=base64ToBlobUrl(obj[k]);}
      else{out[k]=deserializeState(obj[k]);}
    }
    return out;
  }
  return obj;
};

const LS_KEY="mespapiers_v5";

const BackupPanel=({state,onRestore,onClose})=>{
  const [status,setStatus]=useState("");
  const [loading,setLoading]=useState(false);
  const [lastLocal,setLastLocal]=useState(()=>localStorage.getItem(LS_KEY+"_date")||null);
  const fileRef=useRef();

  // ── Export JSON complet (avec fichiers encodés base64)
  const exportJSON=async()=>{
    setLoading(true);setStatus("⏳ Encodage des fichiers...");
    try{
      const serialized=await serializeState(state);
      const blob=new Blob([JSON.stringify({...serialized,_version:5,_date:new Date().toISOString()},null,2)],{type:"application/json"});
      const a=document.createElement("a");a.href=URL.createObjectURL(blob);
      a.download=`numavie_${new Date().toISOString().slice(0,10)}.json`;a.click();
      setStatus("✅ Export JSON réussi — tous vos fichiers sont inclus !");
    }catch(e){setStatus("❌ Erreur: "+e.message);}
    setLoading(false);
  };

  // ── Export ZIP (JSON + fichiers séparés nommés)
  const exportZIP=async()=>{
    setLoading(true);setStatus("⏳ Préparation du ZIP...");
    try{
      // Chargement dynamique de JSZip
      await new Promise((res,rej)=>{
        if(window.JSZip)return res();
        const s=document.createElement("script");
        s.src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js";
        s.onload=res;s.onerror=rej;document.head.appendChild(s);
      });
      const zip=new window.JSZip();
      const docsFolder=zip.folder("fichiers");
      let fileCount=0;

      // Fonction récursive pour collecter les fichiers
      const collectFiles=async(obj,path=[])=>{
        if(Array.isArray(obj)){for(const it of obj)await collectFiles(it,path);}
        else if(obj&&typeof obj==="object"){
          if(obj.dataUrl&&obj.dataUrl.startsWith("data:")&&obj.nom){
            try{
              // Convertir base64 dataUrl en blob pour le ZIP
              const parts=obj.dataUrl.split(",");
              const mime=parts[0].match(/:(.*?);/)[1];
              const binary=atob(parts[1]);
              const bytes=new Uint8Array(binary.length);
              for(let i=0;i<binary.length;i++)bytes[i]=binary.charCodeAt(i);
              const fname=`${fileCount++}_${obj.nom.replace(/[^\w.-]/g,"_")}`;
              docsFolder.file(fname,bytes);
            }catch{}
          }
          for(const k of Object.keys(obj))await collectFiles(obj[k],[...path,k]);
        }
      };
      await collectFiles(state);
      setStatus(`⏳ Compression de ${fileCount} fichier(s)...`);

      // JSON des données (sans blob, juste noms)
      zip.file("donnees.json",JSON.stringify({...state,_version:5,_date:new Date().toISOString()},null,2));
      zip.file("LISEZ_MOI.txt",`SAUVEGARDE MES PAPIERS\nDate: ${new Date().toLocaleString("fr-FR")}\n\nCe ZIP contient:\n- donnees.json : toutes vos données\n- fichiers/ : ${fileCount} fichier(s) joint(s)\n\nPour restaurer: importez donnees.json dans l'application.`);

      const blob=await zip.generateAsync({type:"blob",compression:"DEFLATE"});
      const a=document.createElement("a");a.href=URL.createObjectURL(blob);
      a.download=`numavie_${new Date().toISOString().slice(0,10)}.zip`;a.click();
      setStatus(`✅ ZIP créé — données + ${fileCount} fichier(s) inclus !`);
    }catch(e){setStatus("❌ Erreur ZIP: "+e.message);}
    setLoading(false);
  };

  // ── Export PDF (impression navigateur)
  const exportPDF=()=>{
    const w=window.open("","_blank");
    const {maisons,vehicules,assurances,impots,banque,contacts,alertes,sports,locataires}=state;
    const totalAssur=assurances.filter(a=>a.statut==="actif").reduce((s,a)=>s+a.prime,0);
    const totalBanque=(banque.comptes||[]).reduce((s,c)=>s+c.solde,0)+(banque.epargne||[]).reduce((s,e)=>s+e.solde,0);
    const section=(title,rows)=>`<div class="section"><h2>${title}</h2><table>${rows}</table></div>`;
    const row=(label,val)=>`<tr><td>${label}</td><td>${val||"—"}</td></tr>`;
    w.document.write(`<!DOCTYPE html><html><head><meta charset="UTF-8"><title>NumaVie — ${new Date().toLocaleDateString("fr-FR")}</title>
    <style>*{margin:0;padding:0;box-sizing:border-box}body{font-family:Arial,sans-serif;font-size:11px;color:#222;padding:20px}
    h1{font-size:20px;margin-bottom:4px;color:#1a1a2e}h2{font-size:13px;background:#f0a500;color:#fff;padding:5px 10px;margin:14px 0 6px;border-radius:4px}
    .section{margin-bottom:16px;break-inside:avoid}table{width:100%;border-collapse:collapse}
    td{padding:4px 8px;border:1px solid #ddd}tr:nth-child(even){background:#f9f9f9}
    td:first-child{color:#666;width:38%;font-weight:500}
    .header{display:flex;justify-content:space-between;align-items:center;border-bottom:2px solid #f0a500;padding-bottom:10px;margin-bottom:18px}
    .meta{font-size:10px;color:#888}.grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
    @media print{body{padding:10px}.section{break-inside:avoid}}</style></head><body>
    <div class="header"><div><h1>📁 NumaVie — Sauvegarde complète</h1><div class="meta">Généré le ${new Date().toLocaleString("fr-FR")} · ${maisons.length} biens · ${vehicules.length} véhicules · ${assurances.length} assurances</div></div></div>
    <div class="grid">
    ${section("🏡 Maisons & Biens",maisons.map(m=>row(m.nom,`${m.adresse} · ${m.surface}m² · Valeur: ${m.valeur?m.valeur.toLocaleString("fr-FR")+"€":"—"}`)).join(""))}
    ${section("🚗 Véhicules",vehicules.map(v=>row(v.marque+" "+v.modele,`${v.immat||""} · ${v.annee} · ${v.kilometrage?Number(v.kilometrage).toLocaleString("fr-FR")+"km":"—"} · CT: ${v.dateCT||"—"}`)).join(""))}
    ${section("🛡️ Assurances (total: "+(totalAssur*12).toLocaleString("fr-FR")+"€/an)",assurances.map(a=>row(a.nom,`${a.assureur} · ${a.prime}€/mois · Éch: ${a.dateEcheance||"—"}`)).join(""))}
    ${section("🏦 Banque (patrimoine: "+totalBanque.toLocaleString("fr-FR")+"€)",[...(banque.comptes||[]),...(banque.epargne||[])].map(c=>row(c.nom,`${c.banqueNom} · Solde: ${c.solde.toLocaleString("fr-FR")}€`)).join(""))}
    </div>
    <div class="grid">
    ${section("🏛️ Impôts",[...(impots.declarations||[]),...(impots.paiements||[])].map(i=>row(i.titre,`${i.annee} · ${i.montant?i.montant+"€":""} · ${i.statut}`)).join(""))}
    ${section("👥 Contacts",contacts.map(c=>row(c.nom,`${c.societe||c.type} · ${c.tel||""} · ${c.email||""}`)).join(""))}
    ${section("⚠️ Alertes",alertes.filter(a=>!a.fait).map(a=>row(a.titre,`Échéance: ${a.date} · Priorité: ${a.priorite}`)).join(""))}
    ${section("🏠 Locataires",locataires.map(l=>row(l.prenom+" "+l.nom,`${l.loyer+l.charges}€/mois · ${l.typeBail} · ${l.statut}`)).join(""))}
    </div>
    ${section("🎯 Sports & Loisirs",sports.map(s=>row(s.nom,`${s.categorie} · ${s.niveau} · ${s.frequence||""} · ${(s.seances||[]).length} séances`)).join(""))}
    <div style="margin-top:20px;padding:10px;background:#fffbeb;border:1px solid #f0a500;border-radius:6px;font-size:10px;color:#666">
    ⚠️ Ce document est confidentiel. Il contient des informations personnelles et financières. À conserver en lieu sûr.</div>
    <script>window.onload=()=>window.print();</script></body></html>`);
    w.document.close();
  };

  // ── Sauvegarde manuelle localStorage
  const saveLocal=async()=>{
    setLoading(true);setStatus("⏳ Sauvegarde locale...");
    try{
      const serialized=await serializeState(state);
      const data=JSON.stringify({...serialized,_version:5,_date:new Date().toISOString()});
      localStorage.setItem(LS_KEY,data);
      const d=new Date().toISOString();
      localStorage.setItem(LS_KEY+"_date",d);
      setLastLocal(d);
      setStatus("✅ Sauvegarde locale enregistrée !");
    }catch(e){
      if(e.name==="QuotaExceededError")setStatus("⚠️ Stockage navigateur plein. Utilisez l'export JSON/ZIP.");
      else setStatus("❌ Erreur: "+e.message);
    }
    setLoading(false);
  };

  // ── Effacer localStorage
  const clearLocal=()=>{
    if(!confirm("Effacer la sauvegarde locale ?"))return;
    localStorage.removeItem(LS_KEY);localStorage.removeItem(LS_KEY+"_date");
    setLastLocal(null);setStatus("🗑️ Sauvegarde locale effacée.");
  };

  // ── Import JSON
  const importJSON=async(e)=>{
    const f=e.target.files[0];if(!f)return;
    setLoading(true);setStatus("⏳ Lecture du fichier...");
    try{
      const text=await f.text();
      const parsed=JSON.parse(text);
      const restored=deserializeState(parsed);
      if(!confirm(`Restaurer la sauvegarde du ${parsed._date?new Date(parsed._date).toLocaleString("fr-FR"):"date inconnue"} ?\n\nCela remplacera TOUTES vos données actuelles.`)){
        setStatus("");setLoading(false);return;
      }
      onRestore(restored);
      setStatus("✅ Données restaurées avec succès !");
    }catch(e){setStatus("❌ Fichier invalide: "+e.message);}
    setLoading(false);
  };

  const fmtDate=d=>{try{return new Date(d).toLocaleString("fr-FR");}catch{return d;}};
  const lsSize=()=>{try{const d=localStorage.getItem(LS_KEY);return d?(d.length/1024).toFixed(0)+"Ko":"—";}catch{return "—";}};

  return (
    <Modal title="🔒 Sauvegarde & Sécurité" onClose={onClose} width={700}>
      {/* Barre de statut */}
      {status&&<div style={{marginBottom:16,padding:"10px 14px",background:status.startsWith("✅")?"rgba(34,197,94,0.1)":status.startsWith("❌")?"rgba(239,68,68,0.1)":"rgba(240,165,0,0.1)",border:`1px solid ${status.startsWith("✅")?T.success:status.startsWith("❌")?T.danger:T.accent}33`,borderRadius:8,fontSize:13,color:status.startsWith("✅")?T.success:status.startsWith("❌")?T.danger:T.accent}}>{status}</div>}

      {/* Sauvegarde locale auto */}
      <div style={{background:"#0a0e17",border:`1px solid ${T.border}`,borderRadius:10,padding:16,marginBottom:14}}>
        <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
          <div>
            <div style={{fontWeight:700,color:T.text,fontSize:14,marginBottom:4}}>💾 Sauvegarde automatique navigateur</div>
            <div style={{fontSize:12,color:T.muted}}>Enregistrée dans votre navigateur — survit aux rechargements</div>
            <div style={{fontSize:11,marginTop:6}}>
              {lastLocal?<span style={{color:T.success}}>✅ Dernière sauvegarde : {fmtDate(lastLocal)} · {lsSize()}</span>:<span style={{color:T.warning}}>⚠️ Aucune sauvegarde locale</span>}
            </div>
          </div>
          <div style={{display:"flex",gap:6}}>
            <Btn onClick={saveLocal} disabled={loading}>💾 Sauvegarder</Btn>
            {lastLocal&&<Btn v="danger" sm onClick={clearLocal}>🗑</Btn>}
          </div>
        </div>
      </div>

      <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:12,marginBottom:14}}>
        {/* Export JSON */}
        <div style={{background:"#0a0e17",border:`1px solid ${T.border}`,borderRadius:10,padding:16}}>
          <div style={{fontSize:20,marginBottom:8}}>📦</div>
          <div style={{fontWeight:700,color:T.text,fontSize:14,marginBottom:4}}>Export JSON complet</div>
          <div style={{fontSize:11,color:T.muted,marginBottom:12}}>Toutes vos données + fichiers joints encodés. Format réimportable. Idéal pour sauvegarde régulière.</div>
          <Btn onClick={exportJSON} disabled={loading} style={{width:"100%"}}>⬇ Télécharger .json</Btn>
        </div>

        {/* Export ZIP */}
        <div style={{background:"#0a0e17",border:`1px solid ${T.border}`,borderRadius:10,padding:16}}>
          <div style={{fontSize:20,marginBottom:8}}>🗜️</div>
          <div style={{fontWeight:700,color:T.text,fontSize:14,marginBottom:4}}>Export ZIP complet</div>
          <div style={{fontSize:11,color:T.muted,marginBottom:12}}>Données + chaque fichier séparé dans un dossier. Lisible sans l'application. Archivage long terme.</div>
          <Btn onClick={exportZIP} disabled={loading} style={{width:"100%"}}>⬇ Télécharger .zip</Btn>
        </div>

        {/* Import */}
        <div style={{background:"#0a0e17",border:`1px solid ${T.border}`,borderRadius:10,padding:16,gridColumn:"1/-1"}}>
          <div style={{fontSize:20,marginBottom:8}}>📂</div>
          <div style={{fontWeight:700,color:T.text,fontSize:14,marginBottom:4}}>Importer une sauvegarde</div>
          <div style={{fontSize:11,color:T.muted,marginBottom:12}}>Restaurez un fichier .json exporté précédemment. <span style={{color:T.danger,fontWeight:600}}>Remplace toutes les données actuelles.</span></div>
          <Btn v="ghost" onClick={()=>fileRef.current.click()} disabled={loading} style={{width:"100%"}}>📂 Choisir un fichier .json</Btn>
          <input ref={fileRef} type="file" accept=".json" style={{display:"none"}} onChange={importJSON}/>
        </div>
      </div>

      {/* Conseils sécurité */}
      <div style={{background:"rgba(240,165,0,0.06)",border:"1px solid rgba(240,165,0,0.2)",borderRadius:10,padding:14}}>
        <div style={{fontWeight:700,color:T.accent,fontSize:12,marginBottom:8}}>🔐 Conseils pour une sécurité absolue</div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:6,fontSize:11,color:T.muted}}>
          <div>✅ Exportez un ZIP chaque semaine</div>
          <div>✅ Copiez sur une clé USB ou disque externe</div>
          <div>✅ Gardez 3 sauvegardes (3-2-1 rule)</div>
          <div>✅ Testez la restauration tous les 3 mois</div>
          <div>✅ Sauvegardez avant chaque mise à jour</div>
          <div>✅ Envoyez par email à vous-même</div>
        </div>
      </div>
      {loading&&<div style={{marginTop:12,textAlign:"center",color:T.accent,fontSize:13}}>⏳ Opération en cours, veuillez patienter...</div>}
    </Modal>
  );
};


// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: ENFANTS
// ═══════════════════════════════════════════════════════════════════════════════
const Enfants=({enfants,setEnfants})=>{
  const [selected,setSelected]=useState(null);
  const [showAdd,setShowAdd]=useState(false);
  const [form,setForm]=useState({prenom:"",nom:"",dateNaissance:"",sexe:"",lieuNaissance:"",numeroCNI:"",numeroPasport:"",groupeSanguin:"",medecin:"",note:""});
  const sel=enfants.find(e=>e.id===selected);

  const age=d=>{if(!d)return"";const a=Math.floor((new Date()-new Date(d))/3.156e10);return a<2?Math.floor((new Date()-new Date(d))/2.628e9)+" mois":a+" ans";};

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>👶 Mes Enfants</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>{enfants.length} enfant{enfants.length>1?"s":""} enregistré{enfants.length>1?"s":""}</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Ajouter un enfant</Btn>
      </div>
      {enfants.length===0&&<EmptyState icon="👶" text="Ajoutez vos enfants pour centraliser leur santé, scolarité et documents."/>}
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(320px,1fr))",gap:14}}>
        {enfants.map(e=>{
          const a=age(e.dateNaissance);
          const prochainVaccin=(e.vaccins||[]).find(v=>v.statut==="à faire");
          const rdvAVenir=(e.rdv||[]).filter(r=>r.date>=today()).length;
          return (
            <Card key={e.id} onClick={()=>setSelected(e.id)} style={{cursor:"pointer",borderColor:selected===e.id?T.accent:T.border,padding:0,overflow:"hidden"}}>
              <div style={{background:`linear-gradient(135deg,${e.sexe==="F"?"#f472b6":"#60a5fa"}22,transparent)`,padding:"16px 18px",borderBottom:`1px solid ${T.border}`}}>
                <div style={{display:"flex",alignItems:"center",gap:12}}>
                  <div style={{width:48,height:48,borderRadius:24,background:e.sexe==="F"?"rgba(244,114,182,0.2)":"rgba(96,165,250,0.2)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:24}}>{e.sexe==="F"?"👧":"👦"}</div>
                  <div>
                    <div style={{fontFamily:T.fontD,fontSize:17,fontWeight:700,color:T.text}}>{e.prenom} {e.nom}</div>
                    <div style={{fontSize:12,color:T.muted}}>{a}{e.dateNaissance&&(" · né"+(e.sexe==="F"?"e":"")+" le "+fmt(e.dateNaissance))}</div>
                  </div>
                </div>
              </div>
              <div style={{padding:"12px 18px",display:"flex",gap:6,flexWrap:"wrap"}}>
                {e.ecoleActuelle&&<Badge c={T.info}>🏫 {e.ecoleActuelle}</Badge>}
                {e.classe&&<Badge c={T.muted}>{e.classe}</Badge>}
                {rdvAVenir>0&&<Badge c={T.warning}>🏥 {rdvAVenir} RDV</Badge>}
                {prochainVaccin&&<Badge c={T.danger}>💉 Vaccin à faire</Badge>}
                {(e.docs||[]).length>0&&<Badge c={T.accent}>📎 {e.docs.length}</Badge>}
              </div>
            </Card>
          );
        })}
      </div>
      {sel&&<EnfantDetail key={sel.id} enfant={sel} onUpdate={u=>setEnfants(p=>p.map(e=>e.id===u.id?u:e))} onClose={()=>setSelected(null)} onDelete={()=>{setEnfants(p=>p.filter(e=>e.id!==selected));setSelected(null);}}/>}
      {showAdd&&<Modal title="👶 Nouvel enfant" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Prénom *"><Inp value={form.prenom} onChange={v=>setForm(f=>({...f,prenom:v}))} placeholder="Léa"/></F>
          <F label="Nom *"><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))}/></F>
          <F label="Date de naissance"><Inp type="date" value={form.dateNaissance} onChange={v=>setForm(f=>({...f,dateNaissance:v}))}/></F>
          <F label="Sexe"><Sel value={form.sexe} onChange={v=>setForm(f=>({...f,sexe:v}))}><option value="">—</option><option value="M">Garçon</option><option value="F">Fille</option></Sel></F>
          <F label="Lieu de naissance"><Inp value={form.lieuNaissance} onChange={v=>setForm(f=>({...f,lieuNaissance:v}))}/></F>
          <F label="Groupe sanguin"><Sel value={form.groupeSanguin} onChange={v=>setForm(f=>({...f,groupeSanguin:v}))}><option value="">—</option>{["A+","A−","B+","B−","AB+","AB−","O+","O−"].map(g=><option key={g}>{g}</option>)}</Sel></F>
          <F label="Médecin référent"><Inp value={form.medecin} onChange={v=>setForm(f=>({...f,medecin:v}))} placeholder="Dr. Martin"/></F>
          <F label="N° Sécurité sociale"><Inp value={form.numeroCNI} onChange={v=>setForm(f=>({...f,numeroCNI:v}))}/></F>
        </div>
        <F label="Note"><Txt value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} rows={2}/></F>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={()=>{setEnfants(p=>[...p,{...form,id:uid(),rdv:[],vaccins:[],ordonnances:[],ecoles:[],activites:[],docs:[],echanges:[]}]);setShowAdd(false);}} disabled={!form.prenom}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

const EnfantDetail=({enfant,onUpdate,onClose,onDelete})=>{
  const [tab,setTab]=useState("resume");
  const [selectedItem,setSelectedItem]=useState(null);
  const [showAdd,setShowAdd]=useState(null);
  // Formulaires niveau composant (no IIFE)
  const [rdvEnfForm,setRdvEnfForm]=useState({titre:"",medecin:"",specialite:"",date:today(),heure:"",adresse:"",note:""});
  const [vaccEnfForm,setVaccEnfForm]=useState({nom:"",dateFait:"",dateRappel:"",statut:"fait",medecin:"",note:""});
  const [ecoleForm,setEcoleForm]=useState({nom:"",type:"",ville:"",classe:"",dateEntree:"",dateSortie:"",note:""});
  const [activiteEnfForm,setActiviteEnfForm]=useState({nom:"",icon:"⚽",club:"",jour:"",heure:"",niveau:"",cout:"",licenceExpiry:"",note:""});
  const updTab=(key,arr)=>onUpdate({...enfant,[key]:arr});
  const age=d=>{if(!d)return"";const a=Math.floor((new Date()-new Date(d))/3.156e10);return a<2?Math.floor((new Date()-new Date(d))/2.628e9)+" mois":a+" ans";};

  const TABS=[{id:"resume",icon:"📋",label:"Résumé"},{id:"sante",icon:"🏥",label:"Santé"},{id:"scolarite",icon:"🏫",label:"Scolarité"},{id:"activites",icon:"⚽",label:"Activités"},{id:"documents",icon:"📁",label:"Documents"}];

  const selItem=selectedItem&&(
    (tab==="sante"&&[...(enfant.rdv||[]),...(enfant.vaccins||[]),...(enfant.ordonnances||[])].find(x=>x.id===selectedItem.id))||
    (tab==="scolarite"&&(enfant.ecoles||[]).find(x=>x.id===selectedItem.id))||
    (tab==="activites"&&(enfant.activites||[]).find(x=>x.id===selectedItem.id))
  );

  return (
    <div>
      {/* Header enfant */}
      <div style={{display:"flex",alignItems:"center",gap:12,marginBottom:20}}>
        <button onClick={onClose} style={{background:"none",border:"none",color:T.accent,cursor:"pointer",fontSize:13,fontFamily:T.font}}>← Retour</button>
        <div style={{width:44,height:44,borderRadius:22,background:enfant.sexe==="F"?"rgba(244,114,182,0.2)":"rgba(96,165,250,0.2)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:22}}>{enfant.sexe==="F"?"👧":"👦"}</div>
        <div style={{flex:1}}>
          <h2 style={{fontFamily:T.fontD,fontSize:22,color:T.text,margin:0}}>{enfant.prenom} {enfant.nom}</h2>
          <div style={{color:T.muted,fontSize:12}}>{age(enfant.dateNaissance)}{enfant.dateNaissance&&" · né le "+fmt(enfant.dateNaissance)}{enfant.groupeSanguin&&" · "+enfant.groupeSanguin}</div>
        </div>
        <Btn v="danger" sm onClick={()=>{if(confirm("Supprimer ?"))onDelete();}}>🗑</Btn>
      </div>
      <Tabs tabs={TABS} active={tab} onChange={t=>{setTab(t);setSelectedItem(null);}}/>

      {tab==="resume"&&(
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
          <Card>
            <Divider label="Identité"/>
            <InfoRow label="Prénom / Nom" value={`${enfant.prenom} ${enfant.nom}`}/>
            <InfoRow label="Date de naissance" value={fmt(enfant.dateNaissance)}/>
            <InfoRow label="Lieu de naissance" value={enfant.lieuNaissance}/>
            <InfoRow label="Âge" value={age(enfant.dateNaissance)} color={T.accent}/>
            <InfoRow label="Sexe" value={enfant.sexe==="F"?"Fille":"Garçon"}/>
            <InfoRow label="Groupe sanguin" value={enfant.groupeSanguin} color={T.danger}/>
            <InfoRow label="Médecin" value={enfant.medecin}/>
            <InfoRow label="N° SS" value={enfant.numeroCNI} mono/>
          </Card>
          <Card>
            <Divider label="Scolarité actuelle"/>
            <InfoRow label="École / Lycée" value={enfant.ecoleActuelle}/>
            <InfoRow label="Classe" value={enfant.classe}/>
            <Divider label="Chiffres clés"/>
            <InfoRow label="RDV médicaux" value={(enfant.rdv||[]).length+" RDV"}/>
            <InfoRow label="Vaccins" value={(enfant.vaccins||[]).length+" enregistrés"}/>
            <InfoRow label="Activités" value={(enfant.activites||[]).length+" activité(s)"}/>
            <InfoRow label="Documents" value={(enfant.docs||[]).length+" doc(s)"}/>
            {enfant.note&&<div style={{marginTop:12,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{enfant.note}</div>}
          </Card>
        </div>
      )}

      {tab==="sante"&&(
        <div style={{display:"grid",gap:14}}>
          {/* RDV */}
          <div>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:10}}>
              <div style={{fontWeight:700,color:T.text}}>🏥 Rendez-vous médicaux</div>
              <Btn sm onClick={()=>setShowAdd("rdv")}>+ RDV</Btn>
            </div>
            <div style={{display:"grid",gap:8}}>
              {(enfant.rdv||[]).map(r=>(
                <Card key={r.id} onClick={()=>setSelectedItem({id:r.id,type:"rdv"})} style={{cursor:"pointer",padding:"10px 14px",borderColor:selectedItem?.id===r.id?T.accent:T.border}}>
                  <div style={{display:"flex",justifyContent:"space-between"}}>
                    <div><span style={{fontWeight:600,color:T.text,fontSize:13}}>🏥 {r.titre}</span>{r.medecin&&<span style={{fontSize:11,color:T.muted,marginLeft:8}}>· {r.medecin}</span>}</div>
                    <div style={{textAlign:"right"}}><Badge c={r.date>=today()?T.info:T.muted}>{fmt(r.date)}{r.heure&&" "+r.heure}</Badge></div>
                  </div>
                  {r.note&&<div style={{fontSize:11,color:T.muted,marginTop:4}}>{r.note}</div>}
                </Card>
              ))}
              {!(enfant.rdv||[]).length&&<EmptyState icon="🏥" text="Aucun RDV enregistré"/>}
            </div>
          </div>
          {/* Vaccins */}
          <div>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:10}}>
              <div style={{fontWeight:700,color:T.text}}>💉 Carnet de vaccination</div>
              <Btn sm onClick={()=>setShowAdd("vaccin")}>+ Vaccin</Btn>
            </div>
            <div style={{display:"grid",gap:8}}>
              {(enfant.vaccins||[]).map(v=>(
                <Card key={v.id} onClick={()=>setSelectedItem({id:v.id,type:"vaccin"})} style={{cursor:"pointer",padding:"10px 14px",borderColor:selectedItem?.id===v.id?T.accent:T.border}}>
                  <div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                    <span style={{fontWeight:600,color:T.text,fontSize:13}}>💉 {v.nom}</span>
                    <div style={{display:"flex",gap:6}}>
                      <Badge c={v.statut==="fait"?T.success:T.warning}>{v.statut}</Badge>
                      {v.dateFait&&<Badge c={T.muted}>{fmt(v.dateFait)}</Badge>}
                      {v.dateRappel&&<Badge c={T.info}>Rappel: {fmt(v.dateRappel)}</Badge>}
                    </div>
                  </div>
                  {v.note&&<div style={{fontSize:11,color:T.muted,marginTop:4}}>{v.note}</div>}
                </Card>
              ))}
              {!(enfant.vaccins||[]).length&&<EmptyState icon="💉" text="Aucun vaccin enregistré"/>}
            </div>
          </div>
          {selectedItem&&selItem&&(()=>{
            const isRdv=selectedItem.type==="rdv";
            const isVaccin=selectedItem.type==="vaccin";
            const arr=isRdv?(enfant.rdv||[]):isVaccin?(enfant.vaccins||[]):(enfant.ordonnances||[]);
            const key=isRdv?"rdv":isVaccin?"vaccins":"ordonnances";
            return <FichePanel
              title={selItem.titre||selItem.nom} icon={isRdv?"🏥":"💉"}
              badge={isRdv?fmt(selItem.date):selItem.statut} badgeColor={isRdv?T.info:selItem.statut==="fait"?T.success:T.warning}
              onClose={()=>setSelectedItem(null)}
              onDelete={()=>{updTab(key,arr.filter(x=>x.id!==selItem.id));setSelectedItem(null);}}
              docs={selItem.docs||[]} onDocsChange={nd=>updTab(key,arr.map(x=>x.id===selItem.id?{...x,docs:nd}:x))}
              echanges={selItem.echanges||[]} onEchangesChange={ne=>updTab(key,arr.map(x=>x.id===selItem.id?{...x,echanges:ne}:x))}
              docsLabel={isRdv?"Ordonnance, résultats d'analyse...":"Carnet de santé, certificat de vaccination..."}
              leftContent={<div>
                {isRdv&&<><InfoRow label="Titre" value={selItem.titre}/><InfoRow label="Médecin" value={selItem.medecin}/><InfoRow label="Spécialité" value={selItem.specialite}/><InfoRow label="Date" value={fmt(selItem.date)}/><InfoRow label="Heure" value={selItem.heure}/><InfoRow label="Adresse" value={selItem.adresse}/></>}
                {isVaccin&&<><InfoRow label="Vaccin" value={selItem.nom}/><InfoRow label="Statut" value={selItem.statut}/><InfoRow label="Date d'injection" value={fmt(selItem.dateFait)}/><InfoRow label="Date de rappel" value={fmt(selItem.dateRappel)} color={T.warning}/><InfoRow label="Médecin / Centre" value={selItem.medecin}/></>}
                {selItem.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{selItem.note}</div>}
              </div>}
            />;
          })()}
        </div>
      )}

      {tab==="scolarite"&&(
        <div>
          <div style={{display:"flex",justifyContent:"space-between",marginBottom:10}}>
            <div style={{fontWeight:700,color:T.text}}>🏫 Parcours scolaire</div>
            <Btn sm onClick={()=>setShowAdd("ecole")}>+ Établissement</Btn>
          </div>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10,marginBottom:16}}>
            <F label="École actuelle"><Inp value={enfant.ecoleActuelle||""} onChange={v=>onUpdate({...enfant,ecoleActuelle:v})} placeholder="École primaire Jules Ferry"/></F>
            <F label="Classe actuelle"><Inp value={enfant.classe||""} onChange={v=>onUpdate({...enfant,classe:v})} placeholder="CM2, 3ème..."/></F>
          </div>
          {(enfant.ecoles||[]).map(ec=>(
            <Card key={ec.id} onClick={()=>setSelectedItem({id:ec.id,type:"ecole"})} style={{cursor:"pointer",padding:"10px 14px",marginBottom:8,borderColor:selectedItem?.id===ec.id?T.accent:T.border}}>
              <div style={{display:"flex",justifyContent:"space-between"}}>
                <div><span style={{fontWeight:600,fontSize:13,color:T.text}}>🏫 {ec.nom}</span>{ec.ville&&<span style={{fontSize:11,color:T.muted,marginLeft:8}}>· {ec.ville}</span>}</div>
                <Badge c={T.muted}>{ec.dateEntree&&fmt(ec.dateEntree)}{ec.dateSortie&&" → "+fmt(ec.dateSortie)}</Badge>
              </div>
              {ec.classe&&<div style={{fontSize:11,color:T.muted,marginTop:4}}>Classe : {ec.classe}</div>}
            </Card>
          ))}
          {!(enfant.ecoles||[]).length&&<EmptyState icon="🏫" text="Ajoutez les établissements fréquentés"/>}
          {selectedItem?.type==="ecole"&&(()=>{
            const ec=(enfant.ecoles||[]).find(x=>x.id===selectedItem.id);
            if(!ec)return null;
            return <FichePanel title={ec.nom} icon="🏫" badge={ec.classe} badgeColor={T.info}
              onClose={()=>setSelectedItem(null)} onDelete={()=>{updTab("ecoles",(enfant.ecoles||[]).filter(x=>x.id!==ec.id));setSelectedItem(null);}}
              docs={ec.docs||[]} onDocsChange={nd=>updTab("ecoles",(enfant.ecoles||[]).map(x=>x.id===ec.id?{...x,docs:nd}:x))}
              echanges={ec.echanges||[]} onEchangesChange={ne=>updTab("ecoles",(enfant.ecoles||[]).map(x=>x.id===ec.id?{...x,echanges:ne}:x))}
              docsLabel="Bulletins, certificats de scolarité, règlement..."
              leftContent={<div><InfoRow label="Établissement" value={ec.nom}/><InfoRow label="Type" value={ec.type}/><InfoRow label="Ville" value={ec.ville}/><InfoRow label="Classe" value={ec.classe}/><InfoRow label="Entrée" value={fmt(ec.dateEntree)}/><InfoRow label="Sortie" value={fmt(ec.dateSortie)}/>{ec.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{ec.note}</div>}</div>}
            />;
          })()}
        </div>
      )}

      {tab==="activites"&&(
        <div>
          <div style={{display:"flex",justifyContent:"space-between",marginBottom:10}}>
            <div style={{fontWeight:700,color:T.text}}>⚽ Activités extrascolaires</div>
            <Btn sm onClick={()=>setShowAdd("activite")}>+ Activité</Btn>
          </div>
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(280px,1fr))",gap:10}}>
            {(enfant.activites||[]).map(a=>(
              <Card key={a.id} onClick={()=>setSelectedItem({id:a.id,type:"activite"})} style={{cursor:"pointer",borderColor:selectedItem?.id===a.id?T.accent:T.border}}>
                <div style={{fontSize:22,marginBottom:6}}>{a.icon||"⚽"}</div>
                <div style={{fontWeight:700,color:T.text,marginBottom:4}}>{a.nom}</div>
                {a.club&&<div style={{fontSize:12,color:T.muted}}>🏛️ {a.club}</div>}
                {a.jour&&<div style={{fontSize:12,color:T.muted}}>📅 {a.jour}{a.heure&&" à "+a.heure}</div>}
                {a.cout&&<div style={{fontSize:13,fontWeight:700,color:T.accent,marginTop:6}}>{fmtAmt(a.cout)}/mois</div>}
              </Card>
            ))}
          </div>
          {!(enfant.activites||[]).length&&<EmptyState icon="⚽" text="Ajoutez les activités de l'enfant"/>}
          {selectedItem?.type==="activite"&&(()=>{
            const a=(enfant.activites||[]).find(x=>x.id===selectedItem.id);
            if(!a)return null;
            return <FichePanel title={a.nom} icon={a.icon||"⚽"} badge={a.club} badgeColor={T.info}
              onClose={()=>setSelectedItem(null)} onDelete={()=>{updTab("activites",(enfant.activites||[]).filter(x=>x.id!==a.id));setSelectedItem(null);}}
              docs={a.docs||[]} onDocsChange={nd=>updTab("activites",(enfant.activites||[]).map(x=>x.id===a.id?{...x,docs:nd}:x))}
              echanges={a.echanges||[]} onEchangesChange={ne=>updTab("activites",(enfant.activites||[]).map(x=>x.id===a.id?{...x,echanges:ne}:x))}
              docsLabel="Licences, certificats médicaux, photos..."
              leftContent={<div><InfoRow label="Activité" value={a.nom}/><InfoRow label="Club / Cours" value={a.club}/><InfoRow label="Jour / Heure" value={a.jour&&(a.jour+(a.heure?" à "+a.heure:""))}/><InfoRow label="Niveau" value={a.niveau}/><InfoRow label="Coût mensuel" value={a.cout&&fmtAmt(a.cout)} color={T.accent}/><InfoRow label="Licence expire" value={fmt(a.licenceExpiry)} color={a.licenceExpiry&&daysFrom(a.licenceExpiry)<=30?T.danger:T.text}/>{a.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{a.note}</div>}</div>}
            />;
          })()}
        </div>
      )}

      {tab==="documents"&&(
        <Card>
          <div style={{fontSize:12,color:T.muted,marginBottom:12}}>Documents d'identité et administratifs de {enfant.prenom}</div>
          <DocAttach docs={enfant.docs||[]} onChange={nd=>onUpdate({...enfant,docs:nd})} label="CNI, passeport, carnet de santé, acte de naissance..."/>
        </Card>
      )}

      {/* Modales d'ajout */}
      {showAdd==="rdv"&&<Modal title="🏥 Nouveau RDV" onClose={()=>setShowAdd(null)}>
        <>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
              <F label="Titre *"><Inp value={rdvEnfForm.titre} onChange={v=>setRdvEnfForm(f=>({...f,titre:v}))} placeholder="Contrôle pédiatre"/></F>
              <F label="Médecin"><Inp value={rdvEnfForm.medecin} onChange={v=>setRdvEnfForm(f=>({...f,medecin:v}))}/></F>
              <F label="Date"><Inp type="date" value={rdvEnfForm.date} onChange={v=>setRdvEnfForm(f=>({...f,date:v}))}/></F>
              <F label="Heure"><Inp type="time" value={rdvEnfForm.heure} onChange={v=>setRdvEnfForm(f=>({...f,heure:v}))}/></F>
            </div>
            <F label="Note"><Txt value={rdvEnfForm.note} onChange={v=>setRdvEnfForm(f=>({...f,note:v}))} rows={2}/></F>
            <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
              <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
              <Btn onClick={()=>{updTab("rdv",[...(enfant.rdv||[]),{...rdvEnfForm,id:uid()}]);setRdvEnfForm({titre:"",medecin:"",specialite:"",date:today(),heure:"",adresse:"",note:""});setShowAdd(null);}} disabled={!rdvEnfForm.titre}>💾 Enregistrer</Btn>
            </div>
          </>
      </Modal>}
      {showAdd==="vaccin"&&<Modal title="💉 Nouveau vaccin" onClose={()=>setShowAdd(null)}>
        <>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
              <F label="Vaccin *"><Inp value={vaccEnfForm.nom} onChange={v=>setVaccEnfForm(f=>({...f,nom:v}))} placeholder="DTP, ROR, Covid..."/></F>
              <F label="Statut"><Sel value={vaccEnfForm.statut} onChange={v=>setVaccEnfForm(f=>({...f,statut:v}))}><option value="fait">Fait</option><option value="à faire">À faire</option></Sel></F>
              <F label="Date d'injection"><Inp type="date" value={vaccEnfForm.dateFait} onChange={v=>setVaccEnfForm(f=>({...f,dateFait:v}))}/></F>
              <F label="Date de rappel"><Inp type="date" value={vaccEnfForm.dateRappel} onChange={v=>setVaccEnfForm(f=>({...f,dateRappel:v}))}/></F>
            </div>
            <F label="Note"><Txt value={vaccEnfForm.note} onChange={v=>setVaccEnfForm(f=>({...f,note:v}))} rows={2}/></F>
            <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
              <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
              <Btn onClick={()=>{updTab("vaccins",[...(enfant.vaccins||[]),{...vaccEnfForm,id:uid()}]);setVaccEnfForm({nom:"",dateFait:"",dateRappel:"",statut:"fait",medecin:"",note:""});setShowAdd(null);}} disabled={!vaccEnfForm.nom}>💾</Btn>
            </div>
          </>
      </Modal>}
      {showAdd==="ecole"&&<Modal title="🏫 Établissement scolaire" onClose={()=>setShowAdd(null)}>
        <>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
              <F label="Nom *"><Inp value={ecoleForm.nom} onChange={v=>setEcoleForm(f=>({...f,nom:v}))}/></F>
              <F label="Type"><Sel value={ecoleForm.type} onChange={v=>setEcoleForm(f=>({...f,type:v}))}><option value="">—</option>{["Crèche","Maternelle","Primaire","Collège","Lycée","Université","BTS/IUT","Autre"].map(t=><option key={t}>{t}</option>)}</Sel></F>
              <F label="Ville"><Inp value={ecoleForm.ville} onChange={v=>setEcoleForm(f=>({...f,ville:v}))}/></F>
              <F label="Classe"><Inp value={ecoleForm.classe} onChange={v=>setEcoleForm(f=>({...f,classe:v}))}/></F>
              <F label="Date entrée"><Inp type="date" value={ecoleForm.dateEntree} onChange={v=>setEcoleForm(f=>({...f,dateEntree:v}))}/></F>
              <F label="Date sortie"><Inp type="date" value={ecoleForm.dateSortie} onChange={v=>setEcoleForm(f=>({...f,dateSortie:v}))}/></F>
            </div>
            <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
              <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
              <Btn onClick={()=>{updTab("ecoles",[...(enfant.ecoles||[]),{...ecoleForm,id:uid()}]);setEcoleForm({nom:"",type:"",ville:"",classe:"",dateEntree:"",dateSortie:"",note:""});setShowAdd(null);}} disabled={!ecoleForm.nom}>💾</Btn>
            </div>
          </>
      </Modal>}
      {showAdd==="activite"&&<Modal title="⚽ Activité extrascolaire" onClose={()=>setShowAdd(null)}>
        <>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
              <F label="Activité *"><Inp value={activiteEnfForm.nom} onChange={v=>setActiviteEnfForm(f=>({...f,nom:v}))} placeholder="Football, Danse, Judo..."/></F>
              <F label="Icône"><Inp value={activiteEnfForm.icon} onChange={v=>setActiviteEnfForm(f=>({...f,icon:v}))} placeholder="⚽"/></F>
              <F label="Club / Cours"><Inp value={activiteEnfForm.club} onChange={v=>setActiviteEnfForm(f=>({...f,club:v}))}/></F>
              <F label="Jour(s)"><Inp value={activiteEnfForm.jour} onChange={v=>setActiviteEnfForm(f=>({...f,jour:v}))} placeholder="Mercredi, Samedi..."/></F>
              <F label="Heure"><Inp type="time" value={activiteEnfForm.heure} onChange={v=>setActiviteEnfForm(f=>({...f,heure:v}))}/></F>
              <F label="Coût/mois (€)"><Inp type="number" value={activiteEnfForm.cout} onChange={v=>setActiviteEnfForm(f=>({...f,cout:v}))}/></F>
              <F label="Licence expire"><Inp type="date" value={activiteEnfForm.licenceExpiry} onChange={v=>setActiviteEnfForm(f=>({...f,licenceExpiry:v}))}/></F>
              <F label="Niveau"><Inp value={activiteEnfForm.niveau} onChange={v=>setActiviteEnfForm(f=>({...f,niveau:v}))}/></F>
            </div>
            <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
              <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
              <Btn onClick={()=>{updTab("activites",[...(enfant.activites||[]),{...activiteEnfForm,id:uid(),cout:+activiteEnfForm.cout||0}]);setActiviteEnfForm({nom:"",icon:"⚽",club:"",jour:"",heure:"",niveau:"",cout:"",licenceExpiry:"",note:""});setShowAdd(null);}} disabled={!activiteEnfForm.nom}>💾</Btn>
            </div>
          </>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: ANIMAUX
// ═══════════════════════════════════════════════════════════════════════════════
const Animaux=({animaux,setAnimaux})=>{
  const [selected,setSelected]=useState(null);
  const [showAdd,setShowAdd]=useState(false);
  const [form,setForm]=useState({nom:"",espece:"Chien",race:"",dateNaissance:"",sexe:"M",couleur:"",puce:"",tatouage:"",sterilise:false,medecin:"",assurance:"",note:""});
  const ESPECES=[{v:"Chien",i:"🐕"},{v:"Chat",i:"🐈"},{v:"Lapin",i:"🐇"},{v:"Oiseau",i:"🦜"},{v:"Reptile",i:"🦎"},{v:"Poisson",i:"🐟"},{v:"Rongeur",i:"🐹"},{v:"Cheval",i:"🐴"},{v:"Autre",i:"🐾"}];
  const sel=animaux.find(a=>a.id===selected);
  const age=d=>{if(!d)return"";const a=Math.floor((new Date()-new Date(d))/3.156e10);return a+" an"+(a>1?"s":"");};

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🐾 Mes Animaux</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>{animaux.length} animal{animaux.length>1?"x":""}</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Ajouter un animal</Btn>
      </div>
      {animaux.length===0&&<EmptyState icon="🐾" text="Ajoutez vos animaux pour suivre leur santé, vaccins et documents."/>}
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(300px,1fr))",gap:14}}>
        {animaux.map(a=>{
          const esp=ESPECES.find(e=>e.v===a.espece)||ESPECES[8];
          const prochainVaccin=(a.vaccins||[]).find(v=>v.dateRappel&&daysFrom(v.dateRappel)<=90);
          const rdvAVenir=(a.rdv||[]).filter(r=>r.date>=today()).length;
          return (
            <Card key={a.id} onClick={()=>setSelected(a.id)} style={{cursor:"pointer",borderColor:selected===a.id?T.accent:T.border,padding:0,overflow:"hidden"}}>
              <div style={{background:"rgba(240,165,0,0.05)",padding:"16px 18px",borderBottom:`1px solid ${T.border}`}}>
                <div style={{display:"flex",alignItems:"center",gap:12}}>
                  <div style={{width:48,height:48,borderRadius:24,background:T.accentDim,display:"flex",alignItems:"center",justifyContent:"center",fontSize:26}}>{esp.i}</div>
                  <div>
                    <div style={{fontFamily:T.fontD,fontSize:17,fontWeight:700,color:T.text}}>{a.nom}</div>
                    <div style={{fontSize:12,color:T.muted}}>{a.race||a.espece}{age(a.dateNaissance)&&" · "+age(a.dateNaissance)}</div>
                  </div>
                </div>
              </div>
              <div style={{padding:"12px 18px",display:"flex",gap:6,flexWrap:"wrap"}}>
                {a.puce&&<Badge c={T.info}>🔖 Pucé</Badge>}
                {a.sterilise&&<Badge c={T.success}>✂️ Stérilisé</Badge>}
                {rdvAVenir>0&&<Badge c={T.warning}>🏥 {rdvAVenir} RDV</Badge>}
                {prochainVaccin&&<Badge c={daysFrom(prochainVaccin.dateRappel)<=30?T.danger:T.warning}>💉 Rappel {fmt(prochainVaccin.dateRappel)}</Badge>}
                {(a.docs||[]).length>0&&<Badge c={T.accent}>📎 {a.docs.length}</Badge>}
              </div>
            </Card>
          );
        })}
      </div>
      {sel&&<AnimalDetail key={sel.id} animal={sel} onUpdate={u=>setAnimaux(p=>p.map(a=>a.id===u.id?u:a))} onClose={()=>setSelected(null)} onDelete={()=>{setAnimaux(p=>p.filter(a=>a.id!==selected));setSelected(null);}} ESPECES={ESPECES}/>}
      {showAdd&&<Modal title="🐾 Nouvel animal" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Nom *"><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Rex"/></F>
          <F label="Espèce"><Sel value={form.espece} onChange={v=>setForm(f=>({...f,espece:v}))}>{ESPECES.map(e=><option key={e.v} value={e.v}>{e.i} {e.v}</option>)}</Sel></F>
          <F label="Race"><Inp value={form.race} onChange={v=>setForm(f=>({...f,race:v}))} placeholder="Labrador, Persan..."/></F>
          <F label="Sexe"><Sel value={form.sexe} onChange={v=>setForm(f=>({...f,sexe:v}))}><option value="M">Mâle</option><option value="F">Femelle</option></Sel></F>
          <F label="Date de naissance"><Inp type="date" value={form.dateNaissance} onChange={v=>setForm(f=>({...f,dateNaissance:v}))}/></F>
          <F label="Couleur / Robe"><Inp value={form.couleur} onChange={v=>setForm(f=>({...f,couleur:v}))}/></F>
          <F label="N° de puce électronique"><Inp value={form.puce} onChange={v=>setForm(f=>({...f,puce:v}))} placeholder="250268..." mono/></F>
          <F label="Vétérinaire"><Inp value={form.medecin} onChange={v=>setForm(f=>({...f,medecin:v}))}/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={()=>{setAnimaux(p=>[...p,{...form,id:uid(),rdv:[],vaccins:[],traitements:[],docs:[],echanges:[]}]);setShowAdd(false);}} disabled={!form.nom}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

const AnimalDetail=({animal,onUpdate,onClose,onDelete,ESPECES})=>{
  const [tab,setTab]=useState("resume");
  const [selectedItem,setSelectedItem]=useState(null);
  const [showAdd,setShowAdd]=useState(null);
  const esp=ESPECES.find(e=>e.v===animal.espece)||ESPECES[8];
  const updTab=(key,arr)=>onUpdate({...animal,[key]:arr});
  const age=d=>{if(!d)return"";const a=Math.floor((new Date()-new Date(d))/3.156e10);return a+" an"+(a>1?"s":"");};

  return (
    <div>
      <div style={{display:"flex",alignItems:"center",gap:12,marginBottom:20}}>
        <button onClick={onClose} style={{background:"none",border:"none",color:T.accent,cursor:"pointer",fontSize:13,fontFamily:T.font}}>← Retour</button>
        <div style={{width:44,height:44,borderRadius:22,background:T.accentDim,display:"flex",alignItems:"center",justifyContent:"center",fontSize:22}}>{esp.i}</div>
        <div style={{flex:1}}>
          <h2 style={{fontFamily:T.fontD,fontSize:22,color:T.text,margin:0}}>{animal.nom}</h2>
          <div style={{color:T.muted,fontSize:12}}>{animal.race||animal.espece} {age(animal.dateNaissance)&&"· "+age(animal.dateNaissance)}</div>
        </div>
        <Btn v="danger" sm onClick={()=>{if(confirm("Supprimer ?"))onDelete();}}>🗑</Btn>
      </div>
      <Tabs tabs={[{id:"resume",icon:"📋",label:"Résumé"},{id:"sante",icon:"🏥",label:"Santé / Véto"},{id:"vaccins",icon:"💉",label:"Vaccins"},{id:"traitements",icon:"💊",label:"Traitements"},{id:"documents",icon:"📁",label:"Documents"}]} active={tab} onChange={t=>{setTab(t);setSelectedItem(null);}}/>

      {tab==="resume"&&(
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
          <Card>
            <Divider label="Identité"/>
            <InfoRow label="Espèce" value={animal.espece}/>
            <InfoRow label="Race" value={animal.race}/>
            <InfoRow label="Sexe" value={animal.sexe==="M"?"Mâle":"Femelle"}/>
            <InfoRow label="Date de naissance" value={fmt(animal.dateNaissance)}/>
            <InfoRow label="Âge" value={age(animal.dateNaissance)} color={T.accent}/>
            <InfoRow label="Couleur / Robe" value={animal.couleur}/>
            <InfoRow label="N° de puce" value={animal.puce} mono/>
            <InfoRow label="Stérilisé(e)" value={animal.sterilise?"Oui":"Non"}/>
          </Card>
          <Card>
            <Divider label="Suivi médical"/>
            <InfoRow label="Vétérinaire" value={animal.medecin}/>
            <InfoRow label="Assurance" value={animal.assurance}/>
            <InfoRow label="Visites véto" value={(animal.rdv||[]).length+" visite(s)"}/>
            <InfoRow label="Vaccins" value={(animal.vaccins||[]).length+" enregistrés"}/>
            <InfoRow label="Traitements" value={(animal.traitements||[]).length+" actif(s)"}/>
            {animal.note&&<div style={{marginTop:12,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{animal.note}</div>}
          </Card>
        </div>
      )}

      {tab==="sante"&&(
        <div>
          <div style={{display:"flex",justifyContent:"space-between",marginBottom:10}}>
            <div style={{fontWeight:700,color:T.text}}>🏥 Visites vétérinaires</div>
            <Btn sm onClick={()=>setShowAdd("rdv")}>+ Visite</Btn>
          </div>
          {(animal.rdv||[]).length===0&&<EmptyState icon="🏥" text="Aucune visite enregistrée"/>}
          <div style={{display:"grid",gap:8}}>
            {(animal.rdv||[]).sort((a,b)=>b.date.localeCompare(a.date)).map(r=>(
              <Card key={r.id} onClick={()=>setSelectedItem({id:r.id,type:"rdv"})} style={{cursor:"pointer",padding:"10px 14px",borderColor:selectedItem?.id===r.id?T.accent:T.border}}>
                <div style={{display:"flex",justifyContent:"space-between"}}>
                  <div><span style={{fontWeight:600,color:T.text}}>🏥 {r.titre}</span>{r.medecin&&<span style={{fontSize:11,color:T.muted,marginLeft:8}}>· {r.medecin}</span>}</div>
                  <div style={{display:"flex",gap:6}}>{r.cout&&<span style={{fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{fmtAmt(r.cout)}</span>}<Badge c={T.muted}>{fmt(r.date)}</Badge></div>
                </div>
                {r.diagnostic&&<div style={{fontSize:12,color:T.muted,marginTop:4}}>Diagnostic : {r.diagnostic}</div>}
              </Card>
            ))}
          </div>
          {selectedItem?.type==="rdv"&&(()=>{
            const r=(animal.rdv||[]).find(x=>x.id===selectedItem.id); if(!r)return null;
            return <FichePanel title={r.titre} icon="🏥" badge={fmt(r.date)} badgeColor={T.muted}
              onClose={()=>setSelectedItem(null)} onDelete={()=>{updTab("rdv",(animal.rdv||[]).filter(x=>x.id!==r.id));setSelectedItem(null);}}
              docs={r.docs||[]} onDocsChange={nd=>updTab("rdv",(animal.rdv||[]).map(x=>x.id===r.id?{...x,docs:nd}:x))}
              echanges={r.echanges||[]} onEchangesChange={ne=>updTab("rdv",(animal.rdv||[]).map(x=>x.id===r.id?{...x,echanges:ne}:x))}
              docsLabel="Compte-rendu véto, ordonnance, analyse..."
              leftContent={<div><InfoRow label="Motif" value={r.titre}/><InfoRow label="Vétérinaire" value={r.medecin}/><InfoRow label="Date" value={fmt(r.date)}/><InfoRow label="Coût" value={r.cout&&fmtAmt(r.cout)} color={T.accent}/><InfoRow label="Diagnostic" value={r.diagnostic}/><InfoRow label="Traitement prescrit" value={r.traitement}/>{r.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{r.note}</div>}</div>}
            />;
          })()}
        </div>
      )}

      {tab==="vaccins"&&(
        <div>
          <div style={{display:"flex",justifyContent:"space-between",marginBottom:10}}>
            <div style={{fontWeight:700,color:T.text}}>💉 Vaccinations</div>
            <Btn sm onClick={()=>setShowAdd("vaccin")}>+ Vaccin</Btn>
          </div>
          {(animal.vaccins||[]).length===0&&<EmptyState icon="💉" text="Ajoutez les vaccins de votre animal"/>}
          <div style={{display:"grid",gap:8}}>
            {(animal.vaccins||[]).map(v=>{
              const j=daysFrom(v.dateRappel);
              return (
                <Card key={v.id} onClick={()=>setSelectedItem({id:v.id,type:"vaccin"})} style={{cursor:"pointer",padding:"10px 14px",borderColor:selectedItem?.id===v.id?T.accent:j!=null&&j<=30?T.danger:T.border}}>
                  <div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                    <span style={{fontWeight:600,color:T.text}}>💉 {v.nom}</span>
                    <div style={{display:"flex",gap:6}}>
                      <Badge c={v.statut==="à jour"?T.success:T.warning}>{v.statut}</Badge>
                      {v.dateRappel&&<Badge c={j!=null&&j<=30?T.danger:j!=null&&j<=90?T.warning:T.muted}>Rappel: {fmt(v.dateRappel)}{j!=null&&j<=90&&" ("+j+"j)"}</Badge>}
                    </div>
                  </div>
                </Card>
              );
            })}
          </div>
          {selectedItem?.type==="vaccin"&&(()=>{
            const v=(animal.vaccins||[]).find(x=>x.id===selectedItem.id); if(!v)return null;
            const j=daysFrom(v.dateRappel);
            return <FichePanel title={v.nom} icon="💉" badge={v.statut} badgeColor={v.statut==="à jour"?T.success:T.warning}
              onClose={()=>setSelectedItem(null)} onDelete={()=>{updTab("vaccins",(animal.vaccins||[]).filter(x=>x.id!==v.id));setSelectedItem(null);}}
              docs={v.docs||[]} onDocsChange={nd=>updTab("vaccins",(animal.vaccins||[]).map(x=>x.id===v.id?{...x,docs:nd}:x))}
              echanges={v.echanges||[]} onEchangesChange={ne=>updTab("vaccins",(animal.vaccins||[]).map(x=>x.id===v.id?{...x,echanges:ne}:x))}
              docsLabel="Carnet de vaccination, certificat..."
              leftContent={<div><InfoRow label="Vaccin" value={v.nom}/><InfoRow label="Statut" value={v.statut}/><InfoRow label="Date injection" value={fmt(v.dateFait)}/><InfoRow label="Date de rappel" value={fmt(v.dateRappel)} color={j!=null&&j<=30?T.danger:T.text}/><InfoRow label="Vétérinaire" value={v.medecin}/>{j!=null&&j<=30&&j>=0&&<div style={{marginTop:12,padding:10,background:"rgba(239,68,68,0.1)",borderRadius:8,fontSize:12,color:T.danger}}>⚠️ Rappel dans {j} jours !</div>}</div>}
            />;
          })()}
        </div>
      )}

      {tab==="traitements"&&(
        <div>
          <div style={{display:"flex",justifyContent:"space-between",marginBottom:10}}>
            <div style={{fontWeight:700,color:T.text}}>💊 Traitements & Médicaments</div>
            <Btn sm onClick={()=>setShowAdd("traitement")}>+ Traitement</Btn>
          </div>
          {(animal.traitements||[]).length===0&&<EmptyState icon="💊" text="Ajoutez les traitements en cours"/>}
          <div style={{display:"grid",gap:8}}>
            {(animal.traitements||[]).map(tr=>(
              <Card key={tr.id} onClick={()=>setSelectedItem({id:tr.id,type:"traitement"})} style={{cursor:"pointer",padding:"10px 14px",borderColor:selectedItem?.id===tr.id?T.accent:T.border}}>
                <div style={{display:"flex",justifyContent:"space-between"}}>
                  <div><span style={{fontWeight:600,color:T.text}}>💊 {tr.nom}</span>{tr.posologie&&<span style={{fontSize:11,color:T.muted,marginLeft:8}}>· {tr.posologie}</span>}</div>
                  <Badge c={tr.statut==="actif"?T.success:T.muted}>{tr.statut}</Badge>
                </div>
                {tr.dateDebut&&<div style={{fontSize:11,color:T.muted,marginTop:3}}>Du {fmt(tr.dateDebut)}{tr.dateFin&&" au "+fmt(tr.dateFin)}</div>}
              </Card>
            ))}
          </div>
          {selectedItem?.type==="traitement"&&(()=>{
            const tr=(animal.traitements||[]).find(x=>x.id===selectedItem.id); if(!tr)return null;
            return <FichePanel title={tr.nom} icon="💊" badge={tr.statut} badgeColor={tr.statut==="actif"?T.success:T.muted}
              onClose={()=>setSelectedItem(null)} onDelete={()=>{updTab("traitements",(animal.traitements||[]).filter(x=>x.id!==tr.id));setSelectedItem(null);}}
              docs={tr.docs||[]} onDocsChange={nd=>updTab("traitements",(animal.traitements||[]).map(x=>x.id===tr.id?{...x,docs:nd}:x))}
              echanges={tr.echanges||[]} onEchangesChange={ne=>updTab("traitements",(animal.traitements||[]).map(x=>x.id===tr.id?{...x,echanges:ne}:x))}
              docsLabel="Ordonnance, notice..."
              leftContent={<div><InfoRow label="Médicament" value={tr.nom}/><InfoRow label="Posologie" value={tr.posologie}/><InfoRow label="Début" value={fmt(tr.dateDebut)}/><InfoRow label="Fin" value={fmt(tr.dateFin)}/><InfoRow label="Prescrit par" value={tr.medecin}/><InfoRow label="Statut" value={tr.statut}/>{tr.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{tr.note}</div>}</div>}
            />;
          })()}
        </div>
      )}

      {tab==="documents"&&<Card><DocAttach docs={animal.docs||[]} onChange={nd=>onUpdate({...animal,docs:nd})} label="Passeport, carnet santé, attestation vaccin, assurance..."/></Card>}

      {showAdd==="rdv"&&<Modal title="🏥 Visite vétérinaire" onClose={()=>setShowAdd(null)}>
        <>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
              <F label="Motif *"><Inp value={rdvAnForm.titre} onChange={v=>setRdvAnForm(f=>({...f,titre:v}))} placeholder="Bilan annuel, urgence..."/></F>
              <F label="Vétérinaire"><Inp value={rdvAnForm.medecin} onChange={v=>setRdvAnForm(f=>({...f,medecin:v}))}/></F>
              <F label="Date"><Inp type="date" value={rdvAnForm.date} onChange={v=>setRdvAnForm(f=>({...f,date:v}))}/></F>
              <F label="Coût (€)"><Inp type="number" value={rdvAnForm.cout} onChange={v=>setRdvAnForm(f=>({...f,cout:v}))}/></F>
              <F label="Diagnostic"><Inp value={rdvAnForm.diagnostic} onChange={v=>setRdvAnForm(f=>({...f,diagnostic:v}))}/></F>
              <F label="Traitement prescrit"><Inp value={rdvAnForm.traitement} onChange={v=>setRdvAnForm(f=>({...f,traitement:v}))}/></F>
            </div>
            <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
              <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
              <Btn onClick={()=>{updTab("rdv",[...(animal.rdv||[]),{...rdvAnForm,id:uid(),cout:+rdvAnForm.cout||0}]);setRdvAnForm({titre:"",medecin:"",date:today(),cout:"",diagnostic:"",traitement:"",note:""});setShowAdd(null);}} disabled={!rdvAnForm.titre}>💾</Btn>
            </div>
          </>
      </Modal>}
      {showAdd==="vaccin"&&<Modal title="💉 Vaccination" onClose={()=>setShowAdd(null)}>
        <>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
              <F label="Vaccin *"><Inp value={vaccAnForm.nom} onChange={v=>setVaccAnForm(f=>({...f,nom:v}))} placeholder="Rage, Typhus, Parvo..."/></F>
              <F label="Statut"><Sel value={vaccAnForm.statut} onChange={v=>setVaccAnForm(f=>({...f,statut:v}))}><option value="à jour">À jour</option><option value="à faire">À faire</option><option value="périmé">Périmé</option></Sel></F>
              <F label="Date"><Inp type="date" value={vaccAnForm.dateFait} onChange={v=>setVaccAnForm(f=>({...f,dateFait:v}))}/></F>
              <F label="Date rappel"><Inp type="date" value={vaccAnForm.dateRappel} onChange={v=>setVaccAnForm(f=>({...f,dateRappel:v}))}/></F>
            </div>
            <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
              <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
              <Btn onClick={()=>{updTab("vaccins",[...(animal.vaccins||[]),{...vaccAnForm,id:uid()}]);setVaccAnForm({nom:"",dateFait:today(),dateRappel:"",statut:"à jour",medecin:"",note:""});setShowAdd(null);}} disabled={!vaccAnForm.nom}>💾</Btn>
            </div>
          </>
      </Modal>}
      {showAdd==="traitement"&&<Modal title="💊 Traitement" onClose={()=>setShowAdd(null)}>
        <>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
              <F label="Médicament *"><Inp value={traitAnForm.nom} onChange={v=>setTraitAnForm(f=>({...f,nom:v}))} placeholder="Frontline, Bravecto..."/></F>
              <F label="Posologie"><Inp value={traitAnForm.posologie} onChange={v=>setTraitAnForm(f=>({...f,posologie:v}))} placeholder="1 cp / jour"/></F>
              <F label="Début"><Inp type="date" value={traitAnForm.dateDebut} onChange={v=>setTraitAnForm(f=>({...f,dateDebut:v}))}/></F>
              <F label="Fin"><Inp type="date" value={traitAnForm.dateFin} onChange={v=>setTraitAnForm(f=>({...f,dateFin:v}))}/></F>
            </div>
            <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
              <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
              <Btn onClick={()=>{updTab("traitements",[...(animal.traitements||[]),{...traitAnForm,id:uid()}]);setTraitAnForm({nom:"",posologie:"",dateDebut:today(),dateFin:"",statut:"actif",medecin:"",note:""});setShowAdd(null);}} disabled={!traitAnForm.nom}>💾</Btn>
            </div>
          </>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: VOYAGES & VACANCES
// ═══════════════════════════════════════════════════════════════════════════════
const Voyages=({voyages,setVoyages})=>{
  const [selected,setSelected]=useState(null);
  const [showAdd,setShowAdd]=useState(false);
  const [form,setForm]=useState({destination:"",pays:"",dateDepart:"",dateRetour:"",type:"Vacances",participants:"",budget:"",note:""});
  const sel=voyages.find(v=>v.id===selected);
  const TYPES_VOYAGE=["Vacances","Week-end","Voyage d'affaires","Voyage scolaire","Pèlerinage","Autre"];
  const duree=v=>{if(!v.dateDepart||!v.dateRetour)return"";const j=Math.round((new Date(v.dateRetour)-new Date(v.dateDepart))/86400000);return j+" jour"+(j>1?"s":"");};
  const statut=v=>{const now=today();if(v.dateRetour<now)return{l:"Passé",c:T.muted};if(v.dateDepart<=now)return{l:"En cours",c:T.success};const j=daysFrom(v.dateDepart);return j<=30?{l:"Dans "+j+"j",c:T.warning}:{l:"Prévu",c:T.info};};

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>✈️ Voyages & Vacances</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>{voyages.length} voyage{voyages.length>1?"s":""} · {voyages.filter(v=>v.dateDepart>today()).length} à venir</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Nouveau voyage</Btn>
      </div>
      {voyages.length===0&&<EmptyState icon="✈️" text="Planifiez vos voyages et centralisez réservations, billets et souvenirs."/>}
      {/* Voyages en cours */}
      {voyages.filter(v=>v.dateDepart<=today()&&v.dateRetour>=today()).length>0&&(
        <div style={{marginBottom:20}}>
          <Divider label="✈️ En ce moment"/>
          {voyages.filter(v=>v.dateDepart<=today()&&v.dateRetour>=today()).map(v=>(
            <Card key={v.id} onClick={()=>setSelected(v.id)} style={{cursor:"pointer",borderColor:T.success,background:"rgba(34,197,94,0.04)",marginBottom:8}}>
              <div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                <div style={{display:"flex",alignItems:"center",gap:12}}>
                  <span style={{fontSize:28}}>✈️</span>
                  <div><div style={{fontFamily:T.fontD,fontSize:16,color:T.text,fontWeight:700}}>{v.destination}</div><div style={{fontSize:12,color:T.muted}}>{fmt(v.dateDepart)} → {fmt(v.dateRetour)} · {duree(v)}</div></div>
                </div>
                <Badge c={T.success}>En cours !</Badge>
              </div>
            </Card>
          ))}
        </div>
      )}
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(300px,1fr))",gap:14}}>
        {voyages.filter(v=>!(v.dateDepart<=today()&&v.dateRetour>=today())).sort((a,b)=>b.dateDepart.localeCompare(a.dateDepart)).map(v=>{
          const s=statut(v);
          const totalDepenses=(v.depenses||[]).reduce((s,d)=>s+d.montant,0);
          return (
            <Card key={v.id} onClick={()=>setSelected(v.id)} style={{cursor:"pointer",borderColor:selected===v.id?T.accent:T.border,padding:0,overflow:"hidden"}}>
              <div style={{background:"rgba(56,189,248,0.05)",padding:"14px 16px",borderBottom:`1px solid ${T.border}`}}>
                <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:4}}>
                  <div style={{fontFamily:T.fontD,fontSize:16,fontWeight:700,color:T.text}}>{v.destination}</div>
                  <Badge c={s.c}>{s.l}</Badge>
                </div>
                <div style={{fontSize:12,color:T.muted}}>{fmt(v.dateDepart)} → {fmt(v.dateRetour)} · {duree(v)}</div>
              </div>
              <div style={{padding:"10px 16px",display:"flex",gap:6,flexWrap:"wrap"}}>
                {v.type&&<Badge c={T.muted}>{v.type}</Badge>}
                {v.participants&&<Badge c={T.info}>👥 {v.participants}</Badge>}
                {v.budget&&<Badge c={T.warning}>💰 Budget: {fmtAmt(v.budget)}</Badge>}
                {totalDepenses>0&&<Badge c={T.accent}>Dépenses: {fmtAmt(totalDepenses)}</Badge>}
                {(v.reservations||[]).length>0&&<Badge c={T.purple}>🎫 {v.reservations.length} résa</Badge>}
              </div>
            </Card>
          );
        })}
      </div>
      {sel&&<VoyageDetail key={sel.id} voyage={sel} onUpdate={u=>setVoyages(p=>p.map(v=>v.id===u.id?u:v))} onClose={()=>setSelected(null)} onDelete={()=>{setVoyages(p=>p.filter(v=>v.id!==selected));setSelected(null);}}/>}
      {showAdd&&<Modal title="✈️ Nouveau voyage" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Destination *"><Inp value={form.destination} onChange={v=>setForm(f=>({...f,destination:v}))} placeholder="Paris, Barcelone, Japon..."/></F>
          <F label="Pays"><Inp value={form.pays} onChange={v=>setForm(f=>({...f,pays:v}))}/></F>
          <F label="Type"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}>{TYPES_VOYAGE.map(t=><option key={t}>{t}</option>)}</Sel></F>
          <F label="Participants"><Inp value={form.participants} onChange={v=>setForm(f=>({...f,participants:v}))} placeholder="Famille, 4 personnes..."/></F>
          <F label="Date de départ"><Inp type="date" value={form.dateDepart} onChange={v=>setForm(f=>({...f,dateDepart:v}))}/></F>
          <F label="Date de retour"><Inp type="date" value={form.dateRetour} onChange={v=>setForm(f=>({...f,dateRetour:v}))}/></F>
          <F label="Budget total (€)"><Inp type="number" value={form.budget} onChange={v=>setForm(f=>({...f,budget:v}))}/></F>
        </div>
        <F label="Note"><Txt value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} rows={2}/></F>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={()=>{setVoyages(p=>[...p,{...form,id:uid(),budget:+form.budget||0,reservations:[],depenses:[],docs:[],echanges:[]}]);setShowAdd(false);}} disabled={!form.destination}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

const VoyageDetail=({voyage,onUpdate,onClose,onDelete})=>{
  const [tab,setTab]=useState("resume");
  const [selectedItem,setSelectedItem]=useState(null);
  const [showAdd,setShowAdd]=useState(null);
  const updTab=(key,arr)=>onUpdate({...voyage,[key]:arr});
  const duree=()=>{if(!voyage.dateDepart||!voyage.dateRetour)return"";const j=Math.round((new Date(voyage.dateRetour)-new Date(voyage.dateDepart))/86400000);return j+" jour"+(j>1?"s":"");};
  const totalDepenses=(voyage.depenses||[]).reduce((s,d)=>s+(d.montant||0),0);
  const budgetRestant=(voyage.budget||0)-totalDepenses;
  const CATS_DEPENSE=["Transport","Hébergement","Restauration","Activités","Souvenirs","Assurance","Visa","Autre"];
  const TYPES_RESA=["Vol","Train","Hôtel","Location voiture","Camping","Activité","Restaurant","Autre"];

  return (
    <div>
      <div style={{display:"flex",alignItems:"center",gap:12,marginBottom:20}}>
        <button onClick={onClose} style={{background:"none",border:"none",color:T.accent,cursor:"pointer",fontSize:13,fontFamily:T.font}}>← Retour</button>
        <span style={{fontSize:28}}>✈️</span>
        <div style={{flex:1}}>
          <h2 style={{fontFamily:T.fontD,fontSize:22,color:T.text,margin:0}}>{voyage.destination}</h2>
          <div style={{color:T.muted,fontSize:12}}>{fmt(voyage.dateDepart)} → {fmt(voyage.dateRetour)} · {duree()}{voyage.participants&&" · "+voyage.participants}</div>
        </div>
        <Btn v="danger" sm onClick={()=>{if(confirm("Supprimer ?"))onDelete();}}>🗑</Btn>
      </div>
      <Tabs tabs={[{id:"resume",icon:"📋",label:"Résumé"},{id:"reservations",icon:"🎫",label:"Réservations"},{id:"budget",icon:"💰",label:"Budget"},{id:"documents",icon:"📁",label:"Documents"}]} active={tab} onChange={t=>{setTab(t);setSelectedItem(null);}}/>

      {tab==="resume"&&(
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
          <Card>
            <Divider label="Informations"/>
            <InfoRow label="Destination" value={voyage.destination}/>
            <InfoRow label="Pays" value={voyage.pays}/>
            <InfoRow label="Type" value={voyage.type}/>
            <InfoRow label="Départ" value={fmt(voyage.dateDepart)}/>
            <InfoRow label="Retour" value={fmt(voyage.dateRetour)}/>
            <InfoRow label="Durée" value={duree()} color={T.accent}/>
            <InfoRow label="Participants" value={voyage.participants}/>
            {voyage.note&&<div style={{marginTop:12,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{voyage.note}</div>}
          </Card>
          <Card>
            <Divider label="Budget"/>
            <InfoRow label="Budget prévu" value={voyage.budget&&fmtAmt(voyage.budget)} color={T.warning}/>
            <InfoRow label="Dépensé" value={fmtAmt(totalDepenses)} color={T.danger}/>
            <InfoRow label="Restant" value={fmtAmt(budgetRestant)} color={budgetRestant>=0?T.success:T.danger}/>
            <div style={{marginTop:14,background:T.accentDim,borderRadius:8,padding:12}}>
              {voyage.budget>0&&<div style={{display:"flex",justifyContent:"space-between",marginBottom:4,fontSize:11,color:T.muted}}><span>Consommé</span><span>{Math.round(totalDepenses/voyage.budget*100)}%</span></div>}
              {voyage.budget>0&&<div style={{background:T.border,borderRadius:4,height:6}}><div style={{background:totalDepenses>voyage.budget?T.danger:T.success,height:6,borderRadius:4,width:`${Math.min(100,totalDepenses/voyage.budget*100)}%`,transition:"width 0.5s"}}/></div>}
            </div>
            <Divider label="Réservations"/>
            <InfoRow label="Réservations" value={(voyage.reservations||[]).length+" enregistrée(s)"}/>
            <InfoRow label="Documents" value={(voyage.docs||[]).length+" document(s)"}/>
          </Card>
        </div>
      )}

      {tab==="reservations"&&(
        <div>
          <div style={{display:"flex",justifyContent:"space-between",marginBottom:10}}>
            <div style={{fontWeight:700,color:T.text}}>🎫 Réservations</div>
            <Btn sm onClick={()=>setShowAdd("resa")}>+ Réservation</Btn>
          </div>
          {(voyage.reservations||[]).length===0&&<EmptyState icon="🎫" text="Ajoutez vols, hôtels, locations..."/>}
          <div style={{display:"grid",gap:8}}>
            {(voyage.reservations||[]).sort((a,b)=>(a.date||"").localeCompare(b.date||"")).map(r=>(
              <Card key={r.id} onClick={()=>setSelectedItem({id:r.id,type:"resa"})} style={{cursor:"pointer",padding:"10px 14px",borderColor:selectedItem?.id===r.id?T.accent:T.border}}>
                <div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                  <div>
                    <span style={{fontWeight:600,color:T.text,fontSize:13}}>{r.type==="Vol"?"✈️":r.type==="Train"?"🚂":r.type==="Hôtel"?"🏨":r.type==="Location voiture"?"🚗":"🎫"} {r.titre}</span>
                    {r.fournisseur&&<span style={{fontSize:11,color:T.muted,marginLeft:8}}>· {r.fournisseur}</span>}
                  </div>
                  <div style={{display:"flex",gap:6,alignItems:"center"}}>
                    {r.montant&&<span style={{fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{fmtAmt(r.montant)}</span>}
                    <Badge c={r.statut==="confirmée"?T.success:T.warning}>{r.statut||"confirmée"}</Badge>
                  </div>
                </div>
                {r.date&&<div style={{fontSize:11,color:T.muted,marginTop:3}}>📅 {fmt(r.date)}{r.reference&&" · Réf: "+r.reference}</div>}
              </Card>
            ))}
          </div>
          {selectedItem?.type==="resa"&&(()=>{
            const r=(voyage.reservations||[]).find(x=>x.id===selectedItem.id); if(!r)return null;
            return <FichePanel title={r.titre} icon="🎫" badge={r.statut||"confirmée"} badgeColor={r.statut==="confirmée"?T.success:T.warning}
              onClose={()=>setSelectedItem(null)} onDelete={()=>{updTab("reservations",(voyage.reservations||[]).filter(x=>x.id!==r.id));setSelectedItem(null);}}
              docs={r.docs||[]} onDocsChange={nd=>updTab("reservations",(voyage.reservations||[]).map(x=>x.id===r.id?{...x,docs:nd}:x))}
              echanges={r.echanges||[]} onEchangesChange={ne=>updTab("reservations",(voyage.reservations||[]).map(x=>x.id===r.id?{...x,echanges:ne}:x))}
              docsLabel="Billet, confirmation, voucher, e-ticket..."
              leftContent={<div><InfoRow label="Type" value={r.type}/><InfoRow label="Titre" value={r.titre}/><InfoRow label="Fournisseur" value={r.fournisseur}/><InfoRow label="Date" value={fmt(r.date)}/><InfoRow label="N° réservation" value={r.reference} mono/><InfoRow label="Montant" value={r.montant&&fmtAmt(r.montant)} color={T.accent}/><InfoRow label="Statut" value={r.statut}/>{r.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{r.note}</div>}</div>}
            />;
          })()}
        </div>
      )}

      {tab==="budget"&&(
        <div>
          <div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:12,marginBottom:16}}>
            <StatCard label="Budget prévu" value={voyage.budget?fmtAmt(voyage.budget):"—"} icon="💰" color={T.warning}/>
            <StatCard label="Dépensé" value={fmtAmt(totalDepenses)} icon="💸" color={T.danger}/>
            <StatCard label="Restant" value={fmtAmt(budgetRestant)} icon={budgetRestant>=0?"✅":"⚠️"} color={budgetRestant>=0?T.success:T.danger}/>
          </div>
          <div style={{display:"flex",justifyContent:"space-between",marginBottom:10}}>
            <div style={{fontWeight:700,color:T.text}}>💸 Dépenses</div>
            <Btn sm onClick={()=>setShowAdd("depense")}>+ Dépense</Btn>
          </div>
          {(voyage.depenses||[]).length===0&&<EmptyState icon="💸" text="Enregistrez vos dépenses au fil du voyage"/>}
          <div style={{display:"grid",gap:8}}>
            {(voyage.depenses||[]).sort((a,b)=>b.date.localeCompare(a.date)).map(d=>(
              <div key={d.id} style={{display:"flex",justifyContent:"space-between",padding:"10px 14px",background:"#060a10",borderRadius:10,alignItems:"center"}}>
                <div><div style={{fontWeight:600,color:T.text,fontSize:13}}>{d.libelle}</div><div style={{fontSize:11,color:T.muted}}>{fmt(d.date)} · {d.categorie}</div></div>
                <div style={{display:"flex",alignItems:"center",gap:8}}><span style={{fontWeight:700,color:T.accent,fontFamily:T.fontD}}>{fmtAmt(d.montant)}</span><button onClick={()=>updTab("depenses",(voyage.depenses||[]).filter(x=>x.id!==d.id))} style={{background:"none",border:"none",color:T.muted,cursor:"pointer"}}>🗑</button></div>
              </div>
            ))}
          </div>
          {/* Répartition par catégorie */}
          {(voyage.depenses||[]).length>0&&(
            <Card style={{marginTop:16}}>
              <Divider label="Répartition par catégorie"/>
              {CATS_DEPENSE.filter(c=>(voyage.depenses||[]).some(d=>d.categorie===c)).map(c=>{
                const total=(voyage.depenses||[]).filter(d=>d.categorie===c).reduce((s,d)=>s+d.montant,0);
                return <div key={c} style={{display:"flex",justifyContent:"space-between",padding:"6px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}><span style={{color:T.text}}>{c}</span><span style={{color:T.accent,fontWeight:700}}>{fmtAmt(total)}</span></div>;
              })}
            </Card>
          )}
        </div>
      )}

      {tab==="documents"&&<Card><DocAttach docs={voyage.docs||[]} onChange={nd=>onUpdate({...voyage,docs:nd})} label="Passeports, visas, assurance voyage, billets, réservations..."/></Card>}

      {showAdd==="resa"&&<Modal title="🎫 Nouvelle réservation" onClose={()=>setShowAdd(null)}>
        <>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
              <F label="Type"><Sel value={resaForm.type} onChange={v=>setResaForm(f=>({...f,type:v}))}>{TYPES_RESA.map(t=><option key={t}>{t}</option>)}</Sel></F>
              <F label="Titre *"><Inp value={resaForm.titre} onChange={v=>setResaForm(f=>({...f,titre:v}))} placeholder="Paris → Tokyo, Hôtel Ibis..."/></F>
              <F label="Fournisseur"><Inp value={resaForm.fournisseur} onChange={v=>setResaForm(f=>({...f,fournisseur:v}))} placeholder="Air France, Booking..."/></F>
              <F label="Date"><Inp type="date" value={resaForm.date} onChange={v=>setResaForm(f=>({...f,date:v}))}/></F>
              <F label="N° réservation"><Inp value={resaForm.reference} onChange={v=>setResaForm(f=>({...f,reference:v}))} mono/></F>
              <F label="Montant (€)"><Inp type="number" value={resaForm.montant} onChange={v=>setResaForm(f=>({...f,montant:v}))}/></F>
            </div>
            <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
              <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
              <Btn onClick={()=>{updTab("reservations",[...(voyage.reservations||[]),{...resaForm,id:uid(),montant:+resaForm.montant||0}]);setResaForm({type:"Vol",titre:"",fournisseur:"",date:"",reference:"",montant:"",statut:"confirmée",note:""});setShowAdd(null);}} disabled={!resaForm.titre}>💾</Btn>
            </div>
          </>
      </Modal>}
      {showAdd==="depense"&&<Modal title="💸 Nouvelle dépense" onClose={()=>setShowAdd(null)}>
        <>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
              <F label="Libellé *"><Inp value={depenseForm.libelle} onChange={v=>setDepenseForm(f=>({...f,libelle:v}))} placeholder="Restaurant, Entrée musée..."/></F>
              <F label="Catégorie"><Sel value={depenseForm.categorie} onChange={v=>setDepenseForm(f=>({...f,categorie:v}))}>{CATS_DEPENSE.map(c=><option key={c}>{c}</option>)}</Sel></F>
              <F label="Montant (€) *"><Inp type="number" value={depenseForm.montant} onChange={v=>setDepenseForm(f=>({...f,montant:v}))}/></F>
              <F label="Date"><Inp type="date" value={depenseForm.date} onChange={v=>setDepenseForm(f=>({...f,date:v}))}/></F>
            </div>
            <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:8}}>
              <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
              <Btn onClick={()=>{updTab("depenses",[...(voyage.depenses||[]),{...depenseForm,id:uid(),montant:+depenseForm.montant||0}]);setDepenseForm({libelle:"",categorie:"Restauration",montant:"",date:today(),note:""});setShowAdd(null);}} disabled={!depenseForm.libelle||!depenseForm.montant}>💾</Btn>
            </div>
          </>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: IDENTITÉ
// ═══════════════════════════════════════════════════════════════════════════════
const DOCS_IDENTITE=[
  {id:"cni",label:"Carte d'identité",icon:"🪪",color:"#38bdf8"},
  {id:"passeport",label:"Passeport",icon:"📗",color:"#34d399"},
  {id:"permis",label:"Permis de conduire",icon:"🚗",color:"#f0a500"},
  {id:"vitale",label:"Carte Vitale",icon:"💚",color:"#22c55e"},
  {id:"livret",label:"Livret de famille",icon:"📖",color:"#a78bfa"},
  {id:"secu",label:"N° Sécurité Sociale",icon:"🏥",color:"#f472b6"},
  {id:"passeport_enfant",label:"Passeport enfant",icon:"👶",color:"#fb923c"},
  {id:"titre_sejour",label:"Titre de séjour",icon:"🌍",color:"#60a5fa"},
  {id:"autre",label:"Autre document",icon:"📄",color:"#94a3b8"},
];

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: MODÈLES DE COURRIER
// ═══════════════════════════════════════════════════════════════════════════════
const MODELES_BASE=[
  // ─── BANQUE ───
  {id:"b1",cat:"banque",titre:"Contestation de frais bancaires",tags:["frais","opposition","remboursement"],
   corps:`[Prénom Nom]
[Adresse]
[Code postal Ville]
[Email]
[Téléphone]

[Ville], le [Date]

[Nom de la banque]
Service Réclamations
[Adresse de la banque]

Objet : Contestation de frais bancaires — Compte n° [Numéro de compte]

Madame, Monsieur,

Je me permets de vous contacter au sujet de frais prélevés sur mon compte courant n° [Numéro de compte] le [Date du prélèvement], pour un montant de [Montant] €, au titre de [Description des frais].

Après vérification, ces frais me semblent injustifiés pour les raisons suivantes :
[Expliquer la raison : erreur, double facturation, non-conformité aux conditions générales...]

En conséquence, je vous demande de bien vouloir procéder au remboursement de ces frais dans les meilleurs délais, et de confirmer le crédit de mon compte.

Dans l'attente de votre réponse, que j'espère favorable, je reste à votre disposition.

Veuillez agréer, Madame, Monsieur, l'expression de mes salutations distinguées.

[Signature]
[Prénom Nom]`},

  {id:"b2",cat:"banque",titre:"Demande de renégociation de crédit",tags:["crédit","taux","renégociation"],
   corps:`[Prénom Nom]
[Adresse]
[Code postal Ville]

[Ville], le [Date]

[Nom de la banque]
[Adresse]

Objet : Demande de renégociation de mon crédit immobilier — Référence [Numéro de prêt]

Madame, Monsieur,

Titulaire d'un crédit immobilier contracté le [Date du prêt] pour un montant de [Montant] € au taux de [Taux actuel] % sur [Durée] ans, je souhaite vous soumettre une demande de renégociation de ce prêt.

En effet, compte tenu de l'évolution des taux d'intérêt sur le marché, il m'apparaît possible d'obtenir des conditions plus avantageuses, permettant ainsi de réduire le coût total de mon crédit.

Je serais favorable à un rendez-vous avec votre conseiller afin d'étudier ensemble les possibilités de renégociation.

Dans cette attente, je vous adresse mes salutations distinguées.

[Signature]
[Prénom Nom]`},

  {id:"b3",cat:"banque",titre:"Clôture de compte bancaire",tags:["clôture","compte","résiliation"],
   corps:`[Prénom Nom]
[Adresse]
[Code postal Ville]

[Ville], le [Date]

[Nom de la banque]
Service Clientèle
[Adresse]

Objet : Demande de clôture de compte — N° [Numéro de compte]

Madame, Monsieur,

Je vous demande de bien vouloir procéder à la clôture de mon compte bancaire numéro [Numéro de compte], ouvert en date du [Date d'ouverture].

Je vous prie de :
• Virer le solde créditeur sur mon nouveau compte : IBAN [Nouvel IBAN], domicilié à [Nouvelle banque]
• Résilier tous les moyens de paiement associés (carte bancaire, chéquier)
• Me confirmer la clôture par écrit

Veuillez agréer, Madame, Monsieur, mes salutations distinguées.

[Signature]
[Prénom Nom]`},

  // ─── ASSURANCE ───
  {id:"a1",cat:"assurance",titre:"Résiliation assurance (loi Hamon)",tags:["résiliation","loi hamon","assurance auto","habitation"],
   corps:`[Prénom Nom]
[Adresse]
[Code postal Ville]

[Ville], le [Date]

[Compagnie d'assurance]
Service Résiliation
[Adresse]

Objet : Résiliation de contrat d'assurance — N° [Numéro de contrat] — Loi Hamon

Madame, Monsieur,

Par la présente, conformément aux dispositions de la loi n°2014-344 du 17 mars 2014 dite loi Hamon et à l'article L113-15-2 du Code des assurances, je vous notifie ma décision de résilier le contrat d'assurance [Type : auto/habitation/...] référencé sous le numéro [Numéro de contrat], souscrit le [Date de souscription].

Cette résiliation prend effet 1 mois après réception du présent courrier.

Je vous remercie de bien vouloir me confirmer la prise en compte de cette résiliation et de procéder au remboursement prorata temporis de la prime restante.

Veuillez agréer, Madame, Monsieur, l'expression de mes salutations distinguées.

[Signature]
[Prénom Nom]
Envoi recommandé avec AR`},

  {id:"a2",cat:"assurance",titre:"Déclaration de sinistre",tags:["sinistre","déclaration","dommages"],
   corps:`[Prénom Nom]
[Adresse]
[Code postal Ville]
[N° de contrat]

[Ville], le [Date]

[Compagnie d'assurance]
Service Sinistres
[Adresse]

Objet : Déclaration de sinistre — Contrat n° [Numéro de contrat]

Madame, Monsieur,

J'ai l'honneur de vous déclarer un sinistre survenu le [Date du sinistre] à [Heure] au [Adresse du sinistre].

Nature du sinistre : [Décrire : dégât des eaux, vol, incendie, accident...]

Circonstances : [Décrire précisément ce qui s'est passé]

Estimation des dommages : [Description et montant approximatif]

Tiers impliqués : [Nom et coordonnées si concerné]

Je vous adresse en pièces jointes :
• Photos des dommages
• [Tout autre document utile : devis, factures...]

Je reste à votre disposition pour tout renseignement complémentaire et pour l'intervention d'un expert.

Veuillez agréer, Madame, Monsieur, mes salutations distinguées.

[Signature]
[Prénom Nom]`},

  // ─── ADMINISTRATION ───
  {id:"adm1",cat:"administration",titre:"Demande de logement social (HLM)",tags:["HLM","logement","social","CAF"],
   corps:`[Prénom Nom]
[Adresse actuelle]
[Code postal Ville]
[Téléphone] — [Email]

[Ville], le [Date]

[Organisme HLM / Mairie]
Service Logement Social
[Adresse]

Objet : Demande de logement social

Madame, Monsieur,

Je me permets de vous adresser ma demande de logement social. Voici ma situation actuelle :

Situation familiale : [Célibataire / Marié(e) / Famille avec X enfant(s)]
Revenus mensuels nets : [Montant] €
Situation actuelle : [Locataire / Sans logement / Logement trop petit...]
Motif de la demande : [Expliquer la situation]

Logement recherché : [T2 / T3 / T4...] pour [Nombre] personne(s)
Zone souhaitée : [Commune(s) souhaitée(s)]

Je joins à ce courrier les pièces justificatives suivantes :
• Pièces d'identité
• Justificatif de revenus (3 derniers bulletins de salaire)
• Avis d'imposition
• Justificatif de domicile actuel
• [Tout document complémentaire]

Restant à votre disposition, je vous prie d'agréer, Madame, Monsieur, l'expression de mes salutations distinguées.

[Signature]
[Prénom Nom]`},

  {id:"adm2",cat:"administration",titre:"Contestation d'amende",tags:["amende","contestation","PV","stationnement"],
   corps:`[Prénom Nom]
[Adresse]
[Code postal Ville]
[N° de permis de conduire]
[N° de plaque d'immatriculation]

[Ville], le [Date]

Centre de traitement des amendes
CS 41101
35911 Rennes Cedex 9

Objet : Contestation d'avis de contravention n° [Numéro de l'avis] du [Date]

Madame, Monsieur,

J'ai reçu un avis de contravention n° [Numéro], daté du [Date], pour une infraction au Code de la route [Description de l'infraction] relevée le [Date] à [Heure] [Lieu précis].

Je conteste cet avis pour les raisons suivantes :
[Exposer clairement les motifs : signalisation absente, erreur d'identification du véhicule, véhicule volé, force majeure...]

Je joins à ce courrier les pièces justificatives suivantes :
• Copie de l'avis de contravention
• [Pièces justificatives : photos, attestation, certificat de cession...]

En conséquence, je vous demande de bien vouloir annuler cette contravention.

Veuillez agréer, Madame, Monsieur, l'expression de mes salutations distinguées.

[Signature]
[Prénom Nom]`},

  {id:"adm3",cat:"administration",titre:"Demande de délai de paiement (impôts)",tags:["impôts","délai","paiement","fisc"],
   corps:`[Prénom Nom]
[Adresse]
[Code postal Ville]
[N° fiscal]

[Ville], le [Date]

Direction Générale des Finances Publiques
Centre des Impôts de [Ville]
[Adresse]

Objet : Demande de délai de paiement — Avis d'imposition n° [Numéro]

Madame, Monsieur,

Suite à la réception de mon avis d'imposition n° [Numéro] d'un montant de [Montant] €, je me permets de vous contacter afin de solliciter un délai de paiement.

En effet, en raison de [Situation : difficultés financières temporaires, perte d'emploi, maladie...], il m'est impossible d'honorer ce règlement dans les délais impartis.

Je souhaiterais pouvoir échelonner ce paiement en [Nombre] mensualités à compter du [Date souhaitée].

Je vous adresse en pièces jointes les justificatifs de ma situation financière actuelle.

Dans l'attente de votre accord, je vous prie d'agréer, Madame, Monsieur, mes salutations distinguées.

[Signature]
[Prénom Nom]`},

  // ─── ÉCOLE ───
  {id:"e1",cat:"ecole",titre:"Autorisation d'absence scolaire",tags:["absence","école","autorisation","enfant"],
   corps:`[Prénom Nom du parent]
[Adresse]
[Téléphone]

[Ville], le [Date]

[Directeur/Professeur principal]
[Nom de l'établissement]
[Adresse de l'école]

Objet : Demande d'autorisation d'absence pour [Prénom de l'enfant] — classe de [Classe]

Madame, Monsieur,

Je me permets de vous contacter afin d'obtenir une autorisation d'absence pour mon enfant [Prénom Nom], élève en classe de [Classe], du [Date début] au [Date fin inclus].

Motif de cette absence : [Voyage familial / Raison médicale / Événement familial / Compétition sportive...]

Je m'engage à ce que [Prénom] effectue l'ensemble du travail manqué à son retour et reste en contact avec ses camarades pour rattraper les cours.

Dans l'attente de votre accord, je vous remercie et vous adresse mes respectueuses salutations.

[Signature]
[Prénom Nom du parent]`},

  {id:"e2",cat:"ecole",titre:"Signalement de harcèlement scolaire",tags:["harcèlement","bullying","école","enfant"],
   corps:`[Prénom Nom du parent]
[Adresse]
[Téléphone]
[Email]

[Ville], le [Date]

[Directeur / Proviseur]
[Nom de l'établissement]
[Adresse]

Objet : Signalement de faits de harcèlement à l'encontre de [Prénom de l'enfant]

Madame, Monsieur,

Je me vois dans l'obligation de porter à votre connaissance des faits préoccupants dont est victime mon enfant [Prénom Nom], élève en classe de [Classe].

Depuis [Date approximative de début], [Prénom] est victime de comportements que je qualifie de harcèlement scolaire, notamment :
• [Décrire les faits précis : insultes, exclusion, menaces physiques, cyberharcèlement...]
• [Dates et lieux des incidents si connus]
• [Identité des auteurs si connue]

Ces agissements ont des conséquences sérieuses sur la santé et la scolarité de mon enfant : [Décrire : anxiété, refus d'aller à l'école, baisse des résultats...]

Je sollicite un rendez-vous urgent afin d'envisager les mesures à prendre pour faire cesser ces faits.

Je me réserve le droit, si aucune mesure satisfaisante n'est prise, de saisir les autorités compétentes.

Veuillez agréer, Madame, Monsieur, mes salutations distinguées.

[Signature]
[Prénom Nom]`},

  // ─── LOCATAIRES / PROPRIÉTAIRES ───
  {id:"l1",cat:"locataire",titre:"Mise en demeure de payer les loyers",tags:["loyer","impayé","mise en demeure","locataire"],
   corps:`[Prénom Nom du propriétaire / bailleur]
[Adresse]
[Code postal Ville]

[Ville], le [Date]

[Prénom Nom du locataire]
[Adresse du logement loué]

Objet : Mise en demeure de payer les loyers impayés — Lettre recommandée avec AR

Madame, Monsieur,

Malgré plusieurs relances, je constate que vous n'avez pas réglé les loyers suivants relatifs au bail du logement sis [Adresse] :

• Loyer du [Mois] : [Montant] €
• Loyer du [Mois] : [Montant] €
• Charges : [Montant] €
• Total dû : [Total] €

Par la présente, je vous mets en demeure de régulariser cette situation dans un délai de 8 jours à compter de la réception de ce courrier.

À défaut de règlement dans ce délai, je me verrai contraint(e) d'engager une procédure judiciaire à votre encontre, pouvant conduire à la résiliation de votre bail et à votre expulsion.

Je vous rappelle que votre garant [Nom du garant] sera également sollicité.

Veuillez agréer, Madame, Monsieur, mes salutations.

[Signature]
[Prénom Nom]
Envoi recommandé avec AR`},

  {id:"l2",cat:"locataire",titre:"Congé donné au locataire (reprise / vente)",tags:["congé","bail","résiliation","expulsion","propriétaire"],
   corps:`[Prénom Nom du propriétaire]
[Adresse]
[Code postal Ville]

[Ville], le [Date]

[Prénom Nom du locataire]
[Adresse du logement]

Objet : Congé pour [reprise du logement / vente] — Bail du [Date du bail]

Madame, Monsieur,

Conformément aux articles 15 et suivants de la loi n°89-462 du 6 juillet 1989, je vous notifie par la présente le congé relatif au logement sis [Adresse complète], dont vous êtes locataire depuis le [Date d'entrée].

Motif : [Reprise pour habiter / Vente du logement]

[Si reprise pour habiter :] Je souhaite reprendre ce logement pour y habiter à titre de résidence principale. Le bénéficiaire de cette reprise est : [Nom et lien de parenté].

[Si vente :] Je vous informe que j'envisage de vendre ce bien. Conformément à la loi, vous bénéficiez d'un droit de préemption. Le prix de vente est fixé à [Montant] €.

Ce congé prend effet à l'expiration de votre bail, soit le [Date de fin de bail]. Vous devez libérer les lieux à cette date.

Veuillez agréer, Madame, Monsieur, mes salutations distinguées.

[Signature]
[Prénom Nom]
Envoi recommandé avec AR`},

  {id:"l3",cat:"locataire",titre:"Demande de réparations urgentes (locataire → propriétaire)",tags:["réparations","travaux","logement","décence"],
   corps:`[Prénom Nom du locataire]
[Adresse du logement]
[Code postal Ville]
[Téléphone]

[Ville], le [Date]

[Prénom Nom du propriétaire / Agence immobilière]
[Adresse]

Objet : Demande de réalisation de travaux urgents — Logement sis [Adresse]

Madame, Monsieur,

Locataire du logement situé [Adresse complète] depuis le [Date d'entrée dans les lieux], je vous informe des problèmes suivants qui nécessitent une intervention urgente :

[Décrire précisément les problèmes : fuite d'eau, chaudière en panne, infiltration, moisissures, volets bloqués...]

Ces désordres rendent le logement partiellement impropre à l'habitation et nuisent à ma santé / sécurité.

Je vous demande d'intervenir dans un délai de [15 jours / immédiatement pour une urgence], conformément à vos obligations légales de bailleur au titre des articles 6 et 20-1 de la loi du 6 juillet 1989.

À défaut d'intervention dans ce délai, je serai contraint(e) de saisir la Commission Départementale de Conciliation et/ou de consigner mon loyer.

Veuillez agréer, Madame, Monsieur, mes salutations distinguées.

[Signature]
[Prénom Nom]`},

  // ─── EMPLOYEUR / RH ───
  {id:"rh1",cat:"employeur",titre:"Démission avec préavis",tags:["démission","préavis","CDI","travail"],
   corps:`[Prénom Nom]
[Adresse]
[Code postal Ville]

[Ville], le [Date]

[Nom de l'employeur / Responsable RH]
[Nom de l'entreprise]
[Adresse]

Objet : Lettre de démission

Madame, Monsieur,

Employé(e) en qualité de [Poste] au sein de votre société [Nom de l'entreprise] depuis le [Date d'embauche], je vous informe par la présente de ma décision de démissionner de mes fonctions.

Conformément aux dispositions conventionnelles en vigueur et à mon contrat de travail, j'effectuerai mon préavis d'une durée de [Durée du préavis], qui débutera à la date de réception de ce courrier.

Mon dernier jour de travail sera donc le [Date de fin de préavis].

Je reste pleinement disponible pour assurer la passation de mes dossiers dans les meilleures conditions.

Je vous remercie pour la confiance que vous m'avez témoignée tout au long de ces années.

Veuillez agréer, Madame, Monsieur, l'expression de mes salutations distinguées.

[Signature]
[Prénom Nom]`},

  {id:"rh2",cat:"employeur",titre:"Demande de solde de tout compte contesté",tags:["solde","compte","contestation","licenciement"],
   corps:`[Prénom Nom]
[Adresse]
[Code postal Ville]

[Ville], le [Date]

[Nom de l'employeur]
Service des Ressources Humaines
[Adresse]

Objet : Contestation du solde de tout compte — Ref. [Numéro]

Madame, Monsieur,

Par la présente, je conteste le reçu pour solde de tout compte qui m'a été remis le [Date], dans le délai légal de 6 mois prévu à l'article L1234-20 du Code du travail.

Les éléments suivants n'ont pas été ou ont été insuffisamment pris en compte :
• [Heures supplémentaires non payées : [Montant]]
• [Indemnité compensatrice de congés payés : [Montant]]
• [Indemnité de licenciement insuffisante : [Montant]]
• [Autres éléments : ...]

Je vous demande de régulariser ces manquants dans un délai de 15 jours.

En l'absence de règlement, je saisirai le Conseil des Prud'hommes.

Veuillez agréer, Madame, Monsieur, mes salutations.

[Signature]
[Prénom Nom]`},

  // ─── SANTÉ / MUTUELLE ───
  {id:"s1",cat:"sante",titre:"Contestation d'un refus de remboursement mutuelle",tags:["mutuelle","remboursement","santé","contestation"],
   corps:`[Prénom Nom]
[Adresse]
[N° d'adhérent]
[Téléphone]

[Ville], le [Date]

[Nom de la mutuelle]
Service Réclamations
[Adresse]

Objet : Contestation d'un refus de remboursement — Dossier n° [Numéro]

Madame, Monsieur,

J'ai reçu une décision de refus de remboursement concernant [Nature des soins] effectué(s) le [Date] par [Nom du praticien], pour un montant de [Montant] €.

Ce refus me semble injustifié car [Expliquer : soins couverts par le contrat, erreur de codification, accord préalable obtenu...].

Je vous transmets en pièces jointes :
• Ordonnance médicale
• Feuille de soins
• Relevé de remboursement de la Sécurité Sociale
• [Tout document utile]

Je vous demande de bien vouloir réexaminer ce dossier et procéder au remboursement qui m'est dû.

À défaut, je saisirai le Médiateur de votre organisme.

Veuillez agréer, Madame, Monsieur, mes salutations distinguées.

[Signature]
[Prénom Nom]`},

  // ─── VOISINAGE ───
  {id:"v1",cat:"voisinage",titre:"Mise en demeure troubles du voisinage",tags:["bruit","nuisances","voisin","trouble"],
   corps:`[Prénom Nom]
[Adresse]
[Code postal Ville]

[Ville], le [Date]

[Prénom Nom du voisin]
[Adresse du voisin]

Objet : Mise en demeure de cesser les troubles du voisinage

Madame, Monsieur,

Par la présente, je me vois contraint(e) de vous signaler formellement les troubles anormaux de voisinage dont je suis victime depuis [Date approximative], notamment :

[Décrire précisément : bruits nocturnes, musique, travaux tardifs, odeurs, comportements, ...]

Ces nuisances dépassent les inconvénients ordinaires du voisinage et portent atteinte à ma tranquillité et à ma qualité de vie.

Je vous mets en demeure de faire cesser immédiatement ces troubles.

À défaut de cessation dans un délai de 8 jours, je serai contraint(e) de saisir les autorités compétentes (Mairie, Police Municipale, Tribunal Judiciaire) pour obtenir réparation du préjudice subi.

Veuillez agréer, Madame, Monsieur, mes salutations.

[Signature]
[Prénom Nom]`},
];

const CATS_COURRIER=[
  {id:"banque",     l:"Banque",             icon:"🏦",color:"#38bdf8"},
  {id:"assurance",  l:"Assurances",         icon:"🛡️",color:"#f0a500"},
  {id:"administration",l:"Administration",  icon:"🏛️",color:"#a78bfa"},
  {id:"ecole",      l:"École / Scolarité",  icon:"🎓",color:"#34d399"},
  {id:"locataire",  l:"Locataires / Bail",  icon:"🏠",color:"#fb923c"},
  {id:"employeur",  l:"Employeur / RH",     icon:"💼",color:"#f472b6"},
  {id:"sante",      l:"Santé / Mutuelle",   icon:"🏥",color:"#4ade80"},
  {id:"voisinage",  l:"Voisinage",          icon:"🏘️",color:"#60a5fa"},
  {id:"perso",      l:"Personnalisé",       icon:"✏️",color:"#94a3b8"},
];

const ModelesCourrierModule=({modeles,setModeles})=>{
  const [catFilter,setCatFilter]=useState("all");
  const [search,setSearch]=useState("");
  const [selected,setSelected]=useState(null);
  const [editing,setEditing]=useState(null); // {id, corps, titre, cat, tags}
  const [showAdd,setShowAdd]=useState(false);
  const [formAdd,setFormAdd]=useState({titre:"",cat:"perso",tags:"",corps:""});
  const [vars,setVars]=useState({});   // valeurs des variables pour personnalisation
  const [activeTab,setActiveTab]=useState("liste"); // liste | editeur

  // Fusionner modèles de base + modèles personnalisés
  const allModeles=[...MODELES_BASE,...(modeles.custom||[])];
  const filtered=allModeles.filter(m=>{
    if(catFilter!=="all"&&m.cat!==catFilter)return false;
    if(search&&!m.titre.toLowerCase().includes(search.toLowerCase())&&!(m.tags||[]).some(t=>t.includes(search.toLowerCase())))return false;
    return true;
  });

  const selModele=selected&&allModeles.find(m=>m.id===selected);

  // Extraction variables [Entre crochets]
  const extractVars=corps=>[...new Set([...corps.matchAll(/\[([^\]]+)\]/g)].map(m=>m[1]))];

  // Corps avec variables remplacées
  const corpsPersonnalise=selModele?selModele.corps.replace(/\[([^\]]+)\]/g,(_,v)=>vars[v]||`[${v}]`):("");

  // Copier dans presse-papier
  const copier=()=>{navigator.clipboard.writeText(editing?editing.corps:corpsPersonnalise).then(()=>alert("✅ Copié dans le presse-papier !")).catch(()=>{});};

  // Imprimer
  const imprimer=()=>{
    const txt=editing?editing.corps:corpsPersonnalise;
    const w=window.open("","_blank");
    w.document.write(`<html><head><style>body{font-family:Arial,sans-serif;font-size:13px;line-height:1.8;margin:40px;color:#000;}pre{white-space:pre-wrap;font-family:Arial,sans-serif;}</style></head><body><pre>${txt.replace(/</g,"&lt;")}</pre></body></html>`);
    w.document.close();w.print();
  };

  // Export PDF via jsPDF
  const [pdfLoading,setPdfLoading]=useState(false);
  const exportPDF=async()=>{
    setPdfLoading(true);
    try{
      // Charger jsPDF si nécessaire
      if(!window.jspdf){
        await new Promise((res,rej)=>{
          const s=document.createElement("script");
          s.src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js";
          s.onload=res;s.onerror=rej;
          document.head.appendChild(s);
        });
      }
      const {jsPDF}=window.jspdf;
      const doc=new jsPDF({format:"a4",unit:"mm"});
      const txt=editing?editing.corps:corpsPersonnalise;
      const titre=selModele?.titre||"courrier";
      const margin=20;
      const pageW=doc.internal.pageSize.getWidth();
      const maxW=pageW-margin*2;

      // Police et styles
      doc.setFont("helvetica","normal");
      doc.setFontSize(11);
      doc.setTextColor(30,30,30);

      // Découpage en lignes en respectant les sauts
      const lignes=txt.split("\n");
      let y=margin+6;
      const lineH=6;

      for(const ligne of lignes){
        if(!ligne.trim()){y+=lineH*0.6;continue;}
        const wrapped=doc.splitTextToSize(ligne,maxW);
        for(const wl of wrapped){
          if(y>doc.internal.pageSize.getHeight()-margin){
            doc.addPage();y=margin;
          }
          doc.text(wl,margin,y);
          y+=lineH;
        }
      }

      // Filigrane "CONFIDENTIEL" en option (optionnel, commenté)
      // doc.setTextColor(220,220,220);doc.setFontSize(60);doc.text("CONFIDENTIEL",30,150,{angle:45});

      // Métadonnées
      doc.setProperties({title:titre,author:"NumaVie",creator:"NumaVie — Votre vie numérique"});

      const fname=titre.replace(/[^a-zA-Z0-9-_ éàêèùôî]/g,"_").slice(0,60)+".pdf";
      doc.save(fname);
    }catch(e){
      alert("Erreur génération PDF : "+e.message);
    }
    setPdfLoading(false);
  };

  const saveCustom=()=>{
    const m={...formAdd,id:uid(),tags:formAdd.tags.split(",").map(t=>t.trim()).filter(Boolean)};
    setModeles(p=>({...p,custom:[...(p.custom||[]),m]}));
    setShowAdd(false);setFormAdd({titre:"",cat:"perso",tags:"",corps:""});
  };

  const deleteCustom=id=>{setModeles(p=>({...p,custom:(p.custom||[]).filter(m=>m.id!==id)}));if(selected===id)setSelected(null);};

  const isCustom=id=>(modeles.custom||[]).some(m=>m.id===id);

  const varsList=selModele?extractVars(selModele.corps):[];

  return (
    <div style={{display:"flex",height:"calc(100vh - 44px)",margin:"-22px",overflow:"hidden",background:T.bg}}>
      {/* Sidebar liste */}
      <div style={{width:300,borderRight:`1px solid ${T.border}`,display:"flex",flexDirection:"column",flexShrink:0}}>
        {/* Header sidebar */}
        <div style={{padding:"14px 16px",borderBottom:`1px solid ${T.border}`}}>
          <div style={{fontFamily:T.fontD,fontSize:16,color:T.text,marginBottom:10}}>📝 Modèles de courrier</div>
          <Inp value={search} onChange={setSearch} placeholder="🔍 Rechercher..." style={{marginBottom:8}}/>
          <Btn onClick={()=>setShowAdd(true)} style={{width:"100%"}}>+ Créer un modèle</Btn>
        </div>
        {/* Filtres catégories */}
        <div style={{padding:"10px 12px",borderBottom:`1px solid ${T.border}`,display:"flex",flexWrap:"wrap",gap:5}}>
          <button onClick={()=>setCatFilter("all")} style={{padding:"3px 10px",borderRadius:6,border:`1px solid ${catFilter==="all"?T.accent:T.border}`,background:catFilter==="all"?T.accentDim:"transparent",color:catFilter==="all"?T.accent:T.muted,fontSize:11,cursor:"pointer",fontFamily:T.font}}>Tous</button>
          {CATS_COURRIER.map(c=>(
            <button key={c.id} onClick={()=>setCatFilter(c.id)} style={{padding:"3px 10px",borderRadius:6,border:`1px solid ${catFilter===c.id?c.color:T.border}`,background:catFilter===c.id?c.color+"22":"transparent",color:catFilter===c.id?c.color:T.muted,fontSize:11,cursor:"pointer",fontFamily:T.font}}>{c.icon} {c.l}</button>
          ))}
        </div>
        {/* Liste modèles */}
        <div style={{flex:1,overflow:"auto"}}>
          {filtered.length===0&&<EmptyState icon="📝" text="Aucun modèle trouvé"/>}
          {CATS_COURRIER.map(cat=>{
            const catModeles=filtered.filter(m=>m.cat===cat.id);
            if(catModeles.length===0)return null;
            return (
              <div key={cat.id}>
                <div style={{padding:"8px 16px 4px",fontSize:10,color:cat.color,fontWeight:700,textTransform:"uppercase",letterSpacing:"0.08em",background:"#060a10"}}>{cat.icon} {cat.l}</div>
                {catModeles.map(m=>(
                  <div key={m.id} onClick={()=>{setSelected(m.id);setVars({});setEditing(null);}}
                    style={{padding:"10px 16px",cursor:"pointer",borderBottom:`1px solid ${T.border}`,background:selected===m.id?T.accentDim:"transparent",borderLeft:`3px solid ${selected===m.id?T.accent:"transparent"}`,transition:"background 0.12s"}}>
                    <div style={{fontSize:13,fontWeight:600,color:selected===m.id?T.accent:T.text,marginBottom:3}}>{m.titre}</div>
                    <div style={{display:"flex",gap:4,flexWrap:"wrap"}}>
                      {(m.tags||[]).slice(0,3).map(t=><span key={t} style={{fontSize:9,background:T.border,color:T.muted,borderRadius:4,padding:"1px 5px"}}>{t}</span>)}
                      {isCustom(m.id)&&<span style={{fontSize:9,background:T.accentDim,color:T.accent,borderRadius:4,padding:"1px 5px"}}>✏️ perso</span>}
                    </div>
                  </div>
                ))}
              </div>
            );
          })}
          {/* Modèles perso sans cat prédéfinie */}
          {(modeles.custom||[]).filter(m=>!CATS_COURRIER.find(c=>c.id===m.cat)||m.cat==="perso").filter(m=>filtered.some(f=>f.id===m.id)).length>0&&(
            <div>
              <div style={{padding:"8px 16px 4px",fontSize:10,color:"#94a3b8",fontWeight:700,textTransform:"uppercase",background:"#060a10"}}>✏️ Mes modèles</div>
            </div>
          )}
        </div>
        <div style={{padding:"10px 16px",borderTop:`1px solid ${T.border}`,fontSize:11,color:T.muted,textAlign:"center"}}>{filtered.length} modèle{filtered.length>1?"s":""}</div>
      </div>

      {/* Zone principale */}
      <div style={{flex:1,display:"flex",flexDirection:"column",overflow:"hidden"}}>
        {!selModele?(
          <div style={{flex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:16}}>
            <div style={{fontSize:56}}>📝</div>
            <div style={{fontFamily:T.fontD,fontSize:20,color:T.text}}>Banque de courriers</div>
            <div style={{fontSize:13,color:T.muted,textAlign:"center",maxWidth:400,lineHeight:1.7}}>{allModeles.length} modèles disponibles pour toutes vos démarches administratives, bancaires, scolaires...</div>
            <div style={{display:"flex",gap:8,flexWrap:"wrap",justifyContent:"center"}}>
              {CATS_COURRIER.map(c=>(
                <button key={c.id} onClick={()=>setCatFilter(c.id)} style={{padding:"8px 14px",borderRadius:8,border:`1px solid ${c.color}33`,background:`${c.color}11`,color:c.color,fontSize:12,cursor:"pointer",fontFamily:T.font}}>
                  {c.icon} {c.l} ({allModeles.filter(m=>m.cat===c.id).length})
                </button>
              ))}
            </div>
          </div>
        ):(
          <>
            {/* Toolbar */}
            <div style={{padding:"10px 20px",borderBottom:`1px solid ${T.border}`,display:"flex",alignItems:"center",gap:10,flexShrink:0,background:"#060a10"}}>
              <div style={{flex:1}}>
                <div style={{fontFamily:T.fontD,fontSize:15,color:T.text}}>{selModele.titre}</div>
                <div style={{display:"flex",gap:6,marginTop:3,flexWrap:"wrap"}}>
                  {(()=>{const c=CATS_COURRIER.find(x=>x.id===selModele.cat);return c&&<Badge c={c.color}>{c.icon} {c.l}</Badge>;})()}
                  {(selModele.tags||[]).map(t=><Badge key={t} c={T.muted}>{t}</Badge>)}
                </div>
              </div>
              <div style={{display:"flex",gap:8}}>
                {editing?(
                  <>
                    <Btn sm v="ghost" onClick={()=>setEditing(null)}>✕ Annuler</Btn>
                    <Btn sm onClick={()=>{
                      if(isCustom(selModele.id)){setModeles(p=>({...p,custom:p.custom.map(m=>m.id===selModele.id?{...m,...editing}:m)}));}
                      setEditing(null);
                    }}>💾 Enregistrer</Btn>
                  </>
                ):(
                  <>
                    <Btn sm v="ghost" onClick={()=>setEditing({...selModele})}>✏️ Modifier</Btn>
                    <Btn sm v="ghost" onClick={copier}>📋 Copier</Btn>
                    <Btn sm v="ghost" onClick={imprimer}>🖨️ Imprimer</Btn>
                    <Btn sm onClick={exportPDF} disabled={pdfLoading} style={{background:"#ef4444",color:"#fff",border:"none"}}>{pdfLoading?"⏳":"📄"} PDF</Btn>
                    {isCustom(selModele.id)&&<Btn sm v="danger" onClick={()=>deleteCustom(selModele.id)}>🗑</Btn>}
                  </>
                )}
              </div>
            </div>

            <div style={{flex:1,display:"grid",gridTemplateColumns:varsList.length>0&&!editing?"1fr 300px":"1fr",overflow:"hidden"}}>
              {/* Éditeur / Aperçu */}
              <div style={{overflow:"auto",padding:"20px 24px"}}>
                {editing?(
                  <textarea value={editing.corps} onChange={e=>setEditing(ed=>({...ed,corps:e.target.value}))}
                    style={{width:"100%",height:"calc(100vh - 170px)",background:"#0a0e17",border:`1px solid ${T.border}`,borderRadius:10,padding:"18px 20px",color:T.text,fontFamily:"'Courier New',monospace",fontSize:13,lineHeight:1.8,resize:"none",outline:"none",boxSizing:"border-box"}}/>
                ):(
                  <div style={{background:"#ffffff",borderRadius:12,padding:"40px 48px",minHeight:"80vh",boxShadow:"0 4px 24px rgba(0,0,0,0.4)",fontFamily:"Arial,sans-serif",fontSize:13,lineHeight:1.8,color:"#1a1a1a",whiteSpace:"pre-wrap"}}>
                    {corpsPersonnalise.split(/(\[[^\]]+\])/).map((part,i)=>{
                      const isVar=/^\[.+\]$/.test(part);
                      const varName=isVar?part.slice(1,-1):"";
                      const isFilled=isVar&&vars[varName];
                      return <span key={i} style={isVar?{background:isFilled?"rgba(34,197,94,0.15)":"rgba(240,165,0,0.18)",borderRadius:3,padding:"0 3px",color:isFilled?"#166534":"#92400e",fontWeight:600,cursor:"pointer"} :{}}>{part}</span>;
                    })}
                  </div>
                )}
              </div>

              {/* Panneau variables */}
              {varsList.length>0&&!editing&&(
                <div style={{borderLeft:`1px solid ${T.border}`,overflow:"auto",padding:"16px"}}>
                  <div style={{fontFamily:T.fontD,fontSize:14,color:T.text,marginBottom:4}}>🏷️ Personnaliser</div>
                  <div style={{fontSize:11,color:T.muted,marginBottom:14}}>Remplissez les champs pour personnaliser le courrier. Les zones surlignées seront remplacées automatiquement.</div>
                  <div style={{display:"grid",gap:10}}>
                    {varsList.map(v=>(
                      <div key={v}>
                        <div style={{fontSize:10,color:T.accent,marginBottom:3,fontWeight:600}}>{v}</div>
                        {v.toLowerCase().includes("date")?
                          <input type="date" value={vars[v]||""} onChange={e=>{const d=e.target.value;setVars(vv=>({...vv,[v]:d?new Date(d).toLocaleDateString("fr-FR"):""}));}} style={{width:"100%",background:"#060a10",border:`1px solid ${T.border}`,borderRadius:6,padding:"6px 10px",color:T.text,fontFamily:T.font,fontSize:12,outline:"none",boxSizing:"border-box"}}/>:
                          <input type="text" value={vars[v]||""} onChange={e=>setVars(vv=>({...vv,[v]:e.target.value}))} placeholder={v} style={{width:"100%",background:"#060a10",border:`1px solid ${T.border}`,borderRadius:6,padding:"6px 10px",color:T.text,fontFamily:T.font,fontSize:12,outline:"none",boxSizing:"border-box"}}/>
                        }
                      </div>
                    ))}
                  </div>
                  <div style={{marginTop:16,display:"grid",gap:8}}>
                    <Btn onClick={copier} style={{width:"100%"}}>📋 Copier le courrier</Btn>
                    <Btn v="ghost" onClick={imprimer} style={{width:"100%"}}>🖨️ Imprimer</Btn>
                    <Btn onClick={exportPDF} disabled={pdfLoading} style={{width:"100%",background:"#ef4444",color:"#fff",border:"none"}}>{pdfLoading?"⏳ Génération...":"📄 Télécharger PDF"}</Btn>
                    <Btn v="ghost" onClick={()=>setVars({})} style={{width:"100%"}}>↺ Réinitialiser</Btn>
                  </div>
                  <div style={{marginTop:12,padding:"10px 12px",background:T.accentDim,borderRadius:8,fontSize:11,color:T.muted}}>
                    💡 Cliquez sur une zone <span style={{color:T.accent}}>[surlignée]</span> dans le courrier pour la remplir rapidement.
                  </div>
                </div>
              )}
            </div>
          </>
        )}
      </div>

      {/* Modale ajout modèle perso */}
      {showAdd&&<Modal title="✏️ Créer un modèle personnalisé" onClose={()=>setShowAdd(false)} width={740}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10,marginBottom:10}}>
          <F label="Titre du modèle *"><Inp value={formAdd.titre} onChange={v=>setFormAdd(f=>({...f,titre:v}))} placeholder="Ex: Résiliation contrat internet"/></F>
          <F label="Catégorie"><Sel value={formAdd.cat} onChange={v=>setFormAdd(f=>({...f,cat:v}))}>{CATS_COURRIER.map(c=><option key={c.id} value={c.id}>{c.icon} {c.l}</option>)}</Sel></F>
          <F label="Tags (séparés par virgule)" style={{gridColumn:"1/-1"}}><Inp value={formAdd.tags} onChange={v=>setFormAdd(f=>({...f,tags:v}))} placeholder="résiliation, lettre, ..."/></F>
        </div>
        <F label="Corps du courrier — utilisez [Variable] pour les zones à personnaliser">
          <textarea value={formAdd.corps} onChange={e=>setFormAdd(f=>({...f,corps:e.target.value}))} rows={14} placeholder="[Prénom Nom]&#10;[Adresse]&#10;&#10;[Ville], le [Date]&#10;&#10;Madame, Monsieur,&#10;..." style={{width:"100%",background:"#060a10",border:`1px solid ${T.border}`,borderRadius:8,padding:"12px 14px",color:T.text,fontFamily:"'Courier New',monospace",fontSize:12,lineHeight:1.7,resize:"vertical",outline:"none",boxSizing:"border-box"}}/>
        </F>
        <div style={{fontSize:11,color:T.muted,marginBottom:10}}>💡 Conseil : utilisez <span style={{color:T.accent}}>[Prénom Nom]</span>, <span style={{color:T.accent}}>[Date]</span>, <span style={{color:T.accent}}>[Montant]</span>... pour créer des variables remplissables automatiquement.</div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={saveCustom} disabled={!formAdd.titre||!formAdd.corps}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: AMIS
// ═══════════════════════════════════════════════════════════════════════════════
const RESEAUX_SOCIAUX=[
  {id:"instagram", l:"Instagram",   icon:"📸", color:"#E1306C", base:"https://instagram.com/"},
  {id:"facebook",  l:"Facebook",    icon:"👤", color:"#1877F2", base:"https://facebook.com/"},
  {id:"twitter",   l:"X / Twitter", icon:"🐦", color:"#1DA1F2", base:"https://x.com/"},
  {id:"tiktok",    l:"TikTok",      icon:"🎵", color:"#ff0050", base:"https://tiktok.com/@"},
  {id:"linkedin",  l:"LinkedIn",    icon:"💼", color:"#0A66C2", base:"https://linkedin.com/in/"},
  {id:"youtube",   l:"YouTube",     icon:"▶️", color:"#FF0000", base:"https://youtube.com/@"},
  {id:"snapchat",  l:"Snapchat",    icon:"👻", color:"#FFFC00", base:"https://snapchat.com/add/"},
  {id:"whatsapp",  l:"WhatsApp",    icon:"💬", color:"#25D366", base:"https://wa.me/"},
  {id:"pinterest", l:"Pinterest",   icon:"📌", color:"#E60023", base:"https://pinterest.com/"},
  {id:"twitch",    l:"Twitch",      icon:"🎮", color:"#9146FF", base:"https://twitch.tv/"},
];

const CATS_AMIS=[
  {id:"proches",   l:"Famille proche", icon:"❤️",  color:"#f87171"},
  {id:"amis",      l:"Amis proches",   icon:"⭐",  color:"#f0a500"},
  {id:"collegues", l:"Collègues",      icon:"💼",  color:"#38bdf8"},
  {id:"scolaire",  l:"École / Études", icon:"🎓",  color:"#a78bfa"},
  {id:"sport",     l:"Sport / Loisirs",icon:"⚽",  color:"#34d399"},
  {id:"connaissance",l:"Connaissances",icon:"👋",  color:"#94a3b8"},
];

const AmiDetail=({ami,amis,setAmis,onClose})=>{
  const [tab,setTab]=useState("profil");
  const [editMode,setEditMode]=useState(false);
  const [form,setForm]=useState({...ami});
  const cat=CATS_AMIS.find(c=>c.id===ami.categorie)||CATS_AMIS[1];
  const photoRef=useRef();

  const save=()=>{setAmis(p=>p.map(a=>a.id===ami.id?{...form}:a));setEditMode(false);};

  // Upload photo ami
  const handlePhoto=e=>{
    const file=e.target.files[0];
    if(!file)return;
    const reader=new FileReader();
    reader.onload=ev=>{
      const dataUrl=ev.target.result;
      setForm(f=>({...f,photo:dataUrl}));
      // Sauvegarde immédiate même hors editMode
      setAmis(p=>p.map(a=>a.id===ami.id?{...a,photo:dataUrl}:a));
    };
    reader.readAsDataURL(file);
  };

  const SocialRow=({reseau})=>{
    const rs=RESEAUX_SOCIAUX.find(r=>r.id===reseau.id);
    if(!rs||!reseau.username)return null;
    const url=rs.base+(reseau.url||reseau.username);
    return (
      <div style={{display:"flex",alignItems:"center",gap:10,padding:"10px 14px",background:"#060a10",borderRadius:9,marginBottom:6}}>
        <div style={{width:36,height:36,borderRadius:18,background:rs.color+"22",display:"flex",alignItems:"center",justifyContent:"center",fontSize:18,flexShrink:0}}>{rs.icon}</div>
        <div style={{flex:1}}>
          <div style={{fontSize:11,color:T.muted,marginBottom:1}}>{rs.l}</div>
          <div style={{fontSize:13,fontWeight:600,color:T.text}}>@{reseau.username}</div>
          {reseau.note&&<div style={{fontSize:11,color:T.muted,fontStyle:"italic",marginTop:2}}>{reseau.note}</div>}
        </div>
        <a href={url} target="_blank" rel="noreferrer" style={{background:rs.color+"22",color:rs.color,border:`1px solid ${rs.color}44`,borderRadius:7,padding:"4px 10px",textDecoration:"none",fontSize:11,fontWeight:600,flexShrink:0}}>Voir ↗</a>
      </div>
    );
  };

  const reseauxRenseignes=(ami.reseaux||[]).filter(r=>r.username);

  return (
    <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.7)",zIndex:2000,display:"flex",alignItems:"center",justifyContent:"center",padding:20}}>
      <div style={{background:T.bg,border:`1px solid ${T.border}`,borderRadius:16,width:"min(820px,96vw)",maxHeight:"90vh",display:"flex",flexDirection:"column",overflow:"hidden"}}>
        {/* Header */}
        <div style={{padding:"18px 22px",borderBottom:`1px solid ${T.border}`,display:"flex",alignItems:"center",gap:14,background:`linear-gradient(135deg,${cat.color}12,transparent)`}}>
          {/* Avatar / Photo cliquable */}
          <div style={{position:"relative",flexShrink:0}} onClick={()=>photoRef.current?.click()} title="Cliquer pour changer la photo">
            <div style={{width:64,height:64,borderRadius:32,overflow:"hidden",border:`3px solid ${cat.color}`,cursor:"pointer",background:cat.color+"22",display:"flex",alignItems:"center",justifyContent:"center",fontSize:24,fontWeight:700,color:cat.color}}>
              {(ami.photo||form.photo)
                ?<img src={ami.photo||form.photo} alt="" style={{width:"100%",height:"100%",objectFit:"cover"}}/>
                :(ami.prenom[0]||"?").toUpperCase()
              }
            </div>
            <div style={{position:"absolute",bottom:0,right:0,width:20,height:20,borderRadius:10,background:T.accent,display:"flex",alignItems:"center",justifyContent:"center",fontSize:10,cursor:"pointer",border:`2px solid ${T.bg}`}}>📷</div>
            <input ref={photoRef} type="file" accept="image/*" style={{display:"none"}} onChange={handlePhoto}/>
          </div>
          <div style={{flex:1}}>
            <div style={{fontFamily:T.fontD,fontSize:20,color:T.text,fontWeight:700}}>{ami.prenom} {ami.nom}</div>
            <div style={{display:"flex",gap:8,marginTop:4,alignItems:"center"}}>
              <Badge c={cat.color}>{cat.icon} {cat.l}</Badge>
              {adresseFull(ami)&&<span style={{fontSize:12,color:T.muted}}>📍 {adresseFull(ami)}</span>}
              {!adresseFull(ami)&&ami.ville&&<span style={{fontSize:12,color:T.muted}}>📍 {ami.ville}</span>}
              {reseauxRenseignes.length>0&&<span style={{fontSize:11,color:T.accent}}>🌐 {reseauxRenseignes.length} réseau{reseauxRenseignes.length>1?"x":""}</span>}
            </div>
          </div>
          <div style={{display:"flex",gap:6}}>
            {!editMode&&<Btn sm v="ghost" onClick={()=>setEditMode(true)}>✏️ Modifier</Btn>}
            {editMode&&<><Btn sm v="ghost" onClick={()=>setEditMode(false)}>✕</Btn><Btn sm onClick={save}>💾</Btn></>}
            <Btn sm v="ghost" onClick={onClose}>✕</Btn>
          </div>
        </div>

        <Tabs tabs={[{id:"profil",icon:"👤",label:"Profil"},{id:"reseaux",icon:"🌐",label:`Réseaux (${reseauxRenseignes.length})`},{id:"notes",icon:"📝",label:"Notes & Souvenirs"}]} active={tab} onChange={setTab}/>

        <div style={{flex:1,overflow:"auto",padding:"18px 22px"}}>
          {tab==="profil"&&(
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
              <Card>
                <Divider label="Coordonnées"/>
                {editMode?(
                  <div style={{display:"grid",gap:8}}>
                    <F label="Prénom"><Inp value={form.prenom} onChange={v=>setForm(f=>({...f,prenom:v}))}/></F>
                    <F label="Nom"><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))}/></F>
                    <F label="Email"><Inp type="email" value={form.email||""} onChange={v=>setForm(f=>({...f,email:v}))}/></F>
                    <F label="Téléphone"><Inp value={form.tel||""} onChange={v=>setForm(f=>({...f,tel:v}))}/></F>
                    <F label="Rue / N° et voie"><Inp value={form.rue||""} onChange={v=>setForm(f=>({...f,rue:v}))} placeholder="12 allée des Pins"/></F>
                    <div style={{display:"grid",gridTemplateColumns:"120px 1fr",gap:8}}>
                      <F label="Code postal"><Inp value={form.codePostal||""} onChange={v=>setForm(f=>({...f,codePostal:v}))} placeholder="33210"/></F>
                      <F label="Ville"><Inp value={form.ville||""} onChange={v=>setForm(f=>({...f,ville:v}))} placeholder="Bordeaux"/></F>
                    </div>
                    <F label="Date de naissance"><Inp type="date" value={form.dateNaissance||""} onChange={v=>setForm(f=>({...f,dateNaissance:v}))}/></F>
                    <F label="Catégorie"><Sel value={form.categorie} onChange={v=>setForm(f=>({...f,categorie:v}))}>{CATS_AMIS.map(c=><option key={c.id} value={c.id}>{c.icon} {c.l}</option>)}</Sel></F>
                  </div>
                ):(
                  <div>
                    <InfoRow label="Prénom" value={ami.prenom}/>
                    <InfoRow label="Nom" value={ami.nom}/>
                    <InfoRow label="Email" value={ami.email}/>
                    <InfoRow label="Téléphone" value={ami.tel}/>
                    {ami.rue&&<InfoRow label="Rue" value={ami.rue}/>}
                    {ami.codePostal&&<InfoRow label="Code postal" value={ami.codePostal}/>}
                    {ami.ville&&<InfoRow label="Ville" value={ami.ville}/>}
                    {adresseFull(ami)&&<InfoRow label="Adresse complète" value={adresseFull(ami)}/>}
                    <InfoRow label="Date de naissance" value={ami.dateNaissance&&fmt(ami.dateNaissance)}/>
                    {ami.dateNaissance&&(()=>{
                      const age=new Date().getFullYear()-new Date(ami.dateNaissance).getFullYear();
                      const prochainAnn=new Date(ami.dateNaissance);prochainAnn.setFullYear(new Date().getFullYear());
                      if(prochainAnn<new Date())prochainAnn.setFullYear(new Date().getFullYear()+1);
                      const j=Math.round((prochainAnn-new Date())/86400000);
                      return <div style={{marginTop:10,padding:"8px 12px",background:j<=14?"rgba(240,165,0,0.1)":T.accentDim,borderRadius:8,fontSize:12}}>
                        <span style={{color:T.muted}}>🎂 {age} ans · </span>
                        <span style={{color:j<=14?T.warning:T.accent,fontWeight:600}}>Anniversaire dans {j} jour{j>1?"s":""}</span>
                      </div>;
                    })()}
                    <ContactActions tel={ami.tel} email={ami.email} adresse={adresseFull(ami)}/>
                  </div>
                )}
              </Card>
              <Card>
                <Divider label="Description"/>
                {editMode?(
                  <F label="Description / Comment vous vous êtes rencontrés">
                    <Txt value={form.description||""} onChange={v=>setForm(f=>({...f,description:v}))} rows={4} placeholder="Comment vous vous êtes rencontrés, centres d'intérêts communs..."/>
                  </F>
                ):(
                  ami.description?<div style={{fontSize:13,color:T.muted,lineHeight:1.8,fontStyle:"italic"}}>{ami.description}</div>:<EmptyState icon="📝" text="Ajoutez une description"/>
                )}
                {editMode&&(
                  <F label="Centres d'intérêt (virgule)" style={{marginTop:10}}>
                    <Inp value={(form.interets||[]).join(", ")} onChange={v=>setForm(f=>({...f,interets:v.split(",").map(x=>x.trim()).filter(Boolean)}))}/></F>
                )}
                {!editMode&&(ami.interets||[]).length>0&&(
                  <div style={{marginTop:12,display:"flex",gap:5,flexWrap:"wrap"}}>
                    {ami.interets.map(i=><Badge key={i} c={T.info}>{i}</Badge>)}
                  </div>
                )}
              </Card>
            </div>
          )}

          {tab==="reseaux"&&(
            <div>
              {reseauxRenseignes.length===0&&<EmptyState icon="🌐" text="Aucun réseau social renseigné. Cliquez sur Modifier pour les ajouter."/>}
              {/* Résumé réseaux */}
              {reseauxRenseignes.length>0&&(
                <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(260px,1fr))",gap:10,marginBottom:20}}>
                  {reseauxRenseignes.map(r=><SocialRow key={r.id} reseau={r}/>)}
                </div>
              )}
              {editMode&&(
                <Card>
                  <Divider label="Modifier les réseaux sociaux"/>
                  <div style={{display:"grid",gap:10}}>
                    {RESEAUX_SOCIAUX.map(rs=>{
                      const cur=(form.reseaux||[]).find(r=>r.id===rs.id)||{id:rs.id,username:"",note:""};
                      return (
                        <div key={rs.id} style={{display:"grid",gridTemplateColumns:"auto 1fr 1fr",gap:8,alignItems:"center",padding:"8px 12px",background:"#060a10",borderRadius:8}}>
                          <div style={{display:"flex",alignItems:"center",gap:6,width:120}}>
                            <span style={{fontSize:16}}>{rs.icon}</span>
                            <span style={{fontSize:12,color:rs.color,fontWeight:600}}>{rs.l}</span>
                          </div>
                          <input value={cur.username} onChange={e=>{const v=e.target.value;setForm(f=>{const reseaux=(f.reseaux||RESEAUX_SOCIAUX.map(r=>({id:r.id,username:"",note:""}))).map(r=>r.id===rs.id?{...r,username:v}:r);return{...f,reseaux};});}}
                            placeholder="@username" style={{background:"#0a0e17",border:`1px solid ${T.border}`,borderRadius:6,padding:"5px 9px",color:T.text,fontFamily:T.font,fontSize:12,outline:"none"}}/>
                          <input value={cur.note||""} onChange={e=>{const v=e.target.value;setForm(f=>{const reseaux=(f.reseaux||RESEAUX_SOCIAUX.map(r=>({id:r.id,username:"",note:""}))).map(r=>r.id===rs.id?{...r,note:v}:r);return{...f,reseaux};});}}
                            placeholder="Note (ex: compte perso)" style={{background:"#0a0e17",border:`1px solid ${T.border}`,borderRadius:6,padding:"5px 9px",color:T.text,fontFamily:T.font,fontSize:12,outline:"none"}}/>
                        </div>
                      );
                    })}
                  </div>
                </Card>
              )}
            </div>
          )}

          {tab==="notes"&&(
            <div style={{display:"grid",gap:12}}>
              {editMode&&(
                <F label="Souvenirs / Notes libres">
                  <Txt value={form.notes||""} onChange={v=>setForm(f=>({...f,notes:v}))} rows={6} placeholder="Souvenirs partagés, anecdotes, où vous vous êtes rencontrés..."/>
                </F>
              )}
              {!editMode&&ami.notes&&<Card style={{padding:"14px 18px"}}><div style={{fontSize:13,color:T.text,lineHeight:1.9,whiteSpace:"pre-wrap"}}>{ami.notes}</div></Card>}
              {!editMode&&!ami.notes&&<EmptyState icon="📝" text="Ajoutez des notes et souvenirs sur cet ami"/>}

              {/* Anniversaire rappel */}
              {ami.dateNaissance&&(()=>{
                const prochainAnn=new Date(ami.dateNaissance);prochainAnn.setFullYear(new Date().getFullYear());
                if(prochainAnn<new Date())prochainAnn.setFullYear(new Date().getFullYear()+1);
                const j=Math.round((prochainAnn-new Date())/86400000);
                if(j>30)return null;
                return <div style={{padding:"14px 18px",background:"rgba(240,165,0,0.1)",border:"1px solid rgba(240,165,0,0.3)",borderRadius:10,fontSize:13,color:T.warning}}>
                  🎂 L'anniversaire de {ami.prenom} est dans <strong>{j} jour{j>1?"s":""}</strong> ! Pensez à lui/elle.
                </div>;
              })()}
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

const Amis=({amis,setAmis})=>{
  const [selected,setSelected]=useState(null);
  const [catFilter,setCatFilter]=useState("all");
  const [search,setSearch]=useState("");
  const [showAdd,setShowAdd]=useState(false);
  const EMPTY_AMI={prenom:"",nom:"",categorie:"amis",email:"",tel:"",rue:"",codePostal:"",ville:"",dateNaissance:"",description:"",interets:[],reseaux:RESEAUX_SOCIAUX.map(r=>({id:r.id,username:"",note:""})),notes:""};
  const [form,setForm]=useState({...EMPTY_AMI});

  const filtered=amis.filter(a=>{
    if(catFilter!=="all"&&a.categorie!==catFilter)return false;
    if(search&&![a.prenom,a.nom,a.ville,a.email].some(v=>(v||"").toLowerCase().includes(search.toLowerCase())))return false;
    return true;
  });

  // Anniversaires prochains
  const anniversairesBientot=amis.filter(a=>{
    if(!a.dateNaissance)return false;
    const p=new Date(a.dateNaissance);p.setFullYear(new Date().getFullYear());
    if(p<new Date())p.setFullYear(new Date().getFullYear()+1);
    return Math.round((p-new Date())/86400000)<=30;
  }).sort((a,b)=>{
    const pa=new Date(a.dateNaissance);pa.setFullYear(new Date().getFullYear());if(pa<new Date())pa.setFullYear(new Date().getFullYear()+1);
    const pb=new Date(b.dateNaissance);pb.setFullYear(new Date().getFullYear());if(pb<new Date())pb.setFullYear(new Date().getFullYear()+1);
    return pa-pb;
  });

  const save=()=>{
    setAmis(p=>[...p,{...form,id:uid()}]);
    setShowAdd(false);
    setForm({...EMPTY_AMI});
  };

  const selAmi=selected&&amis.find(a=>a.id===selected);

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>👫 Mes Amis</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>{amis.length} ami{amis.length>1?"s":""} · {amis.filter(a=>(a.reseaux||[]).some(r=>r.username)).length} avec réseaux sociaux</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Ami</Btn>
      </div>

      {/* Anniversaires bientôt */}
      {anniversairesBientot.length>0&&(
        <div style={{background:"rgba(240,165,0,0.07)",border:"1px solid rgba(240,165,0,0.2)",borderRadius:10,padding:"12px 16px",marginBottom:18}}>
          <div style={{fontWeight:700,color:T.warning,marginBottom:8,fontSize:13}}>🎂 Anniversaires dans les 30 prochains jours</div>
          <div style={{display:"flex",gap:8,flexWrap:"wrap"}}>
            {anniversairesBientot.map(a=>{
              const p=new Date(a.dateNaissance);p.setFullYear(new Date().getFullYear());if(p<new Date())p.setFullYear(new Date().getFullYear()+1);
              const j=Math.round((p-new Date())/86400000);
              return <Badge key={a.id} c={j<=7?T.danger:T.warning}>{a.prenom} {a.nom} — dans {j}j</Badge>;
            })}
          </div>
        </div>
      )}

      {/* Filtres */}
      <div style={{display:"flex",gap:8,marginBottom:16,alignItems:"center",flexWrap:"wrap"}}>
        <Inp value={search} onChange={setSearch} placeholder="🔍 Rechercher..." style={{maxWidth:220}}/>
        <button onClick={()=>setCatFilter("all")} style={{padding:"5px 12px",borderRadius:7,border:`1px solid ${catFilter==="all"?T.accent:T.border}`,background:catFilter==="all"?T.accentDim:"transparent",color:catFilter==="all"?T.accent:T.muted,fontSize:12,cursor:"pointer",fontFamily:T.font}}>Tous ({amis.length})</button>
        {CATS_AMIS.map(c=>{
          const n=amis.filter(a=>a.categorie===c.id).length;
          return n>0&&<button key={c.id} onClick={()=>setCatFilter(c.id)} style={{padding:"5px 12px",borderRadius:7,border:`1px solid ${catFilter===c.id?c.color:T.border}`,background:catFilter===c.id?c.color+"22":"transparent",color:catFilter===c.id?c.color:T.muted,fontSize:12,cursor:"pointer",fontFamily:T.font}}>{c.icon} {c.l} ({n})</button>;
        })}
      </div>

      {/* Grille amis */}
      {filtered.length===0&&<EmptyState icon="👫" text="Aucun ami trouvé. Ajoutez votre premier ami !"/>}
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(280px,1fr))",gap:14}}>
        {filtered.map(ami=>{
          const cat=CATS_AMIS.find(c=>c.id===ami.categorie)||CATS_AMIS[1];
          const reseauxDispo=(ami.reseaux||[]).filter(r=>r.username);
          const prochainAnn=ami.dateNaissance&&(()=>{const p=new Date(ami.dateNaissance);p.setFullYear(new Date().getFullYear());if(p<new Date())p.setFullYear(new Date().getFullYear()+1);return Math.round((p-new Date())/86400000);})();
          return (
            <Card key={ami.id} onClick={()=>setSelected(ami.id)} style={{cursor:"pointer",padding:0,overflow:"hidden",borderColor:selected===ami.id?T.accent:T.border}}>
              {/* Header coloré */}
              <div style={{background:`linear-gradient(135deg,${cat.color}18,transparent)`,padding:"14px 16px",borderBottom:`1px solid ${T.border}`}}>
                <div style={{display:"flex",alignItems:"center",gap:10}}>
                  <div style={{width:44,height:44,borderRadius:22,background:cat.color+"28",border:`2px solid ${cat.color}`,overflow:"hidden",display:"flex",alignItems:"center",justifyContent:"center",fontSize:18,fontWeight:700,color:cat.color,flexShrink:0}}>
                    {ami.photo?<img src={ami.photo} alt="" style={{width:"100%",height:"100%",objectFit:"cover"}}/>:(ami.prenom[0]||"?").toUpperCase()}
                  </div>
                  <div style={{flex:1,minWidth:0}}>
                    <div style={{fontFamily:T.fontD,fontSize:15,fontWeight:700,color:T.text}}>{ami.prenom} {ami.nom}</div>
                    <div style={{display:"flex",gap:5,marginTop:2,flexWrap:"wrap"}}>
                      <Badge c={cat.color}>{cat.icon} {cat.l}</Badge>
                      {adresseFull(ami)&&<span style={{fontSize:11,color:T.muted}}>📍 {adresseFull(ami)}</span>}
                      {!adresseFull(ami)&&ami.ville&&<span style={{fontSize:11,color:T.muted}}>📍 {ami.ville}</span>}
                    </div>
                  </div>
                  <button onClick={e=>{e.stopPropagation();if(confirm(`Supprimer ${ami.prenom} ?`))setAmis(p=>p.filter(a=>a.id!==ami.id));}} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:14,opacity:0.5}}>🗑</button>
                </div>
              </div>
              {/* Infos */}
              <div style={{padding:"10px 16px"}}>
                {ami.email&&<div style={{fontSize:12,color:T.muted,marginBottom:3}}>✉️ {ami.email}</div>}
                {ami.tel&&<div style={{fontSize:12,color:T.muted,marginBottom:3}}>📞 {ami.tel}</div>}
                {prochainAnn!==null&&prochainAnn<=30&&<div style={{fontSize:11,color:T.warning,marginBottom:3}}>🎂 Anniversaire dans {prochainAnn}j</div>}
                {/* Réseaux sociaux */}
                {reseauxDispo.length>0&&(
                  <div style={{display:"flex",gap:5,marginTop:8,flexWrap:"wrap"}}>
                    {reseauxDispo.map(r=>{
                      const rs=RESEAUX_SOCIAUX.find(x=>x.id===r.id);
                      if(!rs)return null;
                      return (
                        <a key={r.id} href={rs.base+r.username} target="_blank" rel="noreferrer" onClick={e=>e.stopPropagation()}
                          title={`${rs.l} : @${r.username}`}
                          style={{display:"inline-flex",alignItems:"center",gap:4,background:rs.color+"18",border:`1px solid ${rs.color}44`,color:rs.color,borderRadius:6,padding:"3px 8px",textDecoration:"none",fontSize:11,fontWeight:600}}>
                          {rs.icon} <span style={{maxWidth:70,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>@{r.username}</span>
                        </a>
                      );
                    })}
                  </div>
                )}
                {ami.description&&<div style={{fontSize:11,color:T.muted,fontStyle:"italic",marginTop:8,lineHeight:1.6,overflow:"hidden",display:"-webkit-box",WebkitLineClamp:2,WebkitBoxOrient:"vertical"}}>{ami.description}</div>}
              </div>
            </Card>
          );
        })}
      </div>

      {/* Fiche détail ami */}
      {selAmi&&<AmiDetail ami={selAmi} amis={amis} setAmis={setAmis} onClose={()=>setSelected(null)}/>}

      {/* Modale ajout */}
      {showAdd&&<Modal title="👫 Nouvel ami" onClose={()=>setShowAdd(false)} width={600}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Prénom *"><Inp value={form.prenom} onChange={v=>setForm(f=>({...f,prenom:v}))} placeholder="Marie"/></F>
          <F label="Nom"><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Dupont"/></F>
          <F label="Catégorie"><Sel value={form.categorie} onChange={v=>setForm(f=>({...f,categorie:v}))}>{CATS_AMIS.map(c=><option key={c.id} value={c.id}>{c.icon} {c.l}</option>)}</Sel></F>
          <F label="Date de naissance"><Inp type="date" value={form.dateNaissance} onChange={v=>setForm(f=>({...f,dateNaissance:v}))}/></F>
          <F label="Email"><Inp type="email" value={form.email} onChange={v=>setForm(f=>({...f,email:v}))}/></F>
          <F label="Téléphone"><Inp value={form.tel} onChange={v=>setForm(f=>({...f,tel:v}))}/></F>
        </div>
        <F label="Rue / N° et voie"><Inp value={form.rue||""} onChange={v=>setForm(f=>({...f,rue:v}))} placeholder="12 allée des Roses"/></F>
        <div style={{display:"grid",gridTemplateColumns:"120px 1fr",gap:10,marginTop:4}}>
          <F label="Code postal"><Inp value={form.codePostal||""} onChange={v=>setForm(f=>({...f,codePostal:v}))} placeholder="33000"/></F>
          <F label="Ville"><Inp value={form.ville||""} onChange={v=>setForm(f=>({...f,ville:v}))} placeholder="Bordeaux"/></F>
        </div>
        <F label="Description"><Txt value={form.description} onChange={v=>setForm(f=>({...f,description:v}))} rows={2} placeholder="Comment vous vous êtes rencontrés..."/></F>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={save} disabled={!form.prenom}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: TRAVAIL & CARRIÈRE
// ═══════════════════════════════════════════════════════════════════════════════
const TYPE_CONTRAT=["CDI","CDD","Intérim","Alternance","Stage","Freelance","Fonctionnaire","Autre"];
const STATUT_CONGE=["Validé","En attente","Refusé"];

const Travail=({travail,setTravail})=>{
  const [tab,setTab]=useState("emploi");
  const [showAdd,setShowAdd]=useState(null);
  const [selFiche,setSelFiche]=useState(null);
  const [selPoste,setSelPoste]=useState(null);
  const fileRef=useRef();

  // ── Formulaires extraits au niveau composant (règle des hooks) ──
  const [ficheForm,setFicheForm]=useState({mois:"",salaireBrut:"",salaireNet:"",conges:"",note:""});
  const [congeForm,setCongeForm]=useState({type:"Congés payés",dateDebut:today(),dateFin:"",statut:"En attente",note:""});
  const [formationForm,setFormationForm]=useState({titre:"",organisme:"",dateDebut:"",dateFin:"",duree:"",cout:"",certification:"",note:""});
  const [posteForm,setPosteForm]=useState({poste:"",employeur:"",contrat:"CDI",dateDebut:"",dateFin:"",ville:"",salaire:"",note:""});

  const resetFicheForm=()=>setFicheForm({mois:"",salaireBrut:"",salaireNet:"",conges:"",note:""});
  const resetCongeForm=()=>setCongeForm({type:"Congés payés",dateDebut:today(),dateFin:"",statut:"En attente",note:""});
  const resetFormationForm=()=>setFormationForm({titre:"",organisme:"",dateDebut:"",dateFin:"",duree:"",cout:"",certification:"",note:""});
  const resetPosteForm=()=>setPosteForm({poste:"",employeur:"",contrat:"CDI",dateDebut:"",dateFin:"",ville:"",salaire:"",note:""});

  const emp=travail.employeurActuel||{};
  const updEmp=v=>setTravail(t=>({...t,employeurActuel:{...(t.employeurActuel||{}),...v}}));
  const addFiche=f=>setTravail(t=>({...t,fichesPaie:[...(t.fichesPaie||[]),{...f,id:uid()}]}));
  const delFiche=id=>setTravail(t=>({...t,fichesPaie:(t.fichesPaie||[]).filter(f=>f.id!==id)}));
  const addConge=c=>setTravail(t=>({...t,conges:[...(t.conges||[]),{...c,id:uid()}]}));
  const delConge=id=>setTravail(t=>({...t,conges:(t.conges||[]).filter(c=>c.id!==id)}));
  const addFormation=f=>setTravail(t=>({...t,formations:[...(t.formations||[]),{...f,id:uid()}]}));
  const addPosteHisto=p=>setTravail(t=>({...t,historique:[...(t.historique||[]),{...p,id:uid()}]}));
  const delPoste=id=>setTravail(t=>({...t,historique:(t.historique||[]).filter(p=>p.id!==id)}));

  const fichesPaie=travail.fichesPaie||[];
  const conges=travail.conges||[];
  const formations=travail.formations||[];
  const historique=travail.historique||[];
  const avantages=travail.avantages||{};

  const salaireNet=emp.salaireBrut?Math.round(parseFloat(emp.salaireBrut)*0.77):null;
  const congesValides=conges.filter(c=>c.statut==="Validé");
  const joursTotal=congesValides.reduce((s,c)=>{
    const d1=new Date(c.dateDebut),d2=new Date(c.dateFin);
    return s+Math.round((d2-d1)/86400000)+1;
  },0);
  const fichesByAn=fichesPaie.reduce((m,f)=>{
    const an=(f.mois||"").slice(0,4)||"?";
    if(!m[an])m[an]=[];m[an].push(f);return m;
  },{});

  // Upload fiche de paie — lit ficheForm depuis closure directe
  const handleFileFiche=e=>{
    const file=e.target.files[0];if(!file)return;
    // Reset input pour permettre re-upload du même fichier
    e.target.value="";
    const reader=new FileReader();
    reader.onload=ev=>{
      addFiche({...ficheForm,fichier:{nom:file.name,type:file.type,dataUrl:ev.target.result}});
      resetFicheForm();
      setShowAdd(null);
    };
    reader.readAsDataURL(file);
  };

  const TABS_T=[
    {id:"emploi",icon:"🏢",label:"Mon emploi"},
    {id:"fiches",icon:"📄",label:`Fiches de paie (${fichesPaie.length})`},
    {id:"conges",icon:"🏖️",label:`Congés (${congesValides.length})`},
    {id:"avantages",icon:"⭐",label:"Avantages"},
    {id:"formations",icon:"🎓",label:`Formations (${formations.length})`},
    {id:"historique",icon:"📋",label:`Carrière (${historique.length})`},
  ];

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>💼 Mon Travail</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>
            {emp.poste&&emp.employeur?`${emp.poste} chez ${emp.employeur}`:"Renseignez votre situation professionnelle"}
            {salaireNet&&<span style={{color:T.success,marginLeft:8}}>· ~{salaireNet.toLocaleString("fr-FR")} €/mois net</span>}
          </p>
        </div>
      </div>

      <Tabs tabs={TABS_T} active={tab} onChange={setTab}/>

      {/* ── EMPLOI ACTUEL ── */}
      {tab==="emploi"&&(
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14,marginTop:16}}>
          {/* Fiche employeur */}
          <Card>
            <Divider label="🏢 Employeur actuel"/>
            <div style={{display:"grid",gap:8}}>
              <F label="Employeur / Entreprise"><Inp value={emp.employeur||""} onChange={v=>updEmp({employeur:v})} placeholder="Société ABC"/></F>
              <F label="SIRET"><Inp value={emp.siret||""} onChange={v=>updEmp({siret:v})} placeholder="123 456 789 00012"/></F>
              <div style={{display:"grid",gridTemplateColumns:"1fr 120px",gap:8}}>
                <F label="Code postal"><Inp value={emp.codePostal||""} onChange={v=>updEmp({codePostal:v})} placeholder="33000"/></F>
                <F label="Ville"><Inp value={emp.ville||""} onChange={v=>updEmp({ville:v})} placeholder="Bordeaux"/></F>
              </div>
              <F label="Rue / Adresse"><Inp value={emp.rue||""} onChange={v=>updEmp({rue:v})} placeholder="12 avenue de la Gare"/></F>
              <F label="Site web"><Inp value={emp.site||""} onChange={v=>updEmp({site:v})} placeholder="https://..."/></F>
            </div>
          </Card>

          {/* Mon poste */}
          <Card>
            <Divider label="👤 Mon poste"/>
            <div style={{display:"grid",gap:8}}>
              <F label="Intitulé du poste"><Inp value={emp.poste||""} onChange={v=>updEmp({poste:v})} placeholder="Responsable commercial"/></F>
              <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
                <F label="Type de contrat"><Sel value={emp.contrat||""} onChange={v=>updEmp({contrat:v})}><option value="">—</option>{TYPE_CONTRAT.map(t=><option key={t}>{t}</option>)}</Sel></F>
                <F label="Date d'entrée"><Inp type="date" value={emp.dateEntree||""} onChange={v=>updEmp({dateEntree:v})}/></F>
              </div>
              <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
                <F label="Salaire brut mensuel (€)"><Inp type="number" value={emp.salaireBrut||""} onChange={v=>updEmp({salaireBrut:v})} placeholder="3000"/></F>
                <F label="Coefficient / Niveau"><Inp value={emp.coefficient||""} onChange={v=>updEmp({coefficient:v})} placeholder="Cadre N3"/></F>
              </div>
              <F label="Convention collective"><Inp value={emp.convention||""} onChange={v=>updEmp({convention:v})} placeholder="Métallurgie, Commerce..."/></F>
              {emp.dateEntree&&(()=>{
                const d=new Date(emp.dateEntree);
                const mois=Math.round((new Date()-d)/2629746000);
                const ans=Math.floor(mois/12);const rm=mois%12;
                return <div style={{padding:"8px 12px",background:T.accentDim,borderRadius:8,fontSize:12,color:T.accent}}>
                  🗓️ Ancienneté : <strong>{ans>0?`${ans} an${ans>1?"s":""} `:""}{ rm>0?`${rm} mois`:""}</strong>
                </div>;
              })()}
            </div>
          </Card>

          {/* Contact RH */}
          <Card>
            <Divider label="📞 Contact RH / Responsable"/>
            <div style={{display:"grid",gap:8}}>
              <F label="Nom du responsable RH"><Inp value={emp.rhNom||""} onChange={v=>updEmp({rhNom:v})} placeholder="Mme Dupont"/></F>
              <F label="Email RH"><Inp type="email" value={emp.rhEmail||""} onChange={v=>updEmp({rhEmail:v})}/></F>
              <F label="Téléphone RH"><Inp value={emp.rhTel||""} onChange={v=>updEmp({rhTel:v})}/></F>
              <F label="N° matricule employé"><Inp value={emp.matricule||""} onChange={v=>updEmp({matricule:v})} placeholder="EMP-00123"/></F>
            </div>
            {(emp.rhEmail||emp.rhTel)&&<ContactActions tel={emp.rhTel} email={emp.rhEmail}/>}
          </Card>

          {/* Infos clés */}
          <Card>
            <Divider label="📋 Informations clés"/>
            <div style={{display:"grid",gap:8}}>
              <F label="Jours de congés annuels"><Inp type="number" value={emp.congesAnnuels||""} onChange={v=>updEmp({congesAnnuels:v})} placeholder="25"/></F>
              <F label="RTT annuels"><Inp type="number" value={emp.rtt||""} onChange={v=>updEmp({rtt:v})} placeholder="12"/></F>
              <F label="Temps de travail"><Inp value={emp.tempsTravail||""} onChange={v=>updEmp({tempsTravail:v})} placeholder="35h / semaine"/></F>
              <F label="Lieu de travail"><Inp value={emp.lieuTravail||""} onChange={v=>updEmp({lieuTravail:v})} placeholder="Présentiel / Hybride / Télétravail"/></F>
              <F label="Note personnelle"><Txt value={emp.note||""} onChange={v=>updEmp({note:v})} rows={2}/></F>
            </div>
            {emp.salaireBrut&&(
              <div style={{marginTop:12,padding:"10px 14px",background:"#060a10",borderRadius:9}}>
                <div style={{fontSize:11,color:T.muted,marginBottom:6,fontWeight:600,textTransform:"uppercase",letterSpacing:"0.06em"}}>Estimations salariales</div>
                {[["Net mensuel estimé",`~${Math.round(emp.salaireBrut*0.77).toLocaleString("fr-FR")} €`,T.success],["Brut annuel",`${Math.round(emp.salaireBrut*12).toLocaleString("fr-FR")} €`,T.accent],["Net annuel estimé",`~${Math.round(emp.salaireBrut*0.77*12).toLocaleString("fr-FR")} €`,T.success]].map(([l,v,c])=>(
                  <div key={l} style={{display:"flex",justifyContent:"space-between",fontSize:12,padding:"3px 0",borderBottom:`1px solid ${T.border}`}}>
                    <span style={{color:T.muted}}>{l}</span><span style={{color:c,fontWeight:700}}>{v}</span>
                  </div>
                ))}
              </div>
            )}
          </Card>
        </div>
      )}

      {/* ── FICHES DE PAIE ── */}
      {tab==="fiches"&&(
        <div style={{marginTop:16}}>
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:14}}>
            <div style={{fontSize:13,color:T.muted}}>{fichesPaie.length} fiche{fichesPaie.length!==1?"s":""} archivée{fichesPaie.length!==1?"s":""}</div>
            <Btn onClick={()=>setShowAdd({type:"fiche"})}>+ Fiche de paie</Btn>
          </div>
          {fichesPaie.length===0&&<EmptyState icon="📄" text="Archivez vos fiches de paie — elles seront classées par année automatiquement."/>}
          {Object.entries(fichesByAn).sort(([a],[b])=>b-a).map(([an,fiches])=>(
            <div key={an} style={{marginBottom:20}}>
              <div style={{fontSize:12,color:T.accent,fontWeight:700,textTransform:"uppercase",letterSpacing:"0.08em",marginBottom:8}}>{an} · {fiches.length} fiche{fiches.length>1?"s":""}</div>
              <div style={{display:"grid",gap:6}}>
                {fiches.sort((a,b)=>b.mois?.localeCompare(a.mois||"")||0).map(f=>{
                  const moisLabel=f.mois?new Date(f.mois+"-01").toLocaleDateString("fr-FR",{month:"long",year:"numeric"}):"";
                  return (
                    <div key={f.id} style={{display:"flex",alignItems:"center",gap:12,padding:"10px 14px",background:"#060a10",borderRadius:10,border:`1px solid ${T.border}`}}>
                      <div style={{fontSize:24,flexShrink:0}}>📄</div>
                      <div style={{flex:1}}>
                        <div style={{fontSize:13,fontWeight:600,color:T.text,textTransform:"capitalize"}}>{moisLabel}</div>
                        <div style={{display:"flex",gap:10,marginTop:2,fontSize:11,color:T.muted}}>
                          {f.salaireBrut&&<span>Brut: <strong style={{color:T.text}}>{parseFloat(f.salaireBrut).toLocaleString("fr-FR")} €</strong></span>}
                          {f.salaireNet&&<span>Net: <strong style={{color:T.success}}>{parseFloat(f.salaireNet).toLocaleString("fr-FR")} €</strong></span>}
                          {f.conges&&<span>CP: {f.conges}j</span>}
                          {f.fichier&&<span style={{color:T.accent}}>📎 {f.fichier.nom}</span>}
                        </div>
                      </div>
                      <div style={{display:"flex",gap:6}}>
                        {f.fichier?.dataUrl&&(
                          <a href={f.fichier.dataUrl} download={f.fichier.nom} style={{background:T.accentDim,color:T.accent,border:`1px solid rgba(240,165,0,0.3)`,borderRadius:7,padding:"4px 10px",textDecoration:"none",fontSize:11,fontWeight:600}}>⬇ Télécharger</a>
                        )}
                        {f.fichier?.dataUrl&&f.fichier.type==="application/pdf"&&(
                          <button onClick={()=>setSelFiche(f)} style={{background:"rgba(239,68,68,0.1)",color:"#ef4444",border:"1px solid rgba(239,68,68,0.3)",borderRadius:7,padding:"4px 10px",cursor:"pointer",fontFamily:T.font,fontSize:11}}>👁 Voir</button>
                        )}
                        <button onClick={()=>delFiche(f.id)} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:14,opacity:0.5}}>🗑</button>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          ))}
        </div>
      )}

      {/* ── CONGÉS ── */}
      {tab==="conges"&&(
        <div style={{marginTop:16}}>
          {/* Compteurs */}
          <div style={{display:"grid",gridTemplateColumns:"repeat(4,1fr)",gap:10,marginBottom:18}}>
            {[
              ["Droit annuel",emp.congesAnnuels?`${emp.congesAnnuels}j`:"—",T.accent],
              ["Jours pris",`${joursTotal}j`,T.warning],
              ["Solde estimé",emp.congesAnnuels?`${Math.max(0,parseInt(emp.congesAnnuels)-joursTotal)}j`:"—",T.success],
              ["RTT",emp.rtt?`${emp.rtt}j`:"—",T.info],
            ].map(([l,v,c])=>(
              <div key={l} style={{background:"#060a10",borderRadius:10,padding:"12px 16px",textAlign:"center"}}>
                <div style={{fontSize:10,color:T.muted,textTransform:"uppercase",marginBottom:4,letterSpacing:"0.06em"}}>{l}</div>
                <div style={{fontFamily:T.fontD,fontSize:22,fontWeight:700,color:c}}>{v}</div>
              </div>
            ))}
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",marginBottom:12}}>
            <Btn onClick={()=>setShowAdd({type:"conge"})}>+ Congé / Absence</Btn>
          </div>
          {conges.length===0&&<EmptyState icon="🏖️" text="Enregistrez vos congés, RTT, arrêts maladie..."/>}
          <div style={{display:"grid",gap:6}}>
            {conges.sort((a,b)=>b.dateDebut?.localeCompare(a.dateDebut||"")||0).map(c=>{
              const d1=new Date(c.dateDebut),d2=new Date(c.dateFin);
              const j=c.dateFin?Math.round((d2-d1)/86400000)+1:1;
              const statColor=c.statut==="Validé"?T.success:c.statut==="Refusé"?T.danger:T.warning;
              return (
                <div key={c.id} style={{display:"flex",alignItems:"center",gap:12,padding:"11px 16px",background:"#060a10",borderRadius:10,border:`1px solid ${T.border}`}}>
                  <div style={{fontSize:22,flexShrink:0}}>{c.type==="RTT"?"📅":c.type==="Maladie"?"🏥":c.type==="Maternité/Paternité"?"👶":"🏖️"}</div>
                  <div style={{flex:1}}>
                    <div style={{fontSize:13,fontWeight:600,color:T.text}}>{c.type||"Congés payés"} · <span style={{color:T.accent}}>{j} jour{j>1?"s":""}</span></div>
                    <div style={{fontSize:11,color:T.muted,marginTop:2}}>
                      {fmt(c.dateDebut)}{c.dateFin&&c.dateFin!==c.dateDebut?` → ${fmt(c.dateFin)}`:""}{c.note&&` · ${c.note}`}
                    </div>
                  </div>
                  <Badge c={statColor}>{c.statut||"En attente"}</Badge>
                  <button onClick={()=>delConge(c.id)} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:14,opacity:0.5}}>🗑</button>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {/* ── AVANTAGES ── */}
      {tab==="avantages"&&(
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14,marginTop:16}}>
          {[
            {key:"mutuelle",icon:"🏥",label:"Mutuelle d'entreprise",fields:[{k:"nom",l:"Organisme"},{k:"tauxEmployeur",l:"Part employeur (%)"},{k:"tauxSalarie",l:"Part salarié (%)"},{k:"cotisation",l:"Cotisation mensuelle (€)"}]},
            {key:"ticketsResto",icon:"🍽️",label:"Tickets restaurant",fields:[{k:"valeurFace",l:"Valeur faciale (€)"},{k:"partEmployeur",l:"Part employeur (€)"},{k:"nbParMois",l:"Nombre / mois"}]},
            {key:"epargne",icon:"💰",label:"Épargne salariale",fields:[{k:"type",l:"Type (PEE, PERCO...)"},{k:"abondement",l:"Abondement employeur (%)"},{k:"montant",l:"Versement mensuel (€)"}]},
            {key:"transport",icon:"🚇",label:"Remboursement transport",fields:[{k:"type",l:"Type (Navigo, km...)"},{k:"taux",l:"Taux remboursement (%)"},{k:"montant",l:"Montant mensuel (€)"}]},
            {key:"voiture",icon:"🚗",label:"Véhicule de fonction",fields:[{k:"modele",l:"Modèle"},{k:"immat",l:"Immatriculation"},{k:"avantageNature",l:"Avantage en nature (€/mois)"}]},
            {key:"teletravail",icon:"🏠",label:"Télétravail",fields:[{k:"joursParSemaine",l:"Jours / semaine"},{k:"indemnite",l:"Indemnité (€/jour)"},{k:"equipement",l:"Équipement fourni"}]},
          ].map(av=>(
            <Card key={av.key}>
              <Divider label={`${av.icon} ${av.label}`}/>
              <div style={{display:"grid",gap:7}}>
                {av.fields.map(field=>(
                  <F key={field.k} label={field.l}>
                    <Inp value={(avantages[av.key]||{})[field.k]||""} onChange={v=>setTravail(t=>({...t,avantages:{...t.avantages,[av.key]:{...(t.avantages?.[av.key]||{}),[field.k]:v}}}))}/>
                  </F>
                ))}
              </div>
            </Card>
          ))}
        </div>
      )}

      {/* ── FORMATIONS ── */}
      {tab==="formations"&&(
        <div style={{marginTop:16}}>
          <div style={{display:"flex",justifyContent:"flex-end",marginBottom:12}}>
            <Btn onClick={()=>setShowAdd({type:"formation"})}>+ Formation</Btn>
          </div>
          {formations.length===0&&<EmptyState icon="🎓" text="Enregistrez vos formations professionnelles, certifications, DIF/CPF..."/>}
          <div style={{display:"grid",gap:8}}>
            {formations.map(f=>(
              <div key={f.id} style={{display:"flex",gap:12,padding:"12px 16px",background:"#060a10",borderRadius:10,border:`1px solid ${T.border}`}}>
                <div style={{fontSize:24}}>🎓</div>
                <div style={{flex:1}}>
                  <div style={{fontSize:13,fontWeight:600,color:T.text}}>{f.titre}</div>
                  <div style={{display:"flex",gap:10,marginTop:3,flexWrap:"wrap",fontSize:11,color:T.muted}}>
                    {f.organisme&&<span>🏫 {f.organisme}</span>}
                    {f.dateDebut&&<span>📅 {fmt(f.dateDebut)}{f.dateFin&&` → ${fmt(f.dateFin)}`}</span>}
                    {f.duree&&<span>⏱ {f.duree}h</span>}
                    {f.cout&&<span>💶 {f.cout} €</span>}
                    {f.certification&&<Badge c={T.success}>🏆 {f.certification}</Badge>}
                  </div>
                  {f.note&&<div style={{fontSize:11,color:T.muted,fontStyle:"italic",marginTop:4}}>{f.note}</div>}
                </div>
                <button onClick={()=>setTravail(t=>({...t,formations:t.formations.filter(x=>x.id!==f.id)}))} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:14,opacity:0.5}}>🗑</button>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* ── HISTORIQUE CARRIÈRE ── */}
      {tab==="historique"&&(
        <div style={{marginTop:16}}>
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:14}}>
            <div style={{fontSize:13,color:T.muted}}>Tous vos postes et employeurs passés</div>
            <Btn onClick={()=>setShowAdd({type:"poste"})}>+ Poste passé</Btn>
          </div>
          {historique.length===0&&<EmptyState icon="📋" text="Reconstituez votre carrière — utile pour vos entretiens, votre CV et votre retraite."/>}
          <div style={{position:"relative"}}>
            {historique.sort((a,b)=>b.dateDebut?.localeCompare(a.dateDebut||"")||0).map((p,i)=>{
              const d1=new Date(p.dateDebut);
              const d2=p.dateFin?new Date(p.dateFin):new Date();
              const mois=Math.round((d2-d1)/2629746000);
              return (
                <div key={p.id} style={{display:"flex",gap:14,marginBottom:16}}>
                  <div style={{display:"flex",flexDirection:"column",alignItems:"center",width:24,flexShrink:0}}>
                    <div style={{width:14,height:14,borderRadius:7,background:T.accent,border:`2px solid ${T.bg}`,marginTop:4,flexShrink:0}}/>
                    {i<historique.length-1&&<div style={{width:2,flex:1,background:T.border,marginTop:4}}/>}
                  </div>
                  <div style={{flex:1,padding:"12px 16px",background:"#060a10",borderRadius:10,border:`1px solid ${T.border}`,marginBottom:4}}>
                    <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                      <div>
                        <div style={{fontFamily:T.fontD,fontSize:14,color:T.text,fontWeight:700}}>{p.poste}</div>
                        <div style={{fontSize:12,color:T.accent,marginTop:2}}>{p.employeur}</div>
                      </div>
                      <div style={{textAlign:"right",flexShrink:0,marginLeft:10}}>
                        <div style={{fontSize:11,color:T.muted}}>{p.dateDebut&&fmt(p.dateDebut)} → {p.dateFin?fmt(p.dateFin):"Aujourd'hui"}</div>
                        <div style={{fontSize:11,color:T.muted}}>
                          {Math.floor(mois/12)>0?`${Math.floor(mois/12)} an${Math.floor(mois/12)>1?"s":""} `:""}
                          {mois%12>0?`${mois%12} mois`:""}
                        </div>
                      </div>
                    </div>
                    <div style={{display:"flex",gap:8,marginTop:6,flexWrap:"wrap"}}>
                      {p.contrat&&<Badge c={T.muted}>{p.contrat}</Badge>}
                      {p.ville&&<span style={{fontSize:11,color:T.muted}}>📍 {p.ville}</span>}
                      {p.salaire&&<span style={{fontSize:11,color:T.success}}>💶 {p.salaire} € brut</span>}
                    </div>
                    {p.note&&<div style={{fontSize:11,color:T.muted,fontStyle:"italic",marginTop:6}}>{p.note}</div>}
                  </div>
                  <button onClick={()=>delPoste(p.id)} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:14,opacity:0.5,alignSelf:"flex-start",marginTop:8}}>🗑</button>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {/* ── MODALES ── */}
      {showAdd?.type==="fiche"&&(
        <Modal title="📄 Ajouter une fiche de paie" onClose={()=>{setShowAdd(null);resetFicheForm();}}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Mois *"><Inp type="month" value={ficheForm.mois} onChange={v=>setFicheForm(f=>({...f,mois:v}))}/></F>
            <F label="Salaire brut (€)"><Inp type="number" value={ficheForm.salaireBrut} onChange={v=>setFicheForm(f=>({...f,salaireBrut:v}))}/></F>
            <F label="Salaire net (€)"><Inp type="number" value={ficheForm.salaireNet} onChange={v=>setFicheForm(f=>({...f,salaireNet:v}))}/></F>
            <F label="CP acquis (jours)"><Inp type="number" value={ficheForm.conges} onChange={v=>setFicheForm(f=>({...f,conges:v}))}/></F>
          </div>
          <F label="Note" style={{marginTop:8}}><Inp value={ficheForm.note} onChange={v=>setFicheForm(f=>({...f,note:v}))} placeholder="Prime, heures sup, mois exceptionnel..."/></F>
          <div style={{marginTop:12,padding:"12px 14px",background:"#060a10",borderRadius:8,border:`1px dashed ${T.border}`,cursor:"pointer",textAlign:"center"}}
            onClick={()=>fileRef.current?.click()}>
            <div style={{fontSize:24,marginBottom:4}}>📎</div>
            <div style={{fontSize:12,color:T.muted}}>Cliquer pour joindre le PDF ou une image de la fiche</div>
            <div style={{fontSize:10,color:T.muted,marginTop:2}}>Le fichier sera sauvegardé avec les données ci-dessus</div>
          </div>
          <input ref={fileRef} type="file" accept=".pdf,image/*" style={{display:"none"}} onChange={handleFileFiche}/>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>{setShowAdd(null);resetFicheForm();}}>Annuler</Btn>
            <Btn onClick={()=>{addFiche(ficheForm);resetFicheForm();setShowAdd(null);}} disabled={!ficheForm.mois}>💾 Enregistrer sans fichier</Btn>
          </div>
        </Modal>
      )}

      {showAdd?.type==="conge"&&(
        <Modal title="🏖️ Congé / Absence" onClose={()=>{setShowAdd(null);resetCongeForm();}}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Type"><Sel value={congeForm.type} onChange={v=>setCongeForm(f=>({...f,type:v}))}>{["Congés payés","RTT","Maladie","Maternité/Paternité","Sans solde","Récupération","Autre"].map(t=><option key={t}>{t}</option>)}</Sel></F>
            <F label="Statut"><Sel value={congeForm.statut} onChange={v=>setCongeForm(f=>({...f,statut:v}))}>{STATUT_CONGE.map(s=><option key={s}>{s}</option>)}</Sel></F>
            <F label="Date début"><Inp type="date" value={congeForm.dateDebut} onChange={v=>setCongeForm(f=>({...f,dateDebut:v}))}/></F>
            <F label="Date fin"><Inp type="date" value={congeForm.dateFin} onChange={v=>setCongeForm(f=>({...f,dateFin:v}))}/></F>
          </div>
          <F label="Note" style={{marginTop:8}}><Inp value={congeForm.note} onChange={v=>setCongeForm(f=>({...f,note:v}))} placeholder="Raison, motif..."/></F>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>{setShowAdd(null);resetCongeForm();}}>Annuler</Btn>
            <Btn onClick={()=>{addConge(congeForm);resetCongeForm();setShowAdd(null);}}>💾 Enregistrer</Btn>
          </div>
        </Modal>
      )}

      {showAdd?.type==="formation"&&(
        <Modal title="🎓 Formation professionnelle" onClose={()=>{setShowAdd(null);resetFormationForm();}}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Intitulé *" style={{gridColumn:"1/-1"}}><Inp value={formationForm.titre} onChange={v=>setFormationForm(f=>({...f,titre:v}))} placeholder="React Advanced, Excel VBA..."/></F>
            <F label="Organisme"><Inp value={formationForm.organisme} onChange={v=>setFormationForm(f=>({...f,organisme:v}))} placeholder="AFPA, CPF, interne..."/></F>
            <F label="Certification obtenue"><Inp value={formationForm.certification} onChange={v=>setFormationForm(f=>({...f,certification:v}))} placeholder="TOSA, QSSE..."/></F>
            <F label="Date début"><Inp type="date" value={formationForm.dateDebut} onChange={v=>setFormationForm(f=>({...f,dateDebut:v}))}/></F>
            <F label="Date fin"><Inp type="date" value={formationForm.dateFin} onChange={v=>setFormationForm(f=>({...f,dateFin:v}))}/></F>
            <F label="Durée (heures)"><Inp type="number" value={formationForm.duree} onChange={v=>setFormationForm(f=>({...f,duree:v}))}/></F>
            <F label="Coût (€)"><Inp type="number" value={formationForm.cout} onChange={v=>setFormationForm(f=>({...f,cout:v}))}/></F>
          </div>
          <F label="Note" style={{marginTop:8}}><Txt value={formationForm.note} onChange={v=>setFormationForm(f=>({...f,note:v}))} rows={2}/></F>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>{setShowAdd(null);resetFormationForm();}}>Annuler</Btn>
            <Btn onClick={()=>{addFormation(formationForm);resetFormationForm();setShowAdd(null);}} disabled={!formationForm.titre}>💾 Enregistrer</Btn>
          </div>
        </Modal>
      )}

      {showAdd?.type==="poste"&&(
        <Modal title="📋 Poste passé" onClose={()=>{setShowAdd(null);resetPosteForm();}}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Intitulé du poste *"><Inp value={posteForm.poste} onChange={v=>setPosteForm(f=>({...f,poste:v}))} placeholder="Développeur web"/></F>
            <F label="Employeur *"><Inp value={posteForm.employeur} onChange={v=>setPosteForm(f=>({...f,employeur:v}))} placeholder="Société XYZ"/></F>
            <F label="Type de contrat"><Sel value={posteForm.contrat} onChange={v=>setPosteForm(f=>({...f,contrat:v}))}>{TYPE_CONTRAT.map(t=><option key={t}>{t}</option>)}</Sel></F>
            <F label="Ville"><Inp value={posteForm.ville} onChange={v=>setPosteForm(f=>({...f,ville:v}))}/></F>
            <F label="Date début"><Inp type="date" value={posteForm.dateDebut} onChange={v=>setPosteForm(f=>({...f,dateDebut:v}))}/></F>
            <F label="Date fin (vide = présent)"><Inp type="date" value={posteForm.dateFin} onChange={v=>setPosteForm(f=>({...f,dateFin:v}))}/></F>
            <F label="Salaire brut mensuel (€)" style={{gridColumn:"1/-1"}}><Inp type="number" value={posteForm.salaire} onChange={v=>setPosteForm(f=>({...f,salaire:v}))}/></F>
          </div>
          <F label="Note / Missions principales" style={{marginTop:8}}><Txt value={posteForm.note} onChange={v=>setPosteForm(f=>({...f,note:v}))} rows={2} placeholder="Missions, technologies, réalisations..."/></F>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>{setShowAdd(null);resetPosteForm();}}>Annuler</Btn>
            <Btn onClick={()=>{addPosteHisto(posteForm);resetPosteForm();setShowAdd(null);}} disabled={!posteForm.poste||!posteForm.employeur}>💾 Enregistrer</Btn>
          </div>
        </Modal>
      )}

      {selFiche&&(
        <Modal title={`📄 ${selFiche.fichier?.nom||"Fiche de paie"}`} onClose={()=>setSelFiche(null)} width={700}>
          {selFiche.fichier?.type==="application/pdf"
            ?<PdfViewer dataUrl={selFiche.fichier.dataUrl}/>
            :<img src={selFiche.fichier?.dataUrl} alt="" style={{width:"100%",borderRadius:8}}/>
          }
        </Modal>
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: ABONNEMENTS & RÉCURRENTS
// ═══════════════════════════════════════════════════════════════════════════════
const CATS_ABO=[
  {id:"streaming",l:"Streaming",icon:"🎬",color:"#ef4444"},
  {id:"musique",l:"Musique",icon:"🎵",color:"#a78bfa"},
  {id:"internet",l:"Internet / Téléphonie",icon:"📡",color:"#38bdf8"},
  {id:"sport",l:"Sport / Fitness",icon:"💪",color:"#34d399"},
  {id:"presse",l:"Presse / Lecture",icon:"📰",color:"#f0a500"},
  {id:"logiciel",l:"Logiciels / Cloud",icon:"☁️",color:"#60a5fa"},
  {id:"assurance",l:"Assurances",icon:"🛡️",color:"#fb923c"},
  {id:"autre",l:"Autre",icon:"📦",color:"#94a3b8"},
];
const Abonnements=({abonnements,setAbonnements})=>{
  const [showAdd,setShowAdd]=useState(false);
  const [search,setSearch]=useState("");
  const [catFilter,setCatFilter]=useState("all");
  const EMPTY={nom:"",categorie:"streaming",montant:"",periodicite:"mensuel",dateDebut:"",dateRenouvellement:"",note:"",actif:true};
  const [form,setForm]=useState({...EMPTY});
  const filtered=abonnements.filter(a=>{
    if(catFilter!=="all"&&a.categorie!==catFilter)return false;
    if(search&&!a.nom.toLowerCase().includes(search.toLowerCase()))return false;
    return true;
  });
  const actifs=abonnements.filter(a=>a.actif);
  const totalMensuel=actifs.reduce((s,a)=>{
    const m=parseFloat(a.montant)||0;
    return s+(a.periodicite==="annuel"?m/12:a.periodicite==="trimestriel"?m/3:m);
  },0);
  const toggleActif=id=>setAbonnements(p=>p.map(a=>a.id===id?{...a,actif:!a.actif}:a));
  const del=id=>setAbonnements(p=>p.filter(a=>a.id!==id));
  const save=()=>{setAbonnements(p=>[...p,{...form,id:uid()}]);setShowAdd(false);setForm({...EMPTY});};
  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🔌 Abonnements & Récurrents</h1>
          <p style={{color:T.muted,fontSize:13,marginTop:3}}>{actifs.length} actif{actifs.length>1?"s":""} · <span style={{color:T.danger,fontWeight:700}}>{fmtAmt(totalMensuel)}/mois</span> · <span style={{color:T.warning}}>{fmtAmt(totalMensuel*12)}/an</span></p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Abonnement</Btn>
      </div>
      {/* KPIs */}
      <div style={{display:"grid",gridTemplateColumns:"repeat(4,1fr)",gap:10,marginBottom:18}}>
        {CATS_ABO.map(cat=>{
          const n=actifs.filter(a=>a.categorie===cat.id);
          if(n.length===0)return null;
          const total=n.reduce((s,a)=>{const m=parseFloat(a.montant)||0;return s+(a.periodicite==="annuel"?m/12:a.periodicite==="trimestriel"?m/3:m);},0);
          return <div key={cat.id} style={{background:"#060a10",borderRadius:10,padding:"10px 14px",border:`1px solid ${cat.color}33`}}>
            <div style={{fontSize:11,color:cat.color,fontWeight:700}}>{cat.icon} {cat.l}</div>
            <div style={{fontFamily:T.fontD,fontSize:18,color:T.text,marginTop:4}}>{fmtAmt(total)}<span style={{fontSize:11,color:T.muted}}>/mois</span></div>
            <div style={{fontSize:10,color:T.muted}}>{n.length} abonnement{n.length>1?"s":""}</div>
          </div>;
        }).filter(Boolean)}
      </div>
      <div style={{display:"flex",gap:8,marginBottom:14,flexWrap:"wrap"}}>
        <Inp value={search} onChange={setSearch} placeholder="🔍 Rechercher..." style={{maxWidth:200}}/>
        <button onClick={()=>setCatFilter("all")} style={{padding:"5px 12px",borderRadius:7,border:`1px solid ${catFilter==="all"?T.accent:T.border}`,background:catFilter==="all"?T.accentDim:"transparent",color:catFilter==="all"?T.accent:T.muted,fontSize:12,cursor:"pointer",fontFamily:T.font}}>Tous</button>
        {CATS_ABO.map(c=><button key={c.id} onClick={()=>setCatFilter(c.id)} style={{padding:"5px 10px",borderRadius:7,border:`1px solid ${catFilter===c.id?c.color:T.border}`,background:catFilter===c.id?c.color+"22":"transparent",color:catFilter===c.id?c.color:T.muted,fontSize:11,cursor:"pointer",fontFamily:T.font}}>{c.icon}</button>)}
      </div>
      <div style={{display:"grid",gap:6}}>
        {filtered.length===0&&<EmptyState icon="🔌" text="Ajoutez vos abonnements pour suivre vos dépenses récurrentes."/>}
        {filtered.map(a=>{
          const cat=CATS_ABO.find(c=>c.id===a.categorie)||CATS_ABO[7];
          const mMensuel=parseFloat(a.montant)?(a.periodicite==="annuel"?parseFloat(a.montant)/12:a.periodicite==="trimestriel"?parseFloat(a.montant)/3:parseFloat(a.montant)):0;
          const alertRenouv=a.dateRenouvellement&&daysFrom(a.dateRenouvellement)<=30&&daysFrom(a.dateRenouvellement)>=0;
          return <div key={a.id} style={{display:"flex",alignItems:"center",gap:12,padding:"11px 16px",background:a.actif?"#060a10":"#0a0a0a",borderRadius:10,border:`1px solid ${alertRenouv?"rgba(240,165,0,0.4)":T.border}`,opacity:a.actif?1:0.5}}>
            <div style={{width:38,height:38,borderRadius:10,background:cat.color+"22",display:"flex",alignItems:"center",justifyContent:"center",fontSize:18,flexShrink:0}}>{cat.icon}</div>
            <div style={{flex:1}}>
              <div style={{fontSize:13,fontWeight:700,color:T.text}}>{a.nom}</div>
              <div style={{fontSize:11,color:T.muted,marginTop:1}}>
                <span style={{color:cat.color}}>{cat.l}</span>
                {a.dateRenouvellement&&<span style={{marginLeft:8}}>{alertRenouv?<span style={{color:T.warning}}>⚠️ Renouvellement dans {daysFrom(a.dateRenouvellement)}j</span>:<span>🗓️ {fmt(a.dateRenouvellement)}</span>}</span>}
                {a.note&&<span style={{marginLeft:8,fontStyle:"italic"}}>{a.note}</span>}
              </div>
            </div>
            <div style={{textAlign:"right",flexShrink:0}}>
              <div style={{fontFamily:T.fontD,fontSize:15,fontWeight:700,color:a.actif?T.danger:T.muted}}>{a.periodicite==="mensuel"?fmtAmt(a.montant):fmtAmt(a.montant)}</div>
              <div style={{fontSize:10,color:T.muted}}>{a.periodicite}{a.periodicite!=="mensuel"&&<span> · ~{fmtAmt(mMensuel)}/mois</span>}</div>
            </div>
            <div style={{display:"flex",gap:6,flexShrink:0}}>
              <button onClick={()=>toggleActif(a.id)} title={a.actif?"Désactiver":"Réactiver"} style={{background:a.actif?"rgba(34,197,94,0.15)":"#1a1a2a",border:`1px solid ${a.actif?T.success:T.border}`,color:a.actif?T.success:T.muted,borderRadius:7,padding:"4px 8px",cursor:"pointer",fontSize:12}}>{a.actif?"✓ Actif":"Inactif"}</button>
              <button onClick={()=>del(a.id)} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:13,opacity:0.5}}>🗑</button>
            </div>
          </div>;
        })}
      </div>
      {showAdd&&<Modal title="🔌 Nouvel abonnement" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Nom *" style={{gridColumn:"1/-1"}}><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Netflix, Orange, Spotify..."/></F>
          <F label="Catégorie"><Sel value={form.categorie} onChange={v=>setForm(f=>({...f,categorie:v}))}>{CATS_ABO.map(c=><option key={c.id} value={c.id}>{c.icon} {c.l}</option>)}</Sel></F>
          <F label="Périodicité"><Sel value={form.periodicite} onChange={v=>setForm(f=>({...f,periodicite:v}))}><option value="mensuel">Mensuel</option><option value="trimestriel">Trimestriel</option><option value="annuel">Annuel</option></Sel></F>
          <F label="Montant (€)"><Inp type="number" value={form.montant} onChange={v=>setForm(f=>({...f,montant:v}))} placeholder="9.99"/></F>
          <F label="Date de début"><Inp type="date" value={form.dateDebut} onChange={v=>setForm(f=>({...f,dateDebut:v}))}/></F>
          <F label="Prochain renouvellement" style={{gridColumn:"1/-1"}}><Inp type="date" value={form.dateRenouvellement} onChange={v=>setForm(f=>({...f,dateRenouvellement:v}))}/></F>
          <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} placeholder="Compte partagé, sans engagement..."/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={save} disabled={!form.nom||!form.montant}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: GARANTIES & SAV
// ═══════════════════════════════════════════════════════════════════════════════
const CATS_GAR=[
  {id:"electromenager",l:"Électroménager",icon:"🏠",color:"#38bdf8"},
  {id:"hifi",l:"HiFi / TV / Son",icon:"📺",color:"#a78bfa"},
  {id:"informatique",l:"Informatique",icon:"💻",color:"#34d399"},
  {id:"telephone",l:"Téléphone",icon:"📱",color:"#f0a500"},
  {id:"vehicule",l:"Véhicule",icon:"🚗",color:"#fb923c"},
  {id:"jardinage",l:"Jardinage / Bricolage",icon:"🌿",color:"#22c55e"},
  {id:"autre",l:"Autre",icon:"📦",color:"#94a3b8"},
];
const Garanties=({garanties,setGaranties})=>{
  const [showAdd,setShowAdd]=useState(false);
  const [search,setSearch]=useState("");
  const EMPTY={nom:"",categorie:"electromenager",marque:"",modele:"",numeroSerie:"",dateAchat:"",dureeGarantie:"",finGarantie:"",magasin:"",prix:"",note:"",docs:[]};
  const [form,setForm]=useState({...EMPTY});
  const save=()=>{setGaranties(p=>[...p,{...form,id:uid()}]);setShowAdd(false);setForm({...EMPTY});};
  const filtered=garanties.filter(g=>!search||g.nom.toLowerCase().includes(search.toLowerCase())||g.marque?.toLowerCase().includes(search.toLowerCase()));
  const now=new Date();
  const enCours=garanties.filter(g=>{if(!g.finGarantie)return false;return new Date(g.finGarantie)>=now;});
  const expirees=garanties.filter(g=>g.finGarantie&&new Date(g.finGarantie)<now);
  const bientotExp=enCours.filter(g=>daysFrom(g.finGarantie)<=90);
  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🔧 Garanties & SAV</h1>
          <p style={{color:T.muted,fontSize:13,marginTop:3}}>{garanties.length} produit{garanties.length>1?"s":""} · {enCours.length} garantie{enCours.length>1?"s":""} active{enCours.length>1?"s":""} · {bientotExp.length>0&&<span style={{color:T.warning}}>⚠️ {bientotExp.length} expire bientôt</span>}</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Produit</Btn>
      </div>
      {bientotExp.length>0&&<div style={{padding:"10px 16px",background:"rgba(240,165,0,0.08)",border:"1px solid rgba(240,165,0,0.25)",borderRadius:10,marginBottom:16,fontSize:12,color:T.warning}}>
        ⚠️ Garanties expirant dans les 90 jours : {bientotExp.map(g=><strong key={g.id} style={{marginRight:8}}>{g.nom} ({daysFrom(g.finGarantie)}j)</strong>)}
      </div>}
      <Inp value={search} onChange={setSearch} placeholder="🔍 Rechercher..." style={{maxWidth:260,marginBottom:14}}/>
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(300px,1fr))",gap:12}}>
        {filtered.length===0&&<EmptyState icon="🔧" text="Enregistrez vos appareils et leur garantie pour ne plus rien perdre."/>}
        {filtered.map(g=>{
          const cat=CATS_GAR.find(c=>c.id===g.categorie)||CATS_GAR[6];
          const expired=g.finGarantie&&new Date(g.finGarantie)<now;
          const jours=g.finGarantie&&daysFrom(g.finGarantie);
          const statColor=expired?T.muted:jours<=30?T.danger:jours<=90?T.warning:T.success;
          return <Card key={g.id}>
            <div style={{display:"flex",gap:10,alignItems:"flex-start"}}>
              <div style={{width:40,height:40,borderRadius:10,background:cat.color+"22",display:"flex",alignItems:"center",justifyContent:"center",fontSize:20,flexShrink:0}}>{cat.icon}</div>
              <div style={{flex:1,minWidth:0}}>
                <div style={{fontSize:14,fontWeight:700,color:T.text}}>{g.nom}</div>
                {g.marque&&<div style={{fontSize:11,color:T.muted}}>{g.marque}{g.modele&&` · ${g.modele}`}</div>}
                <div style={{display:"flex",gap:8,marginTop:6,flexWrap:"wrap"}}>
                  {g.dateAchat&&<span style={{fontSize:10,color:T.muted}}>🛒 {fmt(g.dateAchat)}{g.prix&&` · ${fmtAmt(g.prix)}`}</span>}
                </div>
                {g.finGarantie&&<div style={{marginTop:6,fontSize:11,fontWeight:600,color:statColor}}>
                  {expired?"✗ Garantie expirée":"🛡️ Garantie jusqu'au"} {fmt(g.finGarantie)}
                  {!expired&&jours!==null&&<span style={{color:statColor}}> · {jours}j restant{jours>1?"s":""}</span>}
                </div>}
                {g.note&&<div style={{fontSize:10,color:T.muted,fontStyle:"italic",marginTop:4}}>{g.note}</div>}
              </div>
              <button onClick={()=>setGaranties(p=>p.filter(x=>x.id!==g.id))} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:13,opacity:0.5}}>🗑</button>
            </div>
          </Card>;
        })}
      </div>
      {showAdd&&<Modal title="🔧 Nouveau produit" onClose={()=>setShowAdd(false)} width={560}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Nom du produit *" style={{gridColumn:"1/-1"}}><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Lave-linge, iPhone, TV..."/></F>
          <F label="Catégorie"><Sel value={form.categorie} onChange={v=>setForm(f=>({...f,categorie:v}))}>{CATS_GAR.map(c=><option key={c.id} value={c.id}>{c.icon} {c.l}</option>)}</Sel></F>
          <F label="Marque"><Inp value={form.marque} onChange={v=>setForm(f=>({...f,marque:v}))} placeholder="Samsung, Apple..."/></F>
          <F label="Modèle"><Inp value={form.modele} onChange={v=>setForm(f=>({...f,modele:v}))} placeholder="Galaxy S24, iPhone 15..."/></F>
          <F label="N° de série"><Inp value={form.numeroSerie} onChange={v=>setForm(f=>({...f,numeroSerie:v}))}/></F>
          <F label="Date d'achat"><Inp type="date" value={form.dateAchat} onChange={v=>setForm(f=>({...f,dateAchat:v}))}/></F>
          <F label="Fin de garantie"><Inp type="date" value={form.finGarantie} onChange={v=>setForm(f=>({...f,finGarantie:v}))}/></F>
          <F label="Prix d'achat (€)"><Inp type="number" value={form.prix} onChange={v=>setForm(f=>({...f,prix:v}))}/></F>
          <F label="Magasin / Site" style={{gridColumn:"1/-1"}}><Inp value={form.magasin} onChange={v=>setForm(f=>({...f,magasin:v}))} placeholder="Fnac, Darty, Amazon..."/></F>
          <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={form.note} onChange={v=>setForm(f=>({...f,note:v}))}/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={save} disabled={!form.nom}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: ÉNERGIE & COMPTEURS
// ═══════════════════════════════════════════════════════════════════════════════
const Energie=({energie,setEnergie})=>{
  const [tab,setTab]=useState("compteurs");
  const [showAdd,setShowAdd]=useState(null);
  const updFournisseur=(type,v)=>setEnergie(e=>({...e,fournisseurs:{...e.fournisseurs,[type]:{...(e.fournisseurs?.[type]||{}),...v}}}));
  const addReleve=r=>setEnergie(e=>({...e,releves:[...(e.releves||[]),{...r,id:uid()}]}));
  const delReleve=id=>setEnergie(e=>({...e,releves:(e.releves||[]).filter(r=>r.id!==id)}));
  const releves=energie.releves||[];
  const fournisseurs=energie.fournisseurs||{};
  const TYPES_E=[{id:"electricite",l:"Électricité",icon:"⚡",color:"#f0a500",unite:"kWh"},{id:"gaz",l:"Gaz",icon:"🔥",color:"#fb923c",unite:"m³"},{id:"eau",l:"Eau",icon:"💧",color:"#38bdf8",unite:"m³"}];
  return (
    <div>
      <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text,marginBottom:4}}>⚡ Énergie & Compteurs</h1>
      <p style={{color:T.muted,fontSize:13,marginBottom:18}}>Suivez votre consommation et vos fournisseurs</p>
      <Tabs tabs={[{id:"compteurs",icon:"🔢",label:"Compteurs & Relevés"},{id:"fournisseurs",icon:"🏢",label:"Fournisseurs"},{id:"stats",icon:"📊",label:"Statistiques"}]} active={tab} onChange={setTab}/>
      {tab==="compteurs"&&<div style={{marginTop:16}}>
        <div style={{display:"flex",justifyContent:"flex-end",marginBottom:12}}>
          <Btn onClick={()=>setShowAdd("releve")}>+ Relevé</Btn>
        </div>
        {TYPES_E.map(te=>{
          const rTri=releves.filter(r=>r.type===te.id).sort((a,b)=>b.date?.localeCompare(a.date||"")||0);
          if(rTri.length===0)return null;
          const dernier=rTri[0];const avantDernier=rTri[1];
          const conso=avantDernier?dernier.index-avantDernier.index:null;
          return <div key={te.id} style={{marginBottom:18}}>
            <div style={{fontSize:12,color:te.color,fontWeight:700,textTransform:"uppercase",letterSpacing:"0.07em",marginBottom:8}}>{te.icon} {te.l} · N° compteur : {(fournisseurs[te.id]?.numeroCompteur)||"—"}</div>
            {conso!==null&&<div style={{padding:"8px 14px",background:te.color+"12",border:`1px solid ${te.color}33`,borderRadius:8,marginBottom:8,fontSize:12,color:te.color}}>
              Dernière consommation relevée : <strong>{conso} {te.unite}</strong> du {fmt(avantDernier?.date)} au {fmt(dernier.date)}
            </div>}
            <div style={{display:"grid",gap:5}}>
              {rTri.slice(0,5).map(r=><div key={r.id} style={{display:"flex",gap:12,padding:"9px 14px",background:"#060a10",borderRadius:8,border:`1px solid ${T.border}`,alignItems:"center"}}>
                <span style={{fontSize:16}}>{te.icon}</span>
                <div style={{flex:1}}>
                  <span style={{fontSize:13,fontWeight:600,color:T.text,fontFamily:"monospace"}}>{r.index} {te.unite}</span>
                  <span style={{fontSize:11,color:T.muted,marginLeft:10}}>{fmt(r.date)}</span>
                  {r.note&&<span style={{fontSize:11,color:T.muted,fontStyle:"italic",marginLeft:8}}>{r.note}</span>}
                </div>
                <button onClick={()=>delReleve(r.id)} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,opacity:0.5}}>🗑</button>
              </div>)}
            </div>
          </div>;
        })}
        {releves.length===0&&<EmptyState icon="🔢" text="Enregistrez vos relevés de compteur pour suivre votre consommation annuelle."/>}
      </div>}
      {tab==="fournisseurs"&&<div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:14,marginTop:16}}>
        {TYPES_E.map(te=><Card key={te.id}>
          <Divider label={`${te.icon} ${te.l}`}/>
          <div style={{display:"grid",gap:7}}>
            {[{k:"nom",l:"Fournisseur",ph:"EDF, Engie..."},{k:"contrat",l:"N° contrat"},{k:"numeroCompteur",l:"N° compteur"},{k:"puissance",l:te.id==="electricite"?"Puissance (kVA)":"Débit/Pression"},{k:"offre",l:"Offre / Tarif"},{k:"echeanceMensuelle",l:"Échéance mensuelle (€)"},{k:"contact",l:"Tel / Email SAV"}].map(f=>(
              <F key={f.k} label={f.l}><Inp value={(fournisseurs[te.id]||{})[f.k]||""} onChange={v=>updFournisseur(te.id,{[f.k]:v})} placeholder={f.ph||""}/></F>
            ))}
          </div>
        </Card>)}
      </div>}
      {tab==="stats"&&<div style={{marginTop:16}}>
        {TYPES_E.map(te=>{
          const rTri=releves.filter(r=>r.type===te.id).sort((a,b)=>a.date?.localeCompare(b.date||"")||0);
          if(rTri.length<2)return <div key={te.id} style={{color:T.muted,fontSize:12,marginBottom:8}}>Pas assez de relevés pour {te.l} (minimum 2 nécessaires)</div>;
          const consos=[];
          for(let i=1;i<rTri.length;i++)consos.push({label:fmtMois(rTri[i].date?.slice(0,7)),value:rTri[i].index-rTri[i-1].index});
          return <Card key={te.id} style={{marginBottom:14}}>
            <Divider label={`${te.icon} ${te.l} — Historique de consommation`}/>
            <BarChart data={consos.slice(-12)} color={te.color} height={100}/>
            <div style={{fontSize:11,color:T.muted,textAlign:"right",marginTop:4}}>en {te.unite}</div>
          </Card>;
        })}
      </div>}
      {showAdd==="releve"&&(()=>{
        const [f,sf]=useState({type:"electricite",index:"",date:today(),note:""});
        return <Modal title="🔢 Nouveau relevé" onClose={()=>setShowAdd(null)}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Énergie"><Sel value={f.type} onChange={v=>sf(x=>({...x,type:v}))}>{TYPES_E.map(t=><option key={t.id} value={t.id}>{t.icon} {t.l}</option>)}</Sel></F>
            <F label="Date du relevé"><Inp type="date" value={f.date} onChange={v=>sf(x=>({...x,date:v}))}/></F>
            <F label={`Index (${TYPES_E.find(t=>t.id===f.type)?.unite})`} style={{gridColumn:"1/-1"}}><Inp type="number" value={f.index} onChange={v=>sf(x=>({...x,index:parseFloat(v)||0}))}/></F>
            <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={f.note} onChange={v=>sf(x=>({...x,note:v}))} placeholder="Emménagement, départ vacances..."/></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
            <Btn onClick={()=>{addReleve(f);setShowAdd(null);}}>💾 Enregistrer</Btn>
          </div>
        </Modal>;
      })()}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: BUDGET CADEAUX
// ═══════════════════════════════════════════════════════════════════════════════
const BudgetCadeaux=({cadeaux,setCadeaux})=>{
  const [showAdd,setShowAdd]=useState(null);
  const [sel,setSel]=useState(null);
  const EMPTY_P={prenom:"",relation:"",dateAnniversaire:"",budget:"",note:""};
  const EMPTY_I={personneId:"",occasion:"Anniversaire",idee:"",budget:"",statut:"idée",note:"",lien:""};
  // Formulaires niveau composant
  const [personneForm,setPersonneForm]=useState({...EMPTY_P});
  const [ideeForm,setIdeeForm]=useState({...EMPTY_I});
  const personnes=cadeaux.personnes||[];
  const idees=cadeaux.idees||[];
  const addPersonne=p=>setCadeaux(c=>({...c,personnes:[...(c.personnes||[]),{...p,id:uid()}]}));
  const addIdee=i=>setCadeaux(c=>({...c,idees:[...(c.idees||[]),{...i,id:uid()}]}));
  const delPersonne=id=>setCadeaux(c=>({...c,personnes:(c.personnes||[]).filter(p=>p.id!==id),idees:(c.idees||[]).filter(i=>i.personneId!==id)}));
  const delIdee=id=>setCadeaux(c=>({...c,idees:(c.idees||[]).filter(i=>i.id!==id)}));
  const toggleStatut=id=>{const stats=["idée","acheté","offert"];setCadeaux(c=>({...c,idees:c.idees.map(i=>i.id===id?{...i,statut:stats[(stats.indexOf(i.statut)+1)%stats.length]}:i)}));};
  const budgetTotal=idees.filter(i=>i.statut==="acheté"||i.statut==="offert").reduce((s,i)=>s+(parseFloat(i.budget)||0),0);
  const bientotAnn=personnes.filter(p=>{if(!p.dateAnniversaire)return false;const d=new Date(p.dateAnniversaire);d.setFullYear(new Date().getFullYear());if(d<new Date())d.setFullYear(new Date().getFullYear()+1);return Math.round((d-new Date())/86400000)<=30;});
  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🎁 Budget Cadeaux</h1>
          <p style={{color:T.muted,fontSize:13,marginTop:3}}>{personnes.length} personne{personnes.length>1?"s":""} · {idees.length} idée{idees.length>1?"s":""} · Dépensé : <span style={{color:T.success,fontWeight:700}}>{fmtAmt(budgetTotal)}</span></p>
        </div>
        <div style={{display:"flex",gap:8}}>
          <Btn v="ghost" onClick={()=>setShowAdd("idee")}>+ Idée cadeau</Btn>
          <Btn onClick={()=>setShowAdd("personne")}>+ Personne</Btn>
        </div>
      </div>
      {bientotAnn.length>0&&<div style={{padding:"10px 16px",background:"rgba(240,165,0,0.08)",border:"1px solid rgba(240,165,0,0.25)",borderRadius:10,marginBottom:16,fontSize:12,color:T.warning}}>
        🎂 Anniversaires dans les 30j : {bientotAnn.map(p=>{const d=new Date(p.dateAnniversaire);d.setFullYear(new Date().getFullYear());if(d<new Date())d.setFullYear(new Date().getFullYear()+1);return <strong key={p.id} style={{marginRight:8}}>{p.prenom} (dans {Math.round((d-new Date())/86400000)}j)</strong>;})}
      </div>}
      <div style={{display:"grid",gridTemplateColumns:"280px 1fr",gap:16}}>
        {/* Liste personnes */}
        <div>
          <div style={{fontSize:11,color:T.muted,fontWeight:700,textTransform:"uppercase",marginBottom:8,letterSpacing:"0.07em"}}>Personnes</div>
          {personnes.length===0&&<div style={{fontSize:12,color:T.muted,fontStyle:"italic"}}>Aucune personne. Ajoutez vos proches.</div>}
          <div style={{display:"grid",gap:5}}>
            {personnes.map(p=>{
              const nbIdees=idees.filter(i=>i.personneId===p.id).length;
              const budgetDep=idees.filter(i=>i.personneId===p.id&&(i.statut==="acheté"||i.statut==="offert")).reduce((s,i)=>s+(parseFloat(i.budget)||0),0);
              return <div key={p.id} onClick={()=>setSel(sel===p.id?null:p.id)}
                style={{padding:"10px 12px",borderRadius:9,cursor:"pointer",background:sel===p.id?T.accentDim:"#060a10",border:`1px solid ${sel===p.id?T.accent:T.border}`}}>
                <div style={{display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                  <div style={{fontSize:13,fontWeight:600,color:sel===p.id?T.accent:T.text}}>{p.prenom}</div>
                  <button onClick={e=>{e.stopPropagation();delPersonne(p.id);}} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,opacity:0.5}}>🗑</button>
                </div>
                <div style={{fontSize:10,color:T.muted,marginTop:2}}>
                  {p.relation&&<span style={{marginRight:6}}>{p.relation}</span>}
                  {nbIdees>0&&<span>{nbIdees} idée{nbIdees>1?"s":""} · {fmtAmt(budgetDep)} dépensé</span>}
                  {p.budget&&<span style={{marginLeft:6}}>· Budget : {fmtAmt(p.budget)}</span>}
                </div>
              </div>;
            })}
          </div>
        </div>
        {/* Idées */}
        <div>
          <div style={{fontSize:11,color:T.muted,fontWeight:700,textTransform:"uppercase",marginBottom:8,letterSpacing:"0.07em"}}>
            {sel?`Idées pour ${personnes.find(p=>p.id===sel)?.prenom}`:"Toutes les idées"}
          </div>
          {idees.filter(i=>!sel||i.personneId===sel).length===0&&<EmptyState icon="🎁" text="Ajoutez des idées cadeaux !"/>}
          <div style={{display:"grid",gap:6}}>
            {idees.filter(i=>!sel||i.personneId===sel).map(i=>{
              const p=personnes.find(x=>x.id===i.personneId);
              const statColor=i.statut==="offert"?T.success:i.statut==="acheté"?T.info:T.muted;
              return <div key={i.id} style={{display:"flex",gap:10,padding:"10px 14px",background:"#060a10",borderRadius:10,border:`1px solid ${T.border}`,alignItems:"center"}}>
                <span style={{fontSize:20}}>🎁</span>
                <div style={{flex:1}}>
                  <div style={{fontSize:13,fontWeight:600,color:T.text}}>{i.idee}</div>
                  <div style={{fontSize:11,color:T.muted,marginTop:2}}>
                    {p&&!sel&&<span style={{color:T.accent}}>{p.prenom} · </span>}
                    {i.occasion} {i.budget&&`· ${fmtAmt(i.budget)}`}
                    {i.lien&&<a href={i.lien} target="_blank" rel="noreferrer" style={{color:T.info,marginLeft:6,textDecoration:"none"}}>↗ lien</a>}
                    {i.note&&<span style={{fontStyle:"italic",marginLeft:6}}>{i.note}</span>}
                  </div>
                </div>
                <button onClick={()=>toggleStatut(i.id)} style={{padding:"3px 10px",borderRadius:7,border:`1px solid ${statColor}`,background:"transparent",color:statColor,fontSize:11,cursor:"pointer",fontFamily:T.font,flexShrink:0,textTransform:"capitalize"}}>{i.statut}</button>
                <button onClick={()=>delIdee(i.id)} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,opacity:0.5}}>🗑</button>
              </div>;
            })}
          </div>
        </div>
      </div>
      {showAdd==="personne"&&(
        <Modal title="👤 Nouvelle personne" onClose={()=>{setShowAdd(null);setPersonneForm({...EMPTY_P});}}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Prénom *"><Inp value={personneForm.prenom} onChange={v=>setPersonneForm(f=>({...f,prenom:v}))}/></F>
            <F label="Relation"><Inp value={personneForm.relation} onChange={v=>setPersonneForm(f=>({...f,relation:v}))} placeholder="Conjoint, enfant, ami..."/></F>
            <F label="Anniversaire"><Inp type="date" value={personneForm.dateAnniversaire} onChange={v=>setPersonneForm(f=>({...f,dateAnniversaire:v}))}/></F>
            <F label="Budget annuel (€)"><Inp type="number" value={personneForm.budget} onChange={v=>setPersonneForm(f=>({...f,budget:v}))}/></F>
            <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={personneForm.note} onChange={v=>setPersonneForm(f=>({...f,note:v}))}/></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>{setShowAdd(null);setPersonneForm({...EMPTY_P});}}>Annuler</Btn>
            <Btn onClick={()=>{addPersonne(personneForm);setPersonneForm({...EMPTY_P});setShowAdd(null);}} disabled={!personneForm.prenom}>💾</Btn>
          </div>
        </Modal>
      )}
      {showAdd==="idee"&&(
        <Modal title="🎁 Nouvelle idée cadeau" onClose={()=>{setShowAdd(null);setIdeeForm({...EMPTY_I});}}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Pour qui"><Sel value={ideeForm.personneId} onChange={v=>setIdeeForm(f=>({...f,personneId:v}))}><option value="">— Choisir</option>{personnes.map(p=><option key={p.id} value={p.id}>{p.prenom}</option>)}</Sel></F>
            <F label="Occasion"><Sel value={ideeForm.occasion} onChange={v=>setIdeeForm(f=>({...f,occasion:v}))}>{["Anniversaire","Noël","Fête des Mères","Fête des Pères","Saint-Valentin","Mariage","Naissance","Autre"].map(o=><option key={o}>{o}</option>)}</Sel></F>
            <F label="Idée cadeau *" style={{gridColumn:"1/-1"}}><Inp value={ideeForm.idee} onChange={v=>setIdeeForm(f=>({...f,idee:v}))} placeholder="AirPods, cours de cuisine, livre..."/></F>
            <F label="Budget estimé (€)"><Inp type="number" value={ideeForm.budget} onChange={v=>setIdeeForm(f=>({...f,budget:v}))}/></F>
            <F label="Lien (URL)"><Inp value={ideeForm.lien} onChange={v=>setIdeeForm(f=>({...f,lien:v}))} placeholder="https://amazon.fr/..."/></F>
            <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={ideeForm.note} onChange={v=>setIdeeForm(f=>({...f,note:v}))}/></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>{setShowAdd(null);setIdeeForm({...EMPTY_I});}}>Annuler</Btn>
            <Btn onClick={()=>{addIdee(ideeForm);setIdeeForm({...EMPTY_I});setShowAdd(null);}} disabled={!ideeForm.idee}>💾</Btn>
          </div>
        </Modal>
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: COFFRE-FORT MOTS DE PASSE
// ═══════════════════════════════════════════════════════════════════════════════
const CATS_MDP=[
  {id:"banque",l:"Banque",icon:"🏦",color:"#38bdf8"},
  {id:"email",l:"Emails",icon:"✉️",color:"#f0a500"},
  {id:"shopping",l:"Shopping",icon:"🛒",color:"#fb923c"},
  {id:"reseaux",l:"Réseaux sociaux",icon:"📱",color:"#a78bfa"},
  {id:"travail",l:"Travail",icon:"💼",color:"#34d399"},
  {id:"administration",l:"Administration",icon:"🏛️",color:"#60a5fa"},
  {id:"autre",l:"Autre",icon:"🔐",color:"#94a3b8"},
];
const CoffreFort=({motsdepasse,setMotsdepasse})=>{
  const [showAdd,setShowAdd]=useState(false);
  const [search,setSearch]=useState("");
  const [catFilter,setCatFilter]=useState("all");
  const [visible,setVisible]=useState({});
  const [copied,setCopied]=useState(null);
  const EMPTY={site:"",url:"",login:"",motdepasse:"",categorie:"autre",note:""};
  const [form,setForm]=useState({...EMPTY});
  const filtered=motsdepasse.filter(m=>{
    if(catFilter!=="all"&&m.categorie!==catFilter)return false;
    if(search&&![m.site,m.login,m.url].some(v=>(v||"").toLowerCase().includes(search.toLowerCase())))return false;
    return true;
  });
  const copy=(text,id)=>{navigator.clipboard.writeText(text).then(()=>{setCopied(id);setTimeout(()=>setCopied(null),1500);});};
  const genPassword=()=>{const chars="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%&*";return Array.from({length:16},()=>chars[Math.floor(Math.random()*chars.length)]).join("");};
  const save=()=>{setMotsdepasse(p=>[...p,{...form,id:uid()}]);setShowAdd(false);setForm({...EMPTY});};
  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🔐 Coffre-fort</h1>
          <p style={{color:T.muted,fontSize:13,marginTop:3}}>{motsdepasse.length} identifiant{motsdepasse.length>1?"s":""} · Stockage 100% local — aucune donnée transmise</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Identifiant</Btn>
      </div>
      <div style={{padding:"8px 14px",background:"rgba(240,165,0,0.07)",border:"1px solid rgba(240,165,0,0.2)",borderRadius:8,marginBottom:16,fontSize:11,color:T.warning}}>
        🔒 Vos mots de passe sont stockés localement sur votre appareil. Exportez régulièrement une sauvegarde chiffrée.
      </div>
      <div style={{display:"flex",gap:8,marginBottom:14,flexWrap:"wrap"}}>
        <Inp value={search} onChange={setSearch} placeholder="🔍 Site, login..." style={{maxWidth:230}}/>
        <button onClick={()=>setCatFilter("all")} style={{padding:"5px 12px",borderRadius:7,border:`1px solid ${catFilter==="all"?T.accent:T.border}`,background:catFilter==="all"?T.accentDim:"transparent",color:catFilter==="all"?T.accent:T.muted,fontSize:12,cursor:"pointer",fontFamily:T.font}}>Tous</button>
        {CATS_MDP.map(c=><button key={c.id} onClick={()=>setCatFilter(c.id)} style={{padding:"5px 10px",borderRadius:7,border:`1px solid ${catFilter===c.id?c.color:T.border}`,background:catFilter===c.id?c.color+"22":"transparent",color:catFilter===c.id?c.color:T.muted,fontSize:11,cursor:"pointer",fontFamily:T.font}}>{c.icon} {c.l}</button>)}
      </div>
      <div style={{display:"grid",gap:5}}>
        {filtered.length===0&&<EmptyState icon="🔐" text="Ajoutez vos identifiants pour les retrouver facilement."/>}
        {filtered.map(m=>{
          const cat=CATS_MDP.find(c=>c.id===m.categorie)||CATS_MDP[6];
          const isVis=visible[m.id];
          return <div key={m.id} style={{display:"flex",alignItems:"center",gap:12,padding:"10px 16px",background:"#060a10",borderRadius:10,border:`1px solid ${T.border}`}}>
            <div style={{width:34,height:34,borderRadius:8,background:cat.color+"22",display:"flex",alignItems:"center",justifyContent:"center",fontSize:16,flexShrink:0}}>{cat.icon}</div>
            <div style={{flex:1,minWidth:0}}>
              <div style={{fontSize:13,fontWeight:700,color:T.text}}>{m.site}</div>
              <div style={{fontSize:11,color:T.muted}}>{m.login}</div>
            </div>
            <div style={{display:"flex",gap:6,flexShrink:0,alignItems:"center"}}>
              <code style={{fontSize:12,color:isVis?T.text:T.muted,background:"#0a0e17",padding:"2px 8px",borderRadius:5,minWidth:100,fontFamily:"monospace"}}>{isVis?m.motdepasse:"•".repeat(Math.min(m.motdepasse?.length||8,12))}</code>
              <button onClick={()=>setVisible(v=>({...v,[m.id]:!v[m.id]}))} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12}}>👁</button>
              <button onClick={()=>copy(m.motdepasse,m.id+"mdp")} style={{background:copied===m.id+"mdp"?T.accentDim:"#1a1a2a",border:`1px solid ${T.border}`,color:copied===m.id+"mdp"?T.accent:T.muted,borderRadius:6,padding:"3px 8px",cursor:"pointer",fontSize:11,fontFamily:T.font}}>{copied===m.id+"mdp"?"✓":"📋"}</button>
              <button onClick={()=>copy(m.login,m.id+"login")} style={{background:"#1a1a2a",border:`1px solid ${T.border}`,color:T.muted,borderRadius:6,padding:"3px 8px",cursor:"pointer",fontSize:11,fontFamily:T.font}}>@ copier</button>
              {m.url&&<a href={m.url} target="_blank" rel="noreferrer" style={{color:T.info,fontSize:11,textDecoration:"none"}}>↗</a>}
              <button onClick={()=>setMotsdepasse(p=>p.filter(x=>x.id!==m.id))} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,opacity:0.5}}>🗑</button>
            </div>
          </div>;
        })}
      </div>
      {showAdd&&<Modal title="🔐 Nouvel identifiant" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Site / Application *"><Inp value={form.site} onChange={v=>setForm(f=>({...f,site:v}))} placeholder="Netflix, Gmail, impots.gouv..."/></F>
          <F label="Catégorie"><Sel value={form.categorie} onChange={v=>setForm(f=>({...f,categorie:v}))}>{CATS_MDP.map(c=><option key={c.id} value={c.id}>{c.icon} {c.l}</option>)}</Sel></F>
          <F label="URL"><Inp value={form.url} onChange={v=>setForm(f=>({...f,url:v}))} placeholder="https://..."/></F>
          <F label="Identifiant / Email"><Inp value={form.login} onChange={v=>setForm(f=>({...f,login:v}))} placeholder="email@example.com"/></F>
          <F label="Mot de passe" style={{gridColumn:"1/-1"}}>
            <div style={{display:"flex",gap:8}}>
              <Inp value={form.motdepasse} onChange={v=>setForm(f=>({...f,motdepasse:v}))} placeholder="••••••••" style={{flex:1}}/>
              <Btn v="ghost" onClick={()=>setForm(f=>({...f,motdepasse:genPassword()}))}>🎲 Générer</Btn>
            </div>
          </F>
          <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} placeholder="Compte premium, code PIN..."/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={save} disabled={!form.site}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: MA BIBLIOTHÈQUE
// ═══════════════════════════════════════════════════════════════════════════════
const CATS_LIVRE=[{id:"roman",l:"Roman",icon:"📖"},{id:"essai",l:"Essai",icon:"💡"},{id:"bd",l:"BD/Manga",icon:"🎨"},{id:"policier",l:"Policier/Thriller",icon:"🔍"},{id:"sf",l:"SF/Fantastique",icon:"🚀"},{id:"pratique",l:"Pratique",icon:"🛠️"},{id:"biographie",l:"Biographie",icon:"👤"},{id:"autre",l:"Autre",icon:"📚"}];
const Bibliotheque=({bibliotheque,setBibliotheque})=>{
  const [tab,setTab]=useState("en-cours");
  const [showAdd,setShowAdd]=useState(false);
  const EMPTY={titre:"",auteur:"",categorie:"roman",statut:"a-lire",dateDebut:"",dateFin:"",note:"",note_lecture:"",note_sur_5:""};
  const [form,setForm]=useState({...EMPTY});
  const livres=bibliotheque.livres||[];
  const enCours=livres.filter(l=>l.statut==="en-cours");
  const lus=livres.filter(l=>l.statut==="lu");
  const aLire=livres.filter(l=>l.statut==="a-lire");
  const filtered=tab==="en-cours"?enCours:tab==="lu"?lus:tab==="a-lire"?aLire:livres;
  const save=()=>{setBibliotheque(b=>({...b,livres:[...(b.livres||[]),{...form,id:uid()}]}));setShowAdd(false);setForm({...EMPTY});};
  const StarRating=({v})=><span style={{color:"#f0a500",fontSize:14}}>{Array.from({length:5},(_,i)=><span key={i}>{i<v?"★":"☆"}</span>)}</span>;
  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>📚 Ma Bibliothèque</h1>
          <p style={{color:T.muted,fontSize:13,marginTop:3}}>{lus.length} lu{lus.length>1?"s":""} · {enCours.length} en cours · {aLire.length} à lire</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Livre</Btn>
      </div>
      <Tabs tabs={[{id:"en-cours",icon:"📖",label:`En cours (${enCours.length})`},{id:"a-lire",icon:"🔖",label:`À lire (${aLire.length})`},{id:"lu",icon:"✅",label:`Lus (${lus.length})`},{id:"tous",icon:"📚",label:"Tous"}]} active={tab} onChange={setTab}/>
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(280px,1fr))",gap:12,marginTop:16}}>
        {filtered.length===0&&<EmptyState icon="📚" text="Ajoutez vos livres pour suivre vos lectures."/>}
        {filtered.map(l=>{
          const cat=CATS_LIVRE.find(c=>c.id===l.categorie)||CATS_LIVRE[7];
          const statColor=l.statut==="lu"?T.success:l.statut==="en-cours"?T.info:T.muted;
          return <Card key={l.id}>
            <div style={{display:"flex",gap:10}}>
              <div style={{width:42,height:58,borderRadius:6,background:"linear-gradient(135deg,#1a2235,#0a0e17)",border:`1px solid ${T.border}`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:22,flexShrink:0}}>{cat.icon}</div>
              <div style={{flex:1,minWidth:0}}>
                <div style={{fontSize:13,fontWeight:700,color:T.text,lineHeight:1.3}}>{l.titre}</div>
                <div style={{fontSize:11,color:T.muted,marginTop:2}}>{l.auteur}</div>
                <div style={{display:"flex",gap:6,marginTop:5,alignItems:"center"}}>
                  <Badge c={statColor} style={{fontSize:9}}>{l.statut==="lu"?"✅ Lu":l.statut==="en-cours"?"📖 En cours":"🔖 À lire"}</Badge>
                  {l.note_sur_5&&<StarRating v={parseInt(l.note_sur_5)}/>}
                </div>
                {l.note_lecture&&<div style={{fontSize:10,color:T.muted,fontStyle:"italic",marginTop:4,lineHeight:1.5,overflow:"hidden",display:"-webkit-box",WebkitLineClamp:2,WebkitBoxOrient:"vertical"}}>{l.note_lecture}</div>}
              </div>
              <button onClick={()=>setBibliotheque(b=>({...b,livres:b.livres.filter(x=>x.id!==l.id)}))} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,opacity:0.4,alignSelf:"flex-start"}}>🗑</button>
            </div>
          </Card>;
        })}
      </div>
      {showAdd&&<Modal title="📚 Nouveau livre" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Titre *" style={{gridColumn:"1/-1"}}><Inp value={form.titre} onChange={v=>setForm(f=>({...f,titre:v}))}/></F>
          <F label="Auteur"><Inp value={form.auteur} onChange={v=>setForm(f=>({...f,auteur:v}))}/></F>
          <F label="Catégorie"><Sel value={form.categorie} onChange={v=>setForm(f=>({...f,categorie:v}))}>{CATS_LIVRE.map(c=><option key={c.id} value={c.id}>{c.icon} {c.l}</option>)}</Sel></F>
          <F label="Statut"><Sel value={form.statut} onChange={v=>setForm(f=>({...f,statut:v}))}><option value="a-lire">🔖 À lire</option><option value="en-cours">📖 En cours</option><option value="lu">✅ Lu</option></Sel></F>
          <F label="Note /5"><Sel value={form.note_sur_5} onChange={v=>setForm(f=>({...f,note_sur_5:v}))}><option value="">—</option>{[1,2,3,4,5].map(n=><option key={n} value={n}>{"★".repeat(n)}</option>)}</Sel></F>
          <F label="Début de lecture"><Inp type="date" value={form.dateDebut} onChange={v=>setForm(f=>({...f,dateDebut:v}))}/></F>
          <F label="Date de fin"><Inp type="date" value={form.dateFin} onChange={v=>setForm(f=>({...f,dateFin:v}))}/></F>
          <F label="Ma note / critique" style={{gridColumn:"1/-1"}}><Txt value={form.note_lecture} onChange={v=>setForm(f=>({...f,note_lecture:v}))} rows={3} placeholder="Mes impressions sur ce livre..."/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={save} disabled={!form.titre}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: DONS & ASSOCIATIONS
// ═══════════════════════════════════════════════════════════════════════════════
const Dons=({dons,setDons})=>{
  const [showAdd,setShowAdd]=useState(false);
  const EMPTY={association:"",montant:"",date:today(),recuFiscal:true,annee:"",note:""};
  const [form,setForm]=useState({...EMPTY});
  const save=()=>{setDons(p=>[...p,{...form,id:uid()}]);setShowAdd(false);setForm({...EMPTY});};
  const totalAnnee=(an)=>dons.filter(d=>d.date?.startsWith(an)&&d.recuFiscal).reduce((s,d)=>s+(parseFloat(d.montant)||0),0);
  const anneeActuelle=new Date().getFullYear().toString();
  const reduction=totalAnnee(anneeActuelle)*0.66;
  const byAn=dons.reduce((m,d)=>{const an=d.date?.slice(0,4)||"?";if(!m[an])m[an]=[];m[an].push(d);return m;},{});
  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🤲 Dons & Associations</h1>
          <p style={{color:T.muted,fontSize:13,marginTop:3}}>Dons {anneeActuelle} : <span style={{color:T.success,fontWeight:700}}>{fmtAmt(totalAnnee(anneeActuelle))}</span> · Réduction fiscale estimée : <span style={{color:T.accent,fontWeight:700}}>{fmtAmt(reduction)}</span></p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Don</Btn>
      </div>
      <div style={{padding:"10px 16px",background:"rgba(34,197,94,0.07)",border:"1px solid rgba(34,197,94,0.2)",borderRadius:8,marginBottom:18,fontSize:12,color:T.success}}>
        💡 En France, les dons aux associations reconnues d'utilité publique ouvrent droit à une réduction d'impôt de 66% du montant versé (dans la limite de 20% du revenu imposable).
      </div>
      {dons.length===0&&<EmptyState icon="🤲" text="Enregistrez vos dons pour suivre vos réductions fiscales."/>}
      {Object.entries(byAn).sort(([a],[b])=>b-a).map(([an,donsList])=>(
        <div key={an} style={{marginBottom:20}}>
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:8}}>
            <div style={{fontSize:12,color:T.accent,fontWeight:700,textTransform:"uppercase",letterSpacing:"0.07em"}}>{an}</div>
            <div style={{fontSize:12,color:T.muted}}>Total avec reçu fiscal : <span style={{color:T.success}}>{fmtAmt(donsList.filter(d=>d.recuFiscal).reduce((s,d)=>s+(parseFloat(d.montant)||0),0))}</span></div>
          </div>
          <div style={{display:"grid",gap:5}}>
            {donsList.sort((a,b)=>b.date?.localeCompare(a.date||"")||0).map(d=>(
              <div key={d.id} style={{display:"flex",alignItems:"center",gap:12,padding:"10px 16px",background:"#060a10",borderRadius:10,border:`1px solid ${T.border}`}}>
                <span style={{fontSize:20}}>🤲</span>
                <div style={{flex:1}}>
                  <div style={{fontSize:13,fontWeight:600,color:T.text}}>{d.association}</div>
                  <div style={{fontSize:11,color:T.muted,marginTop:2}}>{fmt(d.date)}{d.note&&` · ${d.note}`}</div>
                </div>
                <div style={{textAlign:"right"}}>
                  <div style={{fontFamily:T.fontD,fontSize:14,color:T.success}}>{fmtAmt(d.montant)}</div>
                  {d.recuFiscal&&<div style={{fontSize:10,color:T.accent}}>📋 Reçu fiscal</div>}
                </div>
                <button onClick={()=>setDons(p=>p.filter(x=>x.id!==d.id))} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,opacity:0.5}}>🗑</button>
              </div>
            ))}
          </div>
        </div>
      ))}
      {showAdd&&<Modal title="🤲 Nouveau don" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Association *" style={{gridColumn:"1/-1"}}><Inp value={form.association} onChange={v=>setForm(f=>({...f,association:v}))} placeholder="Croix-Rouge, Médecins Sans Frontières..."/></F>
          <F label="Montant (€)"><Inp type="number" value={form.montant} onChange={v=>setForm(f=>({...f,montant:v}))}/></F>
          <F label="Date"><Inp type="date" value={form.date} onChange={v=>setForm(f=>({...f,date:v}))}/></F>
          <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} placeholder="Don mensuel, ponctuel..."/></F>
          <div style={{gridColumn:"1/-1",display:"flex",alignItems:"center",gap:10}}>
            <input type="checkbox" id="recuFiscal" checked={form.recuFiscal} onChange={e=>setForm(f=>({...f,recuFiscal:e.target.checked}))} style={{accentColor:T.accent}}/>
            <label htmlFor="recuFiscal" style={{fontSize:13,color:T.text,cursor:"pointer"}}>Reçu fiscal disponible (déductible des impôts)</label>
          </div>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={save} disabled={!form.association||!form.montant}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: PROJETS & TRAVAUX
// ═══════════════════════════════════════════════════════════════════════════════
const STATUTS_PROJET=["Planifié","En cours","En pause","Terminé","Annulé"];
const ProjetsModule=({projets,setProjets})=>{
  const [sel,setSel]=useState(null);
  const [showAdd,setShowAdd]=useState(false);
  const [tab,setTab]=useState("infos");
  const EMPTY={nom:"",type:"Travaux",bien:"",budget:"",dateDebut:"",dateFin:"",statut:"Planifié",note:"",artisans:[],devis:[],photos:[],taches:[]};
  const [form,setForm]=useState({...EMPTY});
  // Formulaires inline extraits au niveau composant
  const [tacheForm,setTacheForm]=useState({texte:"",artisan:""});
  const [artisanForm,setArtisanForm]=useState({nom:"",metier:"",tel:"",email:"",siret:"",note:""});
  const [devisForm,setDevisForm]=useState({artisan:"",description:"",montant:"",date:today(),statut:"En attente"});
  const selProjet=sel&&projets.find(p=>p.id===sel);
  const save=()=>{setProjets(p=>[...p,{...form,id:uid()}]);setShowAdd(false);setForm({...EMPTY});};
  const updProjet=(id,v)=>setProjets(p=>p.map(x=>x.id===id?{...x,...v}:x));
  const addTache=(id,t)=>updProjet(id,{taches:[...(selProjet.taches||[]),{...t,id:uid(),fait:false}]});
  const toggleTache=(pid,tid)=>updProjet(pid,{taches:(selProjet.taches||[]).map(t=>t.id===tid?{...t,fait:!t.fait}:t)});
  const totalDevis=proj=>((proj.devis||[]).reduce((s,d)=>s+(parseFloat(d.montant)||0),0));
  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🏗️ Projets & Travaux</h1>
          <p style={{color:T.muted,fontSize:13,marginTop:3}}>{projets.filter(p=>p.statut==="En cours").length} en cours · {projets.filter(p=>p.statut==="Terminé").length} terminé{projets.filter(p=>p.statut==="Terminé").length>1?"s":""}</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Projet</Btn>
      </div>
      <div style={{display:"grid",gridTemplateColumns:sel&&selProjet?"300px 1fr":"1fr",gap:16}}>
        <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(280px,1fr))",gap:12,alignContent:"start"}}>
          {projets.length===0&&<EmptyState icon="🏗️" text="Ajoutez vos projets de travaux, rénovations, aménagements..."/>}
          {projets.map(p=>{
            const statColor=p.statut==="Terminé"?T.success:p.statut==="En cours"?T.info:p.statut==="En pause"?T.warning:T.muted;
            const tachesFaites=(p.taches||[]).filter(t=>t.fait).length;
            const tachesTotal=(p.taches||[]).length;
            const progression=tachesTotal?Math.round(tachesFaites/tachesTotal*100):0;
            return <Card key={p.id} onClick={()=>setSel(p.id===sel?null:p.id)} style={{cursor:"pointer",borderColor:sel===p.id?T.accent:T.border}}>
              <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:8}}>
                <div>
                  <div style={{fontSize:14,fontWeight:700,color:T.text}}>{p.nom}</div>
                  <div style={{fontSize:11,color:T.muted,marginTop:2}}>{p.type}{p.bien&&` · ${p.bien}`}</div>
                </div>
                <Badge c={statColor}>{p.statut}</Badge>
              </div>
              {tachesTotal>0&&<div style={{marginBottom:8}}>
                <div style={{display:"flex",justifyContent:"space-between",fontSize:10,color:T.muted,marginBottom:3}}><span>{tachesFaites}/{tachesTotal} tâches</span><span>{progression}%</span></div>
                <div style={{height:4,background:T.border,borderRadius:2}}><div style={{height:4,background:T.success,borderRadius:2,width:`${progression}%`,transition:"width 0.3s"}}/></div>
              </div>}
              <div style={{display:"flex",gap:8,fontSize:11,color:T.muted,flexWrap:"wrap"}}>
                {p.budget&&<span>💶 Budget : {fmtAmt(p.budget)}</span>}
                {totalDevis(p)>0&&<span>Devis : {fmtAmt(totalDevis(p))}</span>}
                {p.dateDebut&&<span>📅 {fmt(p.dateDebut)}</span>}
              </div>
            </Card>;
          })}
        </div>
        {sel&&selProjet&&(
          <div style={{background:T.bg,border:`1px solid ${T.border}`,borderRadius:14,padding:"18px 20px"}}>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:14}}>
              <div style={{fontFamily:T.fontD,fontSize:18,color:T.text}}>{selProjet.nom}</div>
              <div style={{display:"flex",gap:8}}>
                <Sel value={selProjet.statut} onChange={v=>updProjet(sel,{statut:v})} style={{fontSize:12}}>{STATUTS_PROJET.map(s=><option key={s}>{s}</option>)}</Sel>
                <button onClick={()=>{if(confirm("Supprimer ce projet ?"))setProjets(p=>p.filter(x=>x.id!==sel));setSel(null);}} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:14}}>🗑</button>
                <Btn sm v="ghost" onClick={()=>setSel(null)}>✕</Btn>
              </div>
            </div>
            <Tabs tabs={[{id:"infos",icon:"📋",label:"Infos"},{id:"taches",icon:"✅",label:`Tâches (${(selProjet.taches||[]).length})`},{id:"artisans",icon:"👷",label:"Artisans"},{id:"devis",icon:"💶",label:"Devis"}]} active={tab} onChange={setTab}/>
            <div style={{marginTop:14}}>
              {tab==="infos"&&<div style={{display:"grid",gap:8}}>
                <InfoRow label="Type" value={selProjet.type}/><InfoRow label="Bien concerné" value={selProjet.bien}/><InfoRow label="Budget prévu" value={selProjet.budget&&fmtAmt(selProjet.budget)}/><InfoRow label="Début" value={fmt(selProjet.dateDebut)}/><InfoRow label="Fin prévue" value={fmt(selProjet.dateFin)}/>
                {selProjet.note&&<div style={{padding:"10px 12px",background:"#060a10",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic",marginTop:6}}>{selProjet.note}</div>}
              </div>}
              {tab==="taches"&&<div>
                {(selProjet.taches||[]).map(t=><div key={t.id} style={{display:"flex",alignItems:"center",gap:10,padding:"8px 10px",borderRadius:8,marginBottom:4,background:"#060a10"}}>
                  <input type="checkbox" checked={t.fait} onChange={()=>toggleTache(sel,t.id)} style={{accentColor:T.accent}}/>
                  <span style={{fontSize:13,color:t.fait?T.muted:T.text,textDecoration:t.fait?"line-through":"none"}}>{t.texte}</span>
                  <span style={{fontSize:10,color:T.muted,marginLeft:"auto"}}>{t.artisan}</span>
                </div>)}
                {/* Tâches */}
                <div style={{display:"flex",gap:8,marginTop:8}}>
                  <Inp value={tacheForm.texte} onChange={v=>setTacheForm(f=>({...f,texte:v}))} placeholder="Nouvelle tâche..." style={{flex:1}}/>
                  <Btn sm onClick={()=>{if(tacheForm.texte){addTache(sel,tacheForm);setTacheForm({texte:"",artisan:""});}}}>+</Btn>
                </div>
              </div>}
              {tab==="artisans"&&<div>
                {(selProjet.artisans||[]).map(a=><div key={a.id} style={{padding:"9px 12px",background:"#060a10",borderRadius:8,marginBottom:5}}>
                  <div style={{fontSize:13,fontWeight:600,color:T.text}}>{a.nom}</div>
                  <div style={{fontSize:11,color:T.muted}}>{a.metier}{a.tel&&` · 📞 ${a.tel}`}{a.email&&` · ✉️ ${a.email}`}</div>
                  <div style={{fontSize:10,color:T.muted,marginTop:2}}>{a.siret&&`SIRET: ${a.siret}`}{a.note&&` · ${a.note}`}</div>
                </div>)}
                {/* Artisans */}
                <div style={{marginTop:10}}>
                  <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
                    <F label="Nom / Société"><Inp value={artisanForm.nom} onChange={v=>setArtisanForm(f=>({...f,nom:v}))}/></F>
                    <F label="Métier"><Inp value={artisanForm.metier} onChange={v=>setArtisanForm(f=>({...f,metier:v}))} placeholder="Plombier, Électricien..."/></F>
                    <F label="Téléphone"><Inp value={artisanForm.tel} onChange={v=>setArtisanForm(f=>({...f,tel:v}))}/></F>
                    <F label="SIRET"><Inp value={artisanForm.siret} onChange={v=>setArtisanForm(f=>({...f,siret:v}))}/></F>
                  </div>
                  <Btn sm onClick={()=>{if(artisanForm.nom){updProjet(sel,{artisans:[...(selProjet.artisans||[]),{...artisanForm,id:uid()}]});setArtisanForm({nom:"",metier:"",tel:"",email:"",siret:"",note:""});}}} style={{marginTop:8}}>+ Artisan</Btn>
                </div>
              </div>}
              {tab==="devis"&&<div>
                <div style={{marginBottom:8,fontSize:12,color:T.success}}>Total devis : <strong>{fmtAmt(totalDevis(selProjet))}</strong> · Budget : {fmtAmt(selProjet.budget)} · Écart : <span style={{color:totalDevis(selProjet)>parseFloat(selProjet.budget)?"#ef4444":T.success}}>{fmtAmt(Math.abs(totalDevis(selProjet)-parseFloat(selProjet.budget||0)))}</span></div>
                {(selProjet.devis||[]).map(d=><div key={d.id} style={{display:"flex",justifyContent:"space-between",padding:"9px 12px",background:"#060a10",borderRadius:8,marginBottom:5}}>
                  <div><div style={{fontSize:13,fontWeight:600,color:T.text}}>{d.artisan}</div><div style={{fontSize:11,color:T.muted}}>{d.description}{d.date&&` · ${fmt(d.date)}`}</div></div>
                  <div style={{textAlign:"right"}}><div style={{color:T.success,fontWeight:700}}>{fmtAmt(d.montant)}</div><Badge c={d.statut==="Accepté"?T.success:d.statut==="Refusé"?T.danger:T.muted} style={{fontSize:9}}>{d.statut||"En attente"}</Badge></div>
                </div>)}
                {/* Devis */}
                <div style={{marginTop:10,display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
                  <F label="Artisan"><Inp value={devisForm.artisan} onChange={v=>setDevisForm(f=>({...f,artisan:v}))}/></F>
                  <F label="Montant (€)"><Inp type="number" value={devisForm.montant} onChange={v=>setDevisForm(f=>({...f,montant:v}))}/></F>
                  <F label="Description" style={{gridColumn:"1/-1"}}><Inp value={devisForm.description} onChange={v=>setDevisForm(f=>({...f,description:v}))}/></F>
                  <Sel value={devisForm.statut} onChange={v=>setDevisForm(f=>({...f,statut:v}))} style={{gridColumn:"1/-1"}}><option>En attente</option><option>Accepté</option><option>Refusé</option></Sel>
                  <Btn sm onClick={()=>{if(devisForm.artisan&&devisForm.montant){updProjet(sel,{devis:[...(selProjet.devis||[]),{...devisForm,id:uid()}]});setDevisForm({artisan:"",description:"",montant:"",date:today(),statut:"En attente"});}}}>+ Devis</Btn>
                </div>
              </div>}
            </div>
          </div>
        )}
      </div>
      {showAdd&&<Modal title="🏗️ Nouveau projet" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Nom du projet *" style={{gridColumn:"1/-1"}}><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Rénovation salle de bain, terrasse..."/></F>
          <F label="Type"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}>{["Travaux","Rénovation","Décoration","Aménagement extérieur","Construction","Déménagement","Autre"].map(t=><option key={t}>{t}</option>)}</Sel></F>
          <F label="Bien concerné"><Inp value={form.bien} onChange={v=>setForm(f=>({...f,bien:v}))} placeholder="Maison principale, Appartement..."/></F>
          <F label="Budget prévu (€)"><Inp type="number" value={form.budget} onChange={v=>setForm(f=>({...f,budget:v}))}/></F>
          <F label="Statut"><Sel value={form.statut} onChange={v=>setForm(f=>({...f,statut:v}))}>{STATUTS_PROJET.map(s=><option key={s}>{s}</option>)}</Sel></F>
          <F label="Date début"><Inp type="date" value={form.dateDebut} onChange={v=>setForm(f=>({...f,dateDebut:v}))}/></F>
          <F label="Date fin prévue"><Inp type="date" value={form.dateFin} onChange={v=>setForm(f=>({...f,dateFin:v}))}/></F>
          <F label="Note" style={{gridColumn:"1/-1"}}><Txt value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} rows={2}/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={save} disabled={!form.nom}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: MÉDICAMENTS & PHARMACIE
// ═══════════════════════════════════════════════════════════════════════════════
const Medicaments=({medicaments,setMedicaments})=>{
  const [tab,setTab]=useState("actifs");
  const [showAdd,setShowAdd]=useState(null);
  // Formulaires au niveau composant — pas d'IIFE useState
  const [traitForm,setTraitForm]=useState({nom:"",posologie:"",medecin:"",dateDebut:today(),dateFin:"",statut:"actif",note:""});
  const [ordoForm,setOrdoForm]=useState({medecin:"",date:today(),medicaments:"",note:""});
  const [stockForm,setStockForm]=useState({nom:"",categorie:"",dateExp:"",note:""});
  const resetTraitForm=()=>setTraitForm({nom:"",posologie:"",medecin:"",dateDebut:today(),dateFin:"",statut:"actif",note:""});
  const resetOrdoForm=()=>setOrdoForm({medecin:"",date:today(),medicaments:"",note:""});
  const resetStockForm=()=>setStockForm({nom:"",categorie:"",dateExp:"",note:""});
  const traitements=medicaments.traitements||[];
  const ordonnances=medicaments.ordonnances||[];
  const stock=medicaments.stock||[];
  const addTraitement=t=>setMedicaments(m=>({...m,traitements:[...(m.traitements||[]),{...t,id:uid()}]}));
  const addOrdonnance=o=>setMedicaments(m=>({...m,ordonnances:[...(m.ordonnances||[]),{...o,id:uid()}]}));
  const addStock=s=>setMedicaments(m=>({...m,stock:[...(m.stock||[]),{...s,id:uid()}]}));
  const actifs=traitements.filter(t=>t.statut==="actif");
  const bientotFin=actifs.filter(t=>t.dateFin&&daysFrom(t.dateFin)<=30&&daysFrom(t.dateFin)>=0);
  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>💊 Médicaments & Pharmacie</h1>
          <p style={{color:T.muted,fontSize:13,marginTop:3}}>{actifs.length} traitement{actifs.length>1?"s":""} actif{actifs.length>1?"s":""} · {stock.length} produit{stock.length>1?"s":""} en armoire</p>
        </div>
      </div>
      {bientotFin.length>0&&<div style={{padding:"10px 16px",background:"rgba(240,165,0,0.08)",border:"1px solid rgba(240,165,0,0.25)",borderRadius:10,marginBottom:14,fontSize:12,color:T.warning}}>
        ⚠️ Traitements se terminant bientôt : {bientotFin.map(t=><strong key={t.id} style={{marginRight:8}}>{t.nom} (dans {daysFrom(t.dateFin)}j)</strong>)}
      </div>}
      <Tabs tabs={[{id:"actifs",icon:"💊",label:`Traitements (${traitements.length})`},{id:"ordonnances",icon:"📋",label:`Ordonnances (${ordonnances.length})`},{id:"stock",icon:"🏥",label:`Armoire (${stock.length})`}]} active={tab} onChange={setTab}/>
      {tab==="actifs"&&<div style={{marginTop:16}}>
        <div style={{display:"flex",justifyContent:"flex-end",marginBottom:10}}><Btn onClick={()=>setShowAdd("traitement")}>+ Traitement</Btn></div>
        {traitements.length===0&&<EmptyState icon="💊" text="Enregistrez vos traitements médicaux en cours."/>}
        <div style={{display:"grid",gap:6}}>
          {traitements.sort((a,b)=>a.statut==="actif"?-1:1).map(t=>{
            const statColor=t.statut==="actif"?T.success:T.muted;
            return <div key={t.id} style={{display:"flex",gap:12,padding:"11px 16px",background:"#060a10",borderRadius:10,border:`1px solid ${T.border}`,alignItems:"center"}}>
              <span style={{fontSize:24}}>💊</span>
              <div style={{flex:1}}>
                <div style={{fontSize:13,fontWeight:700,color:T.text}}>{t.nom}</div>
                <div style={{fontSize:11,color:T.muted,marginTop:2}}>
                  {t.posologie&&<span style={{marginRight:8}}>📋 {t.posologie}</span>}
                  {t.medecin&&<span style={{marginRight:8}}>👨‍⚕️ {t.medecin}</span>}
                  {t.dateDebut&&<span>{fmt(t.dateDebut)}{t.dateFin&&` → ${fmt(t.dateFin)}`}</span>}
                </div>
                {t.note&&<div style={{fontSize:10,color:T.muted,fontStyle:"italic",marginTop:3}}>{t.note}</div>}
              </div>
              <Badge c={statColor}>{t.statut==="actif"?"✓ Actif":"Terminé"}</Badge>
              <button onClick={()=>setMedicaments(m=>({...m,traitements:m.traitements.map(x=>x.id===t.id?{...x,statut:x.statut==="actif"?"terminé":"actif"}:x)}))} style={{background:"none",border:`1px solid ${T.border}`,color:T.muted,borderRadius:6,padding:"3px 8px",cursor:"pointer",fontSize:11,fontFamily:T.font}}>↕</button>
              <button onClick={()=>setMedicaments(m=>({...m,traitements:m.traitements.filter(x=>x.id!==t.id)}))} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:13,opacity:0.5}}>🗑</button>
            </div>;
          })}
        </div>
      </div>}
      {tab==="ordonnances"&&<div style={{marginTop:16}}>
        <div style={{display:"flex",justifyContent:"flex-end",marginBottom:10}}><Btn onClick={()=>setShowAdd("ordonnance")}>+ Ordonnance</Btn></div>
        {ordonnances.length===0&&<EmptyState icon="📋" text="Archivez vos ordonnances."/>}
        <div style={{display:"grid",gap:5}}>
          {ordonnances.sort((a,b)=>b.date?.localeCompare(a.date||"")||0).map(o=><div key={o.id} style={{display:"flex",gap:12,padding:"10px 16px",background:"#060a10",borderRadius:10,border:`1px solid ${T.border}`,alignItems:"center"}}>
            <span style={{fontSize:20}}>📋</span>
            <div style={{flex:1}}>
              <div style={{fontSize:13,fontWeight:600,color:T.text}}>{o.medecin}</div>
              <div style={{fontSize:11,color:T.muted}}>{fmt(o.date)}{o.medicaments&&` · ${o.medicaments}`}</div>
            </div>
            <button onClick={()=>setMedicaments(m=>({...m,ordonnances:m.ordonnances.filter(x=>x.id!==o.id)}))} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,opacity:0.5}}>🗑</button>
          </div>)}
        </div>
      </div>}
      {tab==="stock"&&<div style={{marginTop:16}}>
        <div style={{display:"flex",justifyContent:"flex-end",marginBottom:10}}><Btn onClick={()=>setShowAdd("stock")}>+ Produit</Btn></div>
        {stock.length===0&&<EmptyState icon="🏥" text="Inventoriez votre armoire à pharmacie."/>}
        <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(240px,1fr))",gap:10}}>
          {stock.map(s=>{
            const expired=s.dateExp&&new Date(s.dateExp)<new Date();
            return <Card key={s.id} style={{borderColor:expired?"rgba(239,68,68,0.4)":T.border}}>
              <div style={{fontSize:13,fontWeight:700,color:T.text}}>{s.nom}</div>
              <div style={{fontSize:11,color:T.muted,marginTop:2}}>{s.categorie}</div>
              {s.dateExp&&<div style={{fontSize:11,marginTop:4,color:expired?T.danger:T.muted}}>
                {expired?"⚠️ Expiré le ":"📅 Expire le "}{fmt(s.dateExp)}
              </div>}
              {s.note&&<div style={{fontSize:10,color:T.muted,marginTop:3,fontStyle:"italic"}}>{s.note}</div>}
              <button onClick={()=>setMedicaments(m=>({...m,stock:m.stock.filter(x=>x.id!==s.id)}))} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,opacity:0.5,marginTop:6}}>🗑</button>
            </Card>;
          })}
        </div>
      </div>}
      {showAdd==="traitement"&&(
        <Modal title="💊 Nouveau traitement" onClose={()=>{setShowAdd(null);resetTraitForm();}}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Médicament *" style={{gridColumn:"1/-1"}}><Inp value={traitForm.nom} onChange={v=>setTraitForm(f=>({...f,nom:v}))}/></F>
            <F label="Posologie"><Inp value={traitForm.posologie} onChange={v=>setTraitForm(f=>({...f,posologie:v}))} placeholder="1 cp matin et soir"/></F>
            <F label="Prescrit par"><Inp value={traitForm.medecin} onChange={v=>setTraitForm(f=>({...f,medecin:v}))} placeholder="Dr. Martin"/></F>
            <F label="Début"><Inp type="date" value={traitForm.dateDebut} onChange={v=>setTraitForm(f=>({...f,dateDebut:v}))}/></F>
            <F label="Fin (si connu)"><Inp type="date" value={traitForm.dateFin} onChange={v=>setTraitForm(f=>({...f,dateFin:v}))}/></F>
            <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={traitForm.note} onChange={v=>setTraitForm(f=>({...f,note:v}))}/></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>{setShowAdd(null);resetTraitForm();}}>Annuler</Btn>
            <Btn onClick={()=>{addTraitement(traitForm);resetTraitForm();setShowAdd(null);}} disabled={!traitForm.nom}>💾</Btn>
          </div>
        </Modal>
      )}
      {showAdd==="ordonnance"&&(
        <Modal title="📋 Ordonnance" onClose={()=>{setShowAdd(null);resetOrdoForm();}}>
          <div style={{display:"grid",gap:8}}>
            <F label="Médecin"><Inp value={ordoForm.medecin} onChange={v=>setOrdoForm(f=>({...f,medecin:v}))}/></F>
            <F label="Date"><Inp type="date" value={ordoForm.date} onChange={v=>setOrdoForm(f=>({...f,date:v}))}/></F>
            <F label="Médicaments prescrits"><Txt value={ordoForm.medicaments} onChange={v=>setOrdoForm(f=>({...f,medicaments:v}))} rows={3}/></F>
            <F label="Note"><Inp value={ordoForm.note} onChange={v=>setOrdoForm(f=>({...f,note:v}))}/></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>{setShowAdd(null);resetOrdoForm();}}>Annuler</Btn>
            <Btn onClick={()=>{addOrdonnance(ordoForm);resetOrdoForm();setShowAdd(null);}}>💾</Btn>
          </div>
        </Modal>
      )}
      {showAdd==="stock"&&(
        <Modal title="🏥 Produit pharmacie" onClose={()=>{setShowAdd(null);resetStockForm();}}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
            <F label="Nom *"><Inp value={stockForm.nom} onChange={v=>setStockForm(f=>({...f,nom:v}))}/></F>
            <F label="Catégorie"><Sel value={stockForm.categorie} onChange={v=>setStockForm(f=>({...f,categorie:v}))}><option value="">—</option>{["Antidouleur","Antibiotique","Pansements","Antiseptique","Vitamines","Autre"].map(c=><option key={c}>{c}</option>)}</Sel></F>
            <F label="Date expiration"><Inp type="date" value={stockForm.dateExp} onChange={v=>setStockForm(f=>({...f,dateExp:v}))}/></F>
            <F label="Note"><Inp value={stockForm.note} onChange={v=>setStockForm(f=>({...f,note:v}))}/></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>{setShowAdd(null);resetStockForm();}}>Annuler</Btn>
            <Btn onClick={()=>{addStock(stockForm);resetStockForm();setShowAdd(null);}} disabled={!stockForm.nom}>💾</Btn>
          </div>
        </Modal>
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: PATRIMOINE (Tableau de bord)
// ═══════════════════════════════════════════════════════════════════════════════
const Patrimoine=({maisons,vehicules,banque,assurances,travail})=>{
  const immos=maisons.map(m=>({nom:m.nom||m.adresse,valeur:parseFloat(m.valeur)||0,type:"Immobilier"}));
  const vehis=vehicules.map(v=>({nom:`${v.marque||""} ${v.modele||""}`.trim(),valeur:parseFloat(v.valeurEstimee)||0,type:"Véhicule"}));
  const comptesBanque=(banque.comptes||[]).map(c=>({nom:c.nom,valeur:parseFloat(c.solde)||0,type:"Épargne/Liquidités"}));
  const credits=(banque.credits||[]).map(c=>({nom:c.nom,valeur:-(parseFloat(c.solde)||0),type:"Crédit"}));
  const assets=[...immos,...vehis,...comptesBanque.filter(c=>c.valeur>0)];
  const passifs=credits.filter(c=>c.valeur<0);
  const totalActif=assets.reduce((s,a)=>s+a.valeur,0);
  const totalPassif=Math.abs(passifs.reduce((s,p)=>s+p.valeur,0));
  const patrimoineNet=totalActif-totalPassif;
  const salaireMensuel=parseFloat(travail?.employeurActuel?.salaireBrut||0)*0.77;
  const groupBy=(arr,key)=>arr.reduce((m,x)=>{if(!m[x[key]])m[x[key]]=0;m[x[key]]+=x.valeur;return m;},{});
  const byType=groupBy(assets,"type");
  const COLORS={"Immobilier":T.accent,"Véhicule":T.info,"Épargne/Liquidités":T.success};
  return (
    <div>
      <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text,marginBottom:4}}>📊 Mon Patrimoine</h1>
      <p style={{color:T.muted,fontSize:13,marginBottom:18}}>Synthèse de votre situation patrimoniale</p>
      {/* KPIs */}
      <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:14,marginBottom:20}}>
        <div style={{background:`linear-gradient(135deg,rgba(240,165,0,0.1),transparent)`,border:`1px solid rgba(240,165,0,0.3)`,borderRadius:14,padding:"20px 24px"}}>
          <div style={{fontSize:11,color:T.muted,textTransform:"uppercase",marginBottom:6,letterSpacing:"0.07em"}}>Patrimoine net</div>
          <div style={{fontFamily:T.fontD,fontSize:36,fontWeight:700,color:T.accent}}>{fmtAmt(patrimoineNet)}</div>
          <div style={{fontSize:11,color:T.muted,marginTop:4}}>Actifs − Passifs</div>
        </div>
        <div style={{background:"#060a10",border:`1px solid ${T.border}`,borderRadius:14,padding:"20px 24px"}}>
          <div style={{fontSize:11,color:T.muted,textTransform:"uppercase",marginBottom:6,letterSpacing:"0.07em"}}>Total actifs</div>
          <div style={{fontFamily:T.fontD,fontSize:36,fontWeight:700,color:T.success}}>{fmtAmt(totalActif)}</div>
          <div style={{fontSize:11,color:T.muted,marginTop:4}}>{assets.length} élément{assets.length>1?"s":""}</div>
        </div>
        <div style={{background:"#060a10",border:`1px solid ${T.border}`,borderRadius:14,padding:"20px 24px"}}>
          <div style={{fontSize:11,color:T.muted,textTransform:"uppercase",marginBottom:6,letterSpacing:"0.07em"}}>Total dettes</div>
          <div style={{fontFamily:T.fontD,fontSize:36,fontWeight:700,color:T.danger}}>{fmtAmt(totalPassif)}</div>
          <div style={{fontSize:11,color:T.muted,marginTop:4}}>{passifs.length} crédit{passifs.length>1?"s":""}</div>
        </div>
      </div>
      <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:16}}>
        {/* Répartition actifs */}
        <Card>
          <Divider label="Répartition des actifs"/>
          {Object.entries(byType).map(([type,val])=>(
            <div key={type} style={{marginBottom:12}}>
              <div style={{display:"flex",justifyContent:"space-between",fontSize:12,marginBottom:4}}>
                <span style={{color:COLORS[type]||T.muted}}>{type}</span>
                <span style={{color:T.text,fontWeight:700}}>{fmtAmt(val)} · {Math.round(val/totalActif*100)}%</span>
              </div>
              <div style={{height:6,background:T.border,borderRadius:3}}>
                <div style={{height:6,background:COLORS[type]||T.muted,borderRadius:3,width:`${Math.round(val/totalActif*100)}%`,transition:"width 0.5s"}}/>
              </div>
            </div>
          ))}
          {totalActif===0&&<EmptyState icon="📊" text="Renseignez vos maisons, véhicules et comptes bancaires."/>}
        </Card>
        {/* Détail par postes */}
        <Card>
          <Divider label="Détail des actifs"/>
          {assets.length===0&&<EmptyState icon="📋" text="Aucun actif renseigné."/>}
          {assets.map((a,i)=>(
            <div key={i} style={{display:"flex",justifyContent:"space-between",padding:"8px 0",borderBottom:`1px solid ${T.border}`,fontSize:12}}>
              <span style={{color:T.muted}}>{a.nom||"—"}<span style={{fontSize:10,marginLeft:6,color:COLORS[a.type]||T.muted}}>({a.type})</span></span>
              <span style={{fontWeight:700,color:a.valeur>0?T.success:T.danger}}>{fmtAmt(a.valeur)}</span>
            </div>
          ))}
          {passifs.map((p,i)=>(
            <div key={"p"+i} style={{display:"flex",justifyContent:"space-between",padding:"8px 0",borderBottom:`1px solid ${T.border}`,fontSize:12}}>
              <span style={{color:T.muted}}>{p.nom} <span style={{fontSize:10,color:T.danger}}>(dette)</span></span>
              <span style={{fontWeight:700,color:T.danger}}>−{fmtAmt(Math.abs(p.valeur))}</span>
            </div>
          ))}
        </Card>
        {/* Revenus & capacité */}
        {salaireMensuel>0&&<Card>
          <Divider label="Capacité financière mensuelle"/>
          <div style={{display:"grid",gap:8}}>
            {[["Salaire net mensuel",fmtAmt(salaireMensuel),T.success],["Salaire net annuel",fmtAmt(salaireMensuel*12),T.success],["Mensualités crédits",fmtAmt(passifs.reduce((s,p)=>s+Math.abs(p.valeur)/240,0)),T.danger],["Taux d'endettement",`${Math.round(passifs.reduce((s,p)=>s+Math.abs(p.valeur)/240,0)/salaireMensuel*100)}%`,T.warning]].map(([l,v,c])=>(
              <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"6px 0",borderBottom:`1px solid ${T.border}`,fontSize:12}}>
                <span style={{color:T.muted}}>{l}</span><span style={{fontWeight:700,color:c}}>{v}</span>
              </div>
            ))}
          </div>
        </Card>}
        {/* Conseil */}
        <Card>
          <Divider label="💡 Conseils patrimoniaux"/>
          <div style={{fontSize:12,color:T.muted,lineHeight:1.9}}>
            {patrimoineNet>0&&<div>✅ Patrimoine net positif de <strong style={{color:T.success}}>{fmtAmt(patrimoineNet)}</strong></div>}
            {totalPassif>0&&totalActif>0&&<div>{totalPassif/totalActif>0.5?"⚠️ Ratio dettes/actifs élevé (>50%) — surveillez votre endettement.":"✅ Ratio dettes/actifs correct."}</div>}
            {immos.length===0&&<div>💡 L'immobilier est souvent le premier actif patrimonial — pensez à renseigner vos biens.</div>}
            {(banque.comptes||[]).filter(c=>c.type==="epargne").length===0&&<div>💡 Aucune épargne renseignée. Ajoutez vos comptes d'épargne dans Ma Banque.</div>}
          </div>
        </Card>
      </div>
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: RETRAITE
// ═══════════════════════════════════════════════════════════════════════════════
const Retraite=({retraite,setRetraite,travail})=>{
  const [tab,setTab]=useState("simulation");
  // Formulaire carrière au niveau composant
  const [carriereForm,setCarriereForm]=useState({employeur:"",dateDebut:"",dateFin:"",regime:"Régime général",note:""});
  const resetCarriereForm=()=>setCarriereForm({employeur:"",dateDebut:"",dateFin:"",regime:"Régime général",note:""});
  const updR=v=>setRetraite(r=>({...r,...v}));
  const r=retraite;
  const dateNaiss=r.dateNaissance?new Date(r.dateNaissance):null;
  const ageActuel=dateNaiss?Math.floor((new Date()-dateNaiss)/31557600000):null;
  const AGES_DEPART={1960:62,1961:62.25,1962:62.5,1963:62.75,1964:63};
  const anneeNaiss=dateNaiss?.getFullYear();
  const ageLegal=AGES_DEPART[anneeNaiss]||64;
  const annesRestants=ageActuel?Math.max(0,ageLegal-ageActuel):null;
  const trimestresAcquis=parseFloat(r.trimestresAcquis||0);
  const trimestresCible=parseFloat(r.trimestresCible||172);
  const progressionTrimestres=Math.min(100,Math.round(trimestresAcquis/trimestresCible*100));
  const dernierSalaire=parseFloat(travail?.employeurActuel?.salaireBrut||r.dernierSalaire||0)*0.77;
  const pensionEstimee=dernierSalaire*(trimestresAcquis/trimestresCible)*0.5;
  const addCarriere=c=>setRetraite(re=>({...re,carriere:[...(re.carriere||[]),{...c,id:uid()}]}));
  const carriere=r.carriere||[];
  return (
    <div>
      <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text,marginBottom:4}}>🧓 Ma Retraite</h1>
      <p style={{color:T.muted,fontSize:13,marginBottom:18}}>Simulez votre retraite et suivez vos trimestres</p>
      <Tabs tabs={[{id:"simulation",icon:"📊",label:"Simulation"},{id:"trimestres",icon:"🗓️",label:"Trimestres"},{id:"carriere",icon:"📋",label:"Carrière"},{id:"epargne",icon:"💰",label:"Épargne retraite"}]} active={tab} onChange={setTab}/>
      {tab==="simulation"&&<div style={{marginTop:16}}>
        <div style={{display:"grid",gridTemplateColumns:"340px 1fr",gap:16}}>
          <Card style={{padding:"18px 20px"}}>
            <Divider label="Votre situation"/>
            <div style={{display:"grid",gap:8}}>
              <F label="Date de naissance"><Inp type="date" value={r.dateNaissance||""} onChange={v=>updR({dateNaissance:v})}/></F>
              <F label="Régime de retraite"><Sel value={r.regime||""} onChange={v=>updR({regime:v})}><option value="">Choisir</option>{["Régime général (CNAV)","AGIRC-ARRCO","IRCANTEC","RSI","MSA","Fonctionnaire (CNRACL)","Autre"].map(t=><option key={t}>{t}</option>)}</Sel></F>
              <F label="Trimestres acquis"><Inp type="number" value={r.trimestresAcquis||""} onChange={v=>updR({trimestresAcquis:v})} placeholder="80"/></F>
              <F label="Trimestres requis"><Inp type="number" value={r.trimestresCible||172} onChange={v=>updR({trimestresCible:v})}/></F>
              <F label="Âge de départ souhaité (ans)"><Inp type="number" value={r.ageSouhaite||""} onChange={v=>updR({ageSouhaite:v})} placeholder="64"/></F>
            </div>
          </Card>
          <div style={{display:"grid",gap:12,alignContent:"start"}}>
            {ageActuel&&<div style={{background:`linear-gradient(135deg,rgba(240,165,0,0.1),transparent)`,border:"1px solid rgba(240,165,0,0.3)",borderRadius:14,padding:"20px 24px"}}>
              <div style={{fontSize:11,color:T.muted,textTransform:"uppercase",marginBottom:6}}>Pension mensuelle estimée</div>
              <div style={{fontFamily:T.fontD,fontSize:38,fontWeight:700,color:T.accent}}>{pensionEstimee>0?fmtAmt(Math.round(pensionEstimee)):"—"}</div>
              <div style={{fontSize:11,color:T.muted,marginTop:4}}>Estimation approximative — utilisez info-retraite.fr pour un calcul officiel</div>
            </div>}
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
              {ageActuel&&[["Âge actuel",`${ageActuel} ans`,T.text],["Âge légal",`${ageLegal} ans`,T.warning],["Départ dans",annesRestants?`~${Math.round(annesRestants)} ans`:"Bientôt !",annesRestants<=5?T.warning:T.success],["Progression trimes.",`${trimestresAcquis}/${trimestresCible} (${progressionTrimestres}%)`,T.info]].map(([l,v,c])=>(
                <div key={l} style={{background:"#060a10",borderRadius:10,padding:"12px 14px"}}>
                  <div style={{fontSize:10,color:T.muted,textTransform:"uppercase",letterSpacing:"0.06em",marginBottom:4}}>{l}</div>
                  <div style={{fontFamily:T.fontD,fontSize:18,fontWeight:700,color:c}}>{v}</div>
                </div>
              ))}
            </div>
            {trimestresAcquis>0&&<Card>
              <Divider label="Progression trimestres"/>
              <div style={{display:"flex",justifyContent:"space-between",fontSize:11,color:T.muted,marginBottom:6}}><span>{trimestresAcquis} acquis</span><span>{trimestresCible - trimestresAcquis} restants</span></div>
              <div style={{height:12,background:T.border,borderRadius:6}}><div style={{height:12,background:`linear-gradient(90deg,${T.success},${T.accent})`,borderRadius:6,width:`${progressionTrimestres}%`,transition:"width 0.5s"}}/></div>
              <div style={{textAlign:"center",fontSize:11,color:T.accent,marginTop:4,fontWeight:700}}>{progressionTrimestres}%</div>
            </Card>}
          </div>
        </div>
      </div>}
      {tab==="trimestres"&&<div style={{marginTop:16}}>
        <Card>
          <Divider label="Récapitulatif trimestres par période"/>
          <div style={{fontSize:12,color:T.muted,marginBottom:12}}>Reportez ici les informations de votre relevé de carrière disponible sur <a href="https://www.info-retraite.fr" target="_blank" rel="noreferrer" style={{color:T.info}}>info-retraite.fr</a></div>
          <div style={{display:"grid",gap:8}}>
            {[{l:"Emploi salarié privé",k:"salariePrivé"},{l:"Emploi salarié public",k:"salariePublic"},{l:"Emploi non salarié",k:"nonSalarie"},{l:"Périodes assimilées (chômage, maladie...)",k:"assimiles"},{l:"Rachat de trimestres",k:"rachetes"}].map(({l,k})=>(
              <div key={k} style={{display:"grid",gridTemplateColumns:"1fr 100px",gap:10,alignItems:"center"}}>
                <span style={{fontSize:12,color:T.muted}}>{l}</span>
                <Inp type="number" value={(r.trimestresDetail||{})[k]||""} onChange={v=>updR({trimestresDetail:{...(r.trimestresDetail||{}),[k]:v}})} placeholder="0"/>
              </div>
            ))}
            <div style={{borderTop:`1px solid ${T.border}`,paddingTop:8,display:"flex",justifyContent:"space-between",fontSize:13,fontWeight:700}}>
              <span style={{color:T.text}}>Total calculé</span>
              <span style={{color:T.accent}}>{Object.values(r.trimestresDetail||{}).reduce((s,v)=>s+(parseFloat(v)||0),0)} trimestres</span>
            </div>
          </div>
        </Card>
      </div>}
      {tab==="carriere"&&<div style={{marginTop:16}}>
        <div style={{fontSize:12,color:T.muted,marginBottom:12}}>Reconstituez votre carrière pour estimer vos trimestres validés. Les informations du module Travail sont automatiquement intégrées.</div>
        {travail?.historique?.length>0&&<div style={{marginBottom:14}}><Divider label="Depuis le module Travail"/>{travail.historique.map(p=>{const d1=new Date(p.dateDebut);const d2=p.dateFin?new Date(p.dateFin):new Date();const trimestres=Math.floor((d2-d1)/7776000000);return<div key={p.id} style={{padding:"8px 14px",background:"#060a10",borderRadius:8,marginBottom:4,fontSize:12,display:"flex",justifyContent:"space-between"}}><span style={{color:T.text}}>{p.poste} — {p.employeur}</span><span style={{color:T.accent}}>~{trimestres} trim.</span></div>;})}</div>}
        <div>
          <Divider label="Ajouter une période"/>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8}}>
            <F label="Employeur"><Inp value={carriereForm.employeur} onChange={v=>setCarriereForm(f=>({...f,employeur:v}))}/></F>
            <F label="Régime"><Sel value={carriereForm.regime} onChange={v=>setCarriereForm(f=>({...f,regime:v}))}>{["Régime général","Fonction publique","MSA","RSI","Autre"].map(t=><option key={t}>{t}</option>)}</Sel></F>
            <F label="Début"><Inp type="date" value={carriereForm.dateDebut} onChange={v=>setCarriereForm(f=>({...f,dateDebut:v}))}/></F>
            <F label="Fin"><Inp type="date" value={carriereForm.dateFin} onChange={v=>setCarriereForm(f=>({...f,dateFin:v}))}/></F>
          </div>
          <Btn sm onClick={()=>{if(carriereForm.employeur){addCarriere(carriereForm);resetCarriereForm();}}} style={{marginTop:8}}>+ Ajouter</Btn>
        </div>
      </div>}
      {tab==="epargne"&&<div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14,marginTop:16}}>
        {[{k:"per",label:"PER — Plan d'épargne retraite",icon:"💼"},{k:"assuranceVie",label:"Assurance vie",icon:"📋"},{k:"perp",label:"PERP / Madelin",icon:"📄"},{k:"prefon",label:"Préfon (fonctionnaires)",icon:"🏛️"}].map(({k,label,icon})=>(
          <Card key={k}>
            <Divider label={`${icon} ${label}`}/>
            <div style={{display:"grid",gap:7}}>
              {[{fk:"organisme",l:"Organisme"},{fk:"solde",l:"Encours (€)"},{fk:"versementMensuel",l:"Versement mensuel (€)"},{fk:"dateOuverture",l:"Date d'ouverture"},{fk:"note",l:"Note"}].map(({fk,l})=>(
                <F key={fk} label={l}><Inp type={fk==="solde"||fk==="versementMensuel"?"number":"text"} value={(r.epargneRetraite?.[k]||{})[fk]||""} onChange={v=>updR({epargneRetraite:{...r.epargneRetraite,[k]:{...(r.epargneRetraite?.[k]||{}),[fk]:v}}})}/></F>
              ))}
            </div>
          </Card>
        ))}
      </div>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: GUIDE D'UTILISATION
// ═══════════════════════════════════════════════════════════════════════════════
const GUIDE_SECTIONS=[
  {id:"start",icon:"🚀",titre:"Démarrer avec NumaVie",contenu:[
    {q:"Qu'est-ce que NumaVie ?",r:"NumaVie est votre coffre-fort numérique personnel — une application complète pour centraliser TOUTE votre vie administrative, financière, familiale et personnelle en un seul endroit sécurisé. Aucune donnée ne quitte votre appareil ou votre NAS Synology."},
    {q:"Comment naviguer dans l'application ?",r:"La barre latérale gauche est organisée en 6 sections : Accueil (tableau de bord + patrimoine), Mes Biens, Ma Vie, Loisirs, Famille, Contacts & Suivi. Cliquez sur n'importe quel module pour l'ouvrir. Le module actif est mis en surbrillance dorée."},
    {q:"Comment sauvegarder mes données ?",r:"La sauvegarde automatique est active en permanence (localStorage). Pour une sauvegarde sécurisée : cliquez sur 💾 dans la barre du bas → Export JSON (toutes vos données + fichiers). Conservez ce fichier en lieu sûr. Pour restaurer, utilisez Import JSON. Faites une sauvegarde AVANT chaque mise à jour de l'application."},
    {q:"Comment utiliser la recherche globale ?",r:"Cliquez sur l'icône 🔍 dans la barre d'outils (en haut) ou appuyez sur Ctrl+K. Tapez n'importe quel mot-clé : nom d'une personne, montant, date, lieu, référence... La recherche parcourt TOUS les modules simultanément et affiche les résultats classés par pertinence et type."},
  ]},
  {id:"biens",icon:"🏠",titre:"Mes Biens",contenu:[
    {q:"Archivage — Comment classer mes documents ?",r:"Dans Archivage, cliquez + Nouveau document, choisissez le type (facture, contrat, courrier...) et uploadez le fichier. Il sera converti en base64 pour être stocké localement. Utilisez les tags et catégories pour retrouver rapidement. La visionneuse PDF intégrée permet de consulter sans télécharger."},
    {q:"Mes Maisons — Que puis-je enregistrer ?",r:"Pour chaque bien immobilier : adresse complète, surface, DPE, valeur estimée, prix d'achat, notaire, chauffage... Chaque maison a sa propre fiche avec onglets Documents et Échanges. Les assurances et charges liées remontent automatiquement depuis les autres modules."},
    {q:"Gestion locative — Comment suivre mes locataires ?",r:"Ajoutez chaque locataire avec son bail, loyer, dépôt de garantie. Un système de messagerie intégré permet les échanges. Les quittances sont générables automatiquement. Un indicateur dans la sidebar signale les messages non lus."},
    {q:"Garanties & SAV — Comment ne plus perdre ses garanties ?",r:"Enregistrez chaque appareil avec sa date d'achat, sa durée de garantie et sa date de fin. L'application calcule automatiquement le temps restant et affiche une alerte orange 90 jours avant expiration, rouge 30 jours avant. Le numéro de série est stocké pour faciliter les déclarations SAV."},
    {q:"Projets & Travaux — Comment organiser un chantier ?",r:"Créez un projet avec budget, dates et statut. Ajoutez vos artisans (avec SIRET pour vérification), saisissez les devis reçus (comparaison automatique vs budget), et créez une liste de tâches à cocher. La progression en % se calcule automatiquement selon les tâches réalisées."},
  ]},
  {id:"mavie",icon:"💼",titre:"Ma Vie",contenu:[
    {q:"Banque — Comment enregistrer mes transactions ?",r:"Dans Ma Banque, l'onglet Transactions permet d'ajouter manuellement vos opérations par catégorie. Le tableau de bord affiche vos KPIs mensuels, l'évolution sur 6 mois et la répartition par catégorie. Le simulateur de crédit calcule mensualité, capacité d'emprunt et comparatif taux."},
    {q:"Impôts — Comment préparer ma déclaration ?",r:"Enregistrez vos revenus fonciers, charges déductibles, crédits d'impôt au fil de l'année. Le module calcule une estimation de votre impôt. Archivez vos avis d'imposition et utilisez les modèles de courrier pour les demandes de délai de paiement."},
    {q:"Mon Travail — Que faire de mes fiches de paie ?",r:"Dans Travail → Fiches de paie, ajoutez chaque mois en indiquant brut, net et CP acquis. Vous pouvez joindre le PDF de chaque fiche (visualisable directement). L'onglet Carrière vous aide à reconstituer votre historique professionnel, utile pour le calcul retraite."},
    {q:"Ma Retraite — Comment simuler ma pension ?",r:"Renseignez votre date de naissance et vos trimestres acquis (disponibles sur info-retraite.fr). L'application calcule votre âge légal de départ (selon votre année de naissance), votre progression et une estimation de pension. L'onglet Épargne retraite recense vos PER et assurances vie."},
    {q:"Abonnements — Comment éviter les oublis ?",r:"Enregistrez chaque abonnement avec son montant, sa périodicité et sa date de renouvellement. Le tableau de bord calcule votre total mensuel et annuel par catégorie (streaming, internet, logiciels...). Une alerte orange s'affiche 30 jours avant un renouvellement."},
    {q:"Énergie — Comment suivre ma consommation ?",r:"Entrez vos relevés de compteur régulièrement (idéalement 2x/an). L'application calcule automatiquement votre consommation entre deux relevés et affiche un historique graphique. Les informations fournisseur (contrat, numéro de compteur) sont stockées pour les démarches."},
    {q:"Coffre-fort — Mes mots de passe sont-ils sécurisés ?",r:"Oui — toutes les données sont stockées uniquement en local (sur votre appareil ou NAS). Aucune transmission externe. Utilisez le générateur intégré pour créer des mots de passe forts (16 caractères, chiffres, lettres, symboles). La fonction 📋 copie en 1 clic sans afficher le mot de passe."},
  ]},
  {id:"famille",icon:"👨‍👩‍👧‍👦",titre:"Famille & Amis",contenu:[
    {q:"Identité — Que mettre dans ce module ?",r:"Centralisez ici tous vos documents d'identité (carte d'identité, passeport, permis, carte vitale...) avec leurs dates d'expiration. L'application calcule automatiquement le temps restant et génère des alertes dans le module Alertes. Ajoutez aussi les documents de chaque membre de la famille."},
    {q:"Mes Amis — Comment ajouter une photo ?",r:"Ouvrez la fiche d'un ami (clic sur la carte). Dans l'en-tête, cliquez sur l'avatar circulaire ou l'icône 📷. Sélectionnez une photo depuis votre appareil. Elle s'affiche immédiatement sur la fiche ET sur la carte dans la grille. La photo est sauvegardée en base64 avec les autres données."},
    {q:"Mes Enfants — Quel suivi est disponible ?",r:"Pour chaque enfant : résumé (infos de naissance, groupe sanguin, médecin), Santé (vaccins, RDV), Scolarité (établissements, classes), Activités (sports, arts, coûts). Tous les échanges avec médecins ou écoles sont tracés dans l'onglet Échanges de chaque fiche."},
    {q:"Budget Cadeaux — Comment organiser Noël ?",r:"Créez d'abord les personnes de votre liste. Ajoutez ensuite des idées pour chaque personne avec l'occasion (Noël, anniversaire...), le budget estimé et un lien URL vers le produit. Faites évoluer le statut : idée → acheté → offert. Les alertes d'anniversaire à 30 jours sont automatiques."},
  ]},
  {id:"outils",icon:"🔧",titre:"Outils avancés",contenu:[
    {q:"Moteur de recherche — Comment trouver une information ?",r:"Cliquez sur 🔍 Recherche dans la section Accueil ou utilisez le raccourci clavier Ctrl+K. La recherche full-text parcourt simultanément : noms, adresses, montants, dates, notes, références... dans TOUS les modules. Les résultats sont groupés par module avec un lien direct vers la fiche concernée."},
    {q:"Planificateur de Séjour — Comment préparer un voyage ?",r:"Dans Loisirs → Planificateur, créez un nouveau séjour avec destination, dates, budget. Ajoutez des étapes avec lieux, hébergements, activités. La roadmap visuelle affiche votre itinéraire jour par jour. Les liens Google Maps/Waze sont générés automatiquement pour chaque adresse saisie."},
    {q:"Organisateur d'Événements — Mariage, anniversaire... comment faire ?",r:"Dans Famille → Événements, créez votre événement (type, date, lieu, budget). Gérez votre liste d'invités avec confirmation de présence et régime alimentaire. Ajoutez des prestataires (traiteur, DJ, photographe...) avec leurs devis. Le planning heure par heure vous guide le jour J. Le budget se met à jour automatiquement."},
    {q:"Modèles de courrier — Comment exporter en PDF ?",r:"Dans Contacts & Suivi → Modèles courrier, choisissez un modèle dans la bibliothèque (16 disponibles) ou créez le vôtre. Remplissez les variables [entre crochets]. Cliquez sur 📄 Export PDF pour générer un document formaté comme un vrai courrier officiel. Vous pouvez aussi Imprimer ou Copier le texte."},
    {q:"Sauvegarde — Quelle stratégie adopter ?",r:"Stratégie recommandée : (1) La sauvegarde automatique localStorage est continue mais locale. (2) Faites un Export JSON complet chaque dimanche. (3) Stockez ce fichier dans votre NAS Synology, cloud (Drive, Dropbox) ET une clé USB. (4) Avant toute mise à jour de l'app, exportez TOUJOURS une sauvegarde. Un Export ZIP inclut aussi tous les fichiers joints séparément."},
  ]},
  {id:"modules",icon:"📋",titre:"Inventaire des 34 modules",contenu:[
    {q:"🏠 Accueil (2 modules)",r:"⬡ Tableau de bord — Vue synthétique de toute l'application avec alertes urgentes, documents récents, KPIs locatifs et financiers.\n📊 Mon Patrimoine — Synthèse actifs/passifs, valeur nette, répartition par type, conseils patrimoniaux."},
    {q:"🏗️ Mes Biens (6 modules)",r:"📄 Archivage — Gestionnaire documentaire universel avec OCR simulé et visionneuse PDF.\n🏡 Mes Maisons — Fiches immobilières complètes.\n🚗 Véhicules — Suivi entretien, assurance, contrôle technique.\n🏠 Gestion locative — Locataires, loyers, quittances, messagerie.\n🔧 Garanties & SAV — Appareils et dates de garantie.\n🏗️ Projets & Travaux — Chantiers, artisans, devis, tâches."},
    {q:"💼 Ma Vie (11 modules)",r:"🏥 Ma Santé — RDV, ordonnances, remboursements, médecins.\n💊 Médicaments — Traitements, ordonnances, armoire à pharmacie.\n🏛️ Impôts — Déclarations, revenus, charges.\n🏦 Ma Banque — Comptes, transactions, budget, simulateur crédit.\n🛡️ Assurances — Contrats, sinistres, échéances.\n⚖️ Juridique — Procédures, contrats, huissiers.\n💼 Mon Travail — Employeur, fiches de paie, congés, carrière.\n🧓 Ma Retraite — Simulation, trimestres, épargne retraite.\n🔌 Abonnements — Récurrents, alertes renouvellement.\n⚡ Énergie — Compteurs, relevés, fournisseurs.\n🤲 Dons & Asso. — Dons, reçus fiscaux, réduction impôts."},
    {q:"🎉 Loisirs (5 modules)",r:"⚽ Sports & Passions — Activités, clubs, résultats, équipement.\n📸 Photos & Vidéos — Galerie, albums, tag personnes (3 onglets).\n✈️ Voyages & Vacances — Voyages passés et à venir.\n📚 Ma Bibliothèque — Livres lus, en cours, à lire, notes.\n🗺️ Planificateur de Séjour — Roadmap et itinéraires détaillés."},
    {q:"👨‍👩‍👧‍👦 Famille (7 modules)",r:"🪪 Identité — Documents officiels avec alertes expiration.\n👨‍👩‍👧‍👦 Vie de famille — Événements marquants, capsule temporelle.\n👫 Mes Amis — Fiches amis, réseaux sociaux, photos.\n👶 Mes Enfants — Santé, scolarité, activités.\n🐾 Mes Animaux — Vétérinaire, vaccins, traitements.\n🎁 Budget Cadeaux — Idées, statuts, alertes anniversaire.\n🎉 Organisateur d'Événements — Mariage, fête, cérémonie."},
    {q:"📞 Contacts & Suivi (4 modules)",r:"👥 Contacts — Carnet d'adresses professionnel.\n🔔 Alertes — Rappels et échéances urgentes.\n📝 Modèles courrier — 16 modèles + export PDF.\n🔐 Coffre-fort — Mots de passe sécurisés en local."},
  ]},
];

const Guide=()=>{
  const [section,setSection]=useState("start");
  const [open,setOpen]=useState({});
  const [search,setSearch]=useState("");
  const toggle=id=>setOpen(o=>({...o,[id]:!o[id]}));
  const secActive=GUIDE_SECTIONS.find(s=>s.id===section);
  const allQR=GUIDE_SECTIONS.flatMap(s=>s.contenu.map(c=>({...c,section:s.titre,icon:s.icon})));
  const filteredQR=search.length>2?allQR.filter(c=>c.q.toLowerCase().includes(search.toLowerCase())||c.r.toLowerCase().includes(search.toLowerCase())):null;
  return (
    <div>
      <div style={{marginBottom:20}}>
        <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>📖 Guide d'utilisation</h1>
        <p style={{color:T.muted,fontSize:13,marginTop:3}}>NumaVie v1.0 · {GUIDE_SECTIONS.reduce((s,sec)=>s+sec.contenu.length,0)} questions/réponses · {34} modules documentés</p>
      </div>
      <Inp value={search} onChange={setSearch} placeholder="🔍 Rechercher dans le guide..." style={{maxWidth:400,marginBottom:20}}/>
      {filteredQR?(
        <div>
          <div style={{fontSize:12,color:T.muted,marginBottom:12}}>{filteredQR.length} résultat{filteredQR.length>1?"s":""} pour « {search} »</div>
          {filteredQR.map((c,i)=><div key={i} style={{marginBottom:8,border:`1px solid ${T.border}`,borderRadius:10,overflow:"hidden"}}>
            <div style={{padding:"12px 16px",background:"#060a10",fontSize:13,fontWeight:700,color:T.accent}}>{c.icon} {c.section} — {c.q}</div>
            <div style={{padding:"12px 16px",fontSize:12,color:T.muted,lineHeight:1.8,whiteSpace:"pre-line"}}>{c.r}</div>
          </div>)}
        </div>
      ):(
        <div style={{display:"grid",gridTemplateColumns:"220px 1fr",gap:16}}>
          <div style={{display:"grid",gap:4,alignContent:"start"}}>
            {GUIDE_SECTIONS.map(s=>(
              <button key={s.id} onClick={()=>setSection(s.id)} style={{textAlign:"left",padding:"10px 14px",borderRadius:9,border:`1px solid ${section===s.id?T.accent:T.border}`,background:section===s.id?T.accentDim:"transparent",color:section===s.id?T.accent:T.muted,cursor:"pointer",fontFamily:T.font,fontSize:12,fontWeight:section===s.id?700:400}}>
                {s.icon} {s.titre}
              </button>
            ))}
          </div>
          <div>
            <div style={{fontFamily:T.fontD,fontSize:18,color:T.text,marginBottom:14}}>{secActive?.icon} {secActive?.titre}</div>
            {secActive?.contenu.map((item,i)=>{
              const id=section+i;
              return <div key={id} style={{marginBottom:6,border:`1px solid ${open[id]?T.accent:T.border}`,borderRadius:10,overflow:"hidden",transition:"border-color 0.2s"}}>
                <button onClick={()=>toggle(id)} style={{width:"100%",textAlign:"left",padding:"13px 16px",background:open[id]?T.accentDim:"#060a10",border:"none",color:open[id]?T.accent:T.text,cursor:"pointer",fontFamily:T.font,fontSize:13,fontWeight:600,display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                  <span>{item.q}</span><span style={{fontSize:16,color:T.muted,flexShrink:0,marginLeft:10}}>{open[id]?"▲":"▼"}</span>
                </button>
                {open[id]&&<div style={{padding:"14px 16px",background:"#040810",fontSize:12,color:T.muted,lineHeight:1.9,whiteSpace:"pre-line",borderTop:`1px solid ${T.border}`}}>{item.r}</div>}
              </div>;
            })}
          </div>
        </div>
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: RECHERCHE GLOBALE
// ═══════════════════════════════════════════════════════════════════════════════
const RechercheGlobale=({allData,setPage})=>{
  const [query,setQuery]=useState("");
  const [resultats,setResultats]=useState([]);
  const [searching,setSearching]=useState(false);
  const inputRef=useRef();

  useEffect(()=>{inputRef.current?.focus();},[]);

  const search=useCallback((q)=>{
    if(!q||q.trim().length<2){setResultats([]);return;}
    setSearching(true);
    const r=[];const lq=q.toLowerCase().trim();
    const match=v=>v&&String(v).toLowerCase().includes(lq);
    const add=(module,icon,titre,sous,detail,id)=>r.push({module,icon,titre,sous,detail,id:id||uid()});

    // Docs
    (allData.docs||[]).forEach(d=>{if(match(d.nom)||match(d.type)||match(d.fournisseur)||match(d.texte)||match(d.date))add("docs","📄",d.nom||"Document sans titre",d.type,`${d.date||""}${d.fournisseur?" · "+d.fournisseur:""}${d.montant?" · "+d.montant+" €":""}`,d.id);});
    // Maisons
    (allData.maisons||[]).forEach(m=>{if(match(m.nom)||match(m.adresse)||match(m.ville)||match(m.notaire))add("maisons","🏡",m.nom||m.adresse||"Maison","Mes Maisons",`${m.adresse||""}${m.valeur?" · "+m.valeur+" €":""}`,m.id);});
    // Véhicules
    (allData.vehicules||[]).forEach(v=>{if(match(v.marque)||match(v.modele)||match(v.immatriculation)||match(v.note))add("vehicules","🚗",`${v.marque||""} ${v.modele||""}`.trim()||"Véhicule","Véhicules",`${v.immatriculation||""}${v.annee?" · "+v.annee:""}`,v.id);});
    // Locataires
    (allData.locataires||[]).forEach(l=>{if(match(l.nom)||match(l.email)||match(l.tel)||match(l.bienLoue))add("locataires","🏠",l.nom||"Locataire","Gestion locative",`${l.bienLoue||""}${l.loyer?" · "+l.loyer+" €/mois":""}`,l.id);});
    // Contacts
    (allData.contacts||[]).forEach(c=>{if(match(c.nom)||match(c.email)||match(c.tel)||match(c.rue)||match(c.ville)||match(c.societe))add("contacts","👥",c.nom,"Contacts",`${c.societe||""}${c.tel?" · "+c.tel:""}${c.ville?" · "+c.ville:""}`,c.id);});
    // Amis
    (allData.amis||[]).forEach(a=>{if(match(a.prenom)||match(a.nom)||match(a.email)||match(a.ville)||match(a.rue)||match(a.notes)||match(a.description))add("amis","👫",`${a.prenom} ${a.nom}`,"Mes Amis",`${a.ville||""}${a.email?" · "+a.email:""}`,a.id);});
    // Santé
    const sante=allData.sante||{};
    (sante.rdv||[]).forEach(r2=>{if(match(r2.titre)||match(r2.medecin)||match(r2.specialite)||match(r2.adresse))add("sante","🏥",r2.titre,"RDV Santé",`${r2.medecin||""}${r2.date?" · "+r2.date:""}${r2.adresse?" · "+r2.adresse:""}`,r2.id);});
    (sante.medecins||[]).forEach(m2=>{if(match(m2.nom)||match(m2.specialite)||match(m2.adresse))add("sante","👨‍⚕️",m2.nom,"Médecins",`${m2.specialite||""}${m2.adresse?" · "+m2.adresse:""}`,m2.id);});
    // Banque transactions
    const banque=allData.banque||{};
    (banque.transactions||[]).forEach(t=>{if(match(t.libelle)||match(t.categorie)||match(t.montant))add("banque","🏦",t.libelle||"Transaction","Ma Banque",`${t.montant?t.montant+" €":""} · ${t.date||""}`,t.id);});
    // Assurances
    (allData.assurances||[]).forEach(a2=>{if(match(a2.nom)||match(a2.assureur)||match(a2.numero)||match(a2.type))add("assurances","🛡️",a2.nom||a2.type||"Assurance","Assurances",`${a2.assureur||""}${a2.numero?" · N°"+a2.numero:""}`,a2.id);});
    // Travail
    const trav=allData.travail||{};
    if(match(trav.employeurActuel?.employeur)||match(trav.employeurActuel?.poste)){add("travail","💼",trav.employeurActuel?.poste||"Mon poste","Mon Travail",trav.employeurActuel?.employeur||"");}
    (trav.historique||[]).forEach(p=>{if(match(p.poste)||match(p.employeur)||match(p.ville))add("travail","📋",p.poste,"Carrière",`${p.employeur||""}${p.ville?" · "+p.ville:""}`,p.id);});
    (trav.formations||[]).forEach(f=>{if(match(f.titre)||match(f.organisme)||match(f.certification))add("travail","🎓",f.titre,"Formations",`${f.organisme||""}${f.certification?" · "+f.certification:""}`,f.id);});
    // Abonnements
    (allData.abonnements||[]).forEach(a3=>{if(match(a3.nom)||match(a3.note))add("abonnements","🔌",a3.nom,"Abonnements",`${a3.montant||""} €/${a3.periodicite||"mois"}`,a3.id);});
    // Garanties
    (allData.garanties||[]).forEach(g=>{if(match(g.nom)||match(g.marque)||match(g.modele)||match(g.magasin)||match(g.numeroSerie))add("garanties","🔧",g.nom,"Garanties",`${g.marque||""}${g.modele?" · "+g.modele:""}${g.finGarantie?" · fin:"+g.finGarantie:""}`,g.id);});
    // Enfants
    (allData.enfants||[]).forEach(e=>{if(match(e.prenom)||match(e.nom)||match(e.ecoleActuelle)||match(e.lieuNaissance))add("enfants","👶",`${e.prenom} ${e.nom||""}`,"Mes Enfants",`${e.ecoleActuelle||""}${e.dateNaissance?" · né(e) "+e.dateNaissance:""}`,e.id);});
    // Animaux
    (allData.animaux||[]).forEach(a4=>{if(match(a4.nom)||match(a4.espece)||match(a4.race)||match(a4.veterinaire))add("animaux","🐾",a4.nom,"Mes Animaux",`${a4.espece||""} ${a4.race||""}`.trim(),a4.id);});
    // Voyages
    (allData.voyages||[]).forEach(v2=>{if(match(v2.destination)||match(v2.pays)||match(v2.note)||match(v2.hebergement))add("voyages","✈️",v2.destination||"Voyage","Voyages",`${v2.pays||""}${v2.dateDebut?" · "+v2.dateDebut:""}`,v2.id);});
    // Identité documents
    (allData.identite?.documents||[]).forEach(d2=>{if(match(d2.type)||match(d2.numero)||match(d2.nom))add("identite","🪪",d2.type||"Document identité","Identité",`${d2.numero||""}${d2.dateFin?" · expire "+d2.dateFin:""}`,d2.id);});
    // Alertes
    (allData.alertes||[]).forEach(a5=>{if(match(a5.titre)||match(a5.note)||match(a5.categorie))add("alertes","🔔",a5.titre,"Alertes",`${a5.categorie||""}${a5.date?" · "+a5.date:""}`,a5.id);});
    // Projets
    (allData.projets||[]).forEach(p2=>{if(match(p2.nom)||match(p2.bien)||match(p2.note))add("projets","🏗️",p2.nom,"Projets & Travaux",`${p2.type||""}${p2.bien?" · "+p2.bien:""}${p2.statut?" · "+p2.statut:""}`,p2.id);});
    // Dons
    (allData.dons||[]).forEach(d3=>{if(match(d3.association)||match(d3.note))add("dons","🤲",d3.association,"Dons",`${d3.montant||""} €${d3.date?" · "+d3.date:""}`,d3.id);});
    // Bibliothèque
    (allData.bibliotheque?.livres||[]).forEach(l2=>{if(match(l2.titre)||match(l2.auteur)||match(l2.note_lecture))add("bibliotheque","📚",l2.titre,"Bibliothèque",`${l2.auteur||""}${l2.statut?" · "+l2.statut:""}`,l2.id);});
    // Médicaments
    (allData.medicaments?.traitements||[]).forEach(m3=>{if(match(m3.nom)||match(m3.medecin)||match(m3.posologie))add("medicaments","💊",m3.nom,"Médicaments",`${m3.posologie||""}${m3.medecin?" · "+m3.medecin:""}`,m3.id);});
    // Coffre-fort (seulement site et login, pas le mdp)
    (allData.coffreFortData||[]).forEach(c2=>{if(match(c2.site)||match(c2.login)||match(c2.url))add("coffrefort","🔐",c2.site,"Coffre-fort",c2.login||"",c2.id);});
    // Cadeaux
    (allData.cadeaux?.idees||[]).forEach(i=>{if(match(i.idee)||match(i.note)||match(i.occasion))add("cadeaux","🎁",i.idee,"Cadeaux",`${i.occasion||""}${i.budget?" · "+i.budget+" €":""}`,i.id);});

    setResultats(r);setSearching(false);
  },[allData]);

  useEffect(()=>{const t=setTimeout(()=>search(query),250);return()=>clearTimeout(t);},[query,search]);

  const grouped=resultats.reduce((m,r2)=>{if(!m[r2.module])m[r2.module]=[];m[r2.module].push(r2);return m;},{});
  const MOD_LABELS={docs:"📄 Archivage",maisons:"🏡 Maisons",vehicules:"🚗 Véhicules",locataires:"🏠 Locataires",contacts:"👥 Contacts",amis:"👫 Amis",sante:"🏥 Santé",banque:"🏦 Banque",assurances:"🛡️ Assurances",travail:"💼 Travail",abonnements:"🔌 Abonnements",garanties:"🔧 Garanties",enfants:"👶 Enfants",animaux:"🐾 Animaux",voyages:"✈️ Voyages",identite:"🪪 Identité",alertes:"🔔 Alertes",projets:"🏗️ Projets",dons:"🤲 Dons",bibliotheque:"📚 Bibliothèque",medicaments:"💊 Médicaments",coffrefort:"🔐 Coffre-fort",cadeaux:"🎁 Cadeaux"};

  return (
    <div>
      <div style={{marginBottom:20}}>
        <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🔍 Recherche globale</h1>
        <p style={{color:T.muted,fontSize:13,marginTop:3}}>Trouvez n'importe quelle information dans tous vos modules</p>
      </div>
      <div style={{position:"relative",marginBottom:20}}>
        <Inp ref={inputRef} value={query} onChange={setQuery} placeholder="Nom, lieu, montant, date, référence, n° de série..." style={{fontSize:16,padding:"14px 18px 14px 48px",width:"100%"}}/>
        <span style={{position:"absolute",left:14,top:"50%",transform:"translateY(-50%)",fontSize:20,pointerEvents:"none"}}>🔍</span>
        {query&&<button onClick={()=>setQuery("")} style={{position:"absolute",right:14,top:"50%",transform:"translateY(-50%)",background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:16}}>✕</button>}
      </div>
      {query.length>0&&query.length<2&&<div style={{color:T.muted,fontSize:12,textAlign:"center"}}>Tapez au moins 2 caractères...</div>}
      {query.length>=2&&resultats.length===0&&!searching&&(
        <EmptyState icon="🔍" text={`Aucun résultat pour « ${query} ». Essayez avec un autre terme.`}/>
      )}
      {resultats.length>0&&(
        <div>
          <div style={{fontSize:12,color:T.muted,marginBottom:14}}>{resultats.length} résultat{resultats.length>1?"s":""} dans {Object.keys(grouped).length} module{Object.keys(grouped).length>1?"s":""}</div>
          {Object.entries(grouped).map(([mod,items])=>(
            <div key={mod} style={{marginBottom:18}}>
              <div style={{fontSize:11,color:T.accent,fontWeight:700,textTransform:"uppercase",letterSpacing:"0.08em",marginBottom:8}}>{MOD_LABELS[mod]||mod} · {items.length}</div>
              <div style={{display:"grid",gap:5}}>
                {items.slice(0,8).map(item=>(
                  <div key={item.id} onClick={()=>setPage(mod)} style={{display:"flex",gap:12,padding:"10px 16px",background:"#060a10",borderRadius:10,border:`1px solid ${T.border}`,cursor:"pointer",alignItems:"center"}}
                    onMouseEnter={e=>e.currentTarget.style.borderColor=T.accent}
                    onMouseLeave={e=>e.currentTarget.style.borderColor=T.border}>
                    <span style={{fontSize:20,flexShrink:0}}>{item.icon}</span>
                    <div style={{flex:1,minWidth:0}}>
                      <div style={{fontSize:13,fontWeight:600,color:T.text,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}
                        dangerouslySetInnerHTML={{__html:item.titre.replace(new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")})`, "gi"),"<mark style='background:rgba(240,165,0,0.3);color:#f0a500;borderRadius:3px;padding:0 2px'>$1</mark>")}}/>
                      <div style={{fontSize:11,color:T.muted,marginTop:2}}>{item.sous} {item.detail&&`· ${item.detail}`}</div>
                    </div>
                    <span style={{fontSize:11,color:T.accent,flexShrink:0}}>→ Aller</span>
                  </div>
                ))}
                {items.length>8&&<div style={{fontSize:11,color:T.muted,textAlign:"center",padding:"6px 0"}}>+{items.length-8} autres résultats dans ce module</div>}
              </div>
            </div>
          ))}
        </div>
      )}
      {!query&&(
        <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(200px,1fr))",gap:10,marginTop:8}}>
          <div style={{fontSize:12,color:T.muted,gridColumn:"1/-1",marginBottom:4}}>Suggestions de recherche :</div>
          {["loyer","assurance","passeport","prescription","facture EDF","garantie","formation","anniversaire","crédit","vaccin"].map(s=>(
            <button key={s} onClick={()=>setQuery(s)} style={{padding:"8px 14px",background:"#060a10",border:`1px solid ${T.border}`,borderRadius:8,color:T.muted,fontSize:12,cursor:"pointer",fontFamily:T.font,textAlign:"left"}}>
              🔍 {s}
            </button>
          ))}
        </div>
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: PLANIFICATEUR DE SÉJOUR
// ═══════════════════════════════════════════════════════════════════════════════
const PlanificateurSejour=({sejours,setSejours})=>{
  const [sel,setSel]=useState(null);
  const [tab,setTab]=useState("roadmap");
  const [showAdd,setShowAdd]=useState(null);
  const [checkItemText,setCheckItemText]=useState("");
  // Formulaires modales au niveau composant
  const [etapeForm,setEtapeForm]=useState({lieu:"",adresse:"",date:"",duree:"1",note:"",activitesDuJour:""});
  const [hebergForm,setHebergForm]=useState({nom:"",type:"Hôtel",adresse:"",dateArrivee:"",dateDepart:"",prix:"",confirmation:"",note:""});
  const [transportForm,setTransportForm]=useState({type:"Avion",compagnie:"",numero:"",depart:"",arrivee:"",date:"",heure:"",prix:"",note:""});
  const [activiteForm,setActiviteForm]=useState({nom:"",type:"Visite",lieu:"",date:"",heure:"",prix:"",reservation:"",note:""});
  const EMPTY_SEJOUR={nom:"",destination:"",pays:"",dateDebut:"",dateFin:"",budget:"",nbPersonnes:"1",type:"Vacances",statut:"En préparation",note:"",etapes:[],hebergements:[],activites:[],transports:[],docs:[],checklist:[]};
  const [form,setForm]=useState({...EMPTY_SEJOUR});
  const selSejour=sel&&sejours.find(s=>s.id===sel);
  const save=()=>{setSejours(p=>[...p,{...form,id:uid()}]);setShowAdd(null);setForm({...EMPTY_SEJOUR});};
  const updSejour=(v)=>setSejours(p=>p.map(s=>s.id===sel?{...s,...v}:s));
  const addEtape=e=>updSejour({etapes:[...(selSejour.etapes||[]),{...e,id:uid()}]});
  const addHeberg=h=>updSejour({hebergements:[...(selSejour.hebergements||[]),{...h,id:uid()}]});
  const addActivite=a=>updSejour({activites:[...(selSejour.activites||[]),{...a,id:uid()}]});
  const addTransport=t=>updSejour({transports:[...(selSejour.transports||[]),{...t,id:uid()}]});
  const addCheckItem=t=>updSejour({checklist:[...(selSejour.checklist||[]),{texte:t,fait:false,id:uid()}]});
  const toggleCheck=id=>updSejour({checklist:(selSejour.checklist||[]).map(c=>c.id===id?{...c,fait:!c.fait}:c)});

  // Calcul durée
  const duree=(s)=>{if(!s.dateDebut||!s.dateFin)return null;return Math.round((new Date(s.dateFin)-new Date(s.dateDebut))/86400000)+1;};

  const CHECKLIST_DEFAULTS=["Réserver les billets d'avion/train","Réserver l'hébergement","Souscrire assurance voyage","Vérifier validité passeport/carte d'identité","Prévenir la banque du déplacement","Télécharger cartes offline","Préparer pharmacie de voyage","Photocopier documents importants","Informer quelqu'un de l'itinéraire","Prévoir monnaie locale"];

  const TYPE_SEJOUR=["Vacances","City break","Road trip","Trek / Randonnée","Séjour sportif","Culturel","Détente","Professionnel","Croisière","Autre"];

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🗺️ Planificateur de Séjour</h1>
          <p style={{color:T.muted,fontSize:13,marginTop:3}}>Préparez votre prochain voyage étape par étape</p>
        </div>
        <Btn onClick={()=>setShowAdd("sejour")}>+ Nouveau séjour</Btn>
      </div>

      {!sel?(
        <div>
          {sejours.length===0&&<EmptyState icon="🗺️" text="Créez votre premier séjour pour commencer la planification !"/>}
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(310px,1fr))",gap:14}}>
            {sejours.map(s=>{
              const j=duree(s);
              const statColor=s.statut==="Terminé"?T.muted:s.statut==="En cours"?T.success:T.accent;
              const etapesTotal=(s.etapes||[]).length;
              const budgetDepense=(s.activites||[]).reduce((sum,a)=>sum+(parseFloat(a.prix)||0),0)+(s.hebergements||[]).reduce((sum,h)=>sum+(parseFloat(h.prix)||0),0)+(s.transports||[]).reduce((sum,t)=>sum+(parseFloat(t.prix)||0),0);
              return <Card key={s.id} onClick={()=>{setSel(s.id);setTab("roadmap");}} style={{cursor:"pointer",padding:0,overflow:"hidden",borderColor:sel===s.id?T.accent:T.border}}>
                <div style={{background:`linear-gradient(135deg,rgba(240,165,0,0.12),transparent)`,padding:"16px 18px",borderBottom:`1px solid ${T.border}`}}>
                  <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                    <div>
                      <div style={{fontFamily:T.fontD,fontSize:16,fontWeight:700,color:T.text}}>{s.nom||s.destination}</div>
                      <div style={{fontSize:12,color:T.muted,marginTop:2}}>📍 {s.destination}{s.pays&&`, ${s.pays}`}</div>
                    </div>
                    <Badge c={statColor}>{s.statut}</Badge>
                  </div>
                </div>
                <div style={{padding:"12px 18px"}}>
                  <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:6,fontSize:11,color:T.muted}}>
                    {s.dateDebut&&<span>📅 {fmt(s.dateDebut)}{j&&` (${j}j)`}</span>}
                    <span>👥 {s.nbPersonnes} pers.</span>
                    {s.budget&&<span>💶 Budget : {fmtAmt(s.budget)}</span>}
                    {budgetDepense>0&&<span style={{color:budgetDepense>parseFloat(s.budget)?T.danger:T.success}}>Dépensé : {fmtAmt(budgetDepense)}</span>}
                    {etapesTotal>0&&<span>🗺️ {etapesTotal} étape{etapesTotal>1?"s":""}</span>}
                    <span>✈️ {s.type}</span>
                  </div>
                </div>
              </Card>;
            })}
          </div>
        </div>
      ):(selSejour&&(
        <div>
          {/* Header séjour */}
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:16,padding:"16px 20px",background:"#060a10",borderRadius:12,border:`1px solid ${T.border}`}}>
            <div>
              <div style={{fontFamily:T.fontD,fontSize:20,color:T.text}}>{selSejour.nom||selSejour.destination}</div>
              <div style={{fontSize:12,color:T.muted,marginTop:2}}>📍 {selSejour.destination}{selSejour.pays&&`, ${selSejour.pays}`} · {duree(selSejour)&&`${duree(selSejour)} jours`} · {selSejour.nbPersonnes} pers. · Budget : {fmtAmt(selSejour.budget)}</div>
            </div>
            <div style={{display:"flex",gap:8}}>
              <Sel value={selSejour.statut} onChange={v=>updSejour({statut:v})} style={{fontSize:11}}>{["En préparation","Confirmé","En cours","Terminé","Annulé"].map(s=><option key={s}>{s}</option>)}</Sel>
              <Btn sm v="ghost" onClick={()=>setSel(null)}>← Retour</Btn>
              <button onClick={()=>{if(confirm("Supprimer ce séjour ?"))setSejours(p=>p.filter(s=>s.id!==sel));setSel(null);}} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:14}}>🗑</button>
            </div>
          </div>

          <Tabs tabs={[{id:"roadmap",icon:"🗺️",label:"Roadmap"},{id:"hebergement",icon:"🏨",label:`Hébergements (${(selSejour.hebergements||[]).length})`},{id:"transport",icon:"🚆",label:`Transports (${(selSejour.transports||[]).length})`},{id:"activites",icon:"🎯",label:`Activités (${(selSejour.activites||[]).length})`},{id:"budget",icon:"💶",label:"Budget"},{id:"checklist",icon:"✅",label:`Check-list (${(selSejour.checklist||[]).filter(c=>c.fait).length}/${(selSejour.checklist||[]).length})`},{id:"docs",icon:"📎",label:"Documents"}]} active={tab} onChange={setTab}/>

          <div style={{marginTop:16}}>
            {/* ROADMAP */}
            {tab==="roadmap"&&<div>
              <div style={{display:"flex",justifyContent:"flex-end",marginBottom:12}}>
                <Btn onClick={()=>setShowAdd("etape")}>+ Étape</Btn>
              </div>
              {(selSejour.etapes||[]).length===0&&<EmptyState icon="🗺️" text="Ajoutez des étapes pour construire votre roadmap jour par jour."/>}
              <div style={{position:"relative"}}>
                {(selSejour.etapes||[]).sort((a,b)=>a.date?.localeCompare(b.date||"")||0).map((e,i)=>(
                  <div key={e.id} style={{display:"flex",gap:14,marginBottom:12}}>
                    <div style={{display:"flex",flexDirection:"column",alignItems:"center",width:28,flexShrink:0}}>
                      <div style={{width:28,height:28,borderRadius:14,background:T.accent,display:"flex",alignItems:"center",justifyContent:"center",fontSize:12,fontWeight:700,color:"#000",flexShrink:0}}>{i+1}</div>
                      {i<(selSejour.etapes||[]).length-1&&<div style={{width:2,flex:1,background:T.border,minHeight:20,marginTop:4}}/>}
                    </div>
                    <div style={{flex:1,padding:"14px 16px",background:"#060a10",borderRadius:12,border:`1px solid ${T.border}`}}>
                      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                        <div>
                          <div style={{fontFamily:T.fontD,fontSize:15,color:T.text,fontWeight:700}}>{e.lieu}</div>
                          {e.date&&<div style={{fontSize:11,color:T.accent,marginTop:2}}>📅 {fmt(e.date)}{e.duree&&` · ${e.duree} nuit${e.duree>1?"s":""}`}</div>}
                        </div>
                        <button onClick={()=>updSejour({etapes:(selSejour.etapes||[]).filter(x=>x.id!==e.id)})} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:13,opacity:0.5}}>🗑</button>
                      </div>
                      {e.adresse&&<div style={{marginTop:6}}><MapsLinks adresse={e.adresse} label="Ouvrir dans Maps"/></div>}
                      {e.note&&<div style={{fontSize:11,color:T.muted,fontStyle:"italic",marginTop:6}}>{e.note}</div>}
                      {e.activitesDuJour&&<div style={{marginTop:8,fontSize:12,color:T.muted}}>🎯 {e.activitesDuJour}</div>}
                    </div>
                  </div>
                ))}
              </div>
              {selSejour.note&&<div style={{marginTop:14,padding:"12px 16px",background:"rgba(240,165,0,0.06)",border:"1px solid rgba(240,165,0,0.2)",borderRadius:10,fontSize:12,color:T.muted}}>{selSejour.note}</div>}
            </div>}

            {/* HÉBERGEMENTS */}
            {tab==="hebergement"&&<div>
              <div style={{display:"flex",justifyContent:"flex-end",marginBottom:12}}><Btn onClick={()=>setShowAdd("hebergement")}>+ Hébergement</Btn></div>
              {(selSejour.hebergements||[]).length===0&&<EmptyState icon="🏨" text="Ajoutez vos hébergements : hôtels, Airbnb, camping..."/>}
              {(selSejour.hebergements||[]).map(h=><Card key={h.id} style={{marginBottom:8}}>
                <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                  <div>
                    <div style={{fontSize:14,fontWeight:700,color:T.text}}>🏨 {h.nom}</div>
                    <div style={{fontSize:11,color:T.muted,marginTop:3}}>{h.type&&`${h.type} · `}{h.adresse&&`📍 ${h.adresse}`}</div>
                    <div style={{fontSize:11,color:T.muted,marginTop:2}}>{h.dateArrivee&&`Arrivée ${fmt(h.dateArrivee)}`}{h.dateDepart&&` → Départ ${fmt(h.dateDepart)}`}{h.prix&&` · ${fmtAmt(h.prix)}`}</div>
                    {h.confirmation&&<div style={{fontSize:10,color:T.accent,marginTop:2}}>N° confirmation : {h.confirmation}</div>}
                  </div>
                  <button onClick={()=>updSejour({hebergements:(selSejour.hebergements||[]).filter(x=>x.id!==h.id)})} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:13,opacity:0.5}}>🗑</button>
                </div>
                {h.adresse&&<div style={{marginTop:8}}><MapsLinks adresse={h.adresse}/></div>}
              </Card>)}
            </div>}

            {/* TRANSPORTS */}
            {tab==="transport"&&<div>
              <div style={{display:"flex",justifyContent:"flex-end",marginBottom:12}}><Btn onClick={()=>setShowAdd("transport")}>+ Transport</Btn></div>
              {(selSejour.transports||[]).length===0&&<EmptyState icon="🚆" text="Avion, train, voiture, ferry... Enregistrez tous vos transports."/>}
              {(selSejour.transports||[]).sort((a,b)=>a.date?.localeCompare(b.date||"")||0).map(t=><div key={t.id} style={{display:"flex",gap:12,padding:"12px 16px",background:"#060a10",borderRadius:10,border:`1px solid ${T.border}`,marginBottom:6,alignItems:"center"}}>
                <span style={{fontSize:24}}>{t.type==="Avion"?"✈️":t.type==="Train"?"🚆":t.type==="Voiture"?"🚗":t.type==="Ferry"?"⛴️":t.type==="Bus"?"🚌":"🚀"}</span>
                <div style={{flex:1}}>
                  <div style={{fontSize:13,fontWeight:700,color:T.text}}>{t.type} · {t.depart} → {t.arrivee}</div>
                  <div style={{fontSize:11,color:T.muted,marginTop:2}}>{t.date&&fmt(t.date)}{t.heure&&` ${t.heure}`}{t.compagnie&&` · ${t.compagnie}`}{t.numero&&` · N°${t.numero}`}</div>
                  {t.prix&&<div style={{fontSize:11,color:T.success,marginTop:2}}>{fmtAmt(t.prix)}</div>}
                </div>
                <button onClick={()=>updSejour({transports:(selSejour.transports||[]).filter(x=>x.id!==t.id)})} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:13,opacity:0.5}}>🗑</button>
              </div>)}
            </div>}

            {/* ACTIVITÉS */}
            {tab==="activites"&&<div>
              <div style={{display:"flex",justifyContent:"flex-end",marginBottom:12}}><Btn onClick={()=>setShowAdd("activite")}>+ Activité</Btn></div>
              {(selSejour.activites||[]).length===0&&<EmptyState icon="🎯" text="Musées, restaurants, excursions... planifiez vos activités."/>}
              <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(260px,1fr))",gap:10}}>
                {(selSejour.activites||[]).map(a=><Card key={a.id}>
                  <div style={{display:"flex",justifyContent:"space-between"}}>
                    <div style={{fontSize:14,fontWeight:700,color:T.text}}>{a.nom}</div>
                    <button onClick={()=>updSejour({activites:(selSejour.activites||[]).filter(x=>x.id!==a.id)})} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,opacity:0.5}}>🗑</button>
                  </div>
                  <div style={{fontSize:11,color:T.muted,marginTop:4}}>{a.type&&<Badge c={T.info}>{a.type}</Badge>}</div>
                  {a.date&&<div style={{fontSize:11,color:T.muted,marginTop:4}}>📅 {fmt(a.date)}{a.heure&&` ${a.heure}`}</div>}
                  {a.lieu&&<div style={{fontSize:11,color:T.muted,marginTop:2}}>📍 {a.lieu}</div>}
                  {a.prix&&<div style={{fontSize:11,color:T.success,marginTop:2}}>💶 {fmtAmt(a.prix)}/pers.</div>}
                  {a.reservation&&<div style={{fontSize:10,color:T.accent,marginTop:2}}>✓ Réservé · {a.reservation}</div>}
                  {a.lieu&&<div style={{marginTop:8}}><MapsLinks adresse={a.lieu}/></div>}
                </Card>)}
              </div>
            </div>}

            {/* BUDGET */}
            {tab==="budget"&&<div>
              {(()=>{
                const hebergTotal=(selSejour.hebergements||[]).reduce((s,h)=>s+(parseFloat(h.prix)||0),0);
                const transportTotal=(selSejour.transports||[]).reduce((s,t)=>s+(parseFloat(t.prix)||0),0);
                const activitesTotal=(selSejour.activites||[]).reduce((s,a)=>s+(parseFloat(a.prix)||0)*(parseInt(selSejour.nbPersonnes)||1),0);
                const total=hebergTotal+transportTotal+activitesTotal;
                const budget=parseFloat(selSejour.budget)||0;
                const reste=budget-total;
                return <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
                  <Card>
                    <Divider label="Récapitulatif budgétaire"/>
                    {[["🏨 Hébergements",hebergTotal,T.info],["🚆 Transports",transportTotal,T.accent],["🎯 Activités",activitesTotal,T.purple]].map(([l,v,c])=><div key={l} style={{display:"flex",justifyContent:"space-between",padding:"8px 0",borderBottom:`1px solid ${T.border}`,fontSize:12}}><span style={{color:T.muted}}>{l}</span><span style={{fontWeight:700,color:c}}>{fmtAmt(v)}</span></div>)}
                    <div style={{display:"flex",justifyContent:"space-between",padding:"10px 0",fontSize:13,fontWeight:700}}><span style={{color:T.text}}>Total estimé</span><span style={{color:total>budget?T.danger:T.success}}>{fmtAmt(total)}</span></div>
                    {budget>0&&<div style={{padding:"10px 12px",background:reste>=0?"rgba(34,197,94,0.08)":"rgba(239,68,68,0.08)",borderRadius:8,marginTop:4}}>
                      <div style={{fontSize:12,fontWeight:700,color:reste>=0?T.success:T.danger}}>{reste>=0?`✅ Reste dans le budget : ${fmtAmt(reste)}`:`⚠️ Dépassement : ${fmtAmt(Math.abs(reste))}`}</div>
                    </div>}
                  </Card>
                  <Card>
                    <Divider label="Répartition"/>
                    {total>0&&[["Hébergements",hebergTotal,T.info],["Transports",transportTotal,T.accent],["Activités",activitesTotal,T.purple]].map(([l,v,c])=><div key={l} style={{marginBottom:10}}>
                      <div style={{display:"flex",justifyContent:"space-between",fontSize:11,marginBottom:3}}><span style={{color:T.muted}}>{l}</span><span style={{color:c}}>{Math.round(v/total*100)}%</span></div>
                      <div style={{height:6,background:T.border,borderRadius:3}}><div style={{height:6,background:c,borderRadius:3,width:`${Math.round(v/total*100)}%`}}/></div>
                    </div>)}
                  </Card>
                </div>;
              })()}
            </div>}

            {/* CHECK-LIST */}
            {tab==="checklist"&&<div>
              {(selSejour.checklist||[]).length===0&&<div style={{marginBottom:16}}>
                <div style={{fontSize:12,color:T.muted,marginBottom:10}}>Charger la liste pré-remplie :</div>
                <Btn v="ghost" onClick={()=>updSejour({checklist:CHECKLIST_DEFAULTS.map(t=>({texte:t,fait:false,id:uid()}))})}>📋 Charger la liste standard</Btn>
              </div>}
              <div style={{display:"flex",justifyContent:"space-between",fontSize:11,color:T.muted,marginBottom:10}}>
                <span>{(selSejour.checklist||[]).filter(c=>c.fait).length} / {(selSejour.checklist||[]).length} éléments cochés</span>
                <button onClick={()=>updSejour({checklist:(selSejour.checklist||[]).map(c=>({...c,fait:true}))})} style={{background:"none",border:"none",color:T.accent,cursor:"pointer",fontSize:11,fontFamily:T.font}}>Tout cocher</button>
              </div>
              {(selSejour.checklist||[]).length>0&&<div style={{height:6,background:T.border,borderRadius:3,marginBottom:14}}><div style={{height:6,background:T.success,borderRadius:3,width:`${Math.round((selSejour.checklist||[]).filter(c=>c.fait).length/(selSejour.checklist||[]).length*100)}%`,transition:"width 0.3s"}}/></div>}
              <div style={{display:"grid",gap:4}}>
                {(selSejour.checklist||[]).map(c=><div key={c.id} style={{display:"flex",alignItems:"center",gap:10,padding:"8px 12px",borderRadius:8,background:"#060a10"}}>
                  <input type="checkbox" checked={c.fait} onChange={()=>toggleCheck(c.id)} style={{accentColor:T.accent}}/>
                  <span style={{fontSize:13,color:c.fait?T.muted:T.text,textDecoration:c.fait?"line-through":"none"}}>{c.texte}</span>
                  <button onClick={()=>updSejour({checklist:(selSejour.checklist||[]).filter(x=>x.id!==c.id)})} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:11,marginLeft:"auto",opacity:0.5}}>✕</button>
                </div>)}
              </div>
              <div style={{display:"flex",gap:8,marginTop:10}}>
                <Inp value={checkItemText} onChange={setCheckItemText} placeholder="Ajouter un élément..." style={{flex:1}}/>
                <Btn sm onClick={()=>{if(checkItemText.trim()){addCheckItem(checkItemText.trim());setCheckItemText("");}}}>+</Btn>
              </div>
            </div>}

            {/* DOCUMENTS */}
            {tab==="docs"&&<DocAttach docs={selSejour.docs||[]} onChange={nd=>updSejour({docs:nd})} label="Billets, réservations, visa, assurance voyage..."/>}
          </div>
        </div>
      ))}

      {/* MODALES AJOUT */}
      {showAdd==="sejour"&&<Modal title="✈️ Nouveau séjour" onClose={()=>setShowAdd(null)} width={600}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Nom du séjour *" style={{gridColumn:"1/-1"}}><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Vacances Italie 2025, City break Amsterdam..."/></F>
          <F label="Destination *"><Inp value={form.destination} onChange={v=>setForm(f=>({...f,destination:v}))} placeholder="Rome"/></F>
          <F label="Pays"><Inp value={form.pays} onChange={v=>setForm(f=>({...f,pays:v}))} placeholder="Italie"/></F>
          <F label="Date de départ"><Inp type="date" value={form.dateDebut} onChange={v=>setForm(f=>({...f,dateDebut:v}))}/></F>
          <F label="Date de retour"><Inp type="date" value={form.dateFin} onChange={v=>setForm(f=>({...f,dateFin:v}))}/></F>
          <F label="Budget total (€)"><Inp type="number" value={form.budget} onChange={v=>setForm(f=>({...f,budget:v}))}/></F>
          <F label="Nombre de voyageurs"><Inp type="number" value={form.nbPersonnes} onChange={v=>setForm(f=>({...f,nbPersonnes:v}))}/></F>
          <F label="Type"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}>{TYPE_SEJOUR.map(t=><option key={t}>{t}</option>)}</Sel></F>
          <F label="Statut"><Sel value={form.statut} onChange={v=>setForm(f=>({...f,statut:v}))}>{["En préparation","Confirmé","En cours","Terminé","Annulé"].map(s=><option key={s}>{s}</option>)}</Sel></F>
          <F label="Notes / Idées" style={{gridColumn:"1/-1"}}><Txt value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} rows={2} placeholder="Idées d'activités, contacts locaux, infos pratiques..."/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
          <Btn onClick={save} disabled={!form.nom||!form.destination}>💾 Créer le séjour</Btn>
        </div>
      </Modal>}

      {showAdd==="etape"&&sel&&(
        <Modal title="📍 Nouvelle étape" onClose={()=>setShowAdd(null)}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Lieu *" style={{gridColumn:"1/-1"}}><Inp value={etapeForm.lieu} onChange={v=>setEtapeForm(f=>({...f,lieu:v}))} placeholder="Rome, Venise..."/></F>
            <F label="Adresse"><Inp value={etapeForm.adresse} onChange={v=>setEtapeForm(f=>({...f,adresse:v}))} placeholder="Via Condotti, Rome"/></F>
            <F label="Date"><Inp type="date" value={etapeForm.date} onChange={v=>setEtapeForm(f=>({...f,date:v}))}/></F>
            <F label="Nuitées"><Inp type="number" value={etapeForm.duree} onChange={v=>setEtapeForm(f=>({...f,duree:v}))} placeholder="2"/></F>
            <F label="Activités du jour" style={{gridColumn:"1/-1"}}><Inp value={etapeForm.activitesDuJour} onChange={v=>setEtapeForm(f=>({...f,activitesDuJour:v}))} placeholder="Colisée, pasta..."/></F>
            <F label="Notes" style={{gridColumn:"1/-1"}}><Txt value={etapeForm.note} onChange={v=>setEtapeForm(f=>({...f,note:v}))} rows={2}/></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
            <Btn onClick={()=>{if(etapeForm.lieu){addEtape(etapeForm);setEtapeForm({lieu:"",adresse:"",date:"",duree:"1",note:"",activitesDuJour:""});setShowAdd(null);}}} disabled={!etapeForm.lieu}>💾</Btn>
          </div>
        </Modal>
      )}

      {showAdd==="hebergement"&&sel&&(
        <Modal title="🏨 Hébergement" onClose={()=>setShowAdd(null)}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Nom *"><Inp value={hebergForm.nom} onChange={v=>setHebergForm(f=>({...f,nom:v}))} placeholder="Hôtel Roma, Airbnb..."/></F>
            <F label="Type"><Sel value={hebergForm.type} onChange={v=>setHebergForm(f=>({...f,type:v}))}>{["Hôtel","Airbnb","Camping","Gîte","Chambre d'hôtes","Auberge de jeunesse","Maison d'ami","Autre"].map(t=><option key={t}>{t}</option>)}</Sel></F>
            <F label="Adresse" style={{gridColumn:"1/-1"}}><Inp value={hebergForm.adresse} onChange={v=>setHebergForm(f=>({...f,adresse:v}))} placeholder="Via Roma 12, Rome"/></F>
            <F label="Arrivée"><Inp type="date" value={hebergForm.dateArrivee} onChange={v=>setHebergForm(f=>({...f,dateArrivee:v}))}/></F>
            <F label="Départ"><Inp type="date" value={hebergForm.dateDepart} onChange={v=>setHebergForm(f=>({...f,dateDepart:v}))}/></F>
            <F label="Prix total (€)"><Inp type="number" value={hebergForm.prix} onChange={v=>setHebergForm(f=>({...f,prix:v}))}/></F>
            <F label="N° confirmation"><Inp value={hebergForm.confirmation} onChange={v=>setHebergForm(f=>({...f,confirmation:v}))}/></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
            <Btn onClick={()=>{if(hebergForm.nom){addHeberg(hebergForm);setHebergForm({nom:"",type:"Hôtel",adresse:"",dateArrivee:"",dateDepart:"",prix:"",confirmation:"",note:""});setShowAdd(null);}}} disabled={!hebergForm.nom}>💾</Btn>
          </div>
        </Modal>
      )}

      {showAdd==="transport"&&sel&&(
        <Modal title="🚆 Transport" onClose={()=>setShowAdd(null)}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Type"><Sel value={transportForm.type} onChange={v=>setTransportForm(f=>({...f,type:v}))}>{["Avion","Train","Voiture","Bus","Ferry","Métro","Taxi/VTC","Autre"].map(t=><option key={t}>{t}</option>)}</Sel></F>
            <F label="Compagnie"><Inp value={transportForm.compagnie} onChange={v=>setTransportForm(f=>({...f,compagnie:v}))} placeholder="Air France, SNCF..."/></F>
            <F label="De (départ) *"><Inp value={transportForm.depart} onChange={v=>setTransportForm(f=>({...f,depart:v}))} placeholder="Paris CDG"/></F>
            <F label="Vers (arrivée) *"><Inp value={transportForm.arrivee} onChange={v=>setTransportForm(f=>({...f,arrivee:v}))} placeholder="Rome FCO"/></F>
            <F label="Date"><Inp type="date" value={transportForm.date} onChange={v=>setTransportForm(f=>({...f,date:v}))}/></F>
            <F label="Heure départ"><Inp type="time" value={transportForm.heure} onChange={v=>setTransportForm(f=>({...f,heure:v}))}/></F>
            <F label="N° vol/train"><Inp value={transportForm.numero} onChange={v=>setTransportForm(f=>({...f,numero:v}))} placeholder="AF1234"/></F>
            <F label="Prix (€)"><Inp type="number" value={transportForm.prix} onChange={v=>setTransportForm(f=>({...f,prix:v}))}/></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
            <Btn onClick={()=>{if(transportForm.depart&&transportForm.arrivee){addTransport(transportForm);setTransportForm({type:"Avion",compagnie:"",numero:"",depart:"",arrivee:"",date:"",heure:"",prix:"",note:""});setShowAdd(null);}}} disabled={!transportForm.depart||!transportForm.arrivee}>💾</Btn>
          </div>
        </Modal>
      )}

      {showAdd==="activite"&&sel&&(
        <Modal title="🎯 Activité" onClose={()=>setShowAdd(null)}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Nom *" style={{gridColumn:"1/-1"}}><Inp value={activiteForm.nom} onChange={v=>setActiviteForm(f=>({...f,nom:v}))} placeholder="Colisée, restaurant Da Mario..."/></F>
            <F label="Type"><Sel value={activiteForm.type} onChange={v=>setActiviteForm(f=>({...f,type:v}))}>{["Visite","Restaurant","Excursion","Sport","Plage","Shopping","Spectacle","Autre"].map(t=><option key={t}>{t}</option>)}</Sel></F>
            <F label="Lieu / Adresse"><Inp value={activiteForm.lieu} onChange={v=>setActiviteForm(f=>({...f,lieu:v}))}/></F>
            <F label="Date"><Inp type="date" value={activiteForm.date} onChange={v=>setActiviteForm(f=>({...f,date:v}))}/></F>
            <F label="Heure"><Inp type="time" value={activiteForm.heure} onChange={v=>setActiviteForm(f=>({...f,heure:v}))}/></F>
            <F label="Prix / personne (€)"><Inp type="number" value={activiteForm.prix} onChange={v=>setActiviteForm(f=>({...f,prix:v}))}/></F>
            <F label="N° réservation" style={{gridColumn:"1/-1"}}><Inp value={activiteForm.reservation} onChange={v=>setActiviteForm(f=>({...f,reservation:v}))}/></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
            <Btn onClick={()=>{if(activiteForm.nom){addActivite(activiteForm);setActiviteForm({nom:"",type:"Visite",lieu:"",date:"",heure:"",prix:"",reservation:"",note:""});setShowAdd(null);}}} disabled={!activiteForm.nom}>💾</Btn>
          </div>
        </Modal>
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: ORGANISATEUR D'ÉVÉNEMENTS
// ═══════════════════════════════════════════════════════════════════════════════
const TYPE_EVENEMENT=[{id:"mariage",l:"Mariage",icon:"💒",color:"#f472b6"},{id:"anniversaire",l:"Anniversaire",icon:"🎂",color:"#f0a500"},{id:"bapteme",l:"Baptême / Naissance",icon:"👶",color:"#38bdf8"},{id:"deces",l:"Obsèques",icon:"🌹",color:"#94a3b8"},{id:"fete",l:"Fête / Soirée",icon:"🎉",color:"#a78bfa"},{id:"seminaire",l:"Séminaire / Réunion",icon:"💼",color:"#34d399"},{id:"autre",l:"Autre",icon:"📅",color:"#fb923c"}];

const OrganisateurEvenements=({evenements,setEvenements})=>{
  const [sel,setSel]=useState(null);
  const [tab,setTab]=useState("infos");
  const [showAdd,setShowAdd]=useState(null);
  // Formulaires modales au niveau composant
  const [tacheEvForm,setTacheEvForm]=useState({texte:"",echeance:""});
  const [inviteForm,setInviteForm]=useState({prenom:"",nom:"",tel:"",email:"",table:"",regime:"",statut:"En attente",note:""});
  const [prestForm,setPrestForm]=useState({nom:"",type:"Traiteur",tel:"",email:"",montant:"",statut:"En attente",note:""});
  const [planningForm,setPlanningForm]=useState({heure:"",titre:"",lieu:"",duree:"",note:""});
  const EMPTY_EV={nom:"",type:"mariage",date:"",lieu:"",adresse:"",budget:"",nbInvites:"",statut:"En préparation",note:"",invites:[],prestataires:[],planning:[],taches:[],docs:[]};
  const [form,setForm]=useState({...EMPTY_EV});
  const selEv=sel&&evenements.find(e=>e.id===sel);
  const save=()=>{setEvenements(p=>[...p,{...form,id:uid()}]);setShowAdd(null);setForm({...EMPTY_EV});};
  const updEv=v=>setEvenements(p=>p.map(e=>e.id===sel?{...e,...v}:e));

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🎉 Organisateur d'Événements</h1>
          <p style={{color:T.muted,fontSize:13,marginTop:3}}>Mariage, anniversaire, obsèques, séminaire — planifiez tout avec sérénité</p>
        </div>
        <Btn onClick={()=>setShowAdd("evenement")}>+ Événement</Btn>
      </div>

      {!sel?(
        <div>
          {evenements.length===0&&<EmptyState icon="🎉" text="Créez votre premier événement pour commencer l'organisation."/>}
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(300px,1fr))",gap:14}}>
            {evenements.map(ev=>{
              const type=TYPE_EVENEMENT.find(t=>t.id===ev.type)||TYPE_EVENEMENT[6];
              const joursAvant=ev.date?daysFrom(ev.date):null;
              const invitesConf=(ev.invites||[]).filter(i=>i.statut==="Confirmé").length;
              const budgetDepense=(ev.prestataires||[]).reduce((s,p)=>s+(parseFloat(p.montant)||0),0);
              return <Card key={ev.id} onClick={()=>{setSel(ev.id);setTab("infos");}} style={{cursor:"pointer",padding:0,overflow:"hidden",borderColor:type.color+"44"}}>
                <div style={{background:`linear-gradient(135deg,${type.color}14,transparent)`,padding:"16px 18px",borderBottom:`1px solid ${T.border}`}}>
                  <div style={{display:"flex",alignItems:"center",gap:10}}>
                    <div style={{width:44,height:44,borderRadius:22,background:type.color+"22",display:"flex",alignItems:"center",justifyContent:"center",fontSize:22,flexShrink:0}}>{type.icon}</div>
                    <div style={{flex:1}}>
                      <div style={{fontFamily:T.fontD,fontSize:15,fontWeight:700,color:T.text}}>{ev.nom}</div>
                      <div style={{fontSize:11,color:type.color,marginTop:1}}>{type.l}</div>
                    </div>
                    <Badge c={ev.statut==="Terminé"?T.muted:T.success}>{ev.statut}</Badge>
                  </div>
                </div>
                <div style={{padding:"12px 18px",fontSize:11,color:T.muted,display:"grid",gap:3}}>
                  {ev.date&&<div>📅 {fmt(ev.date)}{joursAvant!==null&&joursAvant>=0&&<span style={{color:joursAvant<=30?T.warning:T.muted,marginLeft:6}}>dans {joursAvant}j</span>}</div>}
                  {ev.lieu&&<div>📍 {ev.lieu}</div>}
                  <div>👥 {invitesConf}/{(ev.invites||[]).length} confirmé{invitesConf>1?"s":""} · 💶 {fmtAmt(budgetDepense)}/{fmtAmt(ev.budget)}</div>
                </div>
              </Card>;
            })}
          </div>
        </div>
      ):(selEv&&(()=>{
        const type=TYPE_EVENEMENT.find(t=>t.id===selEv.type)||TYPE_EVENEMENT[6];
        const invitesConf=(selEv.invites||[]).filter(i=>i.statut==="Confirmé").length;
        const invitesDecl=(selEv.invites||[]).filter(i=>i.statut==="Décliné").length;
        const budgetDepense=(selEv.prestataires||[]).reduce((s,p)=>s+(parseFloat(p.montant)||0),0);
        const tachesFaites=(selEv.taches||[]).filter(t=>t.fait).length;
        return <div>
          {/* Header */}
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:16,padding:"16px 20px",background:`linear-gradient(135deg,${type.color}10,transparent)`,borderRadius:12,border:`1px solid ${type.color}33`}}>
            <div style={{display:"flex",alignItems:"center",gap:12}}>
              <span style={{fontSize:32}}>{type.icon}</span>
              <div>
                <div style={{fontFamily:T.fontD,fontSize:20,color:T.text}}>{selEv.nom}</div>
                <div style={{fontSize:12,color:T.muted,marginTop:2}}>{selEv.date&&fmt(selEv.date)}{selEv.lieu&&` · 📍 ${selEv.lieu}`}{selEv.nbInvites&&` · ${selEv.nbInvites} invités prévus`}</div>
              </div>
            </div>
            <div style={{display:"flex",gap:8}}>
              <Sel value={selEv.statut} onChange={v=>updEv({statut:v})} style={{fontSize:11}}>{["En préparation","Confirmé","J-30","J-7","Terminé"].map(s=><option key={s}>{s}</option>)}</Sel>
              <Btn sm v="ghost" onClick={()=>setSel(null)}>← Retour</Btn>
              <button onClick={()=>{if(confirm("Supprimer cet événement ?"))setEvenements(p=>p.filter(e=>e.id!==sel));setSel(null);}} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:14}}>🗑</button>
            </div>
          </div>

          {/* KPIs rapides */}
          <div style={{display:"grid",gridTemplateColumns:"repeat(4,1fr)",gap:10,marginBottom:14}}>
            {[["👥 Confirmés",`${invitesConf}/${(selEv.invites||[]).length}`,T.success],["❌ Déclinés",invitesDecl,T.danger],["💶 Budget",fmtAmt(selEv.budget),T.accent],["✅ Tâches",`${tachesFaites}/${(selEv.taches||[]).length}`,T.info]].map(([l,v,c])=>(
              <div key={l} style={{background:"#060a10",borderRadius:10,padding:"10px 12px",textAlign:"center"}}>
                <div style={{fontSize:10,color:T.muted,marginBottom:4}}>{l}</div>
                <div style={{fontFamily:T.fontD,fontSize:18,fontWeight:700,color:c}}>{v}</div>
              </div>
            ))}
          </div>

          <Tabs tabs={[{id:"infos",icon:"📋",label:"Informations"},{id:"invites",icon:"👥",label:`Invités (${(selEv.invites||[]).length})`},{id:"prestataires",icon:"🏢",label:`Prestataires (${(selEv.prestataires||[]).length})`},{id:"planning",icon:"⏰",label:"Planning J"},{id:"taches",icon:"✅",label:`Tâches (${tachesFaites}/${(selEv.taches||[]).length})`},{id:"budget",icon:"💶",label:"Budget"},{id:"docs",icon:"📎",label:"Documents"}]} active={tab} onChange={setTab}/>

          <div style={{marginTop:14}}>
            {/* INFOS */}
            {tab==="infos"&&<div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
              <Card>
                <Divider label="Informations générales"/>
                <div style={{display:"grid",gap:7}}>
                  <F label="Nom *"><Inp value={selEv.nom} onChange={v=>updEv({nom:v})}/></F>
                  <F label="Date"><Inp type="date" value={selEv.date||""} onChange={v=>updEv({date:v})}/></F>
                  <F label="Lieu / Salle"><Inp value={selEv.lieu||""} onChange={v=>updEv({lieu:v})} placeholder="Château de la Fleur, Langon"/></F>
                  <F label="Adresse"><Inp value={selEv.adresse||""} onChange={v=>updEv({adresse:v})}/></F>
                  <F label="Nombre d'invités prévus"><Inp type="number" value={selEv.nbInvites||""} onChange={v=>updEv({nbInvites:v})}/></F>
                  {selEv.adresse&&<MapsLinks adresse={selEv.adresse}/>}
                </div>
              </Card>
              <Card>
                <Divider label="Notes & Infos pratiques"/>
                <Txt value={selEv.note||""} onChange={v=>updEv({note:v})} rows={6} placeholder="Thème, dresscode, infos pratiques, menu, discours..."/>
              </Card>
            </div>}

            {/* INVITÉS */}
            {tab==="invites"&&<div>
              <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:12}}>
                <div style={{fontSize:12,color:T.muted}}>
                  <span style={{color:T.success}}>✓ {invitesConf} confirmés</span> · <span style={{color:T.warning}}>? {(selEv.invites||[]).filter(i=>!i.statut||i.statut==="En attente").length} en attente</span> · <span style={{color:T.danger}}>✗ {invitesDecl} déclinés</span>
                </div>
                <Btn onClick={()=>setShowAdd("invite")}>+ Invité</Btn>
              </div>
              {(selEv.invites||[]).length===0&&<EmptyState icon="👥" text="Commencez à renseigner votre liste d'invités."/>}
              <div style={{display:"grid",gap:4}}>
                {(selEv.invites||[]).map(inv=>{
                  const statColor=inv.statut==="Confirmé"?T.success:inv.statut==="Décliné"?T.danger:T.warning;
                  return <div key={inv.id} style={{display:"flex",alignItems:"center",gap:10,padding:"9px 14px",background:"#060a10",borderRadius:9,border:`1px solid ${T.border}`}}>
                    <div style={{width:32,height:32,borderRadius:16,background:statColor+"22",display:"flex",alignItems:"center",justifyContent:"center",fontSize:13,fontWeight:700,color:statColor,flexShrink:0}}>{inv.prenom[0]||"?"}</div>
                    <div style={{flex:1}}>
                      <div style={{fontSize:13,fontWeight:600,color:T.text}}>{inv.prenom} {inv.nom||""}</div>
                      <div style={{fontSize:10,color:T.muted}}>{inv.table&&`Table ${inv.table} · `}{inv.regime&&`${inv.regime} · `}{inv.tel||inv.email}</div>
                    </div>
                    <Sel value={inv.statut||"En attente"} onChange={v=>updEv({invites:(selEv.invites||[]).map(i=>i.id===inv.id?{...i,statut:v}:i)})} style={{fontSize:11,maxWidth:120}}>
                      {["En attente","Confirmé","Décliné"].map(s=><option key={s}>{s}</option>)}
                    </Sel>
                    <button onClick={()=>updEv({invites:(selEv.invites||[]).filter(i=>i.id!==inv.id)})} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,opacity:0.5}}>🗑</button>
                  </div>;
                })}
              </div>
            </div>}

            {/* PRESTATAIRES */}
            {tab==="prestataires"&&<div>
              <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:12}}>
                <div style={{fontSize:12,color:T.muted}}>Total prestataires : <span style={{color:T.success,fontWeight:700}}>{fmtAmt(budgetDepense)}</span></div>
                <Btn onClick={()=>setShowAdd("prestataire")}>+ Prestataire</Btn>
              </div>
              {(selEv.prestataires||[]).length===0&&<EmptyState icon="🏢" text="Traiteur, DJ, photographe, fleuriste, officiant... Ajoutez vos prestataires."/>}
              <div style={{display:"grid",gap:6}}>
                {(selEv.prestataires||[]).map(p=>{
                  const statColor=p.statut==="Signé"?T.success:p.statut==="En attente"?T.warning:T.muted;
                  return <Card key={p.id}>
                    <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                      <div>
                        <div style={{fontSize:14,fontWeight:700,color:T.text}}>{p.nom}</div>
                        <div style={{fontSize:11,color:T.accent,marginTop:1}}>{p.type}</div>
                        {p.tel&&<div style={{fontSize:11,color:T.muted,marginTop:3}}>📞 {p.tel}{p.email&&` · ✉️ ${p.email}`}</div>}
                        {p.note&&<div style={{fontSize:10,color:T.muted,fontStyle:"italic",marginTop:4}}>{p.note}</div>}
                      </div>
                      <div style={{textAlign:"right",flexShrink:0,marginLeft:10}}>
                        <div style={{fontFamily:T.fontD,fontSize:16,fontWeight:700,color:T.success}}>{fmtAmt(p.montant)}</div>
                        <Badge c={statColor}>{p.statut||"En attente"}</Badge>
                      </div>
                    </div>
                    <div style={{display:"flex",justifyContent:"space-between",marginTop:8}}>
                      <ContactActions tel={p.tel} email={p.email}/>
                      <button onClick={()=>updEv({prestataires:(selEv.prestataires||[]).filter(x=>x.id!==p.id)})} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,opacity:0.5}}>🗑</button>
                    </div>
                  </Card>;
                })}
              </div>
            </div>}

            {/* PLANNING */}
            {tab==="planning"&&<div>
              <div style={{display:"flex",justifyContent:"flex-end",marginBottom:12}}><Btn onClick={()=>setShowAdd("planning")}>+ Moment</Btn></div>
              {(selEv.planning||[]).length===0&&<EmptyState icon="⏰" text="Créez le planning heure par heure de votre événement (cérémonie, cocktail, dîner...)."/>}
              <div style={{position:"relative"}}>
                {(selEv.planning||[]).sort((a,b)=>a.heure?.localeCompare(b.heure||"")||0).map((p,i)=>(
                  <div key={p.id} style={{display:"flex",gap:14,marginBottom:6}}>
                    <div style={{width:60,flexShrink:0,textAlign:"right",paddingTop:10}}>
                      <span style={{fontFamily:"monospace",fontSize:14,fontWeight:700,color:T.accent}}>{p.heure}</span>
                    </div>
                    <div style={{width:2,background:T.border,flexShrink:0,position:"relative"}}>
                      <div style={{position:"absolute",top:10,left:-4,width:10,height:10,borderRadius:5,background:T.accent}}/>
                    </div>
                    <div style={{flex:1,padding:"8px 14px",background:"#060a10",borderRadius:9,border:`1px solid ${T.border}`,marginBottom:4}}>
                      <div style={{display:"flex",justifyContent:"space-between"}}>
                        <div>
                          <div style={{fontSize:13,fontWeight:700,color:T.text}}>{p.titre}</div>
                          {p.lieu&&<div style={{fontSize:11,color:T.muted,marginTop:1}}>📍 {p.lieu}</div>}
                          {p.note&&<div style={{fontSize:11,color:T.muted,fontStyle:"italic",marginTop:2}}>{p.note}</div>}
                        </div>
                        {p.duree&&<div style={{fontSize:10,color:T.muted,flexShrink:0,marginLeft:8}}>⏱ {p.duree}'</div>}
                      </div>
                    </div>
                    <button onClick={()=>updEv({planning:(selEv.planning||[]).filter(x=>x.id!==p.id)})} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:12,opacity:0.5,alignSelf:"flex-start",paddingTop:10}}>🗑</button>
                  </div>
                ))}
              </div>
            </div>}

            {/* TÂCHES */}
            {tab==="taches"&&<div>
              <div style={{fontSize:11,color:T.muted,marginBottom:8,display:"flex",justifyContent:"space-between"}}>
                <span>{tachesFaites}/{(selEv.taches||[]).length} tâches terminées</span>
                {(selEv.taches||[]).length>0&&<span style={{color:T.accent}}>{Math.round(tachesFaites/(selEv.taches||[]).length*100)}%</span>}
              </div>
              {(selEv.taches||[]).length>0&&<div style={{height:6,background:T.border,borderRadius:3,marginBottom:12}}><div style={{height:6,background:T.success,borderRadius:3,width:`${tachesFaites>0?Math.round(tachesFaites/(selEv.taches||[]).length*100):0}%`,transition:"width 0.3s"}}/></div>}
              <div style={{display:"grid",gap:4,marginBottom:10}}>
                {(selEv.taches||[]).map(t=><div key={t.id} style={{display:"flex",alignItems:"center",gap:10,padding:"8px 12px",borderRadius:8,background:"#060a10"}}>
                  <input type="checkbox" checked={t.fait} onChange={()=>updEv({taches:(selEv.taches||[]).map(x=>x.id===t.id?{...x,fait:!x.fait}:x)})} style={{accentColor:T.accent}}/>
                  <span style={{fontSize:13,flex:1,color:t.fait?T.muted:T.text,textDecoration:t.fait?"line-through":"none"}}>{t.texte}</span>
                  {t.echeance&&<span style={{fontSize:10,color:daysFrom(t.echeance)<=7?T.danger:T.muted}}>📅 {fmt(t.echeance)}</span>}
                  <button onClick={()=>updEv({taches:(selEv.taches||[]).filter(x=>x.id!==t.id)})} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:11,opacity:0.5}}>✕</button>
                </div>)}
              </div>
              <div style={{display:"flex",gap:8}}>
                <Inp value={tacheEvForm.texte} onChange={v=>setTacheEvForm(f=>({...f,texte:v}))} placeholder="Nouvelle tâche..." style={{flex:1}}/>
                <Inp type="date" value={tacheEvForm.echeance} onChange={v=>setTacheEvForm(f=>({...f,echeance:v}))} style={{width:140}}/>
                <Btn sm onClick={()=>{if(tacheEvForm.texte){updEv({taches:[...(selEv.taches||[]),{...tacheEvForm,id:uid(),fait:false}]});setTacheEvForm({texte:"",echeance:""});}}}>+</Btn>
              </div>
            </div>}

            {/* BUDGET */}
            {tab==="budget"&&<div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
              <Card>
                <Divider label="Budget global"/>
                <F label="Budget total prévu (€)"><Inp type="number" value={selEv.budget||""} onChange={v=>updEv({budget:v})}/></F>
                <div style={{marginTop:14,display:"grid",gap:6}}>
                  {[["Prestataires",(selEv.prestataires||[]).reduce((s,p)=>s+(parseFloat(p.montant)||0),0),T.success],["Traiteur",(selEv.prestataires||[]).filter(p=>p.type==="Traiteur").reduce((s,p)=>s+(parseFloat(p.montant)||0),0),T.info]].map(([l,v,c])=>(
                    <div key={l} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:12}}><span style={{color:T.muted}}>{l}</span><span style={{color:c,fontWeight:700}}>{fmtAmt(v)}</span></div>
                  ))}
                  <div style={{display:"flex",justifyContent:"space-between",padding:"9px 0",fontSize:13,fontWeight:700}}>
                    <span style={{color:T.text}}>Total engagé</span>
                    <span style={{color:budgetDepense>parseFloat(selEv.budget||0)?T.danger:T.success}}>{fmtAmt(budgetDepense)}</span>
                  </div>
                  {selEv.budget&&<div style={{padding:"10px 12px",background:parseFloat(selEv.budget)-budgetDepense>=0?"rgba(34,197,94,0.08)":"rgba(239,68,68,0.08)",borderRadius:8,fontSize:12,fontWeight:700,color:parseFloat(selEv.budget)-budgetDepense>=0?T.success:T.danger}}>
                    {parseFloat(selEv.budget)-budgetDepense>=0?`✅ Reste : ${fmtAmt(parseFloat(selEv.budget)-budgetDepense)}`:`⚠️ Dépassement : ${fmtAmt(budgetDepense-parseFloat(selEv.budget))}`}
                  </div>}
                </div>
              </Card>
              <Card>
                <Divider label="Détail prestataires"/>
                {(selEv.prestataires||[]).map(p=>(
                  <div key={p.id} style={{display:"flex",justifyContent:"space-between",padding:"7px 0",borderBottom:`1px solid ${T.border}`,fontSize:11}}>
                    <span style={{color:T.muted}}>{p.type} — {p.nom}</span>
                    <span style={{fontWeight:700,color:T.success}}>{fmtAmt(p.montant)}</span>
                  </div>
                ))}
                {(selEv.prestataires||[]).length===0&&<div style={{color:T.muted,fontSize:12,fontStyle:"italic"}}>Ajoutez des prestataires dans l'onglet Prestataires</div>}
              </Card>
            </div>}

            {/* DOCS */}
            {tab==="docs"&&<DocAttach docs={selEv.docs||[]} onChange={nd=>updEv({docs:nd})} label="Contrats, devis signés, plans de salle, menus..."/>}
          </div>
        </div>;
      })())}

      {/* MODALES */}
      {showAdd==="evenement"&&<Modal title="🎉 Nouvel événement" onClose={()=>setShowAdd(null)} width={560}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Nom *" style={{gridColumn:"1/-1"}}><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Mariage Jean & Marie, Anniversaire 40 ans..."/></F>
          <F label="Type"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}>{TYPE_EVENEMENT.map(t=><option key={t.id} value={t.id}>{t.icon} {t.l}</option>)}</Sel></F>
          <F label="Date"><Inp type="date" value={form.date} onChange={v=>setForm(f=>({...f,date:v}))}/></F>
          <F label="Lieu / Salle"><Inp value={form.lieu} onChange={v=>setForm(f=>({...f,lieu:v}))} placeholder="Château de la Tour"/></F>
          <F label="Adresse"><Inp value={form.adresse} onChange={v=>setForm(f=>({...f,adresse:v}))}/></F>
          <F label="Budget prévu (€)"><Inp type="number" value={form.budget} onChange={v=>setForm(f=>({...f,budget:v}))}/></F>
          <F label="Nombre d'invités"><Inp type="number" value={form.nbInvites} onChange={v=>setForm(f=>({...f,nbInvites:v}))}/></F>
          <F label="Notes" style={{gridColumn:"1/-1"}}><Txt value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} rows={2}/></F>
        </div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
          <Btn onClick={save} disabled={!form.nom}>💾 Créer</Btn>
        </div>
      </Modal>}

      {showAdd==="invite"&&sel&&(
        <Modal title="👤 Invité" onClose={()=>setShowAdd(null)}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Prénom *"><Inp value={inviteForm.prenom} onChange={v=>setInviteForm(f=>({...f,prenom:v}))}/></F>
            <F label="Nom"><Inp value={inviteForm.nom} onChange={v=>setInviteForm(f=>({...f,nom:v}))}/></F>
            <F label="Téléphone"><Inp value={inviteForm.tel} onChange={v=>setInviteForm(f=>({...f,tel:v}))}/></F>
            <F label="Email"><Inp value={inviteForm.email} onChange={v=>setInviteForm(f=>({...f,email:v}))}/></F>
            <F label="Table N°"><Inp type="number" value={inviteForm.table} onChange={v=>setInviteForm(f=>({...f,table:v}))}/></F>
            <F label="Régime alimentaire"><Sel value={inviteForm.regime} onChange={v=>setInviteForm(f=>({...f,regime:v}))}><option value="">Standard</option>{["Végétarien","Vegan","Sans gluten","Sans lactose","Halal","Casher","Allergie autre"].map(r=><option key={r}>{r}</option>)}</Sel></F>
            <F label="Statut"><Sel value={inviteForm.statut} onChange={v=>setInviteForm(f=>({...f,statut:v}))}>{["En attente","Confirmé","Décliné"].map(s=><option key={s}>{s}</option>)}</Sel></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
            <Btn onClick={()=>{if(inviteForm.prenom){updEv({invites:[...(selEv.invites||[]),{...inviteForm,id:uid()}]});setInviteForm({prenom:"",nom:"",tel:"",email:"",table:"",regime:"",statut:"En attente",note:""});setShowAdd(null);}}} disabled={!inviteForm.prenom}>💾</Btn>
          </div>
        </Modal>
      )}

      {showAdd==="prestataire"&&sel&&(
        <Modal title="🏢 Prestataire" onClose={()=>setShowAdd(null)}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Nom / Société *"><Inp value={prestForm.nom} onChange={v=>setPrestForm(f=>({...f,nom:v}))}/></F>
            <F label="Type"><Sel value={prestForm.type} onChange={v=>setPrestForm(f=>({...f,type:v}))}>{["Traiteur","DJ / Musicien","Photographe","Vidéaste","Fleuriste","Officiant","Location salle","Transport","Décoration","Animation","Autre"].map(t=><option key={t}>{t}</option>)}</Sel></F>
            <F label="Téléphone"><Inp value={prestForm.tel} onChange={v=>setPrestForm(f=>({...f,tel:v}))}/></F>
            <F label="Email"><Inp type="email" value={prestForm.email} onChange={v=>setPrestForm(f=>({...f,email:v}))}/></F>
            <F label="Montant devis (€)"><Inp type="number" value={prestForm.montant} onChange={v=>setPrestForm(f=>({...f,montant:v}))}/></F>
            <F label="Statut contrat"><Sel value={prestForm.statut} onChange={v=>setPrestForm(f=>({...f,statut:v}))}>{["En attente","Devis reçu","Signé","Payé","Annulé"].map(s=><option key={s}>{s}</option>)}</Sel></F>
            <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={prestForm.note} onChange={v=>setPrestForm(f=>({...f,note:v}))}/></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
            <Btn onClick={()=>{if(prestForm.nom){updEv({prestataires:[...(selEv.prestataires||[]),{...prestForm,id:uid()}]});setPrestForm({nom:"",type:"Traiteur",tel:"",email:"",montant:"",statut:"En attente",note:""});setShowAdd(null);}}} disabled={!prestForm.nom}>💾</Btn>
          </div>
        </Modal>
      )}

      {showAdd==="planning"&&sel&&(
        <Modal title="⏰ Moment du planning" onClose={()=>setShowAdd(null)}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
            <F label="Heure *"><Inp type="time" value={planningForm.heure} onChange={v=>setPlanningForm(f=>({...f,heure:v}))}/></F>
            <F label="Durée (min)"><Inp type="number" value={planningForm.duree} onChange={v=>setPlanningForm(f=>({...f,duree:v}))} placeholder="30"/></F>
            <F label="Titre *" style={{gridColumn:"1/-1"}}><Inp value={planningForm.titre} onChange={v=>setPlanningForm(f=>({...f,titre:v}))} placeholder="Cérémonie civile, Vin d'honneur, Dîner..."/></F>
            <F label="Lieu"><Inp value={planningForm.lieu} onChange={v=>setPlanningForm(f=>({...f,lieu:v}))}/></F>
            <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={planningForm.note} onChange={v=>setPlanningForm(f=>({...f,note:v}))}/></F>
          </div>
          <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
            <Btn v="ghost" onClick={()=>setShowAdd(null)}>Annuler</Btn>
            <Btn onClick={()=>{if(planningForm.heure&&planningForm.titre){updEv({planning:[...(selEv.planning||[]),{...planningForm,id:uid()}]});setPlanningForm({heure:"",titre:"",lieu:"",duree:"",note:""});setShowAdd(null);}}} disabled={!planningForm.heure||!planningForm.titre}>💾</Btn>
          </div>
        </Modal>
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: CARTES DE FIDÉLITÉ (WALLET)
// ═══════════════════════════════════════════════════════════════════════════════
// Génère un code-barres visuel (style EAN) à partir d'une chaîne
const BarcodeCanvas=({value,width=280,height=60})=>{
  const ref=useRef();
  useEffect(()=>{
    if(!ref.current||!value)return;
    const canvas=ref.current;
    const ctx=canvas.getContext("2d");
    canvas.width=width;canvas.height=height;
    ctx.fillStyle="#fff";ctx.fillRect(0,0,width,height);
    // Patterns larges/étroits basés sur chaque char
    const chars=String(value).replace(/[^0-9A-Z\-\.\ ]/g,"").padEnd(12,"0");
    const bits=[];
    for(let i=0;i<chars.length;i++){
      const code=chars.charCodeAt(i)%10;
      const pat=[1,2,1,2,1,2,1,2,3,1];// largeurs alternantes
      const w=pat[code%pat.length];
      bits.push({w,bar:i%2===0});
      bits.push({w:1,bar:false});
    }
    // Marqueurs début/fin
    bits.unshift({w:1,bar:true},{w:1,bar:false},{w:1,bar:true});
    bits.push({w:1,bar:true},{w:1,bar:false},{w:1,bar:true});
    const total=bits.reduce((s,b)=>s+b.w,0);
    const scale=(width-10)/total;
    let x=5;
    ctx.fillStyle="#000";
    bits.forEach(b=>{
      if(b.bar)ctx.fillRect(Math.round(x),0,Math.max(1,Math.round(b.w*scale)),height-12);
      x+=b.w*scale;
    });
    // Numéro sous le code
    ctx.fillStyle="#000";ctx.font=`bold 9px monospace`;ctx.textAlign="center";
    ctx.fillText(value,width/2,height-2);
  },[value,width,height]);
  return <canvas ref={ref} style={{borderRadius:4}}/>;
};

// QR code simplifié (grille 21x21 pseudo-aléatoire seeded)
const QRCanvas=({value,size=120})=>{
  const ref=useRef();
  useEffect(()=>{
    if(!ref.current||!value)return;
    const canvas=ref.current;canvas.width=size;canvas.height=size;
    const ctx=canvas.getContext("2d");
    ctx.fillStyle="#fff";ctx.fillRect(0,0,size,size);
    const N=21;const cell=Math.floor(size/N);
    // Seed depuis la valeur
    let seed=0;for(let i=0;i<value.length;i++)seed=(seed*31+value.charCodeAt(i))&0xFFFFFF;
    const rand=()=>{seed=(seed*1664525+1013904223)&0xFFFFFF;return seed/0xFFFFFF;};
    ctx.fillStyle="#000";
    for(let r=0;r<N;r++)for(let c=0;c<N;c++){
      // Coins de positionnement (7x7)
      const inCorner=(r<7&&c<7)||(r<7&&c>=N-7)||(r>=N-7&&c<7);
      // Bordure extérieure des coins
      const cornerBorder=(r<=7&&c<=7&&(r===0||r===6||c===0||c===6))||(r<=7&&c>=N-8&&(r===0||r===6||c===N-1||c===N-7))||(r>=N-7&&c<=7&&(r===N-1||r===N-7||c===0||c===6));
      let dark=false;
      if(r<7&&c<7)dark=(r===0||r===6||c===0||c===6||(r>=2&&r<=4&&c>=2&&c<=4));
      else if(r<7&&c>=N-7)dark=(r===0||r===6||c===N-1||c===N-7||(r>=2&&r<=4&&c>=N-5&&c<=N-3));
      else if(r>=N-7&&c<7)dark=(r===N-1||r===N-7||c===0||c===6||(r>=N-5&&r<=N-3&&c>=2&&c<=4));
      else dark=rand()>0.5;
      if(dark){ctx.fillRect(c*cell,r*cell,cell,cell);}
    }
  },[value,size]);
  return <canvas ref={ref} style={{borderRadius:4}}/>;
};

const CATS_WALLET=[
  {id:"supermarche",l:"Supermarché",icon:"🛒",color:"#34d399"},
  {id:"pharmacie",l:"Pharmacie",icon:"💊",color:"#38bdf8"},
  {id:"culture",l:"Culture / Loisirs",icon:"🎭",color:"#a78bfa"},
  {id:"sport",l:"Sport / Fitness",icon:"💪",color:"#fb923c"},
  {id:"restaurant",l:"Restaurant / Café",icon:"🍽️",color:"#f0a500"},
  {id:"transport",l:"Transport",icon:"🚌",color:"#60a5fa"},
  {id:"mode",l:"Mode / Beauté",icon:"👗",color:"#f472b6"},
  {id:"bricolage",l:"Bricolage / Jardin",icon:"🛠️",color:"#84cc16"},
  {id:"autre",l:"Autre",icon:"💳",color:"#94a3b8"},
];
const CARD_GRADIENTS=[
  ["#1a1a3e","#2d2d7a"],["#0f2027","#203a43"],["#1a0533","#3c0f69"],
  ["#0a1628","#0d3b5e"],["#1a0a0a","#5c1010"],["#0a1a0a","#0d5c0d"],
  ["#1a1000","#5c3d00"],["#0a0a1a","#1a1a4e"],["#0d0d0d","#2a2a2a"],
];

const Wallet=({wallet,setWallet})=>{
  const cartes=wallet.cartes||[];
  const [sel,setSel]=useState(null);
  const [showAdd,setShowAdd]=useState(false);
  const [showFull,setShowFull]=useState(null);
  const [modeCode,setModeCode]=useState({});// barcode ou qr par carte
  const [search,setSearch]=useState("");
  const [catFilter,setCatFilter]=useState("all");
  const EMPTY={nom:"",enseigne:"",numero:"",categorie:"supermarche",gradient:0,note:"",pointsActuels:"",pointsMax:"",avantages:""};
  const [form,setForm]=useState({...EMPTY});
  const add=()=>{setWallet(w=>({...w,cartes:[...(w.cartes||[]),{...form,id:uid()}]}));setShowAdd(false);setForm({...EMPTY});};
  const del=id=>setWallet(w=>({...w,cartes:w.cartes.filter(c=>c.id!==id)}));
  const upd=(id,v)=>setWallet(w=>({...w,cartes:w.cartes.map(c=>c.id===id?{...c,...v}:c)}));
  const filtered=cartes.filter(c=>{
    if(catFilter!=="all"&&c.categorie!==catFilter)return false;
    if(search&&![c.nom,c.enseigne,c.numero].some(v=>(v||"").toLowerCase().includes(search.toLowerCase())))return false;
    return true;
  });
  const selCarte=sel&&cartes.find(c=>c.id===sel);

  // Carte rendue graphiquement
  const CardFace=({carte,small,onClick})=>{
    const cat=CATS_WALLET.find(c=>c.id===carte.categorie)||CATS_WALLET[8];
    const [g1,g2]=CARD_GRADIENTS[carte.gradient%CARD_GRADIENTS.length];
    const ratio=small?{width:160,height:100,borderRadius:10,fontSize:11,padding:"10px 14px"}:{width:320,height:200,borderRadius:18,fontSize:14,padding:"20px 24px"};
    return <div onClick={onClick} style={{...ratio,background:`linear-gradient(135deg,${g1},${g2})`,border:`1px solid rgba(255,255,255,0.1)`,cursor:onClick?"pointer":"default",display:"flex",flexDirection:"column",justifyContent:"space-between",position:"relative",overflow:"hidden",flexShrink:0,transition:"transform 0.15s,box-shadow 0.15s",boxShadow:"0 4px 20px rgba(0,0,0,0.4)"}}>
      {/* Cercles décoratifs */}
      <div style={{position:"absolute",right:-20,top:-20,width:small?80:140,height:small?80:140,borderRadius:"50%",background:"rgba(255,255,255,0.05)"}}/>
      <div style={{position:"absolute",right:20,top:small?30:60,width:small?40:80,height:small?40:80,borderRadius:"50%",background:"rgba(255,255,255,0.04)"}}/>
      {/* Header */}
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",position:"relative"}}>
        <div>
          <div style={{color:"rgba(255,255,255,0.6)",fontSize:small?8:10,textTransform:"uppercase",letterSpacing:"0.1em"}}>{cat.l}</div>
          <div style={{color:"#fff",fontFamily:"'Playfair Display',serif",fontSize:small?13:20,fontWeight:700,marginTop:2,lineHeight:1.2}}>{carte.enseigne||carte.nom}</div>
        </div>
        <div style={{fontSize:small?16:26,opacity:0.9}}>{cat.icon}</div>
      </div>
      {/* Numéro */}
      <div style={{position:"relative"}}>
        {!small&&<div style={{color:"rgba(255,255,255,0.4)",fontSize:9,textTransform:"uppercase",letterSpacing:"0.1em",marginBottom:4}}>N° carte</div>}
        <div style={{color:"rgba(255,255,255,0.9)",fontFamily:"monospace",fontSize:small?10:15,letterSpacing:small?"0.05em":"0.15em",fontWeight:600}}>{carte.numero||"— — — —"}</div>
        {carte.nom!==carte.enseigne&&<div style={{color:"rgba(255,255,255,0.5)",fontSize:small?8:10,marginTop:small?2:6}}>{carte.nom}</div>}
      </div>
    </div>;
  };

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18}}>
        <div>
          <h1 style={{fontFamily:"'Playfair Display',serif",fontSize:26,color:"#f0f6fc"}}>💳 Cartes de Fidélité</h1>
          <p style={{color:"#64748b",fontSize:13,marginTop:3}}>{cartes.length} carte{cartes.length>1?"s":" "} · Wallet personnel</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Ajouter une carte</Btn>
      </div>

      {/* Filtres */}
      <div style={{display:"flex",gap:8,marginBottom:16,flexWrap:"wrap"}}>
        <Inp value={search} onChange={setSearch} placeholder="🔍 Rechercher..." style={{maxWidth:200}}/>
        <button onClick={()=>setCatFilter("all")} style={{padding:"5px 12px",borderRadius:8,border:`1px solid ${catFilter==="all"?"#f0a500":"#1e293b"}`,background:catFilter==="all"?"rgba(240,165,0,0.15)":"transparent",color:catFilter==="all"?"#f0a500":"#64748b",fontSize:12,cursor:"pointer",fontFamily:"'DM Sans',sans-serif"}}>Toutes</button>
        {CATS_WALLET.map(c=><button key={c.id} onClick={()=>setCatFilter(c.id)} style={{padding:"5px 10px",borderRadius:8,border:`1px solid ${catFilter===c.id?c.color:"#1e293b"}`,background:catFilter===c.id?c.color+"22":"transparent",color:catFilter===c.id?c.color:"#64748b",fontSize:11,cursor:"pointer",fontFamily:"'DM Sans',sans-serif"}}>{c.icon}</button>)}
      </div>

      {filtered.length===0&&<EmptyState icon="💳" text="Ajoutez vos cartes de fidélité, points, et avantages pour les avoir toujours avec vous."/>}

      {/* Grille de cartes */}
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(340px,1fr))",gap:16}}>
        {filtered.map(carte=>{
          const cat=CATS_WALLET.find(c=>c.id===carte.categorie)||CATS_WALLET[8];
          const isQR=modeCode[carte.id]==="qr";
          const prog=carte.pointsMax&&carte.pointsActuels?Math.min(100,Math.round(parseFloat(carte.pointsActuels)/parseFloat(carte.pointsMax)*100)):null;
          return <div key={carte.id} style={{background:"#060a10",borderRadius:14,border:"1px solid #1e293b",overflow:"hidden"}}>
            {/* Carte visuelle */}
            <div style={{padding:"16px 16px 8px",display:"flex",justifyContent:"center"}}>
              <CardFace carte={carte} small={false} onClick={()=>setShowFull(carte.id)}/>
            </div>
            {/* Code-barres / QR */}
            <div style={{padding:"8px 16px 4px",display:"flex",flexDirection:"column",alignItems:"center",gap:6}}>
              <div style={{background:"#fff",borderRadius:8,padding:"8px 12px",display:"inline-block"}}>
                {isQR?<QRCanvas value={carte.numero||carte.nom} size={100}/>:<BarcodeCanvas value={carte.numero||carte.nom} width={280} height={52}/>}
              </div>
              <div style={{display:"flex",gap:6}}>
                <button onClick={()=>setModeCode(m=>({...m,[carte.id]:isQR?"barcode":"qr"}))} style={{padding:"3px 10px",borderRadius:6,border:"1px solid #1e293b",background:"transparent",color:"#64748b",fontSize:10,cursor:"pointer",fontFamily:"'DM Sans',sans-serif"}}>{isQR?"📊 Code-barres":"⬛ QR Code"}</button>
                <button onClick={()=>setShowFull(carte.id)} style={{padding:"3px 10px",borderRadius:6,border:"1px solid rgba(240,165,0,0.3)",background:"rgba(240,165,0,0.08)",color:"#f0a500",fontSize:10,cursor:"pointer",fontFamily:"'DM Sans',sans-serif"}}>🔍 Plein écran</button>
              </div>
            </div>
            {/* Infos */}
            <div style={{padding:"8px 16px 14px"}}>
              {prog!==null&&<div style={{marginBottom:8}}>
                <div style={{display:"flex",justifyContent:"space-between",fontSize:10,color:"#64748b",marginBottom:3}}><span>Points</span><span style={{color:cat.color}}>{carte.pointsActuels}/{carte.pointsMax} · {prog}%</span></div>
                <div style={{height:5,background:"#1e293b",borderRadius:3}}><div style={{height:5,background:cat.color,borderRadius:3,width:`${prog}%`,transition:"width 0.5s"}}/></div>
              </div>}
              {carte.avantages&&<div style={{fontSize:11,color:"#64748b",marginBottom:6,fontStyle:"italic"}}>✨ {carte.avantages}</div>}
              {carte.note&&<div style={{fontSize:10,color:"#475569",marginBottom:6}}>{carte.note}</div>}
              <div style={{display:"flex",justifyContent:"space-between",marginTop:6}}>
                <button onClick={()=>setSel(sel===carte.id?null:carte.id)} style={{background:"none",border:"1px solid #1e293b",color:"#64748b",borderRadius:6,padding:"4px 10px",cursor:"pointer",fontSize:11,fontFamily:"'DM Sans',sans-serif"}}>✏️ Modifier</button>
                <button onClick={()=>del(carte.id)} style={{background:"none",border:"none",color:"#475569",cursor:"pointer",fontSize:12,opacity:0.6}}>🗑</button>
              </div>
              {/* Mini formulaire édition inline */}
              {sel===carte.id&&<div style={{marginTop:10,padding:"10px",background:"#0a0e17",borderRadius:8,border:"1px solid #1e293b"}}>
                <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:7}}>
                  <F label="Points actuels"><Inp type="number" value={carte.pointsActuels||""} onChange={v=>upd(carte.id,{pointsActuels:v})}/></F>
                  <F label="Points max"><Inp type="number" value={carte.pointsMax||""} onChange={v=>upd(carte.id,{pointsMax:v})}/></F>
                  <F label="Avantages" style={{gridColumn:"1/-1"}}><Inp value={carte.avantages||""} onChange={v=>upd(carte.id,{avantages:v})} placeholder="-10% chaque mois, livraison gratuite..."/></F>
                  <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={carte.note||""} onChange={v=>upd(carte.id,{note:v})}/></F>
                  <F label="Dégradé carte"><Sel value={carte.gradient||0} onChange={v=>upd(carte.id,{gradient:parseInt(v)})}>
                    {CARD_GRADIENTS.map((_,i)=><option key={i} value={i}>Style {i+1}</option>)}
                  </Sel></F>
                </div>
                <Btn sm onClick={()=>setSel(null)} style={{marginTop:8}}>✓ Fermer</Btn>
              </div>}
            </div>
          </div>;
        })}
      </div>

      {/* Plein écran présentation */}
      {showFull&&(()=>{
        const carte=cartes.find(c=>c.id===showFull);
        if(!carte)return null;
        const isQR=modeCode[showFull]==="qr";
        return <div onClick={()=>setShowFull(null)} style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.92)",zIndex:9999,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:24,cursor:"pointer"}}>
          <div style={{fontSize:13,color:"rgba(255,255,255,0.4)",marginBottom:-10}}>Appuyez pour fermer</div>
          <CardFace carte={carte} small={false}/>
          <div style={{background:"#fff",borderRadius:14,padding:"16px 24px",display:"inline-flex",flexDirection:"column",alignItems:"center",gap:8}}>
            {isQR?<QRCanvas value={carte.numero||carte.nom} size={180}/>:<BarcodeCanvas value={carte.numero||carte.nom} width={340} height={80}/>}
          </div>
          <div style={{display:"flex",gap:10}} onClick={e=>e.stopPropagation()}>
            <button onClick={()=>setModeCode(m=>({...m,[showFull]:isQR?"barcode":"qr"}))} style={{padding:"8px 18px",borderRadius:10,border:"1px solid rgba(255,255,255,0.2)",background:"rgba(255,255,255,0.08)",color:"#fff",fontSize:13,cursor:"pointer"}}>
              {isQR?"📊 Afficher code-barres":"⬛ Afficher QR code"}
            </button>
          </div>
        </div>;
      })()}

      {/* Ajout nouvelle carte */}
      {showAdd&&<Modal title="💳 Nouvelle carte" onClose={()=>setShowAdd(false)} width={560}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Enseigne *"><Inp value={form.enseigne} onChange={v=>setForm(f=>({...f,enseigne:v}))} placeholder="Carrefour, Fnac, Décathlon..."/></F>
          <F label="Catégorie"><Sel value={form.categorie} onChange={v=>setForm(f=>({...f,categorie:v}))}>{CATS_WALLET.map(c=><option key={c.id} value={c.id}>{c.icon} {c.l}</option>)}</Sel></F>
          <F label="Nom sur la carte"><Inp value={form.nom} onChange={v=>setForm(f=>({...f,nom:v}))} placeholder="Votre nom ou libellé"/></F>
          <F label="Numéro / Code"><Inp value={form.numero} onChange={v=>setForm(f=>({...f,numero:v}))} placeholder="1234567890123"/></F>
          <F label="Points actuels"><Inp type="number" value={form.pointsActuels} onChange={v=>setForm(f=>({...f,pointsActuels:v}))}/></F>
          <F label="Points max (cagnotte)"><Inp type="number" value={form.pointsMax} onChange={v=>setForm(f=>({...f,pointsMax:v}))}/></F>
          <F label="Avantages" style={{gridColumn:"1/-1"}}><Inp value={form.avantages} onChange={v=>setForm(f=>({...f,avantages:v}))} placeholder="-10% chaque 1er du mois, 2% en cagnotte..."/></F>
          <F label="Note" style={{gridColumn:"1/-1"}}><Inp value={form.note} onChange={v=>setForm(f=>({...f,note:v}))}/></F>
          <F label="Style de la carte" style={{gridColumn:"1/-1"}}>
            <div style={{display:"flex",gap:8,flexWrap:"wrap",marginTop:4}}>
              {CARD_GRADIENTS.map(([g1,g2],i)=>(
                <div key={i} onClick={()=>setForm(f=>({...f,gradient:i}))} style={{width:48,height:30,borderRadius:6,background:`linear-gradient(135deg,${g1},${g2})`,border:`2px solid ${form.gradient===i?"#f0a500":"transparent"}`,cursor:"pointer"}}/>
              ))}
            </div>
          </F>
        </div>
        {/* Aperçu */}
        {(form.enseigne||form.nom)&&<div style={{marginTop:12,display:"flex",justifyContent:"center"}}>
          <CardFace carte={{...form,id:"preview"}} small={false}/>
        </div>}
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:12}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={add} disabled={!form.enseigne}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: PARAMÈTRES — GESTION VISIBILITÉ DES MODULES
// ═══════════════════════════════════════════════════════════════════════════════
const ParametresModules=({visibles,setVisibles})=>{
  const ALL=NAV_GROUPS.flatMap(g=>g.items.map(i=>({...i,groupe:g.label})));
  const toggle=id=>{
    if(MODULES_CORE.has(id))return;// ne pas toucher aux modules core
    setVisibles(v=>v.includes(id)?v.filter(x=>x!==id):[...v,id]);
  };
  const activerGroupe=groupe=>{
    const ids=NAV_GROUPS.find(g=>g.label===groupe)?.items.map(i=>i.id)||[];
    setVisibles(v=>[...new Set([...v,...ids])]);
  };
  const desactiverGroupe=groupe=>{
    const ids=NAV_GROUPS.find(g=>g.label===groupe)?.items.map(i=>i.id).filter(id=>!MODULES_CORE.has(id))||[];
    setVisibles(v=>v.filter(x=>!ids.includes(x)));
  };
  const total=visibles.length;
  return (
    <div>
      <div style={{marginBottom:20}}>
        <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>⚙️ Personnalisation</h1>
        <p style={{color:T.muted,fontSize:13,marginTop:3}}>{total} module{total>1?"s":""} visible{total>1?"s":""} sur {ALL.length} disponibles</p>
      </div>
      <div style={{padding:"12px 16px",background:"rgba(240,165,0,0.07)",border:"1px solid rgba(240,165,0,0.2)",borderRadius:10,marginBottom:20,fontSize:12,color:T.warning}}>
        💡 Masquer un module ne supprime pas vos données — elles sont conservées. Vous pouvez réactiver n'importe quel module à tout moment.
        <br/>Les modules <strong>en surbrillance dorée</strong> sont essentiels et toujours visibles.
      </div>
      <div style={{display:"flex",gap:10,marginBottom:20}}>
        <Btn v="ghost" onClick={()=>setVisibles(DEFAULT_VISIBLES)}>↩ Réinitialiser (défaut)</Btn>
        <Btn v="ghost" onClick={()=>setVisibles(ALL.map(i=>i.id))}>✅ Tout activer</Btn>
        <Btn v="ghost" onClick={()=>setVisibles([...MODULES_CORE])}>🔴 Minimum vital</Btn>
      </div>
      {NAV_GROUPS.map(groupe=>(
        <div key={groupe.label} style={{marginBottom:20}}>
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:8}}>
            <div style={{fontSize:11,color:T.accent,fontWeight:700,textTransform:"uppercase",letterSpacing:"0.08em"}}>{groupe.label}</div>
            <div style={{display:"flex",gap:6}}>
              <button onClick={()=>activerGroupe(groupe.label)} style={{fontSize:10,padding:"3px 8px",borderRadius:6,border:`1px solid ${T.border}`,background:"transparent",color:T.muted,cursor:"pointer",fontFamily:T.font}}>Tout activer</button>
              <button onClick={()=>desactiverGroupe(groupe.label)} style={{fontSize:10,padding:"3px 8px",borderRadius:6,border:`1px solid ${T.border}`,background:"transparent",color:T.muted,cursor:"pointer",fontFamily:T.font}}>Tout masquer</button>
            </div>
          </div>
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(200px,1fr))",gap:8}}>
            {groupe.items.map(item=>{
              const isCore=MODULES_CORE.has(item.id);
              const isVisible=visibles.includes(item.id);
              return <div key={item.id} onClick={()=>toggle(item.id)}
                style={{display:"flex",alignItems:"center",gap:10,padding:"10px 14px",borderRadius:10,border:`1px solid ${isVisible?(isCore?T.accent:T.border):"#0d1117"}`,background:isVisible?(isCore?T.accentDim:"#060a10"):"#0a0c10",cursor:isCore?"default":"pointer",opacity:isCore?1:isVisible?1:0.45,transition:"all 0.15s"}}>
                <span style={{fontSize:18}}>{item.icon}</span>
                <div style={{flex:1}}>
                  <div style={{fontSize:12,fontWeight:600,color:isVisible?T.text:T.muted}}>{item.label}</div>
                  {isCore&&<div style={{fontSize:9,color:T.accent}}>Essentiel</div>}
                </div>
                <div style={{width:18,height:18,borderRadius:9,border:`2px solid ${isCore?T.accent:isVisible?T.success:T.border}`,background:isCore?T.accent:isVisible?T.success:"transparent",display:"flex",alignItems:"center",justifyContent:"center",fontSize:10,color:"#000",fontWeight:700,flexShrink:0}}>
                  {(isCore||isVisible)?"✓":""}
                </div>
              </div>;
            })}
          </div>
        </div>
      ))}
    </div>
  );
};

const Identite=({identite,setIdentite})=>{
  const [selected,setSelected]=useState(null);
  const [showAdd,setShowAdd]=useState(false);
  const [form,setForm]=useState({type:"cni",titulaire:"",numero:"",dateDelivrance:"",dateExpiration:"",organisme:"",note:""});

  const membres=identite.membres||[];
  const docs=identite.docs||[];

  const selDoc=selected&&docs.find(d=>d.id===selected);

  const joursAvantExpiration=d=>{if(!d.dateExpiration)return null;return daysFrom(d.dateExpiration);};
  const statutDoc=d=>{
    const j=joursAvantExpiration(d);
    if(j===null)return{l:"Sans expiration",c:T.muted};
    if(j<0)return{l:"Expiré",c:T.danger};
    if(j<=30)return{l:`Expire dans ${j}j`,c:T.danger};
    if(j<=180)return{l:`Expire dans ${Math.round(j/30)}mois`,c:T.warning};
    return{l:"Valide",c:T.success};
  };

  const expiresSoon=docs.filter(d=>{const j=joursAvantExpiration(d);return j!==null&&j>=0&&j<=180;});

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>🪪 Identité & Documents officiels</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>{docs.length} document{docs.length>1?"s":""}{expiresSoon.length>0&&<span style={{color:T.warning,fontWeight:700}}> · ⚠️ {expiresSoon.length} expirant bientôt</span>}</p>
        </div>
        <Btn onClick={()=>setShowAdd(true)}>+ Ajouter document</Btn>
      </div>

      {/* Alertes expiration */}
      {expiresSoon.length>0&&(
        <div style={{background:"rgba(251,146,60,0.08)",border:"1px solid rgba(251,146,60,0.25)",borderRadius:10,padding:"12px 16px",marginBottom:18}}>
          <div style={{fontWeight:700,color:T.warning,marginBottom:8,fontSize:13}}>⚠️ Documents à renouveler prochainement</div>
          <div style={{display:"flex",gap:8,flexWrap:"wrap"}}>
            {expiresSoon.map(d=>{
              const s=statutDoc(d);
              return <Badge key={d.id} c={s.c}>{DOCS_IDENTITE.find(t=>t.id===d.type)?.icon||"📄"} {d.titulaire||d.type} — {s.l}</Badge>;
            })}
          </div>
        </div>
      )}

      {/* Groupement par type */}
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(300px,1fr))",gap:14}}>
        {docs.length===0&&<EmptyState icon="🪪" text="Ajoutez vos documents d'identité : CNI, passeport, permis, carte vitale..."/>}
        {docs.map(d=>{
          const type=DOCS_IDENTITE.find(t=>t.id===d.type)||DOCS_IDENTITE[8];
          const s=statutDoc(d);
          return (
            <Card key={d.id} onClick={()=>setSelected(d.id)} style={{cursor:"pointer",borderColor:selected===d.id?T.accent:s.c===T.danger?"rgba(239,68,68,0.4)":T.border,padding:0,overflow:"hidden"}}>
              <div style={{background:`${type.color}12`,padding:"14px 16px",borderBottom:`1px solid ${T.border}`}}>
                <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                  <div style={{display:"flex",alignItems:"center",gap:10}}>
                    <span style={{fontSize:26}}>{type.icon}</span>
                    <div>
                      <div style={{fontFamily:T.fontD,fontSize:15,fontWeight:700,color:T.text}}>{type.label}</div>
                      {d.titulaire&&<div style={{fontSize:12,color:T.muted}}>{d.titulaire}</div>}
                    </div>
                  </div>
                  <Badge c={s.c}>{s.l}</Badge>
                </div>
              </div>
              <div style={{padding:"10px 16px",display:"flex",gap:6,flexWrap:"wrap"}}>
                {d.numero&&<Badge c={T.muted}>N° {d.numero}</Badge>}
                {d.dateExpiration&&<Badge c={s.c}>Exp: {fmt(d.dateExpiration)}</Badge>}
                {(d.docs||[]).length>0&&<Badge c={T.accent}>📎 {d.docs.length}</Badge>}
              </div>
            </Card>
          );
        })}
      </div>

      {/* FichePanel document d'identité */}
      {selDoc&&(()=>{
        const type=DOCS_IDENTITE.find(t=>t.id===selDoc.type)||DOCS_IDENTITE[8];
        const s=statutDoc(selDoc);
        const j=joursAvantExpiration(selDoc);
        return <FichePanel
          title={type.label} icon={type.icon}
          badge={s.l} badgeColor={s.c}
          onClose={()=>setSelected(null)}
          onDelete={()=>{setIdentite(p=>({...p,docs:p.docs.filter(d=>d.id!==selDoc.id)}));setSelected(null);}}
          docs={selDoc.docs||[]} onDocsChange={nd=>setIdentite(p=>({...p,docs:p.docs.map(d=>d.id===selDoc.id?{...d,docs:nd}:d)}))}
          echanges={selDoc.echanges||[]} onEchangesChange={ne=>setIdentite(p=>({...p,docs:p.docs.map(d=>d.id===selDoc.id?{...d,echanges:ne}:d)}))}
          docsLabel="Scan recto/verso, photo, PDF officiel..."
          leftContent={<div>
            <InfoRow label="Type" value={type.label}/>
            <InfoRow label="Titulaire" value={selDoc.titulaire}/>
            <InfoRow label="Numéro" value={selDoc.numero} mono/>
            <InfoRow label="Délivré le" value={fmt(selDoc.dateDelivrance)}/>
            <InfoRow label="Expire le" value={fmt(selDoc.dateExpiration)} color={s.c}/>
            <InfoRow label="Organisme" value={selDoc.organisme}/>
            {j!==null&&j>=0&&j<=180&&(
              <div style={{marginTop:12,padding:12,background:j<=30?"rgba(239,68,68,0.1)":"rgba(251,146,60,0.1)",borderRadius:8,fontSize:12,color:j<=30?T.danger:T.warning}}>
                ⚠️ {j<=30?`Ce document expire dans ${j} jours !`:`Pensez à renouveler avant le ${fmt(selDoc.dateExpiration)}.`}
                {selDoc.type==="cni"&&<div style={{marginTop:4,fontSize:11}}>📍 Démarche en ligne : france-identite.gouv.fr</div>}
                {selDoc.type==="passeport"&&<div style={{marginTop:4,fontSize:11}}>📍 Démarche : mairie ou service-public.fr</div>}
                {selDoc.type==="permis"&&<div style={{marginTop:4,fontSize:11}}>📍 Démarche : ants.gouv.fr</div>}
              </div>
            )}
            {selDoc.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{selDoc.note}</div>}
          </div>}
        />;
      })()}

      {/* Ajout document */}
      {showAdd&&<Modal title="🪪 Nouveau document d'identité" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Type de document"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}>{DOCS_IDENTITE.map(t=><option key={t.id} value={t.id}>{t.icon} {t.label}</option>)}</Sel></F>
          <F label="Titulaire"><Inp value={form.titulaire} onChange={v=>setForm(f=>({...f,titulaire:v}))} placeholder="Jean Dupont"/></F>
          <F label="Numéro"><Inp value={form.numero} onChange={v=>setForm(f=>({...f,numero:v}))} placeholder="1234567890123" mono/></F>
          <F label="Organisme de délivrance"><Inp value={form.organisme} onChange={v=>setForm(f=>({...f,organisme:v}))} placeholder="Préfecture de Gironde"/></F>
          <F label="Date de délivrance"><Inp type="date" value={form.dateDelivrance} onChange={v=>setForm(f=>({...f,dateDelivrance:v}))}/></F>
          <F label="Date d'expiration"><Inp type="date" value={form.dateExpiration} onChange={v=>setForm(f=>({...f,dateExpiration:v}))}/></F>
        </div>
        <F label="Note"><Txt value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} rows={2}/></F>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={()=>{setIdentite(p=>({...p,docs:[...(p.docs||[]),{...form,id:uid(),docs:[],echanges:[]}]}));setShowAdd(false);setForm({type:"cni",titulaire:"",numero:"",dateDelivrance:"",dateExpiration:"",organisme:"",note:""});}}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════════════════════════
// MODULE: VIE DE FAMILLE
// ═══════════════════════════════════════════════════════════════════════════════
const TYPES_EVT=[
  {id:"naissance",label:"Naissance",icon:"👶",color:"#60a5fa"},
  {id:"mariage",label:"Mariage",icon:"💍",color:"#f0a500"},
  {id:"pacs",label:"PACS",icon:"🤝",color:"#f0a500"},
  {id:"divorce",label:"Divorce / Séparation",icon:"⚖️",color:"#f87171"},
  {id:"deces",label:"Décès",icon:"🕯️",color:"#94a3b8"},
  {id:"adoption",label:"Adoption",icon:"❤️",color:"#f472b6"},
  {id:"demenagement",label:"Déménagement",icon:"📦",color:"#fb923c"},
  {id:"retraite",label:"Départ en retraite",icon:"🏖️",color:"#34d399"},
  {id:"diplome",label:"Diplôme / Réussite",icon:"🎓",color:"#a78bfa"},
  {id:"autre",label:"Autre événement",icon:"⭐",color:"#94a3b8"},
];

const VieFamille=({vieFamille,setVieFamille})=>{
  const [selected,setSelected]=useState(null);
  const [showAdd,setShowAdd]=useState(false);
  const [showNote,setShowNote]=useState(false);
  const [activeTab,setActiveTab]=useState("evenements");
  const [form,setForm]=useState({type:"naissance",titre:"",personne:"",date:"",lieu:"",note:""});
  const [capsuleNote,setCapsuleNote]=useState("");

  const evenements=vieFamille.evenements||[];
  const capsule=vieFamille.capsule||[];
  const selEvt=selected&&evenements.find(e=>e.id===selected);

  // Chronologie groupée par année
  const byYear=useMemo(()=>{
    const map={};
    [...evenements].sort((a,b)=>b.date.localeCompare(a.date)).forEach(e=>{
      const y=e.date?.slice(0,4)||"?";
      if(!map[y])map[y]=[];
      map[y].push(e);
    });
    return map;
  },[evenements]);

  const saveCapsule=()=>{
    if(!capsuleNote.trim())return;
    setVieFamille(p=>({...p,capsule:[{id:uid(),texte:capsuleNote,date:today(),createdAt:new Date().toISOString()},...(p.capsule||[])]}));
    setCapsuleNote("");setShowNote(false);
  };

  return (
    <div>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:20}}>
        <div>
          <h1 style={{fontFamily:T.fontD,fontSize:26,color:T.text}}>👨‍👩‍👧‍👦 Vie de famille</h1>
          <p style={{color:T.muted,marginTop:3,fontSize:13}}>Chronologie familiale · {evenements.length} événement{evenements.length>1?"s":""} · {capsule.length} souvenir{capsule.length>1?"s":""}</p>
        </div>
        <div style={{display:"flex",gap:8}}>
          {activeTab==="evenements"&&<Btn onClick={()=>setShowAdd(true)}>+ Événement</Btn>}
          {activeTab==="capsule"&&<Btn onClick={()=>setShowNote(true)}>+ Souvenir</Btn>}
        </div>
      </div>

      <Tabs tabs={[{id:"evenements",icon:"📅",label:"Chronologie"},{id:"capsule",icon:"💌",label:"Capsule temporelle"},{id:"stats",icon:"📊",label:"Statistiques"}]} active={activeTab} onChange={t=>{setActiveTab(t);setSelected(null);}}/>

      {activeTab==="evenements"&&(
        <div>
          {evenements.length===0&&<EmptyState icon="📅" text="Commencez votre chronologie familiale : naissances, mariages, déménagements, diplômes..."/>}

          {/* Timeline par année */}
          {Object.entries(byYear).map(([year,evts])=>(
            <div key={year} style={{marginBottom:24}}>
              <div style={{display:"flex",alignItems:"center",gap:10,marginBottom:12}}>
                <div style={{fontFamily:T.fontD,fontSize:18,fontWeight:700,color:T.accent}}>{year}</div>
                <div style={{flex:1,height:1,background:T.border}}/>
                <div style={{fontSize:11,color:T.muted}}>{evts.length} événement{evts.length>1?"s":""}</div>
              </div>
              <div style={{display:"grid",gap:8}}>
                {evts.map(e=>{
                  const type=TYPES_EVT.find(t=>t.id===e.type)||TYPES_EVT[9];
                  return (
                    <Card key={e.id} onClick={()=>setSelected(e.id)} style={{cursor:"pointer",borderColor:selected===e.id?T.accent:T.border,padding:"12px 16px",borderLeft:`4px solid ${type.color}`}}>
                      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start"}}>
                        <div style={{display:"flex",alignItems:"center",gap:10}}>
                          <span style={{fontSize:22,flexShrink:0}}>{type.icon}</span>
                          <div>
                            <div style={{fontWeight:700,color:T.text,fontSize:14}}>{e.titre}</div>
                            <div style={{fontSize:12,color:T.muted,marginTop:2}}>
                              {e.personne&&<span>{e.personne} · </span>}
                              {fmt(e.date)}
                              {e.lieu&&<span> · 📍 {e.lieu}</span>}
                            </div>
                          </div>
                        </div>
                        <div style={{display:"flex",gap:6,alignItems:"center"}}>
                          <Badge c={type.color}>{type.label}</Badge>
                          {(e.docs||[]).length>0&&<Badge c={T.accent}>📎 {e.docs.length}</Badge>}
                        </div>
                      </div>
                      {e.note&&<div style={{fontSize:12,color:T.muted,marginTop:8,fontStyle:"italic",borderTop:`1px solid ${T.border}`,paddingTop:8}}>{e.note}</div>}
                    </Card>
                  );
                })}
              </div>
            </div>
          ))}

          {/* FichePanel événement */}
          {selEvt&&(()=>{
            const type=TYPES_EVT.find(t=>t.id===selEvt.type)||TYPES_EVT[9];
            return <FichePanel
              title={selEvt.titre} icon={type.icon}
              badge={type.label} badgeColor={type.color}
              onClose={()=>setSelected(null)}
              onDelete={()=>{setVieFamille(p=>({...p,evenements:p.evenements.filter(e=>e.id!==selEvt.id)}));setSelected(null);}}
              docs={selEvt.docs||[]} onDocsChange={nd=>setVieFamille(p=>({...p,evenements:p.evenements.map(e=>e.id===selEvt.id?{...e,docs:nd}:e)}))}
              echanges={selEvt.echanges||[]} onEchangesChange={ne=>setVieFamille(p=>({...p,evenements:p.evenements.map(e=>e.id===selEvt.id?{...e,echanges:ne}:e)}))}
              docsLabel={selEvt.type==="mariage"?"Acte de mariage, photos, faire-part...":selEvt.type==="naissance"?"Acte de naissance, carnet de santé...":selEvt.type==="divorce"?"Jugement, ordonnance, accord...":"Documents officiels, photos, souvenirs..."}
              leftContent={<div>
                <InfoRow label="Événement" value={type.icon+" "+type.label}/>
                <InfoRow label="Titre" value={selEvt.titre}/>
                <InfoRow label="Personnes concernées" value={selEvt.personne}/>
                <InfoRow label="Date" value={fmt(selEvt.date)} color={T.accent}/>
                <InfoRow label="Lieu" value={selEvt.lieu}/>
                {selEvt.lieu&&<div style={{marginTop:8}}><MapsLinks adresse={selEvt.lieu}/></div>}
                {selEvt.note&&<div style={{marginTop:14,padding:12,background:"#0a0e17",borderRadius:8,fontSize:12,color:T.muted,fontStyle:"italic"}}>{selEvt.note}</div>}
                {/* Anniversaire si mariage */}
                {(selEvt.type==="mariage"||selEvt.type==="pacs")&&selEvt.date&&(()=>{
                  const annees=new Date().getFullYear()-new Date(selEvt.date).getFullYear();
                  const prochain=new Date(selEvt.date);prochain.setFullYear(new Date().getFullYear());
                  if(prochain<new Date())prochain.setFullYear(new Date().getFullYear()+1);
                  const j=Math.round((prochain-new Date())/86400000);
                  return <div style={{marginTop:12,padding:12,background:"rgba(240,165,0,0.08)",borderRadius:8,fontSize:12,color:T.accent}}>
                    💍 {annees} an{annees>1?"s":""} de {selEvt.type==="mariage"?"mariage":"PACS"} · Prochain anniversaire dans {j} jours
                  </div>;
                })()}
              </div>}
            />;
          })()}
        </div>
      )}

      {activeTab==="capsule"&&(
        <div>
          <div style={{background:"rgba(167,139,250,0.07)",border:"1px solid rgba(167,139,250,0.2)",borderRadius:12,padding:"16px 20px",marginBottom:20}}>
            <div style={{fontFamily:T.fontD,fontSize:15,color:"#a78bfa",marginBottom:4}}>💌 Capsule temporelle</div>
            <div style={{fontSize:13,color:T.muted,lineHeight:1.7}}>Notez vos souvenirs, anecdotes, premiers mots, moments uniques. Ces notes seront précieuses dans le futur.</div>
          </div>
          {capsule.length===0&&<EmptyState icon="💌" text="Commencez à noter vos souvenirs de famille..."/>}
          <div style={{display:"grid",gap:12}}>
            {capsule.map(note=>(
              <Card key={note.id} style={{borderLeft:"3px solid #a78bfa",padding:"14px 18px"}}>
                <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:8}}>
                  <Badge c="#a78bfa">💌 {fmt(note.date)}</Badge>
                  <button onClick={()=>setVieFamille(p=>({...p,capsule:p.capsule.filter(n=>n.id!==note.id)}))} style={{background:"none",border:"none",color:T.muted,cursor:"pointer",fontSize:14}}>🗑</button>
                </div>
                <div style={{fontSize:13,color:T.text,lineHeight:1.8,whiteSpace:"pre-wrap"}}>{note.texte}</div>
              </Card>
            ))}
          </div>
        </div>
      )}

      {activeTab==="stats"&&(
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
          <Card>
            <Divider label="Événements par type"/>
            {TYPES_EVT.filter(t=>evenements.some(e=>e.type===t.id)).map(t=>{
              const count=evenements.filter(e=>e.type===t.id).length;
              return (
                <div key={t.id} style={{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"8px 0",borderBottom:`1px solid ${T.border}`,fontSize:13}}>
                  <span style={{color:T.text}}>{t.icon} {t.label}</span>
                  <Badge c={t.color}>{count}</Badge>
                </div>
              );
            })}
            {!TYPES_EVT.some(t=>evenements.some(e=>e.type===t.id))&&<EmptyState icon="📊" text="Aucun événement"/>}
          </Card>
          <Card>
            <Divider label="Capsule temporelle"/>
            <InfoRow label="Souvenirs enregistrés" value={capsule.length+""}/>
            {capsule.length>0&&<InfoRow label="Premier souvenir" value={fmt(capsule[capsule.length-1].date)}/>}
            {capsule.length>0&&<InfoRow label="Dernier souvenir" value={fmt(capsule[0].date)}/>}
            <Divider label="Chronologie"/>
            <InfoRow label="Événements au total" value={evenements.length+""}/>
            {evenements.length>0&&<InfoRow label="Plus ancien" value={fmt(evenements.sort((a,b)=>a.date.localeCompare(b.date))[0]?.date)}/>}
            {evenements.length>0&&<InfoRow label="Plus récent" value={fmt(evenements.sort((a,b)=>b.date.localeCompare(a.date))[0]?.date)}/>}
          </Card>
        </div>
      )}

      {/* Modale ajout événement */}
      {showAdd&&<Modal title="📅 Nouvel événement familial" onClose={()=>setShowAdd(false)}>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10}}>
          <F label="Type *"><Sel value={form.type} onChange={v=>setForm(f=>({...f,type:v}))}>{TYPES_EVT.map(t=><option key={t.id} value={t.id}>{t.icon} {t.label}</option>)}</Sel></F>
          <F label="Titre *"><Inp value={form.titre} onChange={v=>setForm(f=>({...f,titre:v}))} placeholder="Naissance de Emma, Mariage de..."/></F>
          <F label="Personnes concernées"><Inp value={form.personne} onChange={v=>setForm(f=>({...f,personne:v}))} placeholder="Emma, Jean & Marie..."/></F>
          <F label="Date"><Inp type="date" value={form.date} onChange={v=>setForm(f=>({...f,date:v}))}/></F>
          <F label="Lieu" style={{gridColumn:"1/-1"}}><Inp value={form.lieu} onChange={v=>setForm(f=>({...f,lieu:v}))} placeholder="Mairie de Langon, Bordeaux..."/></F>
        </div>
        <F label="Description / Anecdote"><Txt value={form.note} onChange={v=>setForm(f=>({...f,note:v}))} rows={3} placeholder="Racontez cet événement..."/></F>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8,paddingTop:10}}>
          <Btn v="ghost" onClick={()=>setShowAdd(false)}>Annuler</Btn>
          <Btn onClick={()=>{setVieFamille(p=>({...p,evenements:[...(p.evenements||[]),{...form,id:uid(),docs:[],echanges:[]}]}));setShowAdd(false);setForm({type:"naissance",titre:"",personne:"",date:"",lieu:"",note:"",docs:[],echanges:[]});}} disabled={!form.titre||!form.date}>💾 Enregistrer</Btn>
        </div>
      </Modal>}

      {/* Modale souvenir capsule */}
      {showNote&&<Modal title="💌 Nouveau souvenir" onClose={()=>setShowNote(false)}>
        <F label="Date du souvenir"><Inp type="date" value={capsuleNote.date||today()} onChange={()=>{}}/></F>
        <F label="Racontez ce moment...">
          <Txt value={capsuleNote} onChange={setCapsuleNote} rows={6} placeholder="Aujourd'hui Emma a dit son premier mot... Ce matin, Pierre a..."/>
        </F>
        <div style={{fontSize:11,color:T.muted,marginBottom:10}}>💡 Soyez précis et descriptif — dans 10 ans vous serez content(e) d'avoir ces détails.</div>
        <div style={{display:"flex",justifyContent:"flex-end",gap:8}}>
          <Btn v="ghost" onClick={()=>setShowNote(false)}>Annuler</Btn>
          <Btn onClick={saveCapsule} disabled={!capsuleNote.trim()}>💾 Enregistrer</Btn>
        </div>
      </Modal>}
    </div>
  );
};

export default function App(){
  const [page,setPage]=useState("dashboard");
  const [collapsed,setCollapsed]=useState(false);
  const [visibles,setVisibles]=useState(()=>{try{const s=localStorage.getItem("mespapiers_visibles");return s?JSON.parse(s):DEFAULT_VISIBLES;}catch{return DEFAULT_VISIBLES;}});
  // Persiste les préférences de visibilité séparément
  useEffect(()=>{try{localStorage.setItem("mespapiers_visibles",JSON.stringify(visibles));}catch{}},[visibles]);
  const [showBackup,setShowBackup]=useState(false);
  const [lastAutoSave,setLastAutoSave]=useState(null);

  // State global
  const [docs,setDocs]=useState([]);
  const [maisons,setMaisons]=useState([
    {id:"m1",nom:"Ma Maison",type:"principale",icon:"🏠",adresse:"12 rue des Lilas, 33410 Langon",surface:145,nbPieces:6,anneeConstruction:1985,dpe:"C",chauffage:"Gaz",ecs:"Chaudière",valeur:320000,prixAchat:185000,dateAchat:"2010-06-15",notaire:"Maître Bernard",
      abonnements:[
        {id:uid(),categorie:"electricite",fournisseur:"EDF",reference:"6501234567",montantMensuel:"95",prelevement:"mensuel",dateDebut:"2020-01-01",dateEcheance:"",iban:"FR76123456789",note:"Contrat option Base 9kVA",statut:"actif"},
        {id:uid(),categorie:"gaz",fournisseur:"Engie",reference:"GAZ-789",montantMensuel:"72",prelevement:"mensuel",dateDebut:"2020-01-01",dateEcheance:"",iban:"FR76123456789",note:"",statut:"actif"},
        {id:uid(),categorie:"eau",fournisseur:"Suez",reference:"EAU-456",montantMensuel:"28",prelevement:"trimestriel",dateDebut:"2010-06-15",dateEcheance:"",iban:"",note:"Facturé trimestriellement",statut:"actif"},
        {id:uid(),categorie:"internet",fournisseur:"Orange Fibre",reference:"INT-321",montantMensuel:"39",prelevement:"mensuel",dateDebut:"2022-03-01",dateEcheance:"2025-03-01",iban:"FR76123456789",note:"Fibre 1Gb",statut:"actif"},
        {id:uid(),categorie:"alarme",fournisseur:"Verisure",reference:"VER-111",montantMensuel:"35",prelevement:"mensuel",dateDebut:"2021-06-01",dateEcheance:"",iban:"FR76123456789",note:"Télésurveillance 24h",statut:"actif"},
        {id:uid(),categorie:"entretien",fournisseur:"Viessmann",reference:"CTR-CHAUD",montantMensuel:"15",prelevement:"annuel",dateDebut:"2020-09-01",dateEcheance:"2026-09-01",iban:"",note:"Contrat entretien chaudière annuel (180€/an)",statut:"actif"},
        {id:uid(),categorie:"streaming",fournisseur:"Netflix",reference:"",montantMensuel:"17",prelevement:"mensuel",dateDebut:"2019-01-01",dateEcheance:"",iban:"",note:"Plan standard 2 écrans",statut:"actif"},
      ],
      travaux:[{id:uid(),titre:"Réfection toiture",type:"Toiture",date:"2022-05-10",cout:12000,artisan:"Couvreur Dupont",statut:"terminé",note:"Ardoises",garantie:"2032-05-10"},{id:uid(),titre:"Cuisine équipée",type:"Cuisine",date:"2020-09-01",cout:18000,artisan:"Cuisiniste Leclerc",statut:"terminé",note:"Plan de travail granit",garantie:""}],
      equipements:[{id:uid(),nom:"Chaudière Viessmann",piece:"Cave",marque:"Viessmann",modele:"Vitodens 200",dateAchat:"2020-09-01",garantieJusqu:"2030-09-01",cout:4200,note:"Contrat entretien annuel"},{id:uid(),nom:"Lave-linge",piece:"Cuisine",marque:"Samsung",modele:"WW90T554DAE",dateAchat:"2021-03-15",garantieJusqu:"2026-03-15",cout:650,note:""}],
      documents:[],relevesCpt:[{id:uid(),type:"Électricité",valeur:"14250",unite:"kWh",date:"2025-01-01"},{id:uid(),type:"Gaz",valeur:"8420",unite:"kWh",date:"2025-01-01"}]},
    {id:"m2",nom:"Chalet Montagne",type:"secondaire",icon:"⛰️",adresse:"5 chemin des Crêtes, 74120 Megève",surface:80,nbPieces:4,anneeConstruction:1972,dpe:"E",chauffage:"Électrique",ecs:"Chauffe-eau",valeur:280000,prixAchat:210000,dateAchat:"2018-12-01",notaire:"Maître Duval",
      abonnements:[
        {id:uid(),categorie:"electricite",fournisseur:"EDF",reference:"MEG-654",montantMensuel:"62",prelevement:"mensuel",dateDebut:"2018-12-01",dateEcheance:"",iban:"",note:"Résidence secondaire",statut:"actif"},
        {id:uid(),categorie:"ordures",fournisseur:"Mairie de Megève",reference:"ORD-001",montantMensuel:"18",prelevement:"annuel",dateDebut:"2019-01-01",dateEcheance:"2025-12-31",iban:"",note:"Taxe ordures ménagères (216€/an)",statut:"actif"},
      ],
      travaux:[{id:uid(),titre:"Isolation combles",type:"Isolation",date:"2023-07-01",cout:6500,artisan:"IsoPlus",statut:"terminé",note:"Laine de verre 300mm",garantie:""}],equipements:[],documents:[],relevesCpt:[]},
  ]);
  const [vehicules,setVehicules]=useState([
    {id:"v1",type:"voiture",marque:"Renault",modele:"Clio 5",immat:"AA-123-BB",annee:"2021",couleur:"Blanc nacré",energie:"Essence",kilometrage:38500,prixAchat:18900,dateAchat:"2021-03-01",dateCT:"2025-03-15",dateAssurance:"2025-12-31",
      entretiens:[{id:uid(),type:"Vidange",date:"2024-01-10",kilometrage:30000,cout:85,garage:"Renault Langon",note:"Huile 5W30"}],
      histoCT:[{id:uid(),date:"2023-03-15",resultat:"Favorable",prochainCT:"2025-03-15",centre:"Autovision Langon",cout:79,note:"",defauts:""},{id:uid(),date:"2021-03-10",resultat:"Favorable",prochainCT:"2023-03-10",centre:"Bureau Veritas",cout:74,note:"Première mise en circulation",defauts:""}]},
    {id:"v2",type:"velo",marque:"Trek",modele:"Marlin 7",immat:"",annee:"2022",couleur:"Bleu",energie:"Mécanique",kilometrage:0,prixAchat:850,dateAchat:"2022-06-01",dateCT:"",dateAssurance:"",entretiens:[],histoCT:[]},
  ]);
  const [sports,setSports]=useState([
    {id:"sp1",nom:"Tennis",icon:"🎾",categorie:"Sport",niveau:"Intermédiaire",frequence:"2x/semaine",club:"TC Langon",licenceExpiry:"2025-08-31",note:"Objectif : tournoi été 2025",seances:[{id:uid(),date:"2025-02-24",duree:90,distance:"",calories:420,note:"Victoire 6-3 6-4"},{id:uid(),date:"2025-02-20",duree:60,distance:"",calories:280,note:"Entraînement service"},{id:uid(),date:"2025-02-15",duree:90,distance:"",calories:380,note:""}],equipements:[{id:uid(),nom:"Raquette Wilson Pro Staff",marque:"Wilson"},{id:uid(),nom:"Chaussures Asics",marque:"Asics"}],objectifs:[]},
    {id:"sp2",nom:"Running",icon:"🏃",categorie:"Sport",niveau:"Débutant",frequence:"3x/semaine",club:"",licenceExpiry:"",note:"Préparer semi-marathon",seances:[{id:uid(),date:"2025-02-23",duree:45,distance:8,calories:480,note:"Bonne foulée"},{id:uid(),date:"2025-02-21",duree:35,distance:6,calories:360,note:""},{id:uid(),date:"2025-02-18",duree:50,distance:9,calories:540,note:"Nouveau record 9km"}],equipements:[{id:uid(),nom:"Chaussures Nike Air Zoom",marque:"Nike"}],objectifs:[]},
    {id:"sp3",nom:"Guitare",icon:"🎸",categorie:"Musique",niveau:"Intermédiaire",frequence:"1x/semaine",club:"Cours particuliers",licenceExpiry:"",note:"Apprendre des morceaux de Pink Floyd",seances:[{id:uid(),date:"2025-02-22",duree:60,distance:"",calories:"",note:"Travail Comfortably Numb"},{id:uid(),date:"2025-02-15",duree:60,distance:"",calories:"",note:"Gammes pentatoniques"}],equipements:[{id:uid(),nom:"Gibson Les Paul Standard",marque:"Gibson"},{id:uid(),nom:"Ampli Fender Blues Jr",marque:"Fender"}],objectifs:[]},
  ]);
  const [photos,setPhotos]=useState({medias:[],albums:[],faces:DEMO_FACES,activeFace:null});
  const [locataires,setLocataires]=useState([
    {id:"l1",bienId:"b1",prenom:"Marie",nom:"Leclerc",email:"marie@email.fr",tel:"06 98 76 54 32",typeBail:"Meublé",dateEntree:"2023-01-01",dateFin:"2025-12-31",loyer:750,charges:80,depot:1500,indexEntree:"144.51",statut:"actif",assuranceOk:true,assuranceExpiry:"2025-12-31",profession:"Infirmière",revenuMensuel:2800,paiements:[{id:uid(),mois:"2025-01",montant:830,date:"2025-01-03",mode:"virement",statut:"payé"},{id:uid(),mois:"2025-02",montant:830,date:"2025-02-05",mode:"virement",statut:"payé"},{id:uid(),mois:"2025-03",montant:830,date:null,mode:"",statut:"en attente"}],interventions:[],docs:[],messages:[]},
    {id:"l2",bienId:"b2",prenom:"Pierre",nom:"Dumont",email:"p.dumont@email.fr",tel:"07 11 22 33 44",typeBail:"Vide",dateEntree:"2022-06-01",dateFin:"2025-05-31",loyer:920,charges:100,depot:1840,indexEntree:"140.12",statut:"actif",assuranceOk:true,assuranceExpiry:"2024-11-30",profession:"Ingénieur",revenuMensuel:4200,paiements:[{id:uid(),mois:"2025-01",montant:1020,date:"2025-01-02",mode:"prélèvement",statut:"payé"},{id:uid(),mois:"2025-03",montant:1020,date:null,mode:"",statut:"en attente"}],interventions:[{id:uid(),titre:"Fuite robinet",date:"2025-01-15",statut:"résolu",cout:120,description:"Remplacement joint"}],docs:[],messages:[{id:uid(),de:"locataire",texte:"Bonjour, puis-je peindre le couloir ?",date:"2025-02-10",lu:false}]},
  ]);
  const [biens,setBiens]=useState([
    {id:"b1",nom:"Apt A - 12 rue des Fleurs",type:"Appartement",adresse:"12 rue des Fleurs, 75011 Paris",surface:48,dpe:"C",loyer:750,charges:80,depot:1500},
    {id:"b2",nom:"Apt B - 8 av Gambetta",type:"Appartement",adresse:"8 avenue Gambetta, 69003 Lyon",surface:62,dpe:"D",loyer:920,charges:100,depot:1840},
  ]);
  const [sante,setSante]=useState({rdv:[{id:uid(),titre:"Bilan annuel",medecin:"Dr. Martin",specialite:"Généraliste",date:"2025-04-15",heure:"09:30",adresse:"8 avenue de la République, 33210 Langon",note:""},{id:uid(),titre:"Contrôle dentaire",medecin:"Dr. Leblanc",specialite:"Dentiste",date:"2025-05-10",heure:"14:00",adresse:"3 rue du Dr Fleming, 33210 Langon",note:""}],ordonnances:[],remboursements:[{id:uid(),titre:"Consultation Dr. Martin",medecin:"Dr. Martin",date:"2025-02-01",montant:"25",rembourse:"16.50",mutuelle:"8.50"}],medecins:[{id:uid(),nom:"Dr. Martin",specialite:"Généraliste",email:"dr.martin@cabinet-centre.fr",tel:"05 56 63 21 45",adresse:"8 avenue de la République, 33210 Langon",note:"Médecin traitant — Secteur 1"}],constantes:[{id:uid(),titre:"Poids",montant:"78",unite:"kg",date:"2025-02-01",note:""},{id:uid(),titre:"Tension",montant:"12/8",unite:"",date:"2025-02-01",note:""}]});
  const [impots,setImpots]=useState({declarations:[{id:uid(),annee:"2024",titre:"Déclaration revenus 2024",dateEcheance:"2025-05-31",statut:"en attente",montant:"",note:""}],avis:[{id:uid(),annee:"2023",titre:"Avis d'imposition IR 2023",montant:"3240",statut:"payé",note:""}],paiements:[{id:uid(),annee:"2025",titre:"Taxe foncière",montant:"1850",dateEcheance:"2025-10-15",statut:"en attente",note:""}],deductions:[{id:uid(),annee:"2024",titre:"Travaux bien locatif",montant:"1200",statut:"à vérifier",note:"Fuite robinet Apt B"}]});
  const _c1=uid(),_c2=uid();
  const _genTx=(compteId,moisOffset,libelle,montant,sens,categorie)=>{
    const d=new Date();d.setMonth(d.getMonth()-moisOffset);
    const day=String(Math.max(1,Math.min(28,Math.floor(Math.random()*27)+1))).padStart(2,"0");
    return {id:uid(),compteId,libelle,montant,sens,categorie,date:`${d.toISOString().slice(0,7)}-${day}`,note:"",tags:[]};
  };
  const _txDemo=[
    // Salaires (6 mois)
    ...[0,1,2,3,4,5].map(m=>_genTx(_c1,m,"Salaire net",2850,"credit","salaire")),
    ...[0,1,2,3,4,5].map(m=>_genTx(_c2,m,"Salaire Marie",2400,"credit","salaire")),
    // Loyer
    ...[0,1,2,3,4,5].map(m=>_genTx(_c1,m,"Loyer + charges",950,"debit","loyer")),
    // Alimentation
    ...[0,1,2,3,4,5].flatMap(m=>[_genTx(_c1,m,"Leclerc",68,"debit","alimentation"),_genTx(_c1,m,"Carrefour Market",45,"debit","alimentation"),_genTx(_c2,m,"Lidl",38,"debit","alimentation")]),
    // Restaurant
    ...[0,1,2,3,4,5].flatMap(m=>[_genTx(_c2,m,"Restaurant L'Auberge",62,"debit","restaurant"),_genTx(_c2,m,"McDonald's",18,"debit","restaurant")]),
    // Transport
    ...[0,1,2,3,4,5].flatMap(m=>[_genTx(_c1,m,"Carburant Total",85,"debit","transport"),_genTx(_c1,m,"Péage autoroute",12,"debit","transport")]),
    // Abonnements
    ...[0,1,2,3,4,5].flatMap(m=>[_genTx(_c1,m,"Netflix",17,"debit","abonnements"),_genTx(_c1,m,"Spotify",10,"debit","abonnements"),_genTx(_c1,m,"Forfait Orange",45,"debit","abonnements"),_genTx(_c2,m,"Salle de sport",39,"debit","abonnements")]),
    // Santé
    ...[0,2,4].map(m=>_genTx(_c1,m,"Pharmacie",32,"debit","sante")),
    _genTx(_c1,1,"Médecin généraliste",25,"debit","sante"),
    _genTx(_c2,0,"Dentiste",120,"debit","sante"),
    // Loisirs
    ...[0,1,2,3].map(m=>_genTx(_c2,m,"Cinema CGR",28,"debit","loisirs")),
    _genTx(_c2,0,"Livre Amazon",18,"debit","loisirs"),
    _genTx(_c2,1,"Concert Bordeaux",65,"debit","loisirs"),
    // Shopping
    _genTx(_c2,0,"Zara vêtements",89,"debit","shopping"),
    _genTx(_c1,1,"IKEA",145,"debit","shopping"),
    _genTx(_c2,2,"Amazon",67,"debit","shopping"),
    _genTx(_c2,3,"Decathlon",55,"debit","shopping"),
    // Travaux / Maison
    _genTx(_c1,0,"Bricomarché",48,"debit","travaux"),
    _genTx(_c1,2,"Plombier réparation",180,"debit","travaux"),
    // Assurances
    ...[0,1,2,3,4,5].map(m=>_genTx(_c1,m,"Assurance habitation MMA",38,"debit","assurance")),
    ...[0,1,2,3,4,5].map(m=>_genTx(_c1,m,"Assurance auto AXA",72,"debit","assurance")),
    // Épargne
    ...[0,1,2,3,4,5].map(m=>_genTx(_c1,m,"Virement Livret A",200,"debit","epargne")),
    // Voyages (mois 1 seulement)
    _genTx(_c1,1,"Ryanair Barcelone",195,"debit","voyages"),
    _genTx(_c1,1,"Hôtel Booking",320,"debit","voyages"),
  ];
  const [banque,setBanque]=useState({
    comptes:[
      {id:_c1,nom:"Compte courant",banqueNom:"BNP Paribas",iban:"FR76 1234 5678 9012 3456",solde:4250,type2:"courant"},
      {id:_c2,nom:"Compte joint",banqueNom:"Crédit Agricole",iban:"FR76 9876 5432 1098 7654",solde:1820,type2:"courant"},
    ],
    epargne:[
      {id:uid(),nom:"Livret A",banqueNom:"La Banque Postale",solde:8500,type2:"Livret A"},
      {id:uid(),nom:"PEL",banqueNom:"BNP Paribas",solde:22000,type2:"PEL"},
    ],
    credits:[
      {id:uid(),nom:"Prêt immobilier Apt A",banqueNom:"BNP Paribas",solde:145000,statut:"actif",note:"Taux 1.8% - 20 ans"},
    ],
    transactions:_txDemo,
    budgets:{alimentation:400,restaurant:150,loisirs:100,shopping:200,transport:150,abonnements:120,sante:80,voyages:300},
  });
  const [assurances,setAssurances]=useState([
    {id:uid(),nom:"Habitation Ma Maison",assureur:"AXA",type:"habitation",numero:"AXA-2023-001",prime:38,dateDebut:"2023-01-01",dateEcheance:"2025-12-31",statut:"actif",note:"MRE — résidence principale Langon"},
    {id:uid(),nom:"Habitation Chalet Megève",assureur:"MAIF",type:"habitation",numero:"MAIF-456",prime:25,dateDebut:"2022-06-01",dateEcheance:"2025-05-31",statut:"actif",note:"Résidence secondaire"},
    {id:uid(),nom:"Auto Renault Clio AA-123-BB",assureur:"Matmut",type:"auto",numero:"MAT-789",prime:52,dateDebut:"2021-03-01",dateEcheance:"2025-12-31",statut:"actif",note:"Tous risques · Bonus 0.75"},
    {id:uid(),nom:"Habitation Apt A",assureur:"AXA",type:"pno",numero:"AXA-LOC-001",prime:35,dateDebut:"2023-01-01",dateEcheance:"2025-12-31",statut:"actif",note:"PNO + RC bailleur"},
    {id:uid(),nom:"Habitation Apt B",assureur:"MAAF",type:"pno",numero:"MAAF-456",prime:42,dateDebut:"2022-06-01",dateEcheance:"2025-05-31",statut:"actif",note:""},
    {id:uid(),nom:"Mutuelle santé",assureur:"Harmonie Mutuelle",type:"sante",numero:"HM-999",prime:68,dateDebut:"2020-01-01",dateEcheance:"2025-12-31",statut:"actif",note:"Niveau 3"},
  ]);
  const [juridique,setJuridique]=useState({contrats:[{id:uid(),titre:"Compromis de vente Apt A",parties:"Moi / Mme Leroy",dateSignature:"2022-11-15",dateFin:"",montant:"215000",statut:"terminé",note:"Acte définitif signé chez Maître Dubois"}],procedures:[],correspondances:[]});
  const [contacts,setContacts]=useState([
    {id:uid(),nom:"Maître Dubois",societe:"Cabinet Dubois & Associés",type:"avocat",email:"dubois@cabinet-dubois.fr",tel:"05 56 44 12 78",rue:"15 rue Esprit des Lois",codePostal:"33000",ville:"Bordeaux",note:"Spécialiste droit immobilier et succession",color:"#f87171"},
    {id:uid(),nom:"Dr. Martin",societe:"Cabinet médical du Centre",type:"medecin",email:"dr.martin@cabinet-centre.fr",tel:"05 56 63 21 45",rue:"8 avenue de la République",codePostal:"33210",ville:"Langon",note:"Médecin traitant — Secteur 1",color:"#34d399"},
    {id:uid(),nom:"BNP Paribas — M. Dupont",societe:"BNP Paribas",type:"banque",email:"jean.dupont@bnpparibas.fr",tel:"05 56 01 23 45",rue:"2 cours de l'Intendance",codePostal:"33000",ville:"Bordeaux",note:"Conseiller clientèle particuliers",color:"#38bdf8"},
  ]);
  const [alertes,setAlertes]=useState([
    {id:uid(),titre:"Déclaration revenus 2024",date:"2025-05-31",priorite:"haute",categorie:"impots",note:"Formulaire 2044",fait:false},
    {id:uid(),titre:"Renouvellement bail Pierre Dumont",date:"2025-05-31",priorite:"haute",categorie:"immobilier",note:"",fait:false},
    {id:uid(),titre:"Attestation assurance Marie Leclerc",date:"2025-12-31",priorite:"moyenne",categorie:"assurance",note:"",fait:false},
    {id:uid(),titre:"RDV bilan annuel Dr. Martin",date:"2025-04-15",priorite:"basse",categorie:"sante",note:"",fait:false},
  ]);
  const [modeles,setModeles]=useState({custom:[]});
  const [travail,setTravail]=useState({
    employeurActuel:{employeur:"Société ABC Sud-Ouest",siret:"123 456 789 00012",rue:"12 avenue de la Gare",codePostal:"33210",ville:"Langon",poste:"Responsable Commercial",contrat:"CDI",dateEntree:"2019-03-01",salaireBrut:"3800",coefficient:"Cadre N2",convention:"Commerce de gros",tempsTravail:"39h / semaine",lieuTravail:"Hybride (3j bureau / 2j télétravail)",congesAnnuels:"25",rtt:"10",rhNom:"Mme Lefebvre",rhEmail:"rh@abc-sudouest.fr",rhTel:"05 56 44 00 01",matricule:"EMP-0234",note:""},
    fichesPaie:[
      {id:uid(),mois:"2026-01",salaireBrut:"3800",salaireNet:"2944",conges:"2.08",note:""},
      {id:uid(),mois:"2025-12",salaireBrut:"3800",salaireNet:"2944",conges:"2.08",note:"Prime de fin d'année 500€"},
      {id:uid(),mois:"2025-11",salaireBrut:"3800",salaireNet:"2944",conges:"2.08",note:""},
    ],
    conges:[
      {id:uid(),type:"Congés payés",dateDebut:"2025-07-14",dateFin:"2025-07-25",statut:"Validé",note:"Vacances d'été"},
      {id:uid(),type:"RTT",dateDebut:"2025-05-02",dateFin:"2025-05-02",statut:"Validé",note:"Pont du 1er mai"},
    ],
    avantages:{mutuelle:{nom:"Malakoff Humanis",tauxEmployeur:"60",tauxSalarie:"40",cotisation:"45"},ticketsResto:{valeurFace:"9",partEmployeur:"5.4",nbParMois:"20"},transport:{type:"Abonnement TER",taux:"50",montant:"28"},teletravail:{joursParSemaine:"2",indemnite:"2.50",equipement:"PC portable, écran, casque"}},
    formations:[
      {id:uid(),titre:"Négociation commerciale avancée",organisme:"CCI Bordeaux",dateDebut:"2024-03-11",dateFin:"2024-03-12",duree:"14",cout:"800",certification:"",note:"Financé par le plan de formation"},
    ],
    historique:[
      {id:uid(),poste:"Commercial terrain",employeur:"Distribution SARL",contrat:"CDI",dateDebut:"2014-09-01",dateFin:"2019-02-28",ville:"Bordeaux",salaire:"2800",note:"Gestion d'un portefeuille de 80 clients B2B"},
      {id:uid(),poste:"Assistant commercial",employeur:"Négoce du Vin SA",contrat:"CDD",dateDebut:"2013-06-01",dateFin:"2014-08-31",ville:"Mérignac",salaire:"2100",note:"Stage puis CDD"},
    ],
  });
  const [enfants,setEnfants]=useState([
    {id:uid(),prenom:"Emma",nom:"",dateNaissance:"2016-03-12",sexe:"F",lieuNaissance:"Bordeaux",groupeSanguin:"A+",medecin:"Dr. Petit",ecoleActuelle:"École Jules Ferry",classe:"CE2",rdv:[{id:uid(),titre:"Bilan pédiatrique",medecin:"Dr. Petit",date:"2025-06-10",heure:"10:00",adresse:"",note:""}],vaccins:[{id:uid(),nom:"DTP",statut:"fait",dateFait:"2024-09-15",dateRappel:"2029-09-15",medecin:"Dr. Petit"},{id:uid(),nom:"ROR",statut:"fait",dateFait:"2024-09-15",dateRappel:"",medecin:"Dr. Petit"}],ecoles:[{id:uid(),nom:"École Jules Ferry",type:"Primaire",ville:"Langon",classe:"CE2",dateEntree:"2022-09-01"}],activites:[{id:uid(),nom:"Danse classique",icon:"🩰",club:"Studio Danse Langon",jour:"Mercredi",heure:"14:00",cout:60,niveau:"Débutant"},{id:uid(),nom:"Piano",icon:"🎹",club:"Cours particuliers",jour:"Samedi",heure:"10:00",cout:45,niveau:"Débutant"}],docs:[]},
  ]);
  const [animaux,setAnimaux]=useState([
    {id:uid(),nom:"Filou",espece:"Chien",race:"Golden Retriever",dateNaissance:"2020-05-20",sexe:"M",couleur:"Doré",puce:"250268501234567",tatouage:"",sterilise:true,medecin:"Dr. Veto - Cabinet Langon",assurance:"",rdv:[{id:uid(),titre:"Bilan annuel",medecin:"Dr. Veto",date:"2025-05-15",cout:85,diagnostic:"Bonne santé générale",traitement:""}],vaccins:[{id:uid(),nom:"Rage",statut:"à jour",dateFait:"2024-05-15",dateRappel:"2025-05-15",medecin:"Dr. Veto"},{id:uid(),nom:"CHPPi",statut:"à jour",dateFait:"2024-05-15",dateRappel:"2025-05-15",medecin:"Dr. Veto"}],traitements:[{id:uid(),nom:"Bravecto (anti-puces)",posologie:"1 cp / 3 mois",dateDebut:"2024-03-01",dateFin:"",statut:"actif",medecin:"Dr. Veto"}],docs:[]},
  ]);
  const [voyages,setVoyages]=useState([
    {id:uid(),destination:"Barcelone",pays:"Espagne",dateDepart:"2025-07-14",dateRetour:"2025-07-21",type:"Vacances",participants:"Famille (4 personnes)",budget:3000,note:"Réserver la Sagrada Familia à l'avance",reservations:[{id:uid(),type:"Vol",titre:"Paris CDG → Barcelone BCN",fournisseur:"Vueling",date:"2025-07-14",reference:"VY1234",montant:480,statut:"confirmée"},{id:uid(),type:"Hôtel",titre:"Hôtel Arts Barcelona",fournisseur:"Booking.com",date:"2025-07-14",reference:"BK-78965",montant:1200,statut:"confirmée"}],depenses:[],docs:[]},
    {id:uid(),destination:"Ski - Les Deux Alpes",pays:"France",dateDepart:"2025-02-08",dateRetour:"2025-02-15",type:"Vacances",participants:"Famille",budget:2500,note:"",reservations:[],depenses:[{id:uid(),libelle:"Location appartement",categorie:"Hébergement",montant:1100,date:"2025-02-08"},{id:uid(),libelle:"Forfaits ski x4",categorie:"Activités",montant:720,date:"2025-02-09"},{id:uid(),libelle:"Matériel de ski",categorie:"Transport",montant:280,date:"2025-02-08"}],docs:[]},
  ]);
  const [identite,setIdentite]=useState({
    docs:[
      {id:uid(),type:"cni",titulaire:"Jean Dupont",numero:"",dateDelivrance:"2020-03-15",dateExpiration:"2030-03-14",organisme:"Préfecture de Gironde",note:"",docs:[],echanges:[]},
      {id:uid(),type:"passeport",titulaire:"Jean Dupont",numero:"19AB12345",dateDelivrance:"2019-06-01",dateExpiration:"2029-05-31",organisme:"Mairie de Langon",note:"",docs:[],echanges:[]},
      {id:uid(),type:"permis",titulaire:"Jean Dupont",numero:"B-123456",dateDelivrance:"2005-09-12",dateExpiration:"2035-09-11",organisme:"Préfecture",note:"Permis B",docs:[],echanges:[]},
      {id:uid(),type:"vitale",titulaire:"Jean Dupont",numero:"1 80 01 33 040 123 45",dateDelivrance:"",dateExpiration:"",organisme:"Ameli / CPAM",note:"",docs:[],echanges:[]},
      {id:uid(),type:"livret",titulaire:"Famille Dupont",numero:"",dateDelivrance:"2010-08-20",dateExpiration:"",organisme:"Mairie de Langon",note:"Livret de famille",docs:[],echanges:[]},
    ]
  });
  const [vieFamille,setVieFamille]=useState({
    evenements:[
      {id:uid(),type:"mariage",titre:"Mariage Jean & Marie Dupont",personne:"Jean Dupont & Marie Martin",date:"2010-08-21",lieu:"Mairie de Langon, Langon",note:"Cérémonie civile puis religieuse. 80 invités.",docs:[],echanges:[]},
      {id:uid(),type:"naissance",titre:"Naissance de Emma",personne:"Emma Dupont",date:"2016-03-12",lieu:"Clinique Saint-Louis, Bordeaux",note:"3,2 kg, 50 cm. Premier enfant de la famille.",docs:[],echanges:[]},
      {id:uid(),type:"demenagement",titre:"Déménagement à Langon",personne:"Famille Dupont",date:"2010-06-15",lieu:"12 rue des Lilas, Langon",note:"Achat de la maison principale.",docs:[],echanges:[]},
    ],
    capsule:[
      {id:uid(),texte:"Aujourd'hui Emma a dit son premier mot : 'papa'. Jean était aux larmes. C'était un mardi matin, elle avait exactement 11 mois.",date:"2017-02-12"},
    ]
  });

  const [amis,setAmis]=useState([
    {id:uid(),prenom:"Sophie",nom:"Martin",categorie:"amis",email:"sophie.martin@gmail.com",tel:"06 12 34 56 78",rue:"24 rue Sainte-Catherine",codePostal:"33000",ville:"Bordeaux",dateNaissance:"1988-03-15",description:"Amie de lycée. Passionnée de randonnée et de cuisine italienne.",interets:["Randonnée","Cuisine","Voyages"],reseaux:[{id:"instagram",username:"sophie.rando",note:"Compte perso"},{id:"facebook",username:"sophie.martin.33",note:""},{id:"whatsapp",username:"33612345678",note:""},...RESEAUX_SOCIAUX.filter(r=>!["instagram","facebook","whatsapp"].includes(r.id)).map(r=>({id:r.id,username:"",note:""}))],notes:"Rencontrées au lycée Montaigne en 2004. Elle est venue à mon mariage, je suis marraine de son fils Hugo."},
    {id:uid(),prenom:"Thomas",nom:"Leclerc",categorie:"collegues",email:"t.leclerc@entreprise.fr",tel:"06 98 76 54 32",rue:"5 impasse des Acacias",codePostal:"33210",ville:"Langon",dateNaissance:"1985-11-28",description:"Collègue depuis 5 ans. Très bon professionnel, on déjeune souvent ensemble.",interets:["Football","Photographie"],reseaux:[{id:"linkedin",username:"thomas-leclerc-b33",note:"Profil pro"},{id:"twitter",username:"ThomasLeclerc",note:""},...RESEAUX_SOCIAUX.filter(r=>!["linkedin","twitter"].includes(r.id)).map(r=>({id:r.id,username:"",note:""}))],notes:""},
    {id:uid(),prenom:"Isabelle",nom:"Dupont",categorie:"proches",email:"isabelle.dupont@free.fr",tel:"05 56 78 90 12",rue:"18 allée des Chartrons",codePostal:"33000",ville:"Bordeaux",dateNaissance:"1960-06-10",description:"Sœur aînée. On se voit tous les dimanches.",interets:["Jardinage","Lecture","Pétanque"],reseaux:RESEAUX_SOCIAUX.map(r=>({id:r.id,username:"",note:""})),notes:""},
  ]);

  const [abonnements,setAbonnements]=useState([
    {id:uid(),nom:"Netflix",categorie:"streaming",montant:"17.99",periodicite:"mensuel",dateRenouvellement:"",note:"Formule Premium 4K",actif:true},
    {id:uid(),nom:"Spotify",categorie:"musique",montant:"10.99",periodicite:"mensuel",dateRenouvellement:"",note:"Famille",actif:true},
    {id:uid(),nom:"Orange Fibre",categorie:"internet",montant:"34.99",periodicite:"mensuel",dateRenouvellement:"2025-11-15",note:"Livebox 5 Pro",actif:true},
    {id:uid(),nom:"Microsoft 365",categorie:"logiciel",montant:"99",periodicite:"annuel",dateRenouvellement:"2025-09-01",note:"Famille — 6 utilisateurs",actif:true},
    {id:uid(),nom:"Amazon Prime",categorie:"streaming",montant:"69.90",periodicite:"annuel",dateRenouvellement:"2025-12-03",note:"",actif:true},
  ]);

  const [garanties,setGaranties]=useState([
    {id:uid(),nom:"Lave-linge Bosch",categorie:"electromenager",marque:"Bosch",modele:"Serie 6 WAU28PH9FF",numeroSerie:"BSH2024LV01",dateAchat:"2022-03-15",finGarantie:"2027-03-15",magasin:"Darty Langon",prix:"699",note:"Garantie étendue 5 ans souscrite"},
    {id:uid(),nom:"iPhone 15 Pro",categorie:"telephone",marque:"Apple",modele:"iPhone 15 Pro 256Go",numeroSerie:"",dateAchat:"2023-10-02",finGarantie:"2024-10-02",magasin:"Apple Store Bordeaux",prix:"1299",note:"AppleCare non souscrit"},
    {id:uid(),nom:"Télévision LG OLED",categorie:"hifi",marque:"LG",modele:"OLED55C3",numeroSerie:"",dateAchat:"2023-06-10",finGarantie:"2025-06-10",magasin:"Fnac Bordeaux",prix:"1490",note:""},
  ]);

  const [energie,setEnergie]=useState({
    fournisseurs:{
      electricite:{nom:"EDF",contrat:"0123456789",numeroCompteur:"15432876543210",puissance:"9",offre:"Tarif bleu — Option Base",echeanceMensuelle:"95",contact:"0969367324"},
      gaz:{nom:"Engie",contrat:"987654321",numeroCompteur:"62345678901234",offre:"Gaz Vert",echeanceMensuelle:"68",contact:"0800119026"},
      eau:{nom:"Veolia",contrat:"VEO2024-001",numeroCompteur:"A1234567",offre:"Tarif résidentiel",echeanceMensuelle:"35"},
    },
    releves:[
      {id:uid(),type:"electricite",index:52340,date:"2025-01-01",note:"Relevé début d'année"},
      {id:uid(),type:"electricite",index:50120,date:"2024-07-01",note:""},
      {id:uid(),type:"electricite",index:48200,date:"2024-01-01",note:""},
      {id:uid(),type:"gaz",index:8945,date:"2025-01-01",note:""},
      {id:uid(),type:"gaz",index:8210,date:"2024-07-01",note:""},
      {id:uid(),type:"eau",index:1245,date:"2025-01-01",note:""},
      {id:uid(),type:"eau",index:1090,date:"2024-01-01",note:""},
    ],
  });

  const [cadeaux,setCadeaux]=useState({
    personnes:[
      {id:uid(),prenom:"Emma",relation:"Ma fille",dateAnniversaire:"2016-03-12",budget:"150",note:""},
      {id:uid(),prenom:"Isabelle",relation:"Ma sœur",dateAnniversaire:"1960-06-10",budget:"80",note:""},
    ],
    idees:[
      {id:uid(),personneId:"",idee:"",occasion:"Noël",budget:"",statut:"idée",note:"",lien:""},
    ].filter(i=>i.idee),
  });

  const [coffreFortData,setCoffreFortData]=useState([
    {id:uid(),site:"Impôts — impots.gouv.fr",url:"https://www.impots.gouv.fr",login:"jean.dupont@email.fr",motdepasse:"",categorie:"administration",note:"Numéro fiscal : 1234567890123"},
    {id:uid(),site:"Ameli — assurance maladie",url:"https://www.ameli.fr",login:"jean.dupont@email.fr",motdepasse:"",categorie:"administration",note:"N° sécu : 1 75 06 33 210 000 00"},
  ]);

  const [bibliotheque,setBibliotheque]=useState({livres:[
    {id:uid(),titre:"L'Alchimiste",auteur:"Paulo Coelho",categorie:"roman",statut:"lu",dateDebut:"2023-01-05",dateFin:"2023-01-12",note_sur_5:"4",note_lecture:"Un conte philosophique inspirant sur la quête de sa légende personnelle."},
    {id:uid(),titre:"Sapiens",auteur:"Yuval Noah Harari",categorie:"essai",statut:"lu",dateDebut:"2024-03-01",dateFin:"2024-04-10",note_sur_5:"5",note_lecture:"Magistral. Une perspective radicalement nouvelle sur l'histoire de l'humanité."},
    {id:uid(),titre:"Le Comte de Monte-Cristo",auteur:"Alexandre Dumas",categorie:"roman",statut:"a-lire",note_sur_5:"",note_lecture:""},
  ]});

  const [dons,setDons]=useState([
    {id:uid(),association:"Croix-Rouge française",montant:"50",date:"2025-01-15",recuFiscal:true,note:"Don mensuel"},
    {id:uid(),association:"Médecins Sans Frontières",montant:"100",date:"2024-12-20",recuFiscal:true,note:"Don de fin d'année"},
  ]);

  const [projets,setProjets]=useState([
    {id:uid(),nom:"Rénovation salle de bain",type:"Rénovation",bien:"Maison principale",budget:"8000",dateDebut:"2025-04-01",dateFin:"2025-05-15",statut:"Planifié",note:"Remplacer baignoire par douche à l'italienne, refaire carrelage",artisans:[{id:uid(),nom:"Plomberie Martin",metier:"Plombier",tel:"06 11 22 33 44",email:"martin.plomberie@email.fr",siret:"",note:"Devis en attente"}],devis:[{id:uid(),artisan:"Plomberie Martin",description:"Pose douche + sanitaires",montant:"3800",date:"2025-02-10",statut:"En attente"}],taches:[{id:uid(),texte:"Obtenir 3 devis",artisan:"",fait:true},{id:uid(),texte:"Commander carrelage",artisan:"",fait:false},{id:uid(),texte:"Vidage pièce",artisan:"",fait:false}]},
  ]);

  const [medicaments,setMedicaments]=useState({
    traitements:[
      {id:uid(),nom:"Doliprane 1000mg",posologie:"1 comprimé si douleur (max 3/jour)",medecin:"Dr. Martin",dateDebut:"2024-01-01",dateFin:"",statut:"actif",note:"Antidouleur à prendre si besoin"},
    ],
    ordonnances:[],
    stock:[
      {id:uid(),nom:"Doliprane 1000mg",categorie:"Antidouleur",dateExp:"2026-06-30",note:"Boîte entamée"},
      {id:uid(),nom:"Strips désinfectants",categorie:"Pansements",dateExp:"2027-01-01",note:""},
    ],
  });

  const [retraite,setRetraite]=useState({
    dateNaissance:"1975-06-15",
    regime:"Régime général (CNAV)",
    trimestresAcquis:"95",
    trimestresCible:"172",
    ageSouhaite:"64",
    trimestresDetail:{salariePrivé:"95",salariePublic:"",nonSalarie:"",assimiles:"",rachetes:""},
    carriere:[],
    epargneRetraite:{},
  });

  const [sejours,setSejours]=useState([
    {id:uid(),nom:"Vacances Toscane 2025",destination:"Florence",pays:"Italie",dateDebut:"2025-07-12",dateFin:"2025-07-26",budget:"3500",nbPersonnes:"2",type:"Vacances",statut:"En préparation",note:"Louer une voiture depuis Florence. Visiter Sienne, San Gimignano, Val d'Orcia.",
      etapes:[
        {id:uid(),lieu:"Florence",adresse:"Piazza del Duomo, Florence",date:"2025-07-12",duree:"3",activitesDuJour:"Duomo, Galerie des Offices, Ponte Vecchio",note:"Hôtel proche du centre"},
        {id:uid(),lieu:"Sienne",adresse:"Piazza del Campo, Sienne",date:"2025-07-15",duree:"2",activitesDuJour:"Piazza del Campo, Cathédrale, musées",note:""},
        {id:uid(),lieu:"Val d'Orcia",adresse:"Pienza, Toscane",date:"2025-07-17",duree:"4",activitesDuJour:"Pienza, Montalcino, dégustation vins Brunello",note:"Agriturismo"},
      ],
      hebergements:[{id:uid(),nom:"Hôtel Davanzati",type:"Hôtel",adresse:"Via Porta Rossa, Florence",dateArrivee:"2025-07-12",dateDepart:"2025-07-15",prix:"420",confirmation:"DAV-20250712"}],
      transports:[{id:uid(),type:"Avion",compagnie:"Air France",depart:"Paris CDG",arrivee:"Florence FLR",date:"2025-07-12",heure:"07:30",numero:"AF1892",prix:"320"}],
      activites:[{id:uid(),nom:"Galerie des Offices",type:"Visite",lieu:"Piazzale degli Uffizi, Florence",date:"2025-07-13",heure:"09:00",prix:"25",reservation:"OFF-12345",note:"Réserver en avance !"}],
      checklist:[{id:uid(),texte:"Réserver les billets d'avion",fait:true},{id:uid(),texte:"Réserver hébergements",fait:true},{id:uid(),texte:"Prévenir la banque",fait:false},{id:uid(),texte:"Assurance voyage",fait:false},{id:uid(),texte:"Télécharger cartes offline",fait:false}],
      docs:[],
    },
  ]);

  const [evenementsData,setEvenementsData]=useState([
    {id:uid(),nom:"Anniversaire 50 ans Marie",type:"anniversaire",date:"2025-09-20",lieu:"Restaurant Le Pressoir",adresse:"12 rue du Château, 33210 Langon",budget:"1200",nbInvites:"30",statut:"En préparation",note:"Thème Années 80. Prévoir DJ, buffet froid, décoration rétro.",
      invites:[
        {id:uid(),prenom:"Jean",nom:"Dupont",statut:"Confirmé",table:"1",regime:"",tel:"06 12 34 56 78"},
        {id:uid(),prenom:"Sophie",nom:"Martin",statut:"Confirmé",table:"1",regime:"Végétarien",tel:"06 98 76 54 32"},
        {id:uid(),prenom:"Thomas",nom:"Leclerc",statut:"En attente",table:"",regime:"",tel:"06 11 22 33 44"},
      ],
      prestataires:[
        {id:uid(),nom:"DJ SoundBox",type:"DJ / Musicien",tel:"06 55 44 33 22",email:"djsoundbox@email.fr",montant:"450",statut:"Devis reçu",note:"3h de prestation"},
        {id:uid(),nom:"Traiteur Leblanc",type:"Traiteur",tel:"05 56 78 90 12",email:"",montant:"600",statut:"Signé",note:"Buffet froid 30 personnes"},
      ],
      planning:[
        {id:uid(),heure:"19:00",titre:"Arrivée des invités / Apéritif",lieu:"Bar du restaurant",duree:"60",note:""},
        {id:uid(),heure:"20:00",titre:"Dîner / Buffet",lieu:"Salle principale",duree:"90",note:""},
        {id:uid(),heure:"21:30",titre:"Discours & Gâteau",lieu:"Salle principale",duree:"30",note:""},
        {id:uid(),heure:"22:00",titre:"Soirée dansante",lieu:"Piste de danse",duree:"180",note:"DJ SoundBox"},
      ],
      taches:[
        {id:uid(),texte:"Envoyer les invitations",fait:true,echeance:"2025-08-01"},
        {id:uid(),texte:"Finaliser le menu avec le traiteur",fait:true,echeance:"2025-08-15"},
        {id:uid(),texte:"Commander le gâteau",fait:false,echeance:"2025-09-10"},
        {id:uid(),texte:"Préparer le discours",fait:false,echeance:"2025-09-18"},
        {id:uid(),texte:"Récupérer les réponses invités",fait:false,echeance:"2025-09-01"},
      ],
      docs:[],
    },
  ]);

  const [walletData,setWalletData]=useState({cartes:[
    {id:uid(),nom:"Jean Dupont",enseigne:"Carrefour",numero:"1234567890123",categorie:"supermarche",gradient:0,pointsActuels:"1240",pointsMax:"2000",avantages:"1% en cagnotte dès 10 000 points",note:""},
    {id:uid(),nom:"Jean Dupont",enseigne:"Fnac",numero:"9876543210123",categorie:"culture",gradient:1,pointsActuels:"350",pointsMax:"500",avantages:"Fnac+ : livraison gratuite, avant-premières",note:"Adhésion annuelle 49€"},
    {id:uid(),nom:"Jean Dupont",enseigne:"Décathlon",numero:"4567891234567",categorie:"sport",gradient:3,pointsActuels:"",pointsMax:"",avantages:"2% de remise sous forme de bons",note:""},
    {id:uid(),nom:"Jean Dupont",enseigne:"Pharmacie du Centre",numero:"3210987654321",categorie:"pharmacie",gradient:5,pointsActuels:"80",pointsMax:"200",avantages:"1 point = 1€ de remise",note:""},
  ]});

  const urgentCount=alertes.filter(a=>!a.fait&&daysFrom(a.date)<=7).length;
  const unreadMsg=locataires.reduce((s,l)=>s+(l.messages||[]).filter(m=>!m.lu&&m.de==="locataire").length,0);

  // ── Collecte tout l'état pour la sauvegarde
  const getFullState=useCallback(()=>({
    docs,maisons,vehicules,sports,photos,locataires,biens,
    sante,impots,banque,assurances,juridique,contacts,alertes,
    enfants,animaux,voyages,identite,vieFamille,modeles,amis,travail,
    abonnements,garanties,energie,cadeaux,coffreFortData,bibliotheque,dons,projets,medicaments,retraite,
    sejours,evenementsData,walletData
  }),[docs,maisons,vehicules,sports,photos,locataires,biens,sante,impots,banque,assurances,juridique,contacts,alertes,enfants,animaux,voyages,identite,vieFamille,modeles,amis,travail,abonnements,garanties,energie,cadeaux,coffreFortData,bibliotheque,dons,projets,medicaments,retraite,sejours,evenementsData,walletData]);

  // ── Auto-sauvegarde localStorage à chaque modification
  useEffect(()=>{
    try{
      const stateLight=JSON.parse(JSON.stringify(getFullState(),(k,v)=>k==="url"&&typeof v==="string"&&v.startsWith("blob:")?null:v));
      localStorage.setItem(LS_KEY,JSON.stringify({...stateLight,_version:5,_date:new Date().toISOString()}));
      localStorage.setItem(LS_KEY+"_date",new Date().toISOString());
      setLastAutoSave(new Date().toISOString());
    }catch{}
  },[getFullState]);

  // ── Restauration depuis une sauvegarde JSON
  const handleRestore=(parsed)=>{
    try{
      if(parsed.docs!==undefined)setDocs(parsed.docs||[]);
      if(parsed.maisons!==undefined)setMaisons(parsed.maisons||[]);
      if(parsed.vehicules!==undefined)setVehicules(parsed.vehicules||[]);
      if(parsed.sports!==undefined)setSports(parsed.sports||[]);
      if(parsed.locataires!==undefined)setLocataires(parsed.locataires||[]);
      if(parsed.biens!==undefined)setBiens(parsed.biens||[]);
      if(parsed.sante!==undefined)setSante(parsed.sante);
      if(parsed.impots!==undefined)setImpots(parsed.impots);
      if(parsed.banque!==undefined)setBanque(parsed.banque);
      if(parsed.assurances!==undefined)setAssurances(parsed.assurances||[]);
      if(parsed.juridique!==undefined)setJuridique(parsed.juridique);
      if(parsed.contacts!==undefined)setContacts(parsed.contacts||[]);
      if(parsed.alertes!==undefined)setAlertes(parsed.alertes||[]);
      if(parsed.enfants!==undefined)setEnfants(parsed.enfants||[]);
      if(parsed.animaux!==undefined)setAnimaux(parsed.animaux||[]);
      if(parsed.voyages!==undefined)setVoyages(parsed.voyages||[]);
      if(parsed.identite!==undefined)setIdentite(parsed.identite);
      if(parsed.vieFamille!==undefined)setVieFamille(parsed.vieFamille);
      if(parsed.modeles!==undefined)setModeles(parsed.modeles);
      if(parsed.amis!==undefined)setAmis(parsed.amis);
      if(parsed.travail!==undefined)setTravail(parsed.travail);
      if(parsed.abonnements!==undefined)setAbonnements(parsed.abonnements);
      if(parsed.garanties!==undefined)setGaranties(parsed.garanties);
      if(parsed.energie!==undefined)setEnergie(parsed.energie);
      if(parsed.cadeaux!==undefined)setCadeaux(parsed.cadeaux);
      if(parsed.coffreFortData!==undefined)setCoffreFortData(parsed.coffreFortData);
      if(parsed.bibliotheque!==undefined)setBibliotheque(parsed.bibliotheque);
      if(parsed.dons!==undefined)setDons(parsed.dons);
      if(parsed.projets!==undefined)setProjets(parsed.projets);
      if(parsed.medicaments!==undefined)setMedicaments(parsed.medicaments);
      if(parsed.retraite!==undefined)setRetraite(parsed.retraite);
      if(parsed.sejours!==undefined)setSejours(parsed.sejours);
      if(parsed.evenementsData!==undefined)setEvenementsData(parsed.evenementsData);
      if(parsed.walletData!==undefined)setWalletData(parsed.walletData);
    }catch(e){console.error("Restore error",e);}
  };

  const MODULES={
    dashboard:<Dashboard docs={docs} locataires={locataires} biens={biens} alertes={alertes} contacts={contacts} sante={sante} impots={impots} assurances={assurances}/>,
    patrimoine:<Patrimoine maisons={maisons} vehicules={vehicules} banque={banque} assurances={assurances} travail={travail}/>,
    docs:<Archivage docs={docs} setDocs={setDocs}/>,
    maisons:<Maisons maisons={maisons} setMaisons={setMaisons} assurances={assurances} impots={impots} setPage={setPage}/>,
    vehicules:<Vehicules vehicules={vehicules} setVehicules={setVehicules} assurances={assurances} setPage={setPage}/>,
    locataires:<GestionLocative locataires={locataires} setLocataires={setLocataires} biens={biens} setBiens={setBiens}/>,
    sante:<Sante sante={sante} setSante={setSante}/>,
    impots:<Impots impots={impots} setImpots={setImpots}/>,
    banque:<Banque banque={banque} setBanque={setBanque}/>,
    assurances:<Assurances assurances={assurances} setAssurances={setAssurances}/>,
    juridique:<Juridique juridique={juridique} setJuridique={setJuridique}/>,
    sports:<Sports sports={sports} setSports={setSports}/>,
    photos:<Photos photos={photos} setPhotos={setPhotos}/>,
    voyages:<Voyages voyages={voyages} setVoyages={setVoyages}/>,
    identite:<Identite identite={identite} setIdentite={setIdentite}/>,
    viefamille:<VieFamille vieFamille={vieFamille} setVieFamille={setVieFamille}/>,
    amis:<Amis amis={amis} setAmis={setAmis}/>,
    cadeaux:<BudgetCadeaux cadeaux={cadeaux} setCadeaux={setCadeaux}/>,
    enfants:<Enfants enfants={enfants} setEnfants={setEnfants}/>,
    animaux:<Animaux animaux={animaux} setAnimaux={setAnimaux}/>,
    contacts:<Contacts contacts={contacts} setContacts={setContacts}/>,
    alertes:<Alertes alertes={alertes} setAlertes={setAlertes}/>,
    courrier:<ModelesCourrierModule modeles={modeles} setModeles={setModeles}/>,
    travail:<Travail travail={travail} setTravail={setTravail}/>,
    retraite:<Retraite retraite={retraite} setRetraite={setRetraite} travail={travail}/>,
    abonnements:<Abonnements abonnements={abonnements} setAbonnements={setAbonnements}/>,
    garanties:<Garanties garanties={garanties} setGaranties={setGaranties}/>,
    energie:<Energie energie={energie} setEnergie={setEnergie}/>,
    coffrefort:<CoffreFort motsdepasse={coffreFortData} setMotsdepasse={setCoffreFortData}/>,
    bibliotheque:<Bibliotheque bibliotheque={bibliotheque} setBibliotheque={setBibliotheque}/>,
    dons:<Dons dons={dons} setDons={setDons}/>,
    projets:<ProjetsModule projets={projets} setProjets={setProjets}/>,
    medicaments:<Medicaments medicaments={medicaments} setMedicaments={setMedicaments}/>,
    guide:<Guide/>,
    recherche:<RechercheGlobale allData={getFullState()} setPage={setPage}/>,
    planificateur:<PlanificateurSejour sejours={sejours} setSejours={setSejours}/>,
    evenements:<OrganisateurEvenements evenements={evenementsData} setEvenements={setEvenementsData}/>,
    wallet:<Wallet wallet={walletData} setWallet={setWalletData}/>,
    parametres:<ParametresModules visibles={visibles} setVisibles={setVisibles}/>,
  };

  return (
    <div style={{display:"flex",height:"100vh",background:T.bg,fontFamily:T.font,color:T.text,overflow:"hidden"}}>
      <FontLink/>
      {/* Sidebar */}
      <div style={{width:collapsed?52:220,background:T.sidebar,borderRight:`1px solid ${T.border}`,display:"flex",flexDirection:"column",transition:"width 0.22s",flexShrink:0,overflow:"hidden"}}>
        <div style={{padding:"14px 12px",borderBottom:`1px solid ${T.border}`,display:"flex",alignItems:"center",gap:8,minHeight:54,flexShrink:0}}>
          <div style={{width:30,height:30,borderRadius:8,background:T.accent,display:"flex",alignItems:"center",justifyContent:"center",fontSize:14,fontWeight:700,color:"#000",flexShrink:0}}>M</div>
          {!collapsed&&<div>
            <div style={{fontFamily:T.fontD,fontSize:13,fontWeight:700,color:T.text,whiteSpace:"nowrap"}}>NumaVie</div>
            <div style={{fontSize:9,color:T.muted,whiteSpace:"nowrap"}}>Espace personnel</div>
          </div>}
        </div>
        <nav style={{flex:1,padding:"6px 4px",display:"flex",flexDirection:"column",gap:0,overflowY:"auto"}}>
          {NAV_GROUPS.map(group=>{
            const visibleItems=group.items.filter(n=>visibles.includes(n.id));
            if(visibleItems.length===0)return null;
            return (
              <div key={group.label} style={{marginBottom:4}}>
                {!collapsed&&<div style={{fontSize:9,color:T.muted,textTransform:"uppercase",letterSpacing:"0.1em",padding:"8px 8px 3px",fontWeight:600}}>{group.label}</div>}
                {visibleItems.map(n=>{
                  const active=page===n.id;
                  const badge=(n.id==="alertes"&&urgentCount>0)?urgentCount:(n.id==="locataires"&&unreadMsg>0)?unreadMsg:null;
                  return (
                    <button key={n.id} onClick={()=>setPage(n.id)} title={collapsed?n.label:""} style={{display:"flex",alignItems:"center",gap:8,padding:"7px 8px",borderRadius:7,border:"none",cursor:"pointer",fontFamily:T.font,fontSize:12,background:active?T.accentDim:"transparent",color:active?T.accent:T.muted,fontWeight:active?600:400,transition:"all 0.12s",textAlign:"left",width:"100%"}}>
                      <span style={{fontSize:14,flexShrink:0}}>{n.icon}</span>
                      {!collapsed&&<span style={{whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",flex:1}}>{n.label}</span>}
                      {badge&&!collapsed&&<span style={{background:T.danger,color:"#fff",borderRadius:8,fontSize:9,fontWeight:700,padding:"1px 5px",flexShrink:0}}>{badge}</span>}
                    </button>
                  );
                })}
              </div>
            );
          })}
        </nav>
        <div style={{padding:6,borderTop:`1px solid ${T.border}`,flexShrink:0}}>
          {/* Bouton sauvegarde */}
          <button onClick={()=>setShowBackup(true)} title="Sauvegarde & Sécurité"
            style={{width:"100%",background:"rgba(240,165,0,0.08)",border:"1px solid rgba(240,165,0,0.2)",color:T.accent,cursor:"pointer",padding:"6px 8px",borderRadius:8,fontSize:collapsed?16:12,display:"flex",alignItems:"center",justifyContent:collapsed?"center":"flex-start",gap:6,fontFamily:T.font,marginBottom:4}}>
            <span>🔒</span>{!collapsed&&<span style={{whiteSpace:"nowrap"}}>Sauvegarde</span>}
            {!collapsed&&lastAutoSave&&<span style={{fontSize:9,color:T.success,marginLeft:"auto"}}>●</span>}
          </button>
          <button onClick={()=>setPage("parametres")} title="Personnalisation modules"
            style={{width:"100%",background:page==="parametres"?T.accentDim:"none",border:`1px solid ${page==="parametres"?T.accent:"transparent"}`,color:page==="parametres"?T.accent:T.muted,cursor:"pointer",padding:"6px 8px",borderRadius:8,fontSize:collapsed?16:12,display:"flex",alignItems:"center",justifyContent:collapsed?"center":"flex-start",gap:6,fontFamily:T.font,marginBottom:4}}>
            <span>⚙️</span>{!collapsed&&<span style={{whiteSpace:"nowrap"}}>Personnaliser</span>}
          </button>
          <button onClick={()=>setCollapsed(c=>!c)} style={{width:"100%",background:"none",border:"none",color:T.muted,cursor:"pointer",padding:8,borderRadius:8,fontSize:13,display:"flex",alignItems:"center",justifyContent:"center"}}>
            {collapsed?"▶":"◀"}
          </button>
        </div>
      </div>
      {/* Contenu */}
      <div style={{flex:1,overflow:"auto",padding:22}}>
        {MODULES[page]||<EmptyState icon="🚧" text="Module en construction"/>}
      </div>
      {/* Panel sauvegarde */}
      {showBackup&&<BackupPanel state={getFullState()} onRestore={r=>{handleRestore(r);setShowBackup(false);}} onClose={()=>setShowBackup(false)}/>}
    </div>
  );
}
