// shell.jsx — App shell, navigation, routing, role switch, root
const { useState: useS, useEffect: useE, useRef: useSR } = React;

const NAV = [
  { key:'dashboard',   label:'Dashboard',    icon:'dashboard' },
  { key:'new-lead',    label:'Nouveau lead',  icon:'plus', accent:true },
  { key:'leads',       label:'Mes leads',     icon:'list' },
  { key:'commissions', label:'Commissions',   icon:'euro' },
  { key:'resources',   label:'Ressources',    icon:'download' },
  { key:'settings',    label:'Paramètres',    icon:'settings' },
];

const PAGE_HEAD = {
  dashboard:   { title:`Bonjour ${window.LBC_DATA.PARTNER.firstName}`, sub:'Voici l\'activité de votre réseau ce mois-ci.', wave:true },
  leads:       { title:'Mes leads', sub:'Suivez la progression de chaque client recommandé.' },
  commissions: { title:'Mes commissions', sub:'Vos gains, versés et à venir.' },
  tiers:       { title:'Niveaux partenaires', sub:'Plus vous recommandez, plus votre taux augmente.' },
  resources:   { title:'Ressources partenaires' },
  settings:    { title:'Paramètres', sub:'Gérez votre profil et vos préférences.' },
};
const SKEL_SCREENS = ['dashboard','leads','commissions','lead-detail'];
if (!window.LBC_LINK) window.LBC_LINK = { status:'devis', payment:null };
function linkAccept(l, method){
  return { ...l, status:'accepte', commissionStatus:'attente',
    timeline: window.LBC_DATA.buildTimeline('accepte', l.dates),
    estValue: l.value, commission: Math.round(l.value * l.rate / 100),
    payment: method, deposit: Math.round(l.value*0.3) };
}
function linkEffectue(l){
  return { ...l, status:'effectue', commissionStatus:'valide', timeline: window.LBC_DATA.buildTimeline('effectue', l.dates) };
}

function darken(hex, amt) {
  try { const n = parseInt(hex.slice(1),16); let r=(n>>16)-amt, g=((n>>8)&255)-amt, b=(n&255)-amt;
    r=Math.max(0,Math.min(255,r)); g=Math.max(0,Math.min(255,g)); b=Math.max(0,Math.min(255,b));
    return '#'+((1<<24)+(r<<16)+(g<<8)+b).toString(16).slice(1); } catch(e){ return hex; }
}

