/* Conversations workspace — the platform's centerpiece.
   3-pane: inbox left · thread center · contact / account / AI copilot right (tabbed) */

const { useState: useStateConv, useRef: useRefConv, useEffect: useEffectConv } = React;

function PageConversations({ initialConversationId, onNavigate }) {
  const [activeId, setActiveId] = useStateConv(initialConversationId || CONVERSATIONS[0]?.id || null);
  const [folder, setFolder] = useStateConv("all"); /* all | unread | mine | drafts */
  const [conversations, setConversations] = useStateConv(CONVERSATIONS);
  const active = conversations.find(c => c.id === activeId) || conversations[0] || null;

  /* Empty state — no conversations data is currently available. The
     conversations service isn't wired to a live backend endpoint yet,
     so this list stays empty until that ships. */
  if (conversations.length === 0) {
    return (
      <>
        <PageHeader title="Conversations" />
        <div style={{ padding: "80px 24px", display: "flex", flexDirection: "column", alignItems: "center", textAlign: "center", color: "var(--ink-3)" }}>
          <div style={{
            width: 56, height: 56, borderRadius: 14,
            background: "var(--inset)", color: "var(--ink-3)",
            display: "flex", alignItems: "center", justifyContent: "center",
            marginBottom: 16,
          }}>
            <Icon name="messages" size={26} />
          </div>
          <div style={{ fontSize: 16, fontWeight: 600, color: "var(--ink)", marginBottom: 6 }}>
            No conversations yet
          </div>
          <div style={{ fontSize: 13, color: "var(--ink-3)", maxWidth: 360, lineHeight: 1.55 }}>
            Conversations will appear here once the backend ships a <span className="mono">/conversations</span> endpoint.
            Sample messages, AI summaries, and touchpoint timelines were removed when the static seed was cleared.
          </div>
        </div>
      </>
    );
  }

  /* Filter inbox by folder, then sort by most recent activity */
  const inboxList = conversations.filter(c => {
    if (folder === "unread") return c.unread;
    if (folder === "mine")   return true;
    if (folder === "drafts") return c.messages.some(m => m.status === "draft");
    return true;
  }).slice().sort((a, b) => new Date(b.lastActivityAt) - new Date(a.lastActivityAt));

  return (
    <>
      <PageHeader
        title="Conversations"
        actions={active ? <ConversationActions conversation={active} /> : null}
      />
      <div className="conv-grid">
      <div className="conv-inbox" style={{ display: "contents" }}>
        <ConversationsInbox
          list={inboxList} activeId={activeId} onPick={setActiveId}
          folder={folder} onFolder={setFolder}
          totals={conversations}
        />
      </div>
      <ConversationThread
        conversation={active}
        onSend={(msg) => {
          setConversations(prev => prev.map(c => c.id !== active.id ? c : {
            ...c,
            messages: [...c.messages, msg],
            lastActivityAt: msg.at,
            unread: false,
          }));
        }}
        onMarkDraftSent={(msgId) => {
          setConversations(prev => prev.map(c => c.id !== active.id ? c : {
            ...c,
            messages: c.messages.map(m => m.id !== msgId ? m : { ...m, status: "sent" }),
          }));
        }}
      />
      <div className="conv-context" style={{ display: "contents" }}>
        <ConversationContextPanel conversation={active} onNavigate={onNavigate} />
      </div>
    </div>
    </>
  );
}

/* ────────────────────────────────────────────────────────────────────────
   Inbox (left pane)
   ──────────────────────────────────────────────────────────────────────── */
function ConversationsInbox({ list, activeId, onPick, folder, onFolder, totals }) {
  /* Local filter state — applied AFTER folder filtering. */
  const [filtersOpen, setFiltersOpen] = useStateConv(false);
  const [filters, setFilters] = useStateConv({
    channels: [],          /* empty = all */
    statuses: ["active"],  /* default to active threads only */
    insights: [],
    owners: [],
    range: "all",          /* all | 7d | 30d | quarter */
    unreadOnly: false,
    hasDraft: false,
  });

  /* Apply secondary filters on top of the folder-filtered list passed in. */
  const NOW = Date.now();
  const RANGE_MS = { "7d": 7 * 86400e3, "30d": 30 * 86400e3, "quarter": 90 * 86400e3 };
  const filtered = list.filter(c => {
    if (filters.channels.length && !c.channels.some(ch => filters.channels.includes(ch))) return false;
    if (filters.statuses.length && !filters.statuses.includes(c.status || "active")) return false;
    if (filters.unreadOnly && !c.unread) return false;
    if (filters.hasDraft && !c.messages.some(m => m.status === "draft")) return false;
    if (filters.insights.length && !(c.aiInsights || []).some(i => filters.insights.includes(i.type))) return false;
    if (filters.range !== "all") {
      const cutoff = NOW - (RANGE_MS[filters.range] || 0);
      if (new Date(c.lastActivityAt).getTime() < cutoff) return false;
    }
    return true;
  });

  const activeFilterCount =
    filters.channels.length +
    (filters.statuses.length !== 1 || filters.statuses[0] !== "active" ? 1 : 0) +
    filters.insights.length +
    (filters.unreadOnly ? 1 : 0) +
    (filters.hasDraft ? 1 : 0) +
    (filters.range !== "all" ? 1 : 0);

  return (
    <div style={{
      borderRight: "1px solid var(--line)",
      background: "var(--surface)",
      display: "flex", flexDirection: "column", minHeight: 0, height: "100%",
    }}>
      <div style={{
        padding: "12px 14px",
        borderBottom: "1px solid var(--line)",
        display: "flex", alignItems: "center", gap: 10,
        height: 61, /* match thread header (12 + 36 avatar + 12 + 1 border) */
        flexShrink: 0,
      }}>
        <h2 style={{ fontSize: 14, fontWeight: 600, margin: 0, flexShrink: 0 }}>Inbox</h2>
        <div style={{ flex: 1, minWidth: 0 }}>
          <TextField icon="search" placeholder="Search…" size="sm" />
        </div>
        <div style={{ position: "relative" }}>
          <IconButton icon="sliders" title="Filters" onClick={() => setFiltersOpen(true)} active={activeFilterCount > 0} />
          {activeFilterCount > 0 && (
            <span style={{
              position: "absolute", top: -2, right: -2,
              minWidth: 14, height: 14, padding: "0 3px",
              borderRadius: 7,
              background: "var(--accent)", color: "#fff",
              fontSize: 9, fontWeight: 700,
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              pointerEvents: "none",
              border: "1.5px solid var(--surface)",
              lineHeight: 1,
            }} className="num">{activeFilterCount}</span>
          )}
        </div>
      </div>
      <div style={{
        height: 36, boxSizing: "border-box",
        padding: "0 10px",
        borderBottom: "1px solid var(--line)",
        display: "flex", alignItems: "center", gap: 4, fontSize: 12,
      }}>
        {[
          { id: "all",    label: "All",     count: totals.length },
          { id: "unread", label: "Unread",  count: totals.filter(c => c.unread).length },
          { id: "mine",   label: "Mine",    count: totals.length },
          { id: "drafts", label: "Drafts",  count: totals.filter(c => c.messages.some(m => m.status === "draft")).length },
        ].map(f => (
          <button key={f.id} onClick={() => onFolder(f.id)} style={{
            padding: "4px 8px", borderRadius: 5,
            display: "inline-flex", alignItems: "center", gap: 5,
            color: folder === f.id ? "var(--ink)" : "var(--ink-3)",
            background: folder === f.id ? "var(--inset)" : "transparent",
            fontWeight: folder === f.id ? 600 : 500,
            fontSize: 12,
          }}>
            {f.label}
            {f.count > 0 && <span className="mono num" style={{ color: "var(--ink-4)", fontSize: 11 }}>{f.count}</span>}
          </button>
        ))}
      </div>

      <div data-conv-scroll style={{ flex: 1, overflowY: "auto" }}>
        {filtered.length === 0 ? (
          <div style={{ padding: "40px 18px", textAlign: "center", color: "var(--ink-3)", fontSize: 12.5 }}>
            <Icon name="search" size={20} style={{ color: "var(--ink-4)", marginBottom: 8 }} />
            <div style={{ fontWeight: 600, color: "var(--ink-2)", marginBottom: 4 }}>No matches</div>
            <div>Try removing a filter.</div>
          </div>
        ) : filtered.map(c => <InboxRow key={c.id} c={c} active={c.id === activeId} onClick={() => onPick(c.id)} />)}
      </div>

      <InboxFiltersModal
        open={filtersOpen}
        onClose={() => setFiltersOpen(false)}
        filters={filters}
        setFilters={setFilters}
      />
    </div>
  );
}

