// BeHueman — Global infrastructure: ChatDock, NotificationsDropdown, ContextMenu, ReportModal, ReelsOverlay, Toasts
// =====================================================================

// ---------- Global app store (window.__app) ----------
window.__app = window.__app || {
  listeners: new Set(),
  state: {
    chatOpen: [],         // array of conversation ids open
    chatDockExpanded: true,
    chatList: null,       // 'list' panel open
    reelsViewer: null,    // {authorId, index} when overlay is showing
    reportTarget: null,   // {kind:'post'|'comment'|'profile', id, label} when reporting
    notifOpen: false,
    bookingTarget: null,  // event being booked
    feedConfigOpen: false,
    contextMenu: null,    // {x, y, items:[{label, icon, danger, onClick}]}
    toasts: [],           // [{id, kind, title, body}]
  },
  setState(patch) {
    Object.assign(this.state, typeof patch === 'function' ? patch(this.state) : patch);
    this.listeners.forEach(fn => fn(this.state));
  },
  use() {
    const [, setTick] = useState(0);
    useEffect(() => {
      const fn = () => setTick(t => t + 1);
      this.listeners.add(fn);
      return () => this.listeners.delete(fn);
    }, []);
    return [this.state, this.setState.bind(this)];
  },
  pushToast(kind, title, body) {
    const id = Math.random().toString(36).slice(2);
    this.setState(s => ({ toasts: [...s.toasts, { id, kind, title, body }] }));
    setTimeout(() => this.setState(s => ({ toasts: s.toasts.filter(t => t.id !== id) })), 5000);
  },
};

// ---------- Sample data for chat & notifications ----------
window.__chatData = {
  conversations: [
    { id:'c1', authorId:'hannaw', unread:2, lastMsg:'Wpadasz na czwartkowe live?', lastTime:'14:22', online:true, messages:[
      {from:'hannaw', text:'Hej! Widziałam że zapisałaś moją medytację.', time:'wczoraj 19:14'},
      {from:'hannaw', text:'Daj znać czy działa — robię nową wersję.', time:'wczoraj 19:14'},
      {from:'me',     text:'Tak! Bardzo pomogła. Próbowałam dwa razy.', time:'14:18'},
      {from:'hannaw', text:'Wpadasz na czwartkowe live?', time:'14:22', unread:true},
    ]},
    { id:'c2', authorId:'mokshana', unread:0, lastMsg:'Wysyłam ci link do nowego cyklu', lastTime:'wt', online:false, messages:[
      {from:'mokshana', text:'Wysyłam ci link do nowego cyklu', time:'wtorek'},
    ]},
    { id:'c3', authorId:'mdebski', unread:1, lastMsg:'Masz tę książkę o oddechu?', lastTime:'pn', online:true, messages:[
      {from:'mdebski', text:'Masz tę książkę o oddechu?', time:'poniedziałek', unread:true},
    ]},
    { id:'c4', authorId:'agap', unread:0, lastMsg:'Dziękuję za polecenie!', lastTime:'sob', online:false, messages:[
      {from:'agap', text:'Dziękuję za polecenie!', time:'sobota'},
    ]},
    { id:'c5', authorId:'lenak', unread:0, lastMsg:'Zobacz jak wyszło', lastTime:'14 kwi', online:false, messages:[
      {from:'lenak', text:'Zobacz jak wyszło', time:'14 kwi'},
    ]},
  ],
  totalUnread() { return this.conversations.reduce((s,c) => s + c.unread, 0); },
  byId(id) { return this.conversations.find(c => c.id === id); },
};

