// mariusson — Studio drawer (left side)
//
// The single home for everything the user *does* on the platform that
// isn't browsing the atlas:
//   • Inbox — conversations with artists about open commissions
//   • Receipts — every order with the original receipt panel
//   • Owned — works the user has bought / commissioned (collector)
//   • Payment — saved cards (collectors) or payout methods (artists)
//
// Slides in from the LEFT — deliberately mirroring The Room (which slides
// from the left for an artwork's comments). Profile drawer stays on the
// right; Studio is the place where transactions, money, and messages live.

(() => {
  // ── Messages storage ────────────────────────────────────────────────
  // Threads keyed by `${userId}:${counterpartyId}` — symmetric, but we
  // store both perspectives so each side reads only their own thread
  // ordering. Mock-only: there is no real artist on the other end, so we
  // synthesize a reply from the artist after a small delay to make the
  // surface feel alive.
  const MSG_KEY = 'mariusson:messages';

  function readThreads() {
    try { return JSON.parse(localStorage.getItem(MSG_KEY) || '{}'); }
    catch { return {}; }
  }
  function writeThreads(t) {
    try { localStorage.setItem(MSG_KEY, JSON.stringify(t)); } catch {}
  }
  function threadKey(meId, otherId) { return `${meId}::${otherId}`; }

  function listThreadsForUser(userId) {
    const all = readThreads();
    return Object.entries(all)
      .filter(([k]) => k.startsWith(userId + '::'))
      .map(([k, msgs]) => ({
        key: k,
        otherId: k.split('::')[1],
        msgs: msgs || [],
        lastTs: (msgs && msgs.length) ? msgs[msgs.length - 1].ts : 0,
      }))
      .sort((a, b) => b.lastTs - a.lastTs);
  }

  function getThread(meId, otherId) {
    return (readThreads()[threadKey(meId, otherId)]) || [];
  }

  function postMessage(meId, otherId, otherName, text) {
    const all = readThreads();
    const k = threadKey(meId, otherId);
    const reverseK = threadKey(otherId, meId);
    const m = { id: 'm_' + Math.random().toString(36).slice(2, 10), from: meId, text, ts: Date.now() };
    all[k] = [...(all[k] || []), m];
    all[reverseK] = [...(all[reverseK] || []), m];   // mirror so the artist would see it
    writeThreads(all);
    window.dispatchEvent(new Event('an-messages-changed'));

    // Mock artist auto-reply after a short delay — keeps the inbox feeling
    // populated without a real backend. Skipped if otherId looks like a
    // user id (starts with 'u_'); only fires for catalogue artists.
    if (!String(otherId).startsWith('u_')) {
      setTimeout(() => {
        const replies = [
          'Got it. Looking at your brief now.',
          'Thank you for the note. I\'ll be back in touch within the week.',
          'Interesting. Could you say a little more about scale?',
          'Yes — that direction is one I\'ve been working on.',
          'Let me think on it. Thanks for reaching out.',
        ];
        const reply = {
          id: 'm_' + Math.random().toString(36).slice(2, 10),
          from: otherId,
          fromName: otherName,
          text: replies[Math.floor(Math.random() * replies.length)],
          ts: Date.now(),
        };
        const a2 = readThreads();
        a2[k]        = [...(a2[k] || []),        reply];
        a2[reverseK] = [...(a2[reverseK] || []), reply];
        writeThreads(a2);
        window.dispatchEvent(new Event('an-messages-changed'));
      }, 1800 + Math.random() * 2200);
    }
    return m;
  }

  function useThreads(userId) {
    const [threads, setThreads] = React.useState(() => userId ? listThreadsForUser(userId) : []);
    React.useEffect(() => {
      if (!userId) { setThreads([]); return; }
      const refresh = () => setThreads(listThreadsForUser(userId));
      refresh();
      window.addEventListener('an-messages-changed', refresh);
      window.addEventListener('storage', (e) => { if (e.key === MSG_KEY) refresh(); });
      return () => window.removeEventListener('an-messages-changed', refresh);
    }, [userId]);
    return threads;
  }

  // ── Owned works derivation ──────────────────────────────────────────
  // Collector "owned" = orders of type 'commission' or 'purchase' that
  // resolve to a workId in the catalogue. Donations don't count.
  function ownedWorksForBuyer(buyerId) {
    if (!window.AN_PAY) return [];
    const orders = window.AN_PAY.listOrdersForBuyer(buyerId);
    const owned = orders
      .filter((o) => o.type === 'commission' || o.type === 'purchase')
      .map((o) => ({
        order: o,
        workId: o.workId, workTitle: o.workTitle, workImage: o.workImage,
        artistName: o.artistName, status: o.type === 'commission' ? 'In progress' : 'Owned',
      }));
    // Dedupe: latest-per-workId only (so the same work doesn't show twice)
    const byId = new Map();
    for (const w of owned) {
      const existing = byId.get(w.workId);
      if (!existing || existing.order.createdAt < w.order.createdAt) byId.set(w.workId, w);
    }
    return [...byId.values()].sort((a, b) => b.order.createdAt - a.order.createdAt);
  }

  // ── Studio drawer component ─────────────────────────────────────────
  function StudioDrawer({ account, role, savedIds, catalogue, visible, onClose, onPickWork, onPickCollector }) {
    const [tab, setTab] = React.useState(role === 'artist' ? 'inbox' : 'owned');
    const accent = role === 'artist' ? BAU.red : role === 'collector' ? BAU.yellow : BAU.ink;

    const tabsForRole = role === 'artist'
      ? ['inbox', 'receipts', 'payouts']
      : role === 'collector'
        ? ['owned', 'inbox', 'receipts', 'cards', 'saved']
        : ['saved', 'receipts'];

    return (
      <div data-atlas-panel onClick={onClose} style={{
        position: 'absolute', inset: 0, zIndex: 50,
        background: visible ? 'rgba(14,14,12,0.42)' : 'rgba(14,14,12,0)',
        backdropFilter: visible ? 'blur(4px)' : 'blur(0px)',
        WebkitBackdropFilter: visible ? 'blur(4px)' : 'blur(0px)',
        transition: 'background 280ms var(--ease-out), backdrop-filter 280ms var(--ease-out), -webkit-backdrop-filter 280ms var(--ease-out)',
      }}>
        <div data-atlas-drawer onClick={(e) => e.stopPropagation()} style={{
          position: 'absolute', top: 0, left: 0, bottom: 0,
          width: 'min(640px, 96%)',
          background: BAU.paper, borderRight: `1px solid ${BAU.ink}`,
          transform: visible ? 'translateX(0)' : 'translateX(-100%)',
          transition: 'transform 380ms var(--ease-out)',
          display: 'flex', flexDirection: 'column', overflow: 'hidden',
        }}>
          {/* Bauhaus stripe */}
          <div style={{ display: 'flex', height: 8, flexShrink: 0 }}>
            <div style={{ flex: 1, background: BAU.blue }} />
            <div style={{ flex: 2, background: BAU.ink }} />
            <div style={{ flex: 1, background: accent }} />
          </div>

          {/* Header */}
          <div style={{ padding: '20px 24px 14px', borderBottom: `1px solid ${BAU.rule}`, display: 'flex', alignItems: 'center', gap: 14 }}>
            <span style={{ width: 10, height: 10, background: accent, alignSelf: 'center' }} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontFamily: 'var(--mono)', fontSize: 9.5, letterSpacing: '0.18em', color: BAU.graphite, textTransform: 'uppercase' }}>
                Studio · {role}
              </div>
              <h2 style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 26, margin: '2px 0 0', lineHeight: 1.05, color: BAU.ink }}>
                {role === 'artist' ? 'Your studio' : role === 'collector' ? 'Your collection' : 'Your activity'}
              </h2>
              <div style={{ marginTop: 4, fontFamily: 'var(--sans)', fontSize: 12, color: BAU.graphite }}>
                {role === 'artist'
                  ? 'Briefs from collectors, sales, and where to get paid.'
                  : role === 'collector'
                    ? 'Owned works, receipts, payment methods, conversations.'
                    : 'Saved works and receipts.'}
              </div>
            </div>
            <button onClick={onClose} title="Close studio" aria-label="Close studio" style={{
              width: 28, height: 28, padding: 0,
              background: 'transparent', border: `1px solid ${BAU.ink}`, color: BAU.ink,
              cursor: 'pointer', fontFamily: 'var(--mono)', fontSize: 13,
            }}>×</button>
          </div>

          {/* Tabs */}
          <div role="tablist" style={{
            display: 'flex',
            borderBottom: `1px solid ${BAU.ink}`,
            background: BAU.paper2,
            overflowX: 'auto',
          }}>
            {tabsForRole.map((id) => {
              const labelMap = {
                inbox: 'Inbox', receipts: 'Receipts', payouts: 'Payouts',
                owned: 'Owned', cards: 'Payment', saved: 'Saved',
              };
              const sel = tab === id;
              return (
                <button key={id} onClick={() => setTab(id)} role="tab" aria-selected={sel} style={{
                  flex: 1, minWidth: 90,
                  background: sel ? BAU.paper : 'transparent',
                  color: sel ? BAU.ink : BAU.graphite,
                  border: 'none',
                  borderRight: `1px solid ${BAU.rule}`,
                  borderBottom: sel ? `2px solid ${BAU.ink}` : '2px solid transparent',
                  padding: '12px 8px 10px',
                  cursor: 'pointer',
                  fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.16em',
                  textTransform: 'uppercase',
                  transition: 'background 0.15s var(--ease-out), color 0.15s var(--ease-out)',
                }}>{labelMap[id]}</button>
              );
            })}
          </div>

          {/* Body */}
          <div style={{ flex: 1, overflowY: 'auto', padding: '20px 24px' }}>
            {tab === 'owned'    && <OwnedWorks account={account} catalogue={catalogue} onPickWork={onPickWork} />}
            {tab === 'inbox'    && <Inbox account={account} role={role} catalogue={catalogue} />}
            {tab === 'receipts' && <ReceiptsTab account={account} role={role} onPickCollector={onPickCollector} />}
            {tab === 'cards'    && <CardsTab account={account} />}
            {tab === 'payouts'  && <PayoutsTab account={account} />}
            {tab === 'saved'    && <SavedTab savedIds={savedIds} catalogue={catalogue} onPickWork={onPickWork} />}
          </div>
        </div>
      </div>
    );
  }

  // ── Owned works tab ─────────────────────────────────────────────────
  function OwnedWorks({ account, catalogue, onPickWork }) {
    if (!account) return <Empty kind="Not signed in" body="Sign in to see what you've collected." />;
    const owned = ownedWorksForBuyer(account.id);
    if (!owned.length) return (
      <Empty kind="No owned works yet"
        body="Open any artwork on the atlas, click the artist's name, and use Commission similar →. Your purchases and commissioned works land here." />
    );
    const findInCatalogue = (id) => catalogue?.find((w) => w.id === id);
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <SectionDescription
          title="Owned works"
          body="Pieces you've commissioned or purchased. Click a card to open the work in the atlas." />
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))', gap: 12 }}>
          {owned.map(({ order, workId, workTitle, workImage, artistName, status }) => {
            const work = findInCatalogue(workId);
            return (
              <button key={order.id} onClick={() => work && onPickWork && onPickWork(work)} style={{
                background: BAU.paper, border: `1px solid ${BAU.ink}`,
                padding: 0, cursor: work ? 'pointer' : 'default', textAlign: 'left',
                display: 'flex', flexDirection: 'column',
              }}>
                <div style={{ width: '100%', aspectRatio: '1', overflow: 'hidden', background: BAU.paper2 }}>
                  {workImage ? (
                    <img src={workImage} alt={workTitle || ''} style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
                  ) : work ? (
                    <ArtTile work={work} width={180} height={180} />
                  ) : null}
                </div>
                <div style={{ padding: '10px 12px' }}>
                  <div style={{ fontFamily: 'var(--mono)', fontSize: 9, letterSpacing: '0.14em', color: order.type === 'commission' ? BAU.red : BAU.blue, textTransform: 'uppercase' }}>
                    ● {status}
                  </div>
                  <div style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 14, color: BAU.ink, marginTop: 4, lineHeight: 1.2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                    {workTitle || 'Untitled'}
                  </div>
                  <div style={{ fontFamily: 'var(--sans)', fontSize: 11, color: BAU.graphite }}>
                    {artistName} · €{order.amount.toLocaleString()}
                  </div>
                </div>
              </button>
            );
          })}
        </div>
      </div>
    );
  }

  // ── Inbox tab ───────────────────────────────────────────────────────
  function Inbox({ account, role, catalogue }) {
    if (!account) return <Empty kind="Not signed in" body="Sign in to message artists." />;
    const threads = useThreads(account.id);
    const [active, setActive] = React.useState(null);
    const activeThread = active ? threads.find((t) => t.otherId === active.otherId) : null;

    if (!threads.length && !active) {
      return (
        <Empty kind={role === 'artist' ? 'No briefs yet' : 'Inbox empty'}
          body={role === 'artist'
            ? 'When a collector commissions a work from you, the conversation lands here.'
            : 'When you commission an artist, you can talk to them here. Open an artwork → artist profile → Send a brief.'} />
      );
    }

    if (active && activeThread !== undefined) {
      return <Conversation account={account} catalogue={catalogue}
        otherId={active.otherId} otherName={active.otherName}
        thread={activeThread || { msgs: [] }}
        onBack={() => setActive(null)} />;
    }

    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        <SectionDescription
          title="Conversations"
          body={role === 'artist' ? 'Briefs from collectors. Replies are mocked in this demo.'
                                  : 'Threads with artists you\'ve commissioned. Replies are mocked in this demo.'} />
        {threads.map((t) => {
          const last = t.msgs[t.msgs.length - 1];
          const otherName = last?.fromName || (catalogue || []).find((w) => w.artistId === t.otherId || w.artist === t.otherId)?.artist || t.otherId;
          return (
            <button key={t.key} onClick={() => setActive({ otherId: t.otherId, otherName })} style={{
              textAlign: 'left',
              padding: '12px 14px',
              background: BAU.paper, border: `1px solid ${BAU.rule}`,
              cursor: 'pointer',
              display: 'flex', flexDirection: 'column', gap: 4,
            }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <span style={{ width: 8, height: 8, borderRadius: '50%', background: BAU.red }} />
                <span style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 16 }}>{otherName}</span>
                <span style={{ marginLeft: 'auto', fontFamily: 'var(--mono)', fontSize: 9, color: BAU.graphite }}>
                  {last ? new Date(last.ts).toLocaleDateString() : ''}
                </span>
              </div>
              {last && (
                <div style={{ fontFamily: 'var(--sans)', fontSize: 12.5, color: BAU.graphite, lineHeight: 1.4, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                  {last.from === account.id ? 'You: ' : ''}{last.text}
                </div>
              )}
            </button>
          );
        })}
      </div>
    );
  }

  function Conversation({ account, otherId, otherName, thread, onBack }) {
    const [draft, setDraft] = React.useState('');
    const send = () => {
      if (!draft.trim()) return;
      postMessage(account.id, otherId, otherName, draft.trim());
      setDraft('');
    };
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10, height: '100%' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <button onClick={onBack} style={{
            background: 'transparent', border: `1px solid ${BAU.ink}`,
            padding: '6px 10px', cursor: 'pointer', color: BAU.ink,
            fontFamily: 'var(--mono)', fontSize: 9.5, letterSpacing: '0.14em', textTransform: 'uppercase',
          }}>← Inbox</button>
          <div style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 18 }}>{otherName}</div>
        </div>
        <div style={{ flex: 1, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 8, padding: '6px 0' }}>
          {thread.msgs.map((m) => {
            const mine = m.from === account.id;
            return (
              <div key={m.id} style={{
                alignSelf: mine ? 'flex-end' : 'flex-start',
                maxWidth: '78%',
                padding: '10px 12px',
                background: mine ? BAU.ink : BAU.paper2,
                color: mine ? BAU.paper : BAU.ink,
                border: mine ? 'none' : `1px solid ${BAU.rule}`,
                fontFamily: 'var(--serif)', fontSize: 14, fontStyle: 'italic',
                lineHeight: 1.4,
              }}>
                {m.text}
                <div style={{ marginTop: 4, fontFamily: 'var(--mono)', fontStyle: 'normal', fontSize: 9, opacity: 0.7 }}>
                  {new Date(m.ts).toLocaleString()}
                </div>
              </div>
            );
          })}
        </div>
        <div style={{ borderTop: `1px solid ${BAU.rule}`, paddingTop: 10 }}>
          <textarea value={draft} onChange={(e) => setDraft(e.target.value)}
            placeholder="Write a message…"
            onKeyDown={(e) => { if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) send(); }}
            style={{
              width: '100%', boxSizing: 'border-box',
              minHeight: 70, resize: 'none',
              border: `1px solid ${BAU.rule}`, padding: 10,
              fontFamily: 'var(--serif)', fontSize: 14, fontStyle: 'italic',
              color: BAU.ink, outline: 'none', background: BAU.paper2,
            }} />
          <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: 6 }}>
            <button onClick={send} disabled={!draft.trim()} style={{
              background: draft.trim() ? BAU.ink : BAU.graphite,
              color: BAU.paper, border: 'none',
              padding: '8px 16px', cursor: draft.trim() ? 'pointer' : 'not-allowed',
              fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.16em', textTransform: 'uppercase',
            }}>Send →</button>
          </div>
        </div>
      </div>
    );
  }

  // ── Receipts tab ────────────────────────────────────────────────────
  function ReceiptsTab({ account, role, onPickCollector }) {
    if (!account) return <Empty kind="Not signed in" body="Sign in to see receipts." />;
    const orders = window.useOrders ? window.useOrders() : [];
    const mine = orders.filter((o) =>
      role === 'artist' ? o.artistId === account.id : o.buyerId === account.id
    );
    if (!mine.length) return (
      <Empty kind="No receipts yet"
        body={role === 'artist'
          ? 'Sales and commissions appear here once a collector pays.'
          : 'Every commission, donation, and purchase you make will land here with a receipt.'} />
    );
    const totals = mine.reduce((acc, o) => { acc[o.type] = (acc[o.type] || 0) + o.amount; return acc; }, {});
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <SectionDescription title="Receipts" body="Every transaction with full details. Click a row to view the receipt panel." />
        <div style={{
          display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)',
          border: `1px solid ${BAU.rule}`,
        }}>
          {[
            { key: 'commission', label: 'Commissions', color: BAU.red },
            { key: 'purchase',   label: 'Purchases',   color: BAU.blue },
            { key: 'donate',     label: 'Donations',   color: BAU.yellow },
          ].map((t, i, arr) => (
            <div key={t.key} style={{
              padding: '14px 16px',
              borderRight: i < arr.length - 1 ? `1px solid ${BAU.rule}` : 'none',
              position: 'relative',
            }}>
              <div style={{ position: 'absolute', top: 0, left: 0, width: 18, height: 3, background: t.color }} />
              <div style={{ fontFamily: 'var(--mono)', fontSize: 9, letterSpacing: '0.18em', color: BAU.graphite, textTransform: 'uppercase' }}>{t.label}</div>
              <div style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 24, color: BAU.ink, marginTop: 4 }}>€{(totals[t.key] || 0).toLocaleString()}</div>
            </div>
          ))}
        </div>
        {mine.map((o) => <ReceiptRow key={o.id} order={o} role={role} onPickCollector={onPickCollector} />)}
      </div>
    );
  }

  function ReceiptRow({ order, role, onPickCollector }) {
    const [open, setOpen] = React.useState(false);
    const date = new Date(order.createdAt).toLocaleString();
    const accentByType = { commission: BAU.red, purchase: BAU.blue, donate: BAU.yellow };
    const isArtistView = role === 'artist';
    return (
      <div style={{ border: `1px solid ${BAU.rule}`, background: BAU.paper }}>
        <button onClick={() => setOpen((v) => !v)} style={{
          width: '100%', textAlign: 'left',
          padding: '10px 14px', background: 'transparent', border: 'none', cursor: 'pointer',
          display: 'grid', gridTemplateColumns: '1fr auto', gap: 10, alignItems: 'center',
        }}>
          <div style={{ minWidth: 0 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <span style={{ width: 6, height: 6, background: accentByType[order.type] || BAU.ink }} />
              <span style={{ fontFamily: 'var(--mono)', fontSize: 9, letterSpacing: '0.14em', color: BAU.graphite, textTransform: 'uppercase' }}>{order.type}</span>
              <span style={{ fontFamily: 'var(--mono)', fontSize: 9.5, color: BAU.graphite }}>{date}</span>
            </div>
            <div style={{ marginTop: 3, fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 14, color: BAU.ink, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
              {isArtistView && onPickCollector && order.buyerId ? (
                <span onClick={(e) => { e.stopPropagation(); onPickCollector({ ownerId: order.buyerId }); }}
                  style={{ borderBottom: `1px solid ${BAU.ink}`, cursor: 'pointer' }}>
                  From {order.buyerName}
                </span>
              ) : (
                isArtistView ? `From ${order.buyerName}` : `To ${order.artistName}`
              )}
              {order.workTitle ? ` · ${order.workTitle}` : ''}
            </div>
          </div>
          <div style={{ textAlign: 'right' }}>
            <div style={{ fontFamily: 'var(--mono)', fontSize: 12, color: BAU.ink }}>€{order.amount.toLocaleString()}</div>
            <div style={{ fontFamily: 'var(--mono)', fontSize: 9, color: BAU.graphite }}>{order.id}</div>
          </div>
        </button>
        {open && (
          <div style={{ borderTop: `1px solid ${BAU.rule}`, padding: 14, background: BAU.paper2, display: 'flex', flexDirection: 'column', gap: 6, fontFamily: 'var(--mono)', fontSize: 11, color: BAU.ink }}>
            <ReceiptKv k="Type" v={order.type} />
            <ReceiptKv k="Amount" v={`€${order.amount.toLocaleString()} ${order.currency || 'EUR'}`} />
            <ReceiptKv k="From" v={order.buyerName + (order.buyerEmail ? ` · ${order.buyerEmail}` : '')} />
            <ReceiptKv k="To" v={order.artistName} />
            {order.workTitle && <ReceiptKv k="Work" v={order.workTitle} />}
            {order.brief && <ReceiptKv k="Brief" v={order.brief} />}
            {order.size && <ReceiptKv k="Size" v={order.size} />}
            {order.note && <ReceiptKv k="Note" v={order.note} />}
            <ReceiptKv k="Card" v={`${order.card?.brand || ''} ····${order.card?.last4 || ''} (${order.card?.exp || ''})`} />
            <ReceiptKv k="Status" v={order.status || 'paid'} />
            <ReceiptKv k="Transaction" v={order.id} />
          </div>
        )}
      </div>
    );
  }

  function ReceiptKv({ k, v }) {
    return (
      <div style={{ display: 'grid', gridTemplateColumns: '110px 1fr', gap: 10 }}>
        <span style={{ color: BAU.graphite, textTransform: 'uppercase', letterSpacing: '0.14em', fontSize: 10 }}>{k}</span>
        <span style={{ color: BAU.ink, fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 13 }}>{v}</span>
      </div>
    );
  }

  // ── Saved cards tab (collectors) ────────────────────────────────────
  function CardsTab({ account }) {
    if (!account) return <Empty kind="Not signed in" body="Sign in to manage payment methods." />;
    const cards = window.useSavedCards ? window.useSavedCards(account.id) : [];
    const [adding, setAdding] = React.useState(false);
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <SectionDescription
          title="Payment methods"
          body="Cards you've saved for one-tap commissions and donations. We never store the full number or CVC." />
        {cards.map((c) => (
          <div key={c.id} style={{
            display: 'flex', alignItems: 'center', gap: 14,
            padding: '12px 14px',
            border: `1px solid ${BAU.rule}`, background: BAU.paper,
          }}>
            <div style={{
              width: 42, height: 28,
              background: BAU.ink, color: BAU.paper,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontFamily: 'var(--mono)', fontSize: 9, letterSpacing: '0.1em',
            }}>{c.brand.slice(0, 4).toUpperCase()}</div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontFamily: 'var(--mono)', fontSize: 12, color: BAU.ink }}>
                {c.brand} ····{c.last4}
                {c.label && <span style={{ marginLeft: 8, fontStyle: 'italic', color: BAU.graphite }}>{c.label}</span>}
              </div>
              <div style={{ fontFamily: 'var(--mono)', fontSize: 9.5, color: BAU.graphite }}>
                {c.holder} · exp {c.expMonth}/{String(c.expYear).slice(-2)}
              </div>
            </div>
            <button onClick={() => window.AN_PAY.removeCard(c.id)} style={{
              background: 'transparent', color: BAU.red, border: `1px solid ${BAU.red}`,
              padding: '5px 10px', cursor: 'pointer',
              fontFamily: 'var(--mono)', fontSize: 9, letterSpacing: '0.14em', textTransform: 'uppercase',
            }}>Remove</button>
          </div>
        ))}
        {adding ? (
          <CardForm onCancel={() => setAdding(false)} onSave={(draft) => {
            window.AN_PAY.addCard(account.id, draft);
            setAdding(false);
          }} />
        ) : (
          <button onClick={() => setAdding(true)} style={{
            background: 'transparent', color: BAU.ink, border: `1px dashed ${BAU.ink}`,
            padding: '14px', cursor: 'pointer',
            fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase',
          }}>+ Add a card</button>
        )}
      </div>
    );
  }

  function CardForm({ onCancel, onSave }) {
    const [draft, setDraft] = React.useState({
      holder: '', number: '', expMonth: '', expYear: '', label: '',
    });
    const [error, setError] = React.useState(null);
    const save = () => {
      try { onSave(draft); } catch (e) { setError(e.message); }
    };
    const ip = (k, v) => setDraft((d) => ({ ...d, [k]: v }));
    return (
      <div style={{
        border: `1px solid ${BAU.ink}`, background: BAU.paper2,
        padding: 14, display: 'flex', flexDirection: 'column', gap: 10,
      }}>
        <Row label="Cardholder name">
          <input value={draft.holder} onChange={(e) => ip('holder', e.target.value)} placeholder="As printed on the card"
            style={inputStyle()} />
        </Row>
        <Row label="Card number">
          <input value={draft.number} onChange={(e) => ip('number', e.target.value.replace(/\D/g, '').slice(0, 19))}
            placeholder="4242 4242 4242 4242" inputMode="numeric"
            style={inputStyle()} />
        </Row>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10 }}>
          <Row label="Exp MM"><input value={draft.expMonth} onChange={(e) => ip('expMonth', e.target.value.replace(/\D/g, '').slice(0, 2))} style={inputStyle()} placeholder="MM" /></Row>
          <Row label="Exp YYYY"><input value={draft.expYear} onChange={(e) => ip('expYear', e.target.value.replace(/\D/g, '').slice(0, 4))} style={inputStyle()} placeholder="YYYY" /></Row>
          <Row label="Label (optional)"><input value={draft.label} onChange={(e) => ip('label', e.target.value)} style={inputStyle()} placeholder="Personal, Studio…" /></Row>
        </div>
        {error && <div style={errStyle()}>{error}</div>}
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
          <button onClick={onCancel} style={btnGhost()}>Cancel</button>
          <button onClick={save} style={btnSolid()}>Save card</button>
        </div>
      </div>
    );
  }

  // ── Payout methods tab (artists) ────────────────────────────────────
  function PayoutsTab({ account }) {
    if (!account) return <Empty kind="Not signed in" body="Sign in to manage payout methods." />;
    const list = window.usePayoutMethods ? window.usePayoutMethods(account.id) : [];
    const [adding, setAdding] = React.useState(false);
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <SectionDescription
          title="Payout methods"
          body="Where mariusson deposits your sales and commission fees. Bank transfer, IBAN, or PayPal." />
        {list.map((p) => (
          <div key={p.id} style={{
            display: 'flex', alignItems: 'center', gap: 14,
            padding: '12px 14px', border: `1px solid ${BAU.rule}`, background: BAU.paper,
          }}>
            <div style={{
              width: 56, height: 28, background: BAU.ink, color: BAU.paper,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontFamily: 'var(--mono)', fontSize: 9, letterSpacing: '0.14em', textTransform: 'uppercase',
            }}>{p.kind}</div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontFamily: 'var(--mono)', fontSize: 12, color: BAU.ink }}>
                {p.kind.toUpperCase()} ····{p.tail}
                {p.label && <span style={{ marginLeft: 8, fontStyle: 'italic', color: BAU.graphite }}>{p.label}</span>}
              </div>
              <div style={{ fontFamily: 'var(--mono)', fontSize: 9.5, color: BAU.graphite }}>
                {p.holder}{p.country ? ` · ${p.country}` : ''}
              </div>
            </div>
            <button onClick={() => window.AN_PAY.removePayout(p.id)} style={{
              background: 'transparent', color: BAU.red, border: `1px solid ${BAU.red}`,
              padding: '5px 10px', cursor: 'pointer',
              fontFamily: 'var(--mono)', fontSize: 9, letterSpacing: '0.14em', textTransform: 'uppercase',
            }}>Remove</button>
          </div>
        ))}
        {adding ? (
          <PayoutForm onCancel={() => setAdding(false)} onSave={(draft) => {
            window.AN_PAY.addPayout(account.id, draft);
            setAdding(false);
          }} />
        ) : (
          <button onClick={() => setAdding(true)} style={{
            background: 'transparent', color: BAU.ink, border: `1px dashed ${BAU.ink}`,
            padding: '14px', cursor: 'pointer',
            fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase',
          }}>+ Add a payout method</button>
        )}
      </div>
    );
  }

  function PayoutForm({ onCancel, onSave }) {
    const [draft, setDraft] = React.useState({
      kind: 'bank', holder: '', account: '', country: '', label: '',
    });
    const [error, setError] = React.useState(null);
    const save = () => {
      try { onSave(draft); } catch (e) { setError(e.message); }
    };
    const ip = (k, v) => setDraft((d) => ({ ...d, [k]: v }));
    return (
      <div style={{
        border: `1px solid ${BAU.ink}`, background: BAU.paper2,
        padding: 14, display: 'flex', flexDirection: 'column', gap: 10,
      }}>
        <Row label="Method">
          <select value={draft.kind} onChange={(e) => ip('kind', e.target.value)} style={inputStyle()}>
            <option value="bank">Bank transfer</option>
            <option value="iban">IBAN</option>
            <option value="paypal">PayPal</option>
            <option value="stripe">Stripe Connect</option>
          </select>
        </Row>
        <Row label="Account holder">
          <input value={draft.holder} onChange={(e) => ip('holder', e.target.value)} style={inputStyle()}
            placeholder="As printed on the account" />
        </Row>
        <Row label={draft.kind === 'paypal' ? 'PayPal email' : draft.kind === 'iban' ? 'IBAN' : 'Account number / ID'}>
          <input value={draft.account} onChange={(e) => ip('account', e.target.value)} style={inputStyle()}
            placeholder={draft.kind === 'paypal' ? 'studio@…' : draft.kind === 'iban' ? 'GB00 BANK 0000 0000 0000 00' : 'Account number'} />
        </Row>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
          <Row label="Country (ISO)"><input value={draft.country} onChange={(e) => ip('country', e.target.value.toUpperCase().slice(0, 2))} style={inputStyle()} placeholder="GB" /></Row>
          <Row label="Label (optional)"><input value={draft.label} onChange={(e) => ip('label', e.target.value)} style={inputStyle()} placeholder="Studio account" /></Row>
        </div>
        {error && <div style={errStyle()}>{error}</div>}
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
          <button onClick={onCancel} style={btnGhost()}>Cancel</button>
          <button onClick={save} style={btnSolid()}>Save method</button>
        </div>
      </div>
    );
  }

  // ── Saved tab ────────────────────────────────────────────────────────
  function SavedTab({ savedIds, catalogue, onPickWork }) {
    const ids = [...(savedIds || new Set())];
    if (!ids.length) {
      return <Empty kind="Nothing saved yet"
        body="Click the star on any artwork to save it here. Saves are private to you." />;
    }
    const works = ids.map((id) => (catalogue || []).find((w) => w.id === id)).filter(Boolean);
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <SectionDescription title="Saved works" body="Tiles you've starred. Click any to open it on the atlas." />
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(150px, 1fr))', gap: 10 }}>
          {works.map((w) => (
            <button key={w.id} onClick={() => onPickWork && onPickWork(w)} style={{
              padding: 0, background: BAU.paper, border: `1px solid ${BAU.ink}`,
              cursor: 'pointer', display: 'flex', flexDirection: 'column', textAlign: 'left',
            }}>
              <div style={{ aspectRatio: '1', overflow: 'hidden' }}>
                <ArtTile work={w} width={150} height={150} />
              </div>
              <div style={{ padding: '6px 8px' }}>
                <div style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 12, color: BAU.ink, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{w.title}</div>
                <div style={{ fontFamily: 'var(--mono)', fontSize: 9, color: BAU.graphite }}>{w.artist}</div>
              </div>
            </button>
          ))}
        </div>
      </div>
    );
  }

  // ── Shared tiny components ──────────────────────────────────────────
  function SectionDescription({ title, body }) {
    return (
      <div>
        <div style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 20, color: BAU.ink, lineHeight: 1.1 }}>{title}</div>
        <div style={{ marginTop: 4, fontFamily: 'var(--sans)', fontSize: 12.5, color: BAU.graphite, lineHeight: 1.5 }}>{body}</div>
      </div>
    );
  }
  function Empty({ kind, body }) {
    return (
      <div style={{
        padding: '24px 18px',
        border: `2px dashed ${BAU.rule}`, background: BAU.paper2,
        textAlign: 'center', color: BAU.graphite,
      }}>
        <div style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase' }}>{kind}</div>
        <div style={{ marginTop: 8, fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 14, color: BAU.ink, lineHeight: 1.5 }}>{body}</div>
      </div>
    );
  }
  function Row({ label, children }) {
    return (
      <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
        <span style={{ fontFamily: 'var(--mono)', fontSize: 9, letterSpacing: '0.18em', color: BAU.graphite, textTransform: 'uppercase' }}>{label}</span>
        {children}
      </label>
    );
  }

  // Styles are wrapped in getter functions because BAU is defined in
  // atlas.jsx, which loads AFTER this file. Evaluating these at IIFE-time
  // would crash with "BAU is not defined". Functions defer evaluation
  // until they're called from a component (where BAU is already on
  // the window via Babel's var-hoisting).
  function inputStyle() {
    return {
      width: '100%', boxSizing: 'border-box',
      border: `1px solid ${BAU.rule}`, background: BAU.paper,
      padding: '8px 10px',
      fontFamily: 'var(--sans)', fontSize: 13, color: BAU.ink, outline: 'none',
    };
  }
  function errStyle() {
    return {
      fontFamily: 'var(--mono)', fontSize: 10, color: BAU.red,
      padding: '6px 10px', border: `1px solid ${BAU.red}`,
      background: 'rgba(230,57,70,0.06)',
    };
  }
  function btnGhost() {
    return {
      background: 'transparent', color: BAU.ink, border: `1px solid ${BAU.ink}`,
      padding: '8px 14px', cursor: 'pointer',
      fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.16em', textTransform: 'uppercase',
    };
  }
  function btnSolid() {
    return {
      background: BAU.ink, color: BAU.paper, border: 'none',
      padding: '8px 14px', cursor: 'pointer',
      fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.16em', textTransform: 'uppercase',
    };
  }

  window.StudioDrawer = StudioDrawer;
  window.AN_STUDIO = { listThreadsForUser, getThread, postMessage, ownedWorksForBuyer };
})();