/* Filters modal — channels, statuses, AI insights, recency. */
function InboxFiltersModal({ open, onClose, filters, setFilters }) {
  const toggle = (key, value) => {
    setFilters(prev => {
      const arr = prev[key];
      return { ...prev, [key]: arr.includes(value) ? arr.filter(v => v !== value) : [...arr, value] };
    });
  };
  const set = (key, value) => setFilters(prev => ({ ...prev, [key]: value }));

  const reset = () => setFilters({
    channels: [], statuses: ["active"], insights: [], owners: [],
    range: "all", unreadOnly: false, hasDraft: false,
  });

  return (
    <window.Modal
      open={open}
      onClose={onClose}
      icon="sliders"
      title="Filter inbox"
      subtitle="Narrow down which conversations are surfaced."
      width={520}
      footer={<>
        <Button kind="ghost" onClick={reset}>Reset</Button>
        <div style={{ flex: 1 }} />
        <Button kind="primary" onClick={onClose}>Done</Button>
      </>}
    >
      <FilterGroup label="Channel">
        {[
          { id: "linkedin", label: "LinkedIn" },
          { id: "email",    label: "Email" },
          { id: "sms",      label: "SMS" },
          { id: "whatsapp", label: "WhatsApp" },
          { id: "calendar", label: "Calendar" },
        ].map(opt => (
          <FilterChip
            key={opt.id}
            active={filters.channels.includes(opt.id)}
            onClick={() => toggle("channels", opt.id)}
            icon={<ChannelIcon channel={opt.id} size={12} />}
          >{opt.label}</FilterChip>
        ))}
      </FilterGroup>

      <FilterGroup label="Status">
        {[
          { id: "active",   label: "Active",   tone: "green" },
          { id: "snoozed",  label: "Snoozed",  tone: "warm" },
          { id: "archived", label: "Archived", tone: "neutral" },
        ].map(opt => (
          <FilterChip
            key={opt.id}
            active={filters.statuses.includes(opt.id)}
            onClick={() => toggle("statuses", opt.id)}
            tone={opt.tone}
          >{opt.label}</FilterChip>
        ))}
      </FilterGroup>

      <FilterGroup label="AI signals">
        {[
          { id: "buying_signal",        label: "Buying signal",   icon: "trending-up" },
          { id: "recommended_action",   label: "Recommended action", icon: "target" },
          { id: "weak_signal",          label: "Weak signal",     icon: "zap" },
        ].map(opt => (
          <FilterChip
            key={opt.id}
            active={filters.insights.includes(opt.id)}
            onClick={() => toggle("insights", opt.id)}
            icon={<Icon name={opt.icon} size={11} />}
          >{opt.label}</FilterChip>
        ))}
      </FilterGroup>

      <FilterGroup label="Last activity">
        {[
          { id: "all",     label: "Any time" },
          { id: "7d",      label: "Last 7 days" },
          { id: "30d",     label: "Last 30 days" },
          { id: "quarter", label: "This quarter" },
        ].map(opt => (
          <FilterChip
            key={opt.id}
            active={filters.range === opt.id}
            onClick={() => set("range", opt.id)}
          >{opt.label}</FilterChip>
        ))}
      </FilterGroup>

      <FilterGroup label="Other">
        <FilterChip
          active={filters.unreadOnly}
          onClick={() => set("unreadOnly", !filters.unreadOnly)}
          icon={<Icon name="circle-dot" size={11} />}
        >Unread only</FilterChip>
        <FilterChip
          active={filters.hasDraft}
          onClick={() => set("hasDraft", !filters.hasDraft)}
          icon={<Icon name="edit" size={11} />}
        >Has draft</FilterChip>
      </FilterGroup>
    </window.Modal>
  );
}

function FilterGroup({ label, children }) {
  return (
    <div style={{ marginBottom: 16 }}>
      <div style={{
        fontSize: 10.5, fontWeight: 600,
        color: "var(--ink-3)", textTransform: "uppercase",
        letterSpacing: "0.05em", marginBottom: 8,
      }}>{label}</div>
      <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{children}</div>
    </div>
  );
}

function FilterChip({ active, onClick, icon, children, tone }) {
  const toneColors = {
    green:   { bg: "var(--green-soft)",   bd: "var(--green)",   fg: "var(--green-ink)" },
    warm:    { bg: "var(--warm-soft)",    bd: "var(--warm)",    fg: "var(--warm-ink)" },
    neutral: { bg: "var(--inset)",        bd: "var(--ink-4)",   fg: "var(--ink-2)" },
  };
  const c = tone && toneColors[tone];
  return (
    <button onClick={onClick} style={{
      display: "inline-flex", alignItems: "center", gap: 5,
      padding: "5px 10px", borderRadius: 999,
      fontSize: 12, fontWeight: active ? 600 : 500,
      color: active ? (c?.fg || "var(--accent-ink)") : "var(--ink-2)",
      background: active ? (c?.bg || "var(--accent-soft)") : "var(--surface)",
      border: `1px solid ${active ? (c?.bd || "var(--accent)") : "var(--line-strong)"}`,
      transition: "background 120ms, color 120ms, border-color 120ms",
      cursor: "pointer",
    }}>
      {icon}
      {children}
    </button>
  );
}