window.__notifData = {
  items: [
    { id:1, kind:'mention', authorId:'hannaw', text:'wspomniała o Tobie w komentarzu', preview:'@anna.h ten oddech, o którym mówiłaś — jest w nowym poście', time:'5 min', unread:true, hue:'rose' },
    { id:2, kind:'follow',  authorId:'mdebski', text:'zaczął obserwować Twój profil', time:'godz.', unread:true, hue:'sage' },
    { id:3, kind:'like',    authorId:'mokshana', text:'i 23 inne osoby polubiły Twój post', preview:'O sygnałach ciała przed paniką', time:'2 godz.', unread:true, hue:'amber' },
    { id:4, kind:'comment', authorId:'lenak', text:'odpowiedziała na Twój komentarz', preview:'Tak! Też tak zrobiłam i pomogło', time:'4 godz.', unread:false, hue:'violet' },
    { id:5, kind:'event',   authorId:'mokshana', text:'opublikowała nowe wydarzenie', preview:'Poranna joga w parku — sobota 7:00', time:'wczoraj', unread:false, hue:'sky' },
    { id:6, kind:'system',  text:'Twoja subskrypcja Member została odnowiona', preview:'Następna płatność: 1 czerwca', time:'2 dni', unread:false, hue:'sage' },
    { id:7, kind:'group',   authorId:'hannaw', text:'opublikowała post w grupie Krąg oddechu', preview:'Q&A o oddechu w stresie — czwartek 19:00', time:'3 dni', unread:false, hue:'rose' },
    { id:8, kind:'badge',   text:'Otrzymałaś odznakę "Pierwszy tydzień praktyki"', time:'tydzień', unread:false, hue:'amber' },
  ],
  unread() { return this.items.filter(i => i.unread).length; },
};

// =====================================================================
// CONTEXT MENU
// =====================================================================
function ContextMenu() {
  const [s, set] = window.__app.use();
  const m = s.contextMenu;
  useEffect(() => {
    if (!m) return;
    const close = () => set({ contextMenu: null });
    setTimeout(() => {
      window.addEventListener('click', close, { once:true });
      window.addEventListener('scroll', close, { once:true, capture:true });
    }, 0);
  }, [m]);
  if (!m) return null;
  const x = Math.min(m.x, window.innerWidth - 240);
  const y = Math.min(m.y, window.innerHeight - (m.items.length * 40 + 16));
  return (
    <div className="ctx-menu" style={{ position:'fixed', left:x, top:y, zIndex:1100 }}>
      {m.items.map((it, i) => (
        <button key={i} className={`ctx-item ${it.danger?'danger':''}`}
                onClick={(e) => { e.stopPropagation(); set({ contextMenu: null }); it.onClick && it.onClick(); }}>
          {it.icon && <I name={it.icon} size={14}/>}
          <span>{it.label}</span>
          {it.hint && <span className="ctx-hint">{it.hint}</span>}
        </button>
      ))}
    </div>
  );
}

function openContextMenu(e, items) {
  e.preventDefault(); e.stopPropagation();
  const r = e.currentTarget.getBoundingClientRect();
  window.__app.setState({ contextMenu: { x: r.right - 220, y: r.bottom + 6, items }});
}