/* ---- Sidebar (desktop, partner) ---- */
function Sidebar({ screen, go, partner }) {
  return (
    <aside style={{ width:248, flexShrink:0, background:'var(--navy)', color:'var(--cream)', display:'flex', flexDirection:'column', height:'100%' }}>
      <div style={{ padding:'22px 22px 18px', borderBottom:'1px solid rgba(255,255,255,.07)' }}><Logo size={22} /></div>
      <nav style={{ flex:1, padding:'14px 12px', display:'flex', flexDirection:'column', gap:3 }}>
        {NAV.map(n=>{
          const active = screen===n.key || (n.key==='leads' && screen==='lead-detail') || (n.key==='commissions' && screen==='tiers');
          return (
            <button key={n.key} onClick={()=>go(n.key)} style={{ position:'relative', display:'flex', alignItems:'center', gap:12,
              padding:'10px 14px', borderRadius:9, fontSize:14, fontWeight:500, textAlign:'left', width:'100%',
              color: active?'var(--cream)':'rgba(245,239,227,.62)', background: active?'rgba(255,255,255,.08)':'transparent', transition:'.14s' }}
              onMouseEnter={e=>{ if(!active) e.currentTarget.style.background='rgba(255,255,255,.04)'; }}
              onMouseLeave={e=>{ if(!active) e.currentTarget.style.background='transparent'; }}>
              {active && <span style={{ position:'absolute', left:0, top:8, bottom:8, width:3, borderRadius:3, background:'var(--brand-bright)' }} />}
              <span style={{ display:'flex', color: n.accent && !active ? 'var(--brand-bright)' : 'inherit' }}><Icon name={n.icon} size={19} /></span>
              {n.label}
              {n.accent && <span style={{ marginLeft:'auto', width:7, height:7, borderRadius:'50%', background:'var(--brand-bright)' }} />}
            </button>
          );
        })}
      </nav>
      <div style={{ padding:'14px 16px', borderTop:'1px solid rgba(255,255,255,.07)', display:'flex', alignItems:'center', gap:11 }}>
        <Avatar initials={partner.initials} size={38} />
        <div style={{ minWidth:0, flex:1 }}>
          <div style={{ fontSize:13.5, fontWeight:600, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{partner.firstName} {partner.lastName}</div>
          <div style={{ marginTop:3 }}><TierChip tier={partner.tier} size="sm" /></div>
        </div>
      </div>
    </aside>
  );
}

/* ---- Topbar (desktop, partner) ---- */
function Topbar({ partner, onBell, unread, onSearch }) {
  return (
    <header style={{ height:64, flexShrink:0, background:'rgba(255,255,255,.86)', backdropFilter:'blur(8px)', borderBottom:'1px solid var(--border)',
      display:'flex', alignItems:'center', justifyContent:'space-between', padding:'0 28px', position:'sticky', top:0, zIndex:20 }}>
      <div>
        <div style={{ fontSize:15, fontWeight:600, color:'var(--ink)' }}>{partner.company}</div>
        <div style={{ fontSize:12, color:'var(--muted)' }}>Espace partenaire</div>
      </div>
      <div style={{ display:'flex', alignItems:'center', gap:14 }}>
        <button onClick={onSearch} style={{ display:'flex', alignItems:'center', gap:10, height:38, padding:'0 12px', borderRadius:10, border:'1px solid var(--border-2)', background:'var(--bg)', color:'var(--muted)', fontSize:13 }}>
          <Icon name="search" size={16} />Rechercher<span className="kbd" style={{ marginLeft:6 }}>⌘K</span></button>
        <button onClick={onBell} style={{ position:'relative', color:'var(--ink-2)', display:'flex', padding:8, borderRadius:9 }}
          onMouseEnter={e=>e.currentTarget.style.background='var(--hover)'} onMouseLeave={e=>e.currentTarget.style.background='transparent'}>
          <Icon name="bell" size={20} />
          {unread>0 && <span style={{ position:'absolute', top:4, right:5, minWidth:15, height:15, padding:'0 3px', borderRadius:999, background:'var(--brand-bright)', border:'2px solid #fff', color:'#fff', fontSize:9.5, fontWeight:700, display:'flex', alignItems:'center', justifyContent:'center' }}>{unread}</span>}
        </button>
        <TierChip tier={partner.tier} />
        <Avatar initials={partner.initials} size={34} />
      </div>
    </header>
  );
}

function PageHeader({ head, mobile }) {
  if (!head) return null;
  return (
    <div style={{ marginBottom: mobile?16:22 }}>
      <h1 className="page-title" style={{ fontSize: mobile?21:24 }}>{head.title}{head.wave?' 👋':''}</h1>
      {head.sub && <p style={{ fontSize:14, color:'var(--muted)', margin:'7px 0 0', lineHeight:1.5 }}>{head.sub}</p>}
    </div>
  );
}

function Screen({ screen, ctx }) {
  switch(screen) {
    case 'dashboard':   return <Dashboard {...ctx} />;
    case 'new-lead':    return <NewLead {...ctx} />;
    case 'leads':       return <LeadsList {...ctx} />;
    case 'lead-detail': return <LeadDetail {...ctx} />;
    case 'commissions': return <CommissionsPage {...ctx} />;
    case 'tiers':       return <TiersPage {...ctx} />;
    case 'resources':   return <ResourcesPage {...ctx} />;
    case 'settings':    return <SettingsPage {...ctx} />;
    default:            return <Dashboard {...ctx} />;
  }
}

function Fab({ go }) {
  return (
    <button onClick={()=>go('new-lead')} style={{ position:'absolute', bottom:28, right:28, zIndex:30, display:'inline-flex', alignItems:'center', gap:9,
      background:'var(--brand)', color:'#fff', fontSize:14.5, fontWeight:600, padding:'14px 20px', borderRadius:14, boxShadow:'var(--shadow-fab)', transition:'.18s' }}
      onMouseEnter={e=>{ e.currentTarget.style.background='var(--brand-hover)'; e.currentTarget.style.transform='translateY(-2px)'; }}
      onMouseLeave={e=>{ e.currentTarget.style.background='var(--brand)'; e.currentTarget.style.transform='none'; }}>
      <Icon name="plus" size={19} stroke={2.4} />Envoyer un lead</button>
  );
}

/* ---- Desktop app (partner) ---- */
function DesktopApp({ screen, go, ctx, partner, loading, notif }) {
  const head = PAGE_HEAD[screen];
  const showFab = ['dashboard','leads','commissions'].includes(screen);
  const skel = loading && SKEL_SCREENS.includes(screen);
  return (
    <div style={{ display:'flex', height:'100%' }}>
      <Sidebar screen={screen} go={go} partner={partner} />
      <div style={{ flex:1, minWidth:0, display:'flex', flexDirection:'column', position:'relative' }}>
        <Topbar partner={partner} onBell={notif.toggle} unread={notif.unread} onSearch={ctx.openCmdk} />
        {notif.open && <NotificationsPanel notifs={notif.list} onClose={notif.close} onReadAll={notif.readAll} />}
        <main className="scroll" style={{ flex:1, overflowY:'auto', padding:'28px 36px 60px' }}>
          <div style={{ maxWidth:1180, margin:'0 auto' }} key={screen}>
            <div className="fade-in">
              <PageHeader head={head} />
              {skel ? <PageSkeleton screen={screen} mobile={false} /> : <Screen screen={screen} ctx={ctx} />}
            </div>
          </div>
        </main>
        {showFab && <Fab go={go} />}
      </div>
    </div>
  );
}

/* ---- Mobile ---- */
const MNAV = [
  { key:'dashboard', label:'Accueil', icon:'dashboard' },
  { key:'leads', label:'Leads', icon:'list' },
  { key:'new-lead', label:'Lead', icon:'plus', center:true },
  { key:'commissions', label:'Gains', icon:'euro' },
  { key:'settings', label:'Profil', icon:'user' },
];
function MobileNav({ screen, go }) {
  return (
    <div style={{ flexShrink:0, background:'rgba(255,255,255,.95)', backdropFilter:'blur(10px)', borderTop:'1px solid var(--border)',
      display:'flex', alignItems:'center', justifyContent:'space-around', padding:'8px 8px 26px' }}>
      {MNAV.map(n=>{
        const active = screen===n.key || (n.key==='leads'&&screen==='lead-detail') || (n.key==='commissions'&&screen==='tiers');
        if (n.center) return (
          <button key={n.key} onClick={()=>go(n.key)} style={{ display:'flex', flexDirection:'column', alignItems:'center', gap:3, marginTop:-18 }}>
            <span style={{ width:50, height:50, borderRadius:16, background:'var(--brand)', color:'#fff', display:'flex', alignItems:'center', justifyContent:'center', boxShadow:'var(--shadow-fab)' }}>
              <Icon name="plus" size={24} stroke={2.4} /></span></button>
        );
        return (
          <button key={n.key} onClick={()=>go(n.key)} style={{ display:'flex', flexDirection:'column', alignItems:'center', gap:4, padding:'4px 10px', color: active?'var(--brand)':'var(--faint)', minWidth:54 }}>
            <Icon name={n.icon} size={21} stroke={active?2.2:1.8} />
            <span style={{ fontSize:10.5, fontWeight: active?600:500 }}>{n.label}</span></button>
        );
      })}
    </div>
  );
}

function MobileApp({ screen, go, ctx, partner, loading, notif }) {
  const head = PAGE_HEAD[screen];
  const skel = loading && SKEL_SCREENS.includes(screen);
  return (
    <div style={{ height:'100%', display:'flex', flexDirection:'column', background:'var(--bg)', position:'relative' }}>
      <header style={{ flexShrink:0, background:'#fff', borderBottom:'1px solid var(--border)', paddingTop:50, paddingBottom:12, paddingLeft:18, paddingRight:18, display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <Logo size={19} showSub={false} color="var(--navy)" />
        <div style={{ display:'flex', alignItems:'center', gap:12 }}>
          <button onClick={ctx.openCmdk} style={{ color:'var(--ink-2)', display:'flex' }}><Icon name="search" size={20} /></button>
          <span style={{ display:'inline-flex', alignItems:'center', gap:5, fontSize:11.5, fontWeight:600, padding:'4px 10px', borderRadius:999, background:'var(--bg)', color:'var(--ink-2)', border:'1px solid var(--border)' }}>
            <span style={{ width:7, height:7, borderRadius:'50%', background:'#B0703A' }} />{partner.tier}</span>
          <button onClick={notif.toggle} style={{ position:'relative', color:'var(--ink-2)', display:'flex' }}><Icon name="bell" size={21} />
            {notif.unread>0 && <span style={{ position:'absolute', top:-3, right:-3, minWidth:14, height:14, padding:'0 3px', borderRadius:999, background:'var(--brand-bright)', border:'1.5px solid #fff', color:'#fff', fontSize:9, fontWeight:700, display:'flex', alignItems:'center', justifyContent:'center' }}>{notif.unread}</span>}</button>
        </div>
      </header>
      {notif.open && <NotificationsPanel notifs={notif.list} onClose={notif.close} onReadAll={notif.readAll} mobile />}
      <div className="scroll" style={{ flex:1, overflowY:'auto', padding:'20px 18px 28px' }} key={screen}>
        <div className="fade-in">
          {head ? <PageHeader head={head} mobile /> : null}
          {skel ? <PageSkeleton screen={screen} mobile /> : <Screen screen={screen} ctx={{ ...ctx, mobile:true }} />}
        </div>
      </div>
      <MobileNav screen={screen} go={go} />
    </div>
  );
}

/* ============== ROOT ============== */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "primary": "#B63D24",
  "font": "Geist",
  "density": "regular",
  "tierStyle": "gradient"
}/*EDITMODE-END*/;

function App() {
  const [tw, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const isNarrow = ()=> typeof window!=='undefined' && window.innerWidth < 820;
  const [realMobile, setRealMobile] = useS(isNarrow());
  const [mode, setMode] = useS(isNarrow()?'mobile':'desktop');
  useE(()=>{ const h=()=>{ const m=isNarrow(); setRealMobile(m); setMode(m?'mobile':'desktop'); }; window.addEventListener('resize',h); return ()=>window.removeEventListener('resize',h); }, []);
  // Sur un vrai téléphone : plein écran (pas la maquette iPhone). Sur desktop : maquette pour l'aperçu admin.
  const Frame = ({ dark, children })=> realMobile ? <div className="stage-desktop">{children}</div> : <IOSDevice dark={dark}>{children}</IOSDevice>;
  const [role, setRole] = useS('partner');
  const [auth, setAuth] = useS(false);
  const [screen, setScreen] = useS('login');
  const [adminScreen, setAdminScreen] = useS('i_accueil');
  const [clientScreen, setClientScreen] = useS('suivi');
  const [clientStatus, setClientStatus] = useS('devis');
  const [clientPayment, setClientPayment] = useS(null);
  const [clientSolde, setClientSolde] = useS(false);
  const [payOpen, setPayOpen] = useS(false);
  const [payMode, setPayMode] = useS('acompte');
  const [retrievals, setRetrievals] = useS([
  ]);
  const [boxItems, setBoxItems] = useS(()=> window.SEED_BOX.slice());
  const [staffAuth, setStaffAuth] = useS(false);
  const [sbProfile, setSbProfile] = useS(null);
  const [chat, setChat] = useS([{ from:'staff', text:`Bonjour ${window.CLIENT.firstName}, je suis Karim, votre conseiller LBC. Une question sur votre déménagement ?`, time:'09:12' }]);
  const [notes, setNotes] = useS([{ who:'TL', text:'Cliente recommandée par notre meilleure agence — à soigner.', time:'29 mai, 14h02' }]);
  const [authScreen, setAuthScreen] = useS('login');
  const [params, setParams] = useS({});
  const [toast, setToast] = useS({ show:false, msg:'' });
  // Leads = projection partenaire de la base unique partagée avec le cockpit admin (synchro temps réel)
  window.LBC_INT.useStore();
  const leads = window.LBC_INT.partnerLeads(window.LBC_DATA.PARTNER.company);
  const [loading, setLoading] = useS(false);
  const [notifList, setNotifList] = useS(()=> window.LBC_DATA.NOTIFS);
  const [notifOpen, setNotifOpen] = useS(false);
  const [cmdk, setCmdk] = useS(false);
  const [tour, setTour] = useS(false);
  const [seenTour, setSeenTour] = useS(false);
  const [doc, setDoc] = useS(null);
  const partner = window.LBC_DATA.PARTNER;

  // apply tweaks
  useE(()=>{
    const r = document.documentElement;
    r.style.setProperty('--brand', tw.primary);
    r.style.setProperty('--brand-bright', tw.primary);
    r.style.setProperty('--brand-hover', darken(tw.primary, 16));
    r.style.setProperty('--font', tw.font);
  }, [tw.primary, tw.font]);

  // ⌘K
  useE(()=>{
    const h = (e)=>{ if((e.metaKey||e.ctrlKey) && e.key.toLowerCase()==='k'){ e.preventDefault(); if(auth && role==='partner') setCmdk(v=>!v); }
      if(e.key==='Escape'){ setCmdk(false); setNotifOpen(false); } };
    window.addEventListener('keydown', h); return ()=>window.removeEventListener('keydown', h);
  }, [auth, role]);

  const go = (s, p={}) => {
    if (role==='admin') { setAdminScreen(s); setParams(p); return; }
    if (role==='client') { setClientScreen(s); return; }
    setScreen(s); setParams(p); setNotifOpen(false);
    if (SKEL_SCREENS.includes(s)) { setLoading(true); setTimeout(()=>setLoading(false), 460); }
  };
  const showToast = (msg) => { setToast({ show:true, msg }); setTimeout(()=>setToast(t=>({ ...t, show:false })), 2600); };
  const openDoc = (kind, lead) => setDoc({ kind, lead });

  const addLead = (f) => {
    // crée le déménagement (partenaire = société du compte connecté) ; la synchro Supabase le persiste,
    // le partenaire le revoit à la reconnexion et l'admin le voit aussi.
    window.LBC_INT.addPartnerLead(f);
    showToast('Lead envoyé — LBC contacte '+(f.first||'votre client')+' sous 24h');
  };

  const login = () => { setAuth(true); setScreen('dashboard'); if(!seenTour){ setTimeout(()=>setTour(true), 350); } };
  const logout = () => { setAuth(false); setAuthScreen('login'); setScreen('login'); setNotifOpen(false); };
  const switchRole = (r) => {
    if(r==='client' && window.LBC_SB && window.LBC_SB.fillClientFromMove){
      const moves=(window.LBC_INT.store.db.moves)||[];
      const mv = moves.find(m=>(m.inventaire||[]).length && Number(m.montant)>0) || moves.find(m=>m.statut==='devis_envoye') || moves.find(m=>(m.inventaire||[]).length) || moves[0];
      window.LBC_SB.fillClientFromMove(mv);
      const map={ devis_a_envoyer:'recu', devis_envoye:'devis', confirme:'accepte', attente_paiement:'accepte', termine:'effectue', refuse:'recu', annule:'recu' };
      setClientStatus(mv?(map[mv.statut]||'devis'):'recu'); setClientScreen('suivi'); setBoxItems([]);
    }
    setRole(r); setNotifOpen(false); setCmdk(false);
  };
  const applyProfile = (p) => { setSbProfile(p); const r = p.role==='admin'?'admin':(p.role==='client'?'client':'partner'); setRole(r); setAuth(true); setStaffAuth(true);
    if(r==='client'){ setClientScreen('suivi'); setBoxItems([]); const mv=(window.LBC_INT.store.db.moves||[])[0]; const map={ devis_a_envoyer:'recu', devis_envoye:'devis', devis_accepte:'accepte', confirme:'accepte', attente_paiement:'accepte', termine:'effectue', refuse:'recu', annule:'recu' }; setClientStatus(mv?(map[mv.statut]||'devis'):'recu'); }
  };
  const sbLogout = async () => { try{ if(window.LBC_SB) await window.LBC_SB.signOut(); }catch(e){} setSbProfile(null); setAuth(false); setStaffAuth(false); setRole('partner'); setScreen('login'); };
  // Reprise de session : lien magique client OU session déjà active -> connexion auto
  useE(()=>{ if(window.LBC_SB && window.LBC_SB.restore){ window.LBC_SB.restore().then(p=>{ if(p) applyProfile(p); }).catch(()=>{}); } }, []);
  const acceptDevis = () => { setPayMode('acompte'); setPayOpen(true); };
  const paySolde = () => { setPayMode('solde'); setPayOpen(true); };
  const completePayment = (method) => {
    if (payMode==='solde') {
      setClientSolde(true); setClientStatus('termine');
      window.LBC_LINK = { ...window.LBC_LINK, status:'effectue', soldePaid:true };
      window.LBC_INT.setMoveStatut('L-2420','termine');
      setNotifList(ns => [{ id:'eff'+Date.now(), icon:'check', tone:'verse', title:'Déménagement effectué', body:'Élise Moreau a réglé le solde — votre commission est débloquée.', time:'À l\'instant', unread:true }, ...ns]);
      showToast('Solde réglé — merci de votre confiance !'); return;
    }
    setClientStatus('accepte'); setClientPayment(method);
    window.LBC_LINK = { status:'accepte', payment:method };
    window.LBC_INT.setMoveStatut('L-2420','confirme');
    setNotifList(ns => [{ id:'lnk'+Date.now(), icon:'check', tone:'effectue', title:'Lead accepté + acompte versé', body:'Élise Moreau a accepté son devis (Nice → Bordeaux) et réglé l\'acompte.', time:'À l\'instant', unread:true }, ...ns]);
  };
  const closePayment = () => { setPayOpen(false); if(payMode==='acompte' && clientStatus==='accepte') setClientScreen('suivi'); };
  const requestRetrieval = () => {
    setRetrievals(rs => rs.some(r=>r.client==='Élise Moreau') ? rs : [{ id:'R-'+Date.now(), client:'Élise Moreau', box:'Box M', requested:'À l\'instant', status:'en attente' }, ...rs]);
    showToast('Demande de récupération envoyée — LBC vous recontacte pour planifier');
  };
  const scheduleRetrieval = (id) => { setRetrievals(rs => rs.map(r=>r.id===id?{...r,status:'planifié'}:r)); showToast('Récupération planifiée — le client est notifié'); };
  const boxApi = { items: boxItems,
    add:(it)=>setBoxItems(x=>[...x,it]),
    remove:(id)=>setBoxItems(x=>x.filter(i=>i.id!==id)),
    reorder:(from,to)=>setBoxItems(x=>{ const a=[...x]; const [m]=a.splice(from,1); a.splice(to,0,m); return a; }) };
  const chatApi = { msgs: chat,
    send:(from,text)=>{ setChat(c=>[...c,{ from, text, time:'à l\'instant' }]);
      if(from==='client'){ setNotifList(ns=>[{ id:'msg'+Date.now(), icon:'mail', tone:'devis', title:'Nouveau message client', body:'Élise Moreau vous a écrit.', time:'À l\'instant', unread:true }, ...ns]);
        setTimeout(()=>setChat(c=>[...c,{ from:'staff', text:'Bien noté Élise, je m\'en occupe et reviens vers vous très vite.', time:'à l\'instant' }]), 1500); } } };
  const notesApi = { notes, add:(text)=>setNotes(n=>[...n,{ who:'TL', text, time:'à l\'instant' }]) };

  const unread = notifList.filter(n=>n.unread).length;
  const notif = { open:notifOpen, list:notifList, unread,
    toggle:()=>setNotifOpen(v=>!v), close:()=>setNotifOpen(false),
    readAll:()=>setNotifList(ns=>ns.map(n=>({ ...n, unread:false }))) };

  const ctx = { go, leads, partner, addLead, showToast, openDoc, openCmdk:()=>setCmdk(true), tw, mobile:false, id:params.id };

  // statement rows for print
  const stmtRows = leads.filter(l=>['accepte','effectue','verse'].includes(l.status)).map(l=>({
    l, cs: l.commissionStatus==='verse'?{l:'Versé'}:(l.commissionStatus==='valide'?{l:'Validé'}:{l:'En attente'}) }));

  let body;
  if (window.SbLogin && !sbProfile) {
    const sl = <window.SbLogin onLogin={applyProfile} />;
    body = mode==='mobile' ? <Frame dark>{sl}</Frame> : <div className="stage-desktop">{sl}</div>;
  } else if (sbProfile && sbProfile.role==='partenaire' && sbProfile.statut!=='actif') {
    const pend = (
      <div style={{ height:'100%', display:'flex', alignItems:'center', justifyContent:'center', background:'var(--navy-deep)', padding:24 }}>
        <div style={{ width:'min(420px,100%)', background:'var(--card)', borderRadius:16, padding:'34px 30px', textAlign:'center', boxShadow:'var(--shadow-pop)' }}>
          <div style={{ fontSize:34 }}>⏳</div>
          <div style={{ fontSize:18, fontWeight:800, color:'var(--ink)', marginTop:8 }}>Compte en attente de validation</div>
          <p style={{ fontSize:13.5, color:'var(--muted)', lineHeight:1.6, marginTop:10 }}>Ton compte partenaire a bien été créé. L'équipe LBC doit le valider avant que tu accèdes à tes leads. Tu y auras accès dès l'activation.</p>
          <button onClick={sbLogout} style={{ marginTop:20, height:42, padding:'0 18px', borderRadius:10, background:'var(--bg)', border:'1px solid var(--border-2)', color:'var(--ink-2)', fontSize:13.5, fontWeight:600, display:'inline-flex', alignItems:'center', gap:8 }}><Icon name="logout" size={15} />Se déconnecter</button>
        </div>
      </div>
    );
    body = mode==='mobile' ? <Frame dark>{pend}</Frame> : <div className="stage-desktop">{pend}</div>;
  } else if (role==='admin' && !staffAuth) {
    const Login = window.SbLogin || StaffLogin;
    const sl = <Login kind="admin" onLogin={()=>setStaffAuth(true)} />;
    body = mode==='mobile' ? <Frame dark>{sl}</Frame> : <div className="stage-desktop">{sl}</div>;
  } else if (role==='admin') {
    body = mode==='mobile'
      ? <Frame><LBCApp screen={adminScreen} go={go} showToast={showToast} selId={params.id} retrievals={retrievals} scheduleRetrieval={scheduleRetrieval} boxApi={boxApi} chatApi={chatApi} notesApi={notesApi} mobile /></Frame>
      : <div className="stage-desktop"><LBCApp screen={adminScreen} go={go} showToast={showToast} selId={params.id} retrievals={retrievals} scheduleRetrieval={scheduleRetrieval} boxApi={boxApi} chatApi={chatApi} notesApi={notesApi} /></div>;
  } else if (role==='client') {
    const clientEl = <ClientApp screen={clientScreen} go={go} status={clientStatus} accept={acceptDevis} paySolde={paySolde} soldePaid={clientSolde} payment={clientPayment} openDoc={openDoc} requestRetrieval={requestRetrieval} boxApi={boxApi} chatApi={chatApi} mobile={mode==='mobile'} showToast={showToast} />;
    body = mode==='mobile'
      ? <Frame>{clientEl}</Frame>
      : <div className="stage-desktop">{clientEl}</div>;
  } else if (!auth) {
    const AuthScreen = authScreen==='register' ? RegisterScreen : LoginScreen;
    const authProps = { mobile: mode==='mobile', onLogin:login, go:(s)=>setAuthScreen(s) };
    body = mode==='mobile'
      ? <Frame dark><AuthScreen {...authProps} /></Frame>
      : <div className="stage-desktop"><AuthScreen {...authProps} /></div>;
  } else {
    body = mode==='mobile'
      ? <Frame><MobileApp screen={screen} go={go} ctx={{...ctx, mobile:true}} partner={partner} loading={loading} notif={notif} /></Frame>
      : <div className="stage-desktop"><DesktopApp screen={screen} go={go} ctx={ctx} partner={partner} loading={loading} notif={notif} /></div>;
  }

  const stageCls = 'stage' + (tw.density==='compact'?' density-compact':tw.density==='comfy'?' density-comfy':'');

  return (
    <div className={stageCls}>
      <div className="chrome">
        <div className="chrome-brand"><span className="chrome-dot" />{(sbProfile && sbProfile.role==='admin') ? 'LBC Platform · Prototype' : 'LBC Déménagement'}</div>
        <div className="chrome-controls">
          {sbProfile && sbProfile.role==='admin' && <div className="seg">
            <button className={role==='partner'?'on':''} onClick={()=>switchRole('partner')}><Icon name="user" size={14} />Partenaire</button>
            <button className={role==='admin'?'on':''} onClick={()=>switchRole('admin')}><Icon name="layers" size={14} />Admin LBC</button>
            <button className={role==='client'?'on':''} onClick={()=>switchRole('client')}><Icon name="truck" size={14} />Client</button>
          </div>}
          {sbProfile && sbProfile.role==='admin' && <div className="seg">
            <button className={mode==='desktop'?'on':''} onClick={()=>setMode('desktop')}>Bureau</button>
            <button className={mode==='mobile'?'on':''} onClick={()=>setMode('mobile')}><Icon name="phone" size={14} />Mobile</button>
          </div>}
          {sbProfile && <button className="chrome-reset" onClick={sbLogout}><Icon name="logout" size={15} />Déconnexion{sbProfile.role==='admin'?' (admin)':''}</button>}
        </div>
      </div>
      <div className="stage-body">
        {(mode==='mobile' && !realMobile) ? <div className="stage-mobile">{body}</div> : body}
        {cmdk && role==='partner' && <CommandPalette leads={leads} go={go} onClose={()=>setCmdk(false)} />}
        {tour && role==='partner' && <OnboardingTour go={go} onClose={()=>{ setTour(false); setSeenTour(true); }} />}
        {payOpen && role==='client' && <PaymentFlow total={CLIENT.devis} reference={CLIENT.ref} date={CLIENT.date} mode={payMode} onComplete={completePayment} onClose={closePayment} showToast={showToast} />}
        {doc && <PrintDoc kind={doc.kind} lead={doc.lead} partner={partner} rows={stmtRows} showToast={showToast} onClose={()=>setDoc(null)} />}
      </div>
      <Toast show={toast.show}>{toast.msg}</Toast>
      <TweaksPanel>
        <TweakSection label="Marque" />
        <TweakColor label="Couleur primaire" value={tw.primary}
          options={['#B63D24','#E0411F','#15384E','#1F8A5B']} onChange={v=>setTweak('primary', v)} />
        <TweakRadio label="Police" value={tw.font} options={['Geist','Inter','System']}
          onChange={v=>setTweak('font', v==='System'?'system-ui':v)} />
        <TweakSection label="Mise en page" />
        <TweakRadio label="Densité" value={tw.density} options={['compact','regular','comfy']}
          onChange={v=>setTweak('density', v)} />
        <TweakRadio label="Carte niveau" value={tw.tierStyle} options={['gradient','solid']}
          onChange={v=>setTweak('tierStyle', v)} />
      </TweaksPanel>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