function InboxRow({ c, active, onClick }) {
  const contact = getContact(c.contactId);
  const company = getCompany(c.companyId);
  const lastMsg = c.messages[c.messages.length - 1];
  const hasDraft = c.messages.some(m => m.status === "draft");
  const preview = lastMsg ? (lastMsg.body || "").replace(/\s+/g, " ").slice(0, 90) : "";

  return (
    <button onClick={onClick} style={{
      display: "block", width: "100%",
      padding: "12px 14px",
      borderBottom: "1px solid var(--line)",
      textAlign: "left",
      background: active ? "var(--inset)" : "transparent",
      borderLeft: active ? "2px solid var(--ink)" : "2px solid transparent",
      transition: "background 120ms",
    }}
    onMouseEnter={(e) => { if (!active) e.currentTarget.style.background = "var(--surface-2)"; }}
    onMouseLeave={(e) => { if (!active) e.currentTarget.style.background = "transparent"; }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 5 }}>
        <Avatar name={contact ? `${contact.firstName} ${contact.lastName}` : c.title} src={contact?.profilePictureUrl} size={28} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
            <span style={{ fontSize: 13, fontWeight: 600, color: "var(--ink)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", flex: 1 }}>
              {contact ? `${contact.firstName} ${contact.lastName}` : c.title}
            </span>
            <span className="mono" style={{ fontSize: 10.5, color: "var(--ink-3)", flexShrink: 0 }}>{fmtRelative(c.lastActivityAt)}</span>
          </div>
          <div style={{ fontSize: 11.5, color: "var(--ink-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
            {[company?.name, contact?.position || c.subtitle].filter(Boolean).join(" · ")}
          </div>
        </div>
      </div>
      <div style={{
        fontSize: 12, color: "var(--ink-3)",
        display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical",
        overflow: "hidden", lineHeight: 1.4, paddingLeft: 38,
      }}>
        {lastMsg && (
          <span style={{ display: "inline-flex", alignItems: "center", gap: 4, marginRight: 4 }}>
            <ChannelIcon channel={lastMsg.channel} size={11} />
          </span>
        )}
        {preview}
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 6, marginTop: 6, paddingLeft: 38 }}>
        {c.unread && <Badge tone="violet" dot size="sm">Unread</Badge>}
        {hasDraft && <Badge tone="warm" size="sm" icon="edit">Draft</Badge>}
        {!c.unread && !hasDraft && lastMsg?.direction === "inbound" && <Badge tone="green" size="sm">Replied</Badge>}
      </div>
    </button>
  );
}

/* ────────────────────────────────────────────────────────────────────────
   Thread (center pane)
   ──────────────────────────────────────────────────────────────────────── */
function ConversationThread({ conversation, onSend, onMarkDraftSent }) {
  const contact = getContact(conversation.contactId);
  const company = getCompany(conversation.companyId);
  const draft   = conversation.messages.find(m => m.status === "draft");
  const [composerOpen, setComposerOpen] = useStateConv(!!draft);
  const [composerText, setComposerText] = useStateConv(draft?.body || "");
  const [composerChannel, setComposerChannel] = useStateConv("linkedin");
  const [composerExpanded, setComposerExpanded] = useStateConv(false);
  const [summaryOpen, setSummaryOpen] = useStateConv(false);

  const handleSend = () => {
    if (!composerText.trim()) return;
    if (draft) {
      onMarkDraftSent(draft.id);
    } else {
      onSend({
        id: "m-" + Math.random().toString(36).slice(2, 8),
        channel: composerChannel,
        direction: "outbound",
        from: CURRENT_USER.id,
        body: composerText,
        at: new Date().toISOString(),
        status: "sent",
      });
    }
    setComposerText("");
    setComposerOpen(false);
  };

  return (
    <div style={{ display: "flex", flexDirection: "column", background: "var(--bg)", minWidth: 0, minHeight: 0, height: "100%" }}>
      {/* Header */}
      <div style={{
        padding: "0 24px",
        height: 61,
        borderBottom: "1px solid var(--line)",
        background: "var(--surface)",
        display: "flex", alignItems: "center", gap: 14, flexShrink: 0,
      }}>
        <Avatar name={contact ? `${contact.firstName} ${contact.lastName}` : conversation.title} src={contact?.profilePictureUrl} size={36} />
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <span style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)" }}>
              {contact ? `${contact.firstName} ${contact.lastName}` : conversation.title}
            </span>
            <Badge tone="green" dot size="sm">Connected</Badge>
          </div>
          <div style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 1 }}>
            {contact?.position} · {company?.name} · {contact?.location}
          </div>
        </div>
        {/* AI Summary trigger — opens a side drawer with the full summary
           and the AI insight list. The inline summary card was moved out
           of the thread so the message feed gets the full vertical space. */}
        <button onClick={() => setSummaryOpen(true)} title="View AI summary" style={{
          display: "inline-flex", alignItems: "center", gap: 6,
          padding: "5px 10px", borderRadius: 999,
          fontSize: 12, fontWeight: 600,
          color: "var(--accent-ink, var(--ink))",
          background: "color-mix(in oklch, var(--accent) 10%, var(--surface))",
          border: "1px solid color-mix(in oklch, var(--accent) 25%, var(--line))",
          flexShrink: 0,
          transition: "filter 120ms",
        }}
        onMouseEnter={(e) => e.currentTarget.style.filter = "brightness(0.96)"}
        onMouseLeave={(e) => e.currentTarget.style.filter = "none"}>
          <Icon name="sparkles" size={12} style={{ color: "var(--accent)" }} />
          AI summary
        </button>
      </div>

      {/* Thread — yields to the composer when expanded so the textarea
         can grow upward instead of pushing the header off-screen. */}
      <div data-conv-scroll style={{
        flex: composerExpanded ? "0 0 0" : 1,
        display: composerExpanded ? "none" : "block",
        overflowY: "auto",
        padding: "20px 24px 24px",
        minHeight: 0,
      }}>
        <div style={{ maxWidth: 720, margin: "0 auto" }}>
          {conversation.messages.length === 0 && (
            <EmptyState icon="messages" title="No messages yet" body="Send the first message to start the conversation." />
          )}
          {groupByDay(conversation.messages).map((group, i) => (
            <DayGroup key={i} day={group.day} messages={group.messages} />
          ))}
        </div>
      </div>

      {/* Composer */}
      <Composer
        contact={contact}
        open={composerOpen}
        onOpen={() => setComposerOpen(true)}
        channel={composerChannel}
        onChannel={setComposerChannel}
        availableChannels={conversation.channels.filter(c => c !== "manual_note")}
        text={composerText}
        onText={setComposerText}
        onSend={handleSend}
        hasDraft={!!draft}
        expanded={composerExpanded}
        onExpandedChange={setComposerExpanded}
      />

      {/* AI summary drawer — opened by the "AI summary" button in the
         header. Renders the full account summary plus any AI insights and
         the touchpoint timeline. */}
      <ConversationSummaryDrawer
        open={summaryOpen}
        onClose={() => setSummaryOpen(false)}
        conversation={conversation}
        contact={contact}
        company={company}
      />
    </div>
  );
}

/* ConversationSummaryDrawer — side drawer with the AI-generated account
   summary, AI insights, relationship summary, and touchpoint timeline.
   Replaces the old sticky summary card that lived inside the thread. */