// =====================================================================
// REPORT MODAL  (Zgłoś — kontekstowo z menu posta/komentarza/profilu)
// =====================================================================
function ReportModal() {
  const [s, set] = window.__app.use();
  const t = s.reportTarget;
  const [reason, setReason] = useState(null);
  const [details, setDetails] = useState('');
  const [done, setDone] = useState(false);
  if (!t) return null;
  const reasons = [
    { id:'hate',     label:'Mowa nienawiści, dyskryminacja', hue:'rose' },
    { id:'harass',   label:'Nękanie, atak osobisty',         hue:'rose' },
    { id:'spam',     label:'Spam, scam, fake account',       hue:'amber' },
    { id:'misinfo',  label:'Wprowadzające w błąd informacje', hue:'amber' },
    { id:'sexual',   label:'Treści seksualne, nieodpowiednie', hue:'violet' },
    { id:'self-harm',label:'Autoagresja, samookaleczenie',   hue:'violet' },
    { id:'copyright',label:'Naruszenie praw autorskich',     hue:'sky' },
    { id:'other',    label:'Inny powód — opisz poniżej',     hue:'sage' },
  ];
  const close = () => { setReason(null); setDetails(''); setDone(false); set({ reportTarget: null }); };
  const submit = () => {
    setDone(true);
    setTimeout(() => { close(); window.__app.pushToast('ok','Zgłoszenie wysłane','Moderacja sprawdzi je w ciągu 24 godzin.'); }, 900);
  };
  const targetLabel = t.kind === 'post' ? 'post' : t.kind === 'comment' ? 'komentarz' : 'profil';
  return (
    <Modal title={`Zgłoś ${targetLabel}`} onClose={close} footer={
      done ? null :
      <>
        <button className="btn btn-ghost" onClick={close}>Anuluj</button>
        <button className="btn btn-primary" disabled={!reason} onClick={submit}>Wyślij zgłoszenie</button>
      </>
    }>
      {done ? (
        <div className="col gap-12" style={{padding:'20px 0', textAlign:'center'}}>
          <div style={{fontSize:48, lineHeight:1}}>✓</div>
          <div style={{fontFamily:'var(--font-serif)', fontSize:20, fontWeight:500}}>Dziękujemy.</div>
          <div className="muted" style={{fontSize:13.5, lineHeight:1.5, maxWidth:340, margin:'0 auto'}}>
            Twoje zgłoszenie trafi do moderacji. Zachowujemy anonimowość — autor nie zobaczy Twojego nicku.
          </div>
        </div>
      ) : (
        <>
          <div className="muted" style={{fontSize:12.5, lineHeight:1.5, marginBottom:14}}>
            Zgłaszasz: <b>{t.label}</b>. Zachowujemy Twoją anonimowość. Niezasadne zgłoszenia mogą skutkować ostrzeżeniem konta.
          </div>
          <div className="form-label" style={{marginBottom:8}}>Powód</div>
          <div className="col gap-6" style={{marginBottom:16}}>
            {reasons.map(r => (
              <button key={r.id} onClick={()=>setReason(r.id)} className="row gap-12" style={{
                padding:'12px 14px', cursor:'pointer', textAlign:'left', borderRadius:'var(--r-2)',
                border: reason===r.id ? '2px solid var(--ink-1)' : '1px solid var(--line)',
                background: reason===r.id ? `color-mix(in oklab, var(--hue-${r.hue}) 14%, var(--bg-elev))` : 'var(--bg-elev)',
              }}>
                <div style={{width:14, height:14, borderRadius:'50%', border:'2px solid var(--ink-1)', display:'grid', placeItems:'center', flexShrink:0}}>
                  {reason===r.id && <div style={{width:6, height:6, borderRadius:'50%', background:'var(--ink-1)'}}/>}
                </div>
                <span style={{fontSize:13.5}}>{r.label}</span>
              </button>
            ))}
          </div>
          {reason && (
            <div className="form-group" style={{marginBottom:0}}>
              <div className="form-label">Dodatkowe informacje (opcjonalnie)</div>
              <textarea className="input" rows={3} value={details} onChange={e=>setDetails(e.target.value)} placeholder="Opisz kontekst, jeśli to pomoże moderatorom."/>
            </div>
          )}
        </>
      )}
    </Modal>
  );
}

function openReport(kind, id, label) { window.__app.setState({ reportTarget: { kind, id, label } }); }

// =====================================================================
// NOTIFICATIONS DROPDOWN (bell-triggered)
// =====================================================================
function NotificationsDropdown() {
  const [s, set] = window.__app.use();
  const [tab, setTab] = useState('all');
  if (!s.notifOpen) return null;
  const items = window.__notifData.items.filter(i => {
    if (tab === 'mentions') return ['mention','comment'].includes(i.kind);
    if (tab === 'system') return ['system','badge'].includes(i.kind);
    return true;
  });
  const grouped = (() => {
    const today = items.filter(i => /min|godz/.test(i.time));
    const earlier = items.filter(i => !/min|godz/.test(i.time));
    return [['Dzisiaj', today], ['Wcześniej', earlier]].filter(([,arr]) => arr.length);
  })();
  const close = () => set({ notifOpen: false });
  return (
    <>
      <div onClick={close} style={{ position:'fixed', inset:0, zIndex:900 }}/>
      <div className="notif-pop" onClick={e=>e.stopPropagation()}>
        <div className="notif-head">
          <div style={{fontFamily:'var(--font-serif)', fontSize:20, fontWeight:500}}>Powiadomienia</div>
          <button className="btn btn-ghost btn-sm" onClick={()=>{ window.__notifData.items.forEach(i=>i.unread=false); set({}); }}>
            Oznacz wszystkie
          </button>
        </div>
        <div className="notif-tabs">
          {[['all','Wszystkie'],['mentions','Wzmianki'],['system','System']].map(([k,l]) => (
            <button key={k} className={tab===k?'on':''} onClick={()=>setTab(k)}>{l}</button>
          ))}
        </div>
        <div className="notif-body">
          {grouped.length === 0 && <div className="empty" style={{padding:32}}><div className="muted">Tu pusto.</div></div>}
          {grouped.map(([g, arr]) => (
            <Fragment key={g}>
              <div className="notif-group-label">{g}</div>
              {arr.map(n => {
                const a = n.authorId ? AppData.getAuthor(n.authorId) : null;
                return (
                  <div key={n.id} className={`notif-item ${n.unread?'unread':''}`}>
                    {a ? <Avatar author={a} size={36}/> :
                      <div style={{width:36, height:36, borderRadius:'50%', background:`color-mix(in oklab, var(--hue-${n.hue}) 30%, var(--bg-elev))`, display:'grid', placeItems:'center'}}>
                        <I name={n.kind==='badge'?'Sparkle':n.kind==='system'?'Shield':'Bell'} size={16}/>
                      </div>}
                    <div style={{flex:1, minWidth:0}}>
                      <div style={{fontSize:13, lineHeight:1.4}}>
                        {a && <b>{a.name}</b>} <span className="muted">{n.text}</span>
                      </div>
                      {n.preview && <div className="notif-preview">"{n.preview}"</div>}
                      <div className="notif-time">{n.time}</div>
                    </div>
                    {n.unread && <span className="notif-dot" style={{background:`var(--hue-${n.hue})`}}/>}
                  </div>
                );
              })}
            </Fragment>
          ))}
        </div>
        <div className="notif-foot">
          <button className="btn btn-ghost btn-sm" style={{width:'100%'}}>Konfiguracja powiadomień</button>
        </div>
      </div>
    </>
  );
}