function ConversationSummaryDrawer({ open, onClose, conversation, contact, company }) {
  if (!conversation) return null;
  const insights   = conversation.aiInsights || [];
  const touchpoints = conversation.touchpoints || [];
  const insightToneOf = (type) => ({
    weak_signal: "blue", buying_signal: "green",
    recommended_action: "violet", risk: "red", note: "neutral",
  })[type] || "neutral";
  const insightLabelOf = (type) => ({
    weak_signal: "Weak signal", buying_signal: "Buying signal",
    recommended_action: "Recommended action", risk: "Risk", note: "Note",
  })[type] || type;

  return (
    <window.SlideOver
      open={open}
      onClose={onClose}
      width={460}
      icon="sparkles"
      title={
        <span style={{ display: "inline-flex", alignItems: "center", gap: 8 }}>
          <span>AI summary</span>
          <AIChip>generated · 2h ago</AIChip>
        </span>
      }
      subtitle={contact ? `${contact.firstName} ${contact.lastName} · ${company?.name || ""}` : conversation.title}
      footer={
        <>
          <Button kind="ghost" size="md" onClick={onClose}>Close</Button>
          <Button size="md" icon="refresh">Regenerate</Button>
        </>
      }
    >
      <div style={{ padding: 18, display: "flex", flexDirection: "column", gap: 18 }}>
        {/* Headline summary */}
        <section>
          <div style={{
            fontSize: 11, fontWeight: 600, color: "var(--ink-3)",
            textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: 8,
          }}>
            Account summary
          </div>
          <div style={{
            padding: "12px 14px",
            background: "linear-gradient(180deg, color-mix(in oklch, var(--accent) 6%, var(--surface)), var(--surface))",
            border: "1px solid color-mix(in oklch, var(--accent) 18%, var(--line))",
            borderRadius: 10,
            fontSize: 13, color: "var(--ink-2)", lineHeight: 1.55,
          }}>
            {conversation.aiSummary || "No summary generated yet."}
          </div>
        </section>

        {conversation.relationshipSummary && (
          <section>
            <div style={{
              fontSize: 11, fontWeight: 600, color: "var(--ink-3)",
              textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: 8,
            }}>
              Relationship
            </div>
            <div style={{ fontSize: 12.5, color: "var(--ink-2)", lineHeight: 1.55 }}>
              {conversation.relationshipSummary}
            </div>
          </section>
        )}

        {/* AI insights */}
        {insights.length > 0 && (
          <section>
            <div style={{
              fontSize: 11, fontWeight: 600, color: "var(--ink-3)",
              textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: 8,
              display: "flex", justifyContent: "space-between", alignItems: "center",
            }}>
              <span>AI insights</span>
              <span style={{ color: "var(--ink-4)", fontWeight: 500 }}>{insights.length}</span>
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
              {insights.map((ins, i) => (
                <div key={i} style={{
                  padding: "10px 12px",
                  background: "var(--surface)",
                  border: "1px solid var(--line)",
                  borderRadius: 8,
                }}>
                  <div style={{ display: "flex", justifyContent: "space-between", gap: 8, marginBottom: 4 }}>
                    <Badge tone={insightToneOf(ins.type)} size="sm" dot>{insightLabelOf(ins.type)}</Badge>
                    {typeof ins.confidence === "number" && (
                      <span className="mono num" style={{ fontSize: 11, color: "var(--ink-3)" }}>
                        {Math.round(ins.confidence * 100)}%
                      </span>
                    )}
                  </div>
                  <div style={{ fontSize: 12.5, fontWeight: 600, color: "var(--ink)" }}>{ins.title}</div>
                  <div style={{ fontSize: 12, color: "var(--ink-2)", marginTop: 3, lineHeight: 1.5 }}>{ins.body}</div>
                </div>
              ))}
            </div>
          </section>
        )}

        {/* Touchpoint timeline */}
        {touchpoints.length > 0 && (
          <section>
            <div style={{
              fontSize: 11, fontWeight: 600, color: "var(--ink-3)",
              textTransform: "uppercase", letterSpacing: "0.04em", marginBottom: 8,
            }}>
              Recent touchpoints
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 0 }}>
              {touchpoints.slice().sort((a, b) => new Date(b.at) - new Date(a.at)).map((t, i) => (
                <div key={i} style={{
                  display: "flex", gap: 10, alignItems: "flex-start",
                  padding: "8px 0",
                  borderBottom: i === touchpoints.length - 1 ? "none" : "1px solid var(--line)",
                }}>
                  <div style={{
                    width: 22, height: 22, borderRadius: 999,
                    background: "var(--inset)", color: "var(--ink-3)",
                    display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0,
                  }}>
                    <Icon name="circle" size={8} style={{ color: "var(--accent)" }} />
                  </div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 12.5, color: "var(--ink)" }}>{t.label}</div>
                    <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)" }}>
                      {window.fmtRelative(t.at)} · {window.fmtDate(t.at)}
                    </div>
                  </div>
                </div>
              ))}
            </div>
          </section>
        )}
      </div>
    </window.SlideOver>
  );
}

/* ConversationActions — channel chips + phone/calendar/more.
   Rendered in the PageHeader (top-right) for whichever conversation is active. */
function ConversationActions({ conversation }) {
  /* Channel color map mirrors the one in <ChannelIcon /> in primitives.jsx —
     when we change the chip variant from "tinted bg + colored icon" to
     "filled colored bg + white icon", we need the same lookup. */
  const CHANNEL_BG = {
    blue: "var(--blue)", green: "var(--green)", warm: "var(--warm)",
    violet: "var(--accent)", neutral: "var(--ink-2)",
  };
  const Chip = ({ bg, icon, title, onClick, fg = "#fff" }) => (
    <button onClick={onClick} title={title} style={{
      width: 30, height: 30, borderRadius: 999,
      display: "inline-flex", alignItems: "center", justifyContent: "center",
      background: bg, color: fg,
      border: "1px solid color-mix(in oklch, " + bg + " 70%, transparent)",
      boxShadow: "inset 0 1px 0 rgba(255,255,255,0.18)",
      transition: "transform 80ms, filter 120ms",
      cursor: "pointer",
      flexShrink: 0,
    }}
    onMouseEnter={(e) => e.currentTarget.style.filter = "brightness(1.08)"}
    onMouseLeave={(e) => e.currentTarget.style.filter = "none"}
    onMouseDown={(e) => e.currentTarget.style.transform = "translateY(0.5px)"}
    onMouseUp={(e) => e.currentTarget.style.transform = "none"}>
      <Icon name={icon} size={13} style={{ color: fg }} />
    </button>
  );
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 5 }}>
      {conversation.channels.map(ch => {
        const meta = CHANNEL_META[ch];
        /* manual_note (Internal note) gets a yellow chip with black icon
           — same colour theme as the Internal-note badge in the message feed,
           and the yellow + black gives much better contrast than warm + white. */
        if (ch === "manual_note") {
          return (
            <Chip key={ch}
              bg="oklch(0.88 0.14 92)"
              fg="#1a1a1a"
              icon={meta?.icon}
              title={meta?.label} />
          );
        }
        return (
          <Chip key={ch}
            bg={CHANNEL_BG[meta?.color] || CHANNEL_BG.neutral}
            icon={meta?.icon}
            title={meta?.label} />
        );
      })}
      <div style={{ width: 1, height: 18, background: "var(--line)", margin: "0 4px" }} />
      <Chip bg={CHANNEL_BG.green}   icon="phone"           title="Call" />
      <Chip bg={CHANNEL_BG.violet}  icon="calendar"        title="Book meeting" />
      <Chip bg={CHANNEL_BG.neutral} icon="more-horizontal" title="More" />
    </div>
  );
}

function groupByDay(messages) {
  const groups = {};
  messages.forEach(m => {
    const k = m.at.slice(0, 10);
    (groups[k] = groups[k] || []).push(m);
  });
  return Object.keys(groups).sort().map(day => ({ day, messages: groups[day] }));
}

function DayGroup({ day, messages }) {
  return (
    <div style={{ marginBottom: 16 }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10, margin: "12px 0 14px" }}>
        <div style={{ flex: 1, height: 1, background: "var(--line)" }} />
        <span className="mono" style={{ fontSize: 11, color: "var(--ink-3)", fontWeight: 500 }}>
          {fmtDate(day, { day: "2-digit", month: "long", year: "numeric" })}
        </span>
        <div style={{ flex: 1, height: 1, background: "var(--line)" }} />
      </div>
      {messages.map(m => <MessageBubble key={m.id} m={m} />)}
    </div>
  );
}

function MessageBubble({ m }) {
  if (m.direction === "system") {
    return (
      <div style={{
        textAlign: "center", margin: "10px 0",
        fontSize: 11.5, color: "var(--ink-3)",
        display: "flex", alignItems: "center", justifyContent: "center", gap: 6,
      }}>
        <Icon name="circle-check" size={12} style={{ color: "var(--green)" }} />
        {m.body} · <span className="mono">{fmtTime(m.at)}</span>
      </div>
    );
  }

  if (m.direction === "internal") {
    const user = getUser(m.from);
    /* Match the yellow chip in the topbar — soft yellow card with a slightly
       darker yellow dashed border, and a darkened title color for contrast. */
    return (
      <div style={{
        margin: "10px 0",
        padding: 12,
        background: "oklch(0.96 0.08 92)",
        border: "1px dashed oklch(0.78 0.16 92)",
        borderRadius: 10,
      }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }}>
          <Icon name="edit" size={13} style={{ color: "oklch(0.36 0.09 80)" }} />
          <span style={{ fontSize: 11.5, fontWeight: 600, color: "oklch(0.36 0.09 80)" }}>
            Internal note · {user?.name}
          </span>
          <span className="mono" style={{ fontSize: 10.5, color: "var(--ink-3)", marginLeft: "auto" }}>{fmtTime(m.at)}</span>
        </div>
        <div style={{ fontSize: 13, color: "var(--ink-2)", lineHeight: 1.5 }}>{m.body}</div>
      </div>
    );
  }

  const isOutbound = m.direction === "outbound";
  const meta = CHANNEL_META[m.channel];

  return (
    <div style={{ display: "flex", justifyContent: isOutbound ? "flex-end" : "flex-start", marginBottom: 10 }}>
      <div style={{ maxWidth: "78%", display: "flex", flexDirection: "column", gap: 4 }}>
        <div style={{
          display: "flex", alignItems: "center", gap: 6,
          fontSize: 11, color: "var(--ink-3)",
          padding: "0 4px",
          flexDirection: isOutbound ? "row-reverse" : "row",
        }}>
          <ChannelIcon channel={m.channel} size={11} />
          <span style={{ fontWeight: 500 }}>{meta?.label}</span>
          <span>·</span>
          <span className="mono">{fmtTime(m.at)}</span>
          {m.aiGenerated && <AIChip>drafted</AIChip>}
        </div>
        <div style={{
          padding: "10px 14px",
          background: isOutbound ? "var(--ink)" : "var(--surface)",
          color: isOutbound ? "#fff" : "var(--ink)",
          border: isOutbound ? "none" : "1px solid var(--line)",
          borderRadius: 12,
          borderBottomRightRadius: isOutbound ? 4 : 12,
          borderBottomLeftRadius: isOutbound ? 12 : 4,
          fontSize: 13, lineHeight: 1.55,
          boxShadow: isOutbound ? "none" : "var(--shadow-1)",
          opacity: m.status === "draft" ? 0.7 : 1,
        }}>
          {m.body}
        </div>
        {m.status === "draft" && (
          <div style={{ display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 6 }}>
            <Badge tone="warm" size="sm" icon="edit">Draft</Badge>
          </div>
        )}
        {m.relatedContentIds?.length > 0 && (
          <div style={{ display: "flex", justifyContent: isOutbound ? "flex-end" : "flex-start", marginTop: 2 }}>
            {m.relatedContentIds.map(id => {
              const item = window.CONTENT.find(c => c.id === id);
              if (!item) return null;
              return (
                <div key={id} style={{
                  display: "inline-flex", alignItems: "center", gap: 6,
                  padding: "5px 9px", background: "var(--inset)",
                  border: "1px solid var(--line)", borderRadius: 7,
                  fontSize: 11.5, color: "var(--ink-2)",
                }}>
                  <Icon name="paperclip" size={11} />
                  {item.title}
                </div>
              );
            })}
          </div>
        )}
      </div>
    </div>
  );
}