// =====================================================================
// CHAT DOCK (FB-style, only when phase >= FF3)
// =====================================================================
function ChatDock({ phase }) {
  const [s, set] = window.__app.use();
  const order = { FF1:1, FF2:2, FF3:3, GL:4 };
  if (order[phase] < 3) return null;
  const list = window.__chatData.conversations;
  const total = window.__chatData.totalUnread();

  return (
    <div className="chat-dock">
      {/* open chat windows */}
      <div className="chat-windows">
        {s.chatOpen.map(cid => {
          const c = window.__chatData.byId(cid);
          if (!c) return null;
          return <ChatWindow key={cid} conv={c}/>;
        })}
      </div>
      {/* list panel */}
      {s.chatList && (
        <div className="chat-list-panel">
          <div className="chat-list-head">
            <div style={{fontFamily:'var(--font-serif)', fontSize:18, fontWeight:500}}>Wiadomości</div>
            <button className="icon-btn" style={{border:'none', background:'transparent'}} onClick={()=>set({ chatList:false })}>
              <I name="X" size={14}/>
            </button>
          </div>
          <div className="chat-list-search">
            <I name="Search" size={14}/>
            <input placeholder="Szukaj rozmowy"/>
          </div>
          <div className="chat-list-body">
            {list.map(c => {
              const a = AppData.getAuthor(c.authorId);
              return (
                <button key={c.id} className="chat-list-item" onClick={()=>{
                  set({ chatList:false, chatOpen: [...new Set([c.id, ...s.chatOpen])].slice(0,3) });
                  c.unread = 0;
                }}>
                  <div style={{position:'relative'}}>
                    <Avatar author={a} size={42}/>
                    {c.online && <span className="online-dot"/>}
                  </div>
                  <div style={{flex:1, minWidth:0, textAlign:'left'}}>
                    <div className="row" style={{justifyContent:'space-between', alignItems:'baseline', gap:8}}>
                      <span style={{fontSize:13, fontWeight: c.unread?700:500, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'}}>{a.name}</span>
                      <span style={{fontSize:11, color:'var(--ink-3)', flexShrink:0}}>{c.lastTime}</span>
                    </div>
                    <div className="row" style={{justifyContent:'space-between', gap:8}}>
                      <span style={{fontSize:12, color: c.unread?'var(--ink-1)':'var(--ink-3)', fontWeight: c.unread?500:400, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'}}>{c.lastMsg}</span>
                      {c.unread > 0 && <span style={{background:'var(--accent)', color:'white', fontSize:10.5, fontWeight:700, padding:'1px 6px', borderRadius:'var(--r-pill)', flexShrink:0}}>{c.unread}</span>}
                    </div>
                  </div>
                </button>
              );
            })}
          </div>
        </div>
      )}
      {/* dock launcher */}
      <button className="chat-launcher" onClick={()=>set({ chatList: !s.chatList })}>
        <I name="Send" size={18}/>
        <span>Wiadomości</span>
        {total > 0 && <span className="chat-launcher-badge">{total}</span>}
      </button>
    </div>
  );
}

function ChatWindow({ conv }) {
  const [s, set] = window.__app.use();
  const [draft, setDraft] = useState('');
  const a = AppData.getAuthor(conv.authorId);
  const [collapsed, setCollapsed] = useState(false);
  const close = () => set({ chatOpen: s.chatOpen.filter(id => id !== conv.id) });
  const send = () => {
    if (!draft.trim()) return;
    conv.messages.push({ from:'me', text: draft, time:'teraz' });
    conv.lastMsg = draft;
    conv.lastTime = 'teraz';
    setDraft('');
  };
  return (
    <div className={`chat-window ${collapsed?'collapsed':''}`}>
      <div className="chat-w-head" onClick={()=>setCollapsed(c => !c)}>
        <div style={{position:'relative'}}>
          <Avatar author={a} size={30}/>
          {conv.online && <span className="online-dot small"/>}
        </div>
        <div style={{flex:1, minWidth:0}}>
          <div style={{fontSize:13, fontWeight:600, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'}}>{a.name}</div>
          <div style={{fontSize:11, color: conv.online?'var(--hue-sage)':'var(--ink-3)'}}>{conv.online?'aktywna':'offline'}</div>
        </div>
        <button className="chat-w-btn" onClick={(e)=>{ e.stopPropagation(); setCollapsed(c=>!c); }}>{collapsed?'▲':'▼'}</button>
        <button className="chat-w-btn" onClick={(e)=>{ e.stopPropagation(); close(); }}><I name="X" size={12}/></button>
      </div>
      {!collapsed && <>
        <div className="chat-w-body">
          {conv.messages.map((m,i) => (
            <div key={i} className={`chat-msg ${m.from==='me'?'me':'other'}`}>
              <div className="chat-bubble">{m.text}</div>
              <div className="chat-time">{m.time}</div>
            </div>
          ))}
        </div>
        <div className="chat-w-input">
          <input value={draft} onChange={e=>setDraft(e.target.value)} onKeyDown={e=>e.key==='Enter'&&send()} placeholder="Napisz wiadomość…"/>
          <button className="chat-send" onClick={send}><I name="Send" size={14}/></button>
        </div>
      </>}
    </div>
  );
}

function openChat(authorId) {
  let conv = window.__chatData.conversations.find(c => c.authorId === authorId);
  if (!conv) {
    conv = { id:'c-'+authorId, authorId, unread:0, lastMsg:'', lastTime:'teraz', online:true, messages:[] };
    window.__chatData.conversations.unshift(conv);
  }
  conv.unread = 0;
  const cur = window.__app.state.chatOpen;
  if (!cur.includes(conv.id)) {
    window.__app.setState({ chatOpen: [conv.id, ...cur].slice(0,3) });
  }
}

// =====================================================================
// REELS OVERLAY (vertical viewer, profile-only)
// =====================================================================
function ReelsOverlay() {
  const [s, set] = window.__app.use();
  if (!s.reelsViewer) return null;
  const v = s.reelsViewer;
  const reels = v.reels || [];
  const [idx, setIdx] = useState(v.index || 0);
  const r = reels[idx];
  if (!r) return null;
  const a = AppData.getAuthor(r.authorId);
  const close = () => set({ reelsViewer: null });
  return (
    <div className="reels-overlay" onClick={close}>
      <button className="reels-close" onClick={close}><I name="X" size={18}/></button>
      <div className="reels-stage" onClick={e=>e.stopPropagation()}>
        <button className="reels-nav up" onClick={()=>setIdx(i => Math.max(0, i-1))} disabled={idx===0}>↑</button>
        <div className="reel" style={{background:`linear-gradient(160deg, var(--hue-${r.hue}), color-mix(in oklab, var(--hue-${r.hue}) 50%, var(--ink-1)))`}}>
          {/* fake video — pulsing */}
          <div className="reel-shimmer"/>
          <div className="reel-overlay">
            <div className="reel-author">
              <Avatar author={a} size={40}/>
              <div style={{flex:1}}>
                <div className="row gap-4"><span style={{color:'white', fontWeight:600, fontSize:14}}>{a.name}</span>{a.verified && <VerifiedBadge/>}</div>
                <div style={{fontSize:11, color:'rgba(255,255,255,.7)'}}>@{a.handle}</div>
              </div>
              <button className="btn btn-accent btn-sm">Obserwuj</button>
            </div>
            <div className="reel-title">{r.title}</div>
            <div className="reel-meta">{r.views} obejrzeń · {r.dur}</div>
          </div>
          <div className="reel-actions">
            <button className="reel-act"><I name="Heart" size={22}/><span>284</span></button>
            <button className="reel-act"><I name="Comment" size={22}/><span>47</span></button>
            <button className="reel-act"><I name="Share" size={22}/></button>
            <button className="reel-act" onClick={(e)=>openContextMenu(e, [
              { label:'Zgłoś reels', icon:'Shield', danger:true, onClick: () => openReport('post', r.id, r.title) },
              { label:'Zapisz do biblioteki', icon:'Bookmark', onClick:()=>window.__app.pushToast('ok','Zapisano','Reels jest w Twojej bibliotece.') },
              { label:'Skopiuj link', icon:'Link', onClick:()=>window.__app.pushToast('ok','Skopiowano','Link do reels jest w schowku.') },
            ])}><I name="More" size={20}/></button>
          </div>
        </div>
        <button className="reels-nav down" onClick={()=>setIdx(i => Math.min(reels.length-1, i+1))} disabled={idx===reels.length-1}>↓</button>
      </div>
      <div className="reels-counter">{idx+1} / {reels.length}</div>
    </div>
  );
}

// =====================================================================
// FEED CONFIG SIDE PANEL (right-side drawer)
// =====================================================================
function FeedConfigPanel() {
  const [s, set] = window.__app.use();
  const [mode, setMode] = useState('latest');
  const [domains, setDomains] = useState(new Set(['rozwoj','medycyna']));
  const [langs, setLangs] = useState(new Set(['pl']));
  const [showSponsored, setShowSponsored] = useState(true);
  const [autoTranslate, setAutoTranslate] = useState(false);
  if (!s.feedConfigOpen) return null;
  const close = () => set({ feedConfigOpen: false });
  const toggle = (set, val) => { const n = new Set(set); n.has(val) ? n.delete(val) : n.add(val); return n; };

  return (
    <>
      <div onClick={close} style={{position:'fixed', inset:0, background:'rgba(31,27,22,.18)', zIndex:900}}/>
      <div className="side-drawer" onClick={e=>e.stopPropagation()}>
        <div className="side-drawer-head">
          <div>
            <div className="section-eyebrow">Konfiguracja feedu</div>
            <div style={{fontFamily:'var(--font-serif)', fontSize:24, fontWeight:500, marginTop:4}}>Czego chcesz dziś?</div>
          </div>
          <button className="icon-btn" style={{border:'none', background:'transparent'}} onClick={close}><I name="X" size={16}/></button>
        </div>
        <div className="side-drawer-body">
          {/* Mode */}
          <div className="form-group">
            <div className="form-label">Tryb feedu</div>
            <div className="col gap-6">
              {[
                ['latest','Najnowsze','Wszystko świeże, chronologicznie'],
                ['popular','Najpopularniejsze','Co rezonuje teraz w społeczności'],
                ['friends','Od znajomych autorów','Tylko Ci, których obserwujesz'],
                ['for-you','Dla Ciebie','Algorytm uczy się z Twoich preferencji'],
              ].map(([k,l,d]) => (
                <button key={k} onClick={()=>setMode(k)} className="row gap-12" style={{
                  padding:'12px 14px', cursor:'pointer', textAlign:'left', borderRadius:'var(--r-2)',
                  border: mode===k?'2px solid var(--ink-1)':'1px solid var(--line)',
                  background: mode===k?'var(--bg-soft)':'var(--bg-elev)',
                }}>
                  <div style={{width:14, height:14, borderRadius:'50%', border:'2px solid var(--ink-1)', display:'grid', placeItems:'center', flexShrink:0, marginTop:2}}>
                    {mode===k && <div style={{width:6, height:6, borderRadius:'50%', background:'var(--ink-1)'}}/>}
                  </div>
                  <div>
                    <div style={{fontSize:13, fontWeight:600}}>{l}</div>
                    <div className="muted" style={{fontSize:11.5, marginTop:2}}>{d}</div>
                  </div>
                </button>
              ))}
            </div>
          </div>
          {/* Domains */}
          <div className="form-group">
            <div className="form-label">Dziedziny ({domains.size})</div>
            <div className="row gap-6" style={{flexWrap:'wrap'}}>
              {AppData.domains.map(d => (
                <button key={d.id} className={`chip chip-hue-${d.hue} ${domains.has(d.id)?'active':''}`}
                        onClick={()=>setDomains(s=>toggle(s,d.id))}>{d.label}</button>
              ))}
            </div>
          </div>
          {/* Lang */}
          <div className="form-group">
            <div className="form-label">Języki postów</div>
            <div className="row gap-6" style={{flexWrap:'wrap'}}>
              {['pl','en','de','es','fr'].map(l => (
                <button key={l} className={`chip ${langs.has(l)?'active':''}`} onClick={()=>setLangs(s=>toggle(s,l))}>{l.toUpperCase()}</button>
              ))}
            </div>
          </div>
          {/* Toggles */}
          <div className="form-group">
            <div className="form-label">Doświadczenie</div>
            <div className="col gap-12">
              <label className="row" style={{justifyContent:'space-between', cursor:'pointer'}}>
                <div>
                  <div style={{fontSize:13, fontWeight:600}}>Posty sponsorowane</div>
                  <div className="muted" style={{fontSize:11.5}}>Zawsze oznaczone — można wyłączyć.</div>
                </div>
                <Toggle on={showSponsored} onChange={setShowSponsored}/>
              </label>
              <label className="row" style={{justifyContent:'space-between', cursor:'pointer'}}>
                <div>
                  <div style={{fontSize:13, fontWeight:600}}>Auto-tłumaczenie postów</div>
                  <div className="muted" style={{fontSize:11.5}}>Treści w innym języku tłumaczone automatycznie (Google).</div>
                </div>
                <Toggle on={autoTranslate} onChange={setAutoTranslate}/>
              </label>
            </div>
          </div>
        </div>
        <div className="side-drawer-foot">
          <button className="btn btn-ghost" onClick={()=>{ setMode('latest'); setDomains(new Set()); setLangs(new Set(['pl'])); }}>Resetuj</button>
          <button className="btn btn-primary" onClick={()=>{ window.__app.pushToast('ok','Zapisano','Feed dostosowany do Ciebie.'); close(); }}>Zapisz preferencje</button>
        </div>
      </div>
    </>
  );
}

// =====================================================================
// BOOKING MODAL (rezerwacja sesji partnerskiej)
// =====================================================================
function BookingModal() {
  const [s, set] = window.__app.use();
  const t = s.bookingTarget;
  const [day, setDay] = useState(12);
  const [slot, setSlot] = useState(null);
  const [confirmed, setConfirmed] = useState(false);
  if (!t) return null;
  const days = Array.from({length:14}, (_,i) => i+8);
  const slots = ['09:00','10:30','12:00','13:30','15:00','16:30','18:00','19:30'];
  const taken = ['10:30','15:00','18:00'];
  const close = () => { setDay(12); setSlot(null); setConfirmed(false); set({ bookingTarget: null }); };

  return (
    <Modal title="Zarezerwuj termin" wide onClose={close} footer={
      confirmed ? <button className="btn btn-primary" onClick={close}>Gotowe</button> :
      <>
        <button className="btn btn-ghost" onClick={close}>Anuluj</button>
        <button className="btn btn-primary" disabled={!slot} style={{background:'#635bff', opacity:slot?1:0.4}} onClick={()=>{ setConfirmed(true); window.__app.pushToast('ok','Termin zarezerwowany',`${day} maja, ${slot} · Płatność potwierdzona.`); }}>
          {slot ? `Zarezerwuj — ${t.price||180} zł` : 'Wybierz godzinę'}
        </button>
      </>
    }>
      {confirmed ? (
        <div className="col gap-12" style={{padding:'20px 0', textAlign:'center'}}>
          <div style={{fontSize:48, lineHeight:1}}>✓</div>
          <div style={{fontFamily:'var(--font-serif)', fontSize:22, fontWeight:500}}>Termin zablokowany.</div>
          <div className="muted" style={{fontSize:13.5, lineHeight:1.5, maxWidth:380, margin:'0 auto'}}>
            <b>{day} maja 2026, {slot}</b> · {t.label}<br/>
            Wysłaliśmy potwierdzenie e-mailem. Anulowanie do 24h przed sesją bez opłat.
          </div>
        </div>
      ) : (
        <>
          <div className="row gap-12" style={{padding:14, background:'var(--bg-soft)', borderRadius:'var(--r-2)', marginBottom:18}}>
            <div style={{width:42, height:42, borderRadius:8, background:`linear-gradient(135deg, ${t.cover?.[0]||'#E8B872'}, ${t.cover?.[1]||'#94463F'})`, flexShrink:0}}/>
            <div style={{flex:1, minWidth:0}}>
              <div style={{fontFamily:'var(--font-serif)', fontSize:16, fontWeight:500}}>{t.label}</div>
              <div className="muted" style={{fontSize:12}}>{t.partner||'Studio Mokshana'} · {t.duration||'60 min'} · {t.price||180} zł</div>
            </div>
          </div>
          <div className="form-label">Wybierz dzień</div>
          <div className="row gap-6 mb-16" style={{flexWrap:'wrap'}}>
            {days.map(d => {
              const date = new Date(2026, 4, d);
              const isPast = d < 8;
              const isActive = day === d;
              return (
                <button key={d} onClick={()=>!isPast && setDay(d)} disabled={isPast} style={{
                  width:50, padding:'8px 4px', textAlign:'center', cursor: isPast?'not-allowed':'pointer',
                  border: isActive?'2px solid var(--ink-1)':'1px solid var(--line)',
                  borderRadius:'var(--r-2)',
                  background: isActive?'var(--ink-1)':'var(--bg-elev)',
                  color: isActive?'var(--bg-elev)':'var(--ink-1)',
                  opacity: isPast?0.3:1,
                }}>
                  <div style={{fontSize:9, fontWeight:600}}>{['nd','pn','wt','śr','cz','pt','sb'][date.getDay()]}</div>
                  <div style={{fontFamily:'var(--font-serif)', fontSize:16, fontWeight:500}}>{d}</div>
                </button>
              );
            })}
          </div>
          <div className="form-label">Dostępne sloty — {day} maja</div>
          <div style={{display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:8, marginBottom:14}}>
            {slots.map(sl => {
              const isTaken = taken.includes(sl);
              const isActive = slot === sl;
              return (
                <button key={sl} onClick={()=>!isTaken && setSlot(sl)} disabled={isTaken} style={{
                  padding:'10px 4px', textAlign:'center', cursor:isTaken?'not-allowed':'pointer',
                  border: isActive?'2px solid var(--ink-1)':'1px solid var(--line)',
                  borderRadius:'var(--r-2)',
                  background: isActive?'var(--hue-amber)':isTaken?'var(--bg-soft)':'var(--bg-elev)',
                  textDecoration: isTaken?'line-through':'none',
                  color: isTaken?'var(--ink-4)':'var(--ink-1)',
                  fontSize:13, fontWeight:600,
                }}>
                  {sl}
                </button>
              );
            })}
          </div>
          <div className="muted" style={{fontSize:11.5, lineHeight:1.4}}>Płatność realizowana przez Stripe. Po zapłaceniu termin jest zablokowany.</div>
        </>
      )}
    </Modal>
  );
}
function openBooking(target) { window.__app.setState({ bookingTarget: target }); }

// =====================================================================
// TOASTS
// =====================================================================
function Toasts() {
  const [s] = window.__app.use();
  return (
    <div className="toast-stack">
      {s.toasts.map(t => (
        <div key={t.id} className={`toast toast-${t.kind||'ok'}`}>
          <div className="toast-bar"/>
          <div style={{flex:1}}>
            <div className="toast-title">{t.title}</div>
            {t.body && <div className="toast-body">{t.body}</div>}
          </div>
          <button className="icon-btn" style={{border:'none', background:'transparent'}}
                  onClick={()=>window.__app.setState(s => ({ toasts: s.toasts.filter(x=>x.id!==t.id) }))}>
            <I name="X" size={12}/>
          </button>
        </div>
      ))}
    </div>
  );
}

// =====================================================================
// GLOBAL OVERLAYS — single mount point
// =====================================================================
function GlobalOverlays({ phase }) {
  return <>
    <ContextMenu/>
    <ReportModal/>
    <NotificationsDropdown/>
    <FeedConfigPanel/>
    <BookingModal/>
    <ChatDock phase={phase}/>
    <ReelsOverlay/>
    <Toasts/>
  </>;
}

// Expose
Object.assign(window, {
  ContextMenu, openContextMenu,
  ReportModal, openReport,
  NotificationsDropdown,
  ChatDock, openChat,
  ReelsOverlay,
  FeedConfigPanel,
  BookingModal, openBooking,
  Toasts,
  GlobalOverlays,
});