function Composer({ contact, open, onOpen, channel, onChannel, availableChannels, text, onText, onSend, hasDraft, expanded, onExpandedChange }) {
  /* Composer textarea has two sizes: compact (default) and expanded.
     When expanded, the outer container takes flex:1 so it grows UPWARD
     into the thread region rather than pushing the header off-screen. */
  const setExpanded = onExpandedChange;
  if (!open) {
    return (
      <div style={{
        padding: "12px 24px 16px",
        borderTop: "1px solid var(--line)",
        background: "var(--surface)",
        flexShrink: 0,
      }}>
        <button onClick={onOpen} style={{
          width: "100%", textAlign: "left",
          padding: "10px 14px", borderRadius: 10,
          background: "var(--inset)",
          color: "var(--ink-3)", fontSize: 13,
          display: "flex", alignItems: "center", gap: 8,
        }}>
          <Icon name="edit" size={13} />
          Reply to {contact?.firstName}…
          <span style={{ flex: 1 }} />
          <Kbd>R</Kbd>
        </button>
      </div>
    );
  }

  return (
    <div style={{
      padding: 0,
      borderTop: "1px solid var(--line)",
      background: "var(--surface)",
      flexShrink: 0,
      flexGrow: expanded ? 1 : 0,
      minHeight: 0,
      display: "flex",
      flexDirection: "column",
    }}>
      <div style={{
        border: "none",
        borderRadius: 0,
        background: "var(--surface)",
        overflow: "hidden",
        boxShadow: "none",
        flex: expanded ? 1 : "0 0 auto",
        minHeight: 0,
        display: "flex",
        flexDirection: "column",
      }}>
        {/* Channel switcher — fixed height to match the inbox folder tabs
           strip on the left pane exactly. */}
        <div style={{
          height: 36, boxSizing: "border-box",
          display: "flex", alignItems: "center", gap: 4,
          padding: "0 10px",
          borderBottom: "1px solid var(--line)",
          background: "var(--surface-2)",
        }}>
          {availableChannels.map(ch => (
            <button key={ch} onClick={() => onChannel(ch)} style={{
              display: "inline-flex", alignItems: "center", gap: 5,
              padding: "4px 8px", borderRadius: 5, fontSize: 12,
              fontWeight: channel === ch ? 600 : 500,
              color: channel === ch ? "var(--ink)" : "var(--ink-3)",
              background: channel === ch ? "var(--surface)" : "transparent",
              border: "1px solid transparent",
              boxShadow: channel === ch ? "var(--shadow-1)" : "none",
            }}>
              <ChannelIcon channel={ch} size={12} />
              {CHANNEL_META[ch]?.label}
            </button>
          ))}
          <div style={{ flex: 1 }} />
          {hasDraft && <Badge tone="warm" size="sm" icon="edit">Editing draft</Badge>}
        </div>

        {/* Textarea */}
        <div style={{ position: "relative", flex: expanded ? 1 : "0 0 auto", minHeight: 0, display: "flex" }}>
          <textarea
            value={text}
            onChange={(e) => onText(e.target.value)}
            placeholder={`Write to ${contact?.firstName}…`}
            style={{
              width: "100%",
              height: expanded ? "100%" : 96,
              flex: expanded ? 1 : "0 0 auto",
              padding: 14, paddingBottom: 40,
              fontSize: 13, lineHeight: 1.55,
              border: "none", outline: "none", resize: "none",
              background: "transparent", color: "var(--ink)",
              fontFamily: "inherit",
              display: "block",
              transition: expanded ? "none" : "height 180ms ease",
            }}
          />
          {/* Expand / collapse toggle — diagonal bar with arrows at the
              extremities (expand) or meeting at the centre (collapse). */}
          <button
            type="button"
            onClick={() => setExpanded(v => !v)}
            title={expanded ? "Collapse" : "Expand"}
            style={{
              position: "absolute",
              right: 10, bottom: 10,
              width: 26, height: 26, borderRadius: 6,
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              color: "var(--ink-3)",
              background: "var(--surface)",
              border: "1px solid var(--line)",
              boxShadow: "var(--shadow-1)",
              transition: "background 120ms, color 120ms",
            }}
            onMouseEnter={(e) => { e.currentTarget.style.background = "var(--inset)"; e.currentTarget.style.color = "var(--ink)"; }}
            onMouseLeave={(e) => { e.currentTarget.style.background = "var(--surface)"; e.currentTarget.style.color = "var(--ink-3)"; }}
          >
            <Icon name={expanded ? "collapse-diagonal" : "expand-diagonal"} size={14} />
          </button>
        </div>

        {/* Toolbar */}
        <div style={{
          display: "flex", alignItems: "center", gap: 6,
          padding: "8px 10px",
          borderTop: "1px solid var(--line)",
          background: "var(--surface-2)",
        }}>
          <IconButton icon="paperclip" title="Attach content" />
          <IconButton icon="image" title="Add image" />
          <IconButton icon="smile" title="Emoji" />
          <div style={{ width: 1, height: 16, background: "var(--line)", margin: "0 4px" }} />
          <RefineMenu
            options={[
              { icon: "sparkles", label: "Rewrite with AI",
                hint: "Reframe with a stronger hook",
                onClick: () => onText("Hi " + (contact?.firstName || "there") + ", quick thought after reading your latest update — would love 15 minutes next week to compare notes on " + (contact?.companyName ? `how ${contact.companyName.split(" ")[0]} is approaching this.` : "this.") + " Open to it?") },
              { icon: "minus",   label: "Make shorter",   hint: "Tighten copy without losing intent" },
              { icon: "user",    label: "More personal",  hint: "Reference recent activity, role, signals" },
              { icon: "trending-up", label: "More direct CTA", hint: "Make the ask explicit" },
              { icon: "clock",   label: "Soften the ask", hint: "Lower-stakes tone" },
            ]}
          />
          <div style={{ flex: 1 }} />
          <Button kind="ghost" size="sm" icon="clock">Schedule</Button>
          {(() => {
            /* Send button reflects the active channel — same color treatment
               as the channel chips in the topbar so the user knows where the
               message will go before they click. */
            const CHANNEL_BG = {
              blue: "var(--blue)", green: "var(--green)", warm: "var(--warm)",
              violet: "var(--accent)", neutral: "var(--ink-2)",
            };
            const meta  = CHANNEL_META[channel] || {};
            const bg    = CHANNEL_BG[meta.color] || "var(--accent)";
            const titleAttr = ({
              linkedin: hasDraft ? "Send LinkedIn DM" : "Send LinkedIn DM",
              email:    "Send email",
              sms:      "Send SMS",
              whatsapp: "Send WhatsApp",
            })[channel] || (hasDraft ? "Send" : "Send now");
            const icon = meta.icon || "send";
            return (
              <button onClick={onSend} title={titleAttr} style={{
                display: "inline-flex", alignItems: "center", gap: 6,
                padding: "4px 12px", height: 26, fontSize: 12,
                fontWeight: 600, letterSpacing: "-0.005em",
                color: "#fff", background: bg,
                border: "1px solid color-mix(in oklch, " + bg + " 70%, transparent)",
                boxShadow: "inset 0 1px 0 rgba(255,255,255,0.18), 0 1px 0 oklch(0.85 0.005 80 / 0.4)",
                borderRadius: 7, cursor: "pointer",
                transition: "filter 120ms, transform 60ms",
              }}
              onMouseEnter={(e) => e.currentTarget.style.filter = "brightness(1.05)"}
              onMouseLeave={(e) => e.currentTarget.style.filter = "none"}
              onMouseDown={(e) => e.currentTarget.style.transform = "translateY(0.5px)"}
              onMouseUp={(e) => e.currentTarget.style.transform = "none"}>
                <Icon name={icon} size={12} />
                Send
              </button>
            );
          })()}
        </div>
      </div>
    </div>
  );
}

/* ────────────────────────────────────────────────────────────────────────
   Right pane — tabbed: Contact / Account / AI Copilot
   ──────────────────────────────────────────────────────────────────────── */
function ConversationContextPanel({ conversation, onNavigate }) {
  const [tab, setTab] = useStateConv("contact");
  const contact = getContact(conversation.contactId);
  const company = getCompany(conversation.companyId);

  return (
    <div style={{
      borderLeft: "1px solid var(--line)",
      background: "var(--surface)",
      display: "flex", flexDirection: "column", minHeight: 0, height: "100%",
    }}>
      <div style={{
        display: "flex", padding: "10px 12px 0",
        borderBottom: "1px solid var(--line)",
      }}>
        <Tab active={tab === "contact"} onClick={() => setTab("contact")}>Contact</Tab>
        <Tab active={tab === "account"} onClick={() => setTab("account")}>Account</Tab>
        <Tab active={tab === "ai"} onClick={() => setTab("ai")} badge={conversation.aiInsights.length}>
          <Icon name="sparkles" size={12} style={{ color: "var(--accent)" }} /> Copilot
        </Tab>
      </div>
      <div data-conv-scroll style={{ flex: 1, overflowY: "auto" }}>
        {tab === "contact" && <ContactPanel contact={contact} conversation={conversation} />}
        {tab === "account" && <AccountPanel company={company} onNavigate={() => onNavigate("account-detail", { companyId: company.id })} />}
        {tab === "ai" && <AICopilotPanel conversation={conversation} contact={contact} company={company} />}
      </div>
    </div>
  );
}

function ContactPanel({ contact, conversation }) {
  if (!contact) return null;
  return (
    <div>
      {/* Profile header */}
      <div style={{ padding: "20px 18px 16px", borderBottom: "1px solid var(--line)" }}>
        <Avatar name={`${contact.firstName} ${contact.lastName}`} src={contact.profilePictureUrl} size={56} />
        <div style={{ fontSize: 16, fontWeight: 600, color: "var(--ink)", marginTop: 10 }}>
          {contact.firstName} {contact.lastName}
        </div>
        <div style={{ fontSize: 12.5, color: "var(--ink-2)", marginTop: 3, lineHeight: 1.45 }}>{contact.headline}</div>
        <MetaLine items={[
          <><Icon name="map-pin" size={11} />{contact.location}</>,
          contact.connectionsCount && <><Icon name="users" size={11} /><span className="mono num">{contact.connectionsCount.toLocaleString()}</span> conn.</>,
        ]} />
        <div style={{ display: "flex", gap: 6, marginTop: 12, flexWrap: "wrap" }}>
          <Button kind="primary" size="sm" icon="send">Message</Button>
          <Button size="sm" icon="calendar">Book</Button>
          <Button size="sm" icon="check-square">Task</Button>
          <Button size="sm" icon="linkedin">Profile</Button>
        </div>
      </div>

      {/* Relationship scores */}
      <div style={{ padding: "16px 18px", borderBottom: "1px solid var(--line)" }}>
        <SectionTitle>Relationship intelligence</SectionTitle>
        <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          <ScoreBar label="Relationship strength" value={contact.abm.relationshipStrength} tone="green" />
          <ScoreBar label="Engagement"             value={contact.abm.engagementScore} tone="violet" />
          <ScoreBar label="Intent"                 value={contact.abm.intentScore} tone="warm" />
        </div>
        <div style={{
          marginTop: 12, padding: "8px 10px",
          background: "var(--inset)", borderRadius: 7,
          fontSize: 12, color: "var(--ink-2)",
          display: "flex", alignItems: "center", gap: 8,
        }}>
          <Icon name="zap" size={12} style={{ color: "var(--accent)" }} />
          <span>{contact.abm.lastSignal}</span>
        </div>
      </div>

      {/* Buying committee */}
      <div style={{ padding: "16px 18px", borderBottom: "1px solid var(--line)" }}>
        <SectionTitle>Role in committee</SectionTitle>
        <div style={{ display: "flex", gap: 8, alignItems: "center", marginBottom: 8 }}>
          <Badge tone="violet" icon="target">{contact.abm.persona}</Badge>
          <Badge tone="blue">{contact.abm.buyingCommitteeRole.replace(/_/g, " ")}</Badge>
        </div>
        <div style={{ fontSize: 12, color: "var(--ink-3)" }}>
          <div style={{ fontWeight: 500, color: "var(--ink-2)", marginBottom: 4 }}>Department · Seniority</div>
          <span>{DEPT_LABEL[contact.department]} · {SENIORITY_LABEL[contact.seniority]}</span>
        </div>
      </div>

      {/* Experience */}
      <div style={{ padding: "16px 18px", borderBottom: "1px solid var(--line)" }}>
        <SectionTitle right={<button style={{ fontSize: 11.5, color: "var(--ink-3)" }}>{contact.experience?.length || 0} positions</button>}>
          Experience
        </SectionTitle>
        <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          {(contact.experience || []).map((e, i) => (
            <div key={i} style={{ display: "flex", gap: 10 }}>
              <div style={{
                width: 28, height: 28, borderRadius: 6,
                background: "var(--inset)", color: "var(--ink-3)",
                fontSize: 10, fontWeight: 600,
                display: "flex", alignItems: "center", justifyContent: "center",
                flexShrink: 0,
              }}>
                <Icon name="briefcase" size={13} />
              </div>
              <div style={{ minWidth: 0, flex: 1 }}>
                <div style={{ fontSize: 12.5, fontWeight: 600, color: "var(--ink)" }}>{e.position}</div>
                <div style={{ fontSize: 11.5, color: "var(--ink-2)" }}>{e.company}</div>
                <div style={{ fontSize: 11, color: "var(--ink-3)", marginTop: 2 }} className="mono">
                  {e.period} · {e.duration}
                </div>
              </div>
            </div>
          ))}
          {(!contact.experience || contact.experience.length === 0) && (
            <div style={{ fontSize: 12, color: "var(--ink-3)", fontStyle: "italic" }}>No experience synced yet.</div>
          )}
        </div>
      </div>

      {/* Skills */}
      {contact.topSkills?.length > 0 && (
        <div style={{ padding: "16px 18px" }}>
          <SectionTitle>Top skills</SectionTitle>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 5 }}>
            {contact.topSkills.map(s => <Badge key={s} tone="neutral">{s}</Badge>)}
          </div>
        </div>
      )}
    </div>
  );
}

function AccountPanel({ company, onNavigate }) {
  if (!company) return null;
  return (
    <div>
      <div style={{ padding: "20px 18px 16px", borderBottom: "1px solid var(--line)" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
          <CompanyLogo company={company} size={44} />
          <div style={{ minWidth: 0, flex: 1 }}>
            <div style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)" }}>{company.name}</div>
            <div style={{ fontSize: 12, color: "var(--ink-3)" }}>{company.industry} · {company.employeeRange} employees</div>
          </div>
        </div>
        <div style={{ fontSize: 12.5, color: "var(--ink-2)", marginTop: 12, lineHeight: 1.5 }}>{company.description}</div>
        <div style={{ display: "flex", gap: 6, marginTop: 12 }}>
          <Button kind="primary" size="sm" icon="arrow-right" onClick={onNavigate}>Open Account 360</Button>
          <Button size="sm" icon="external">Website</Button>
        </div>
      </div>

      <div style={{ padding: "16px 18px", borderBottom: "1px solid var(--line)" }}>
        <SectionTitle>ABM Scorecard</SectionTitle>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          <ScoreTile label="Priority"     value={company.abm.priorityScore} tone="violet" />
          <ScoreTile label="Fit"          value={company.abm.fitScore} tone="green" />
          <ScoreTile label="Intent"       value={company.abm.intentScore} tone="warm" />
          <ScoreTile label="Relationship" value={company.abm.relationshipScore} tone="blue" />
        </div>
      </div>

      <div style={{ padding: "16px 18px", borderBottom: "1px solid var(--line)" }}>
        <SectionTitle>Lifecycle</SectionTitle>
        <LifecyclePill stage={company.abm.lifecycleStage} />
        <div style={{ marginTop: 12, fontSize: 12, color: "var(--ink-2)", lineHeight: 1.5 }}>
          <span style={{ color: "var(--ink-3)" }}>Next best action — </span>
          {company.abm.nextBestAction}
        </div>
      </div>

      <div style={{ padding: "16px 18px", borderBottom: "1px solid var(--line)" }}>
        <SectionTitle>Stakeholders ({company.abm.stakeholdersCount})</SectionTitle>
        <div style={{ fontSize: 12, color: "var(--ink-3)" }}>
          <span className="mono num">{company.abm.connectedStakeholdersCount}</span> connected · <span className="mono num">{company.abm.stakeholdersCount - company.abm.connectedStakeholdersCount}</span> to map
        </div>
      </div>

      <div style={{ padding: "16px 18px" }}>
        <SectionTitle>Tech stack</SectionTitle>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 5 }}>
          {company.technologies.map(t => <Badge key={t} tone="neutral">{t}</Badge>)}
        </div>
      </div>
    </div>
  );
}

function ScoreTile({ label, value, tone }) {
  return (
    <div style={{
      padding: 12, background: "var(--surface-2)",
      border: "1px solid var(--line)", borderRadius: 8,
      display: "flex", alignItems: "center", gap: 10,
    }}>
      <ScoreRing value={value} tone={tone} size={32} />
      <div>
        <div style={{ fontSize: 10.5, color: "var(--ink-3)", letterSpacing: "0.04em", textTransform: "uppercase", fontWeight: 600 }}>{label}</div>
        <div className="mono num" style={{ fontSize: 14, fontWeight: 600, color: "var(--ink)" }}>{value}</div>
      </div>
    </div>
  );
}

function AICopilotPanel({ conversation, contact, company }) {
  const insightIcon = { weak_signal: "zap", recommended_action: "target", buying_signal: "trending-up" };
  const insightTone = { weak_signal: "warm",  recommended_action: "violet", buying_signal: "green" };
  const [generating, setGenerating] = useStateConv(false);

  return (
    <div>
      <div style={{ padding: "16px 18px 12px" }}>
        <div style={{
          padding: "12px 14px",
          borderRadius: 10,
          background: "linear-gradient(180deg, color-mix(in oklch, var(--accent) 6%, transparent), transparent)",
          border: "1px solid color-mix(in oklch, var(--accent) 18%, var(--line))",
        }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }}>
            <Icon name="sparkles" size={14} style={{ color: "var(--accent)" }} />
            <span style={{ fontSize: 12.5, fontWeight: 600, color: "var(--ink)" }}>Next best action</span>
          </div>
          <div style={{ fontSize: 13, color: "var(--ink-2)", lineHeight: 1.5 }}>
            {contact?.abm.recommendedNextAction || company?.abm.nextBestAction}
          </div>
          <div style={{ display: "flex", gap: 6, marginTop: 10 }}>
            <Button kind="accent" size="sm" icon="send">Do it</Button>
            <Button size="sm" icon="clock">Snooze</Button>
          </div>
        </div>
      </div>

      <div style={{ padding: "0 18px 16px" }}>
        <SectionTitle>Insights</SectionTitle>
        <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          {conversation.aiInsights.map((ins, i) => (
            <div key={i} style={{
              padding: "10px 12px", borderRadius: 9,
              background: "var(--surface-2)",
              border: "1px solid var(--line)",
            }}>
              <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 4 }}>
                <Badge tone={insightTone[ins.type] || "neutral"} icon={insightIcon[ins.type] || "circle"} size="sm">
                  {ins.type.replace(/_/g, " ")}
                </Badge>
                <span className="mono" style={{ fontSize: 10.5, color: "var(--ink-3)", marginLeft: "auto" }}>
                  {Math.round(ins.confidence * 100)}% conf.
                </span>
              </div>
              <div style={{ fontSize: 12.5, fontWeight: 600, color: "var(--ink)", marginBottom: 2 }}>{ins.title}</div>
              <div style={{ fontSize: 12, color: "var(--ink-3)", lineHeight: 1.5 }}>{ins.body}</div>
            </div>
          ))}
          {conversation.aiInsights.length === 0 && (
            <div style={{ fontSize: 12, color: "var(--ink-3)", fontStyle: "italic" }}>No insights yet.</div>
          )}
        </div>
      </div>

      <div style={{ padding: "0 18px 16px" }}>
        <SectionTitle>Recommended content</SectionTitle>
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          {window.CONTENT.slice(0, 2).map(c => (
            <div key={c.id} style={{
              padding: 10, borderRadius: 8,
              border: "1px solid var(--line)", background: "var(--surface-2)",
              display: "flex", gap: 10, alignItems: "flex-start",
            }}>
              <div style={{
                width: 32, height: 40, borderRadius: 4,
                background: "var(--inset)",
                display: "flex", alignItems: "center", justifyContent: "center",
                color: "var(--ink-3)", flexShrink: 0,
              }}>
                <Icon name="file-text" size={14} />
              </div>
              <div style={{ minWidth: 0, flex: 1 }}>
                <div style={{ fontSize: 12, fontWeight: 600, color: "var(--ink)" }}>{c.title}</div>
                <div style={{ fontSize: 11, color: "var(--ink-3)" }}>{c.type.replace(/_/g, " ")}</div>
              </div>
              <IconButton icon="paperclip" title="Attach to message" />
            </div>
          ))}
        </div>
      </div>

      <div style={{ padding: "0 18px 24px" }}>
        <SectionTitle>Ask copilot</SectionTitle>
        <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
          {[
            "Draft a follow-up message that references hospitality HR challenges.",
            "Who else should I map at Majestic?",
            "What's the right next step?",
          ].map((p, i) => (
            <button key={i} style={{
              textAlign: "left", padding: "8px 10px",
              background: "var(--surface-2)",
              border: "1px solid var(--line)", borderRadius: 7,
              fontSize: 12, color: "var(--ink-2)",
              display: "flex", alignItems: "center", gap: 8,
            }}
            onClick={() => { setGenerating(true); setTimeout(() => setGenerating(false), 600); }}>
              <Icon name="sparkles" size={11} style={{ color: "var(--accent)" }} />
              {p}
              <span style={{ flex: 1 }} />
              <Icon name="arrow-up-right" size={10} style={{ color: "var(--ink-4)" }} />
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}

/* RefineMenu — small dropup that wraps AI rewriting options into a single
   "Refine" trigger so the composer toolbar stays compact. */
function RefineMenu({ options }) {
  const [open, setOpen] = useStateConv(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    const onKey = (e) => { if (e.key === "Escape") setOpen(false); };
    document.addEventListener("mousedown", onDoc);
    document.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("mousedown", onDoc);
      document.removeEventListener("keydown", onKey);
    };
  }, [open]);
  return (
    <div ref={ref} style={{ position: "relative", display: "inline-flex" }}>
      <button onClick={() => setOpen(v => !v)} title="Refine with AI" style={{
        display: "inline-flex", alignItems: "center", gap: 5,
        padding: "4px 9px", height: 26, fontSize: 12, fontWeight: 600,
        color: "var(--accent)",
        background: open ? "color-mix(in oklch, var(--accent) 10%, transparent)" : "transparent",
        border: "1px solid " + (open ? "color-mix(in oklch, var(--accent) 25%, var(--line))" : "transparent"),
        borderRadius: 6, cursor: "pointer",
        transition: "background 120ms",
      }}>
        <Icon name="sparkles" size={12} />
        Refine
        <Icon name={open ? "chevron-down" : "chevron-up"} size={11} />
      </button>
      {open && (
        <div style={{
          position: "absolute",
          bottom: "calc(100% + 6px)", left: 0,
          minWidth: 240,
          background: "var(--surface)",
          border: "1px solid var(--line-strong)",
          borderRadius: 10,
          boxShadow: "0 16px 36px oklch(0.2 0 0 / 0.14), 0 4px 10px oklch(0.2 0 0 / 0.06)",
          padding: 5,
          zIndex: 60,
          animation: "fadein 140ms ease",
        }}>
          <div style={{
            padding: "6px 10px 4px", fontSize: 10, fontWeight: 600,
            color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: "0.05em",
            display: "flex", alignItems: "center", gap: 6,
          }}>
            <Icon name="sparkles" size={10} style={{ color: "var(--accent)" }} />
            Refine with AI
          </div>
          {options.map((opt, i) => (
            <button key={i}
              onClick={() => { opt.onClick && opt.onClick(); setOpen(false); }}
              style={{
                display: "flex", alignItems: "flex-start", gap: 10,
                width: "100%", padding: "7px 10px", borderRadius: 7,
                color: "var(--ink)", textAlign: "left",
                transition: "background 100ms",
              }}
              onMouseEnter={(e) => e.currentTarget.style.background = "var(--surface-2)"}
              onMouseLeave={(e) => e.currentTarget.style.background = "transparent"}
            >
              <div style={{
                width: 22, height: 22, borderRadius: 6, flexShrink: 0,
                background: "var(--accent-soft, color-mix(in oklch, var(--accent) 10%, var(--surface)))",
                color: "var(--accent)",
                display: "flex", alignItems: "center", justifyContent: "center",
              }}>
                <Icon name={opt.icon || "sparkles"} size={11} />
              </div>
              <div style={{ minWidth: 0, flex: 1 }}>
                <div style={{ fontSize: 12.5, fontWeight: 600 }}>{opt.label}</div>
                {opt.hint && (
                  <div style={{ fontSize: 11, color: "var(--ink-3)", marginTop: 1 }}>{opt.hint}</div>
                )}
              </div>
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

window.PageConversations = PageConversations;
