// Teklens.AI chat — redesigned interactive prototype
const { useState, useEffect, useRef, useMemo, useCallback, Fragment } = React;

// ---------- ICONS ----------
const Icon = ({ name, size = 18, stroke = 1.6, className = "" }) => {
  const s = size;
  const sw = stroke;
  const common = { width: s, height: s, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: sw, strokeLinecap: "round", strokeLinejoin: "round", className };
  switch (name) {
    case "sparkles":return <svg {...common}><path d="M12 3l1.6 4.4L18 9l-4.4 1.6L12 15l-1.6-4.4L6 9l4.4-1.6L12 3z" /><path d="M19 15l.7 1.8L21.5 17l-1.8.7L19 19l-.7-1.3L16.5 17l1.8-.2L19 15z" /></svg>;
    case "users":return <svg {...common}><circle cx="9" cy="8" r="3" /><path d="M3 20c0-3 3-5 6-5s6 2 6 5" /><circle cx="17" cy="9" r="2.5" /><path d="M15 20c0-2.5 2-4 4-4s2.5 1 2.5 3" /></svg>;
    case "eye":return <svg {...common}><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z" /><circle cx="12" cy="12" r="3" /></svg>;
    case "settings":return <svg {...common}><circle cx="12" cy="12" r="3" /><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3h.1a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8v.1a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z" /></svg>;
    case "building":return <svg {...common}><rect x="4" y="3" width="16" height="18" rx="1.5" /><path d="M9 7h.01M15 7h.01M9 11h.01M15 11h.01M9 15h.01M15 15h.01M10 21v-4h4v4" /></svg>;
    case "home":return <svg {...common}><path d="M3 11l9-7 9 7v9a2 2 0 0 1-2 2h-4v-7H9v7H5a2 2 0 0 1-2-2v-9z" /></svg>;
    case "plus":return <svg {...common}><path d="M12 5v14M5 12h14" /></svg>;
    case "chevron-right":return <svg {...common}><path d="M9 6l6 6-6 6" /></svg>;
    case "chevron-down":return <svg {...common}><path d="M6 9l6 6 6-6" /></svg>;
    case "chevron-up-down":return <svg {...common}><path d="M8 9l4-4 4 4M8 15l4 4 4-4" /></svg>;
    case "chevron-left":return <svg {...common}><path d="M15 6l-6 6 6 6" /></svg>;
    case "panel-left-close":return <svg {...common}><rect x="3" y="4" width="18" height="16" rx="2" /><path d="M9 4v16M15 10l-3 2 3 2" /></svg>;
    case "panel-left-open":return <svg {...common}><rect x="3" y="4" width="18" height="16" rx="2" /><path d="M9 4v16M12 10l3 2-3 2" /></svg>;
    case "panel-right":return <svg {...common}><rect x="3" y="4" width="18" height="16" rx="2" /><path d="M15 4v16" /></svg>;
    case "folder":return <svg {...common}><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z" /></svg>;
    case "hash":return <svg {...common}><path d="M5 9h14M5 15h14M10 3L8 21M16 3l-2 18" /></svg>;
    case "user":return <svg {...common}><circle cx="12" cy="8" r="4" /><path d="M4 21c0-4 4-7 8-7s8 3 8 7" /></svg>;
    case "message":return <svg {...common}><path d="M4 5a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H9l-5 4V5z" /></svg>;
    case "send":return <svg {...common}><path d="M5 12l14-7-5 16-3-7-6-2z" /></svg>;
    case "mic":return <svg {...common}><rect x="9" y="3" width="6" height="12" rx="3" /><path d="M5 11a7 7 0 0 0 14 0M12 18v3" /></svg>;
    case "branch":return <svg {...common}><circle cx="6" cy="5" r="2" /><circle cx="18" cy="6" r="2" /><circle cx="6" cy="19" r="2" /><path d="M6 7v10M6 12c0-3 3-5 6-5h4" /></svg>;
    case "model":return <svg {...common}><path d="M12 2l1.8 4.6L18.5 8l-4.7 1.4L12 14l-1.8-4.6L5.5 8l4.7-1.4L12 2z" /></svg>;
    case "wand":return <svg {...common}><path d="M15 4l1 2 2 1-2 1-1 2-1-2-2-1 2-1 1-2zM4 20l9-9" /></svg>;
    case "tool":return <svg {...common}><path d="M14 7a4 4 0 0 0 5 5l3 3-4 4-3-3a4 4 0 0 1-5-5L4 4l3-3 7 6z" /></svg>;
    case "search":return <svg {...common}><circle cx="11" cy="11" r="7" /><path d="M21 21l-4.5-4.5" /></svg>;
    case "check":return <svg {...common}><path d="M5 12l5 5 9-11" /></svg>;
    case "edit":return <svg {...common}><path d="M4 20h4l10-10-4-4L4 16v4z" /><path d="M14 6l4 4" /></svg>;
    case "lab":return <svg {...common}><path d="M9 3v6L4 19a2 2 0 0 0 2 3h12a2 2 0 0 0 2-3l-5-10V3" /><path d="M8 3h8" /></svg>;
    case "story":return <svg {...common} stroke="none" fill="currentColor"><path d="M5 4l4 4-4 4 4 4-4 4V4z" opacity=".4" /><path d="M9 8l4-4 4 4-4 4 4 4-4 4-4-4 4-4-4-4z" /></svg>;
    case "paperclip":return <svg {...common}><path d="M21 11l-9 9a5 5 0 0 1-7-7l9-9a3.5 3.5 0 1 1 5 5l-9 9a2 2 0 1 1-3-3l8-8" /></svg>;
    case "x":return <svg {...common}><path d="M6 6l12 12M18 6L6 18" /></svg>;
    case "filter":return <svg {...common}><path d="M3 5h18l-7 9v6l-4-2v-4L3 5z" /></svg>;
    case "filter-funnel":return <svg {...common}><path d="M3 5h18l-7 8v6l-4-2v-4L3 5z" /></svg>;
    case "file":return <svg {...common}><path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9l-6-6z" /><path d="M14 3v6h6M8 13h8M8 17h6" /></svg>;
    case "mail":return <svg {...common}><rect x="3" y="5" width="18" height="14" rx="2" /><path d="M3 7l9 6 9-6" /></svg>;
    case "image":return <svg {...common}><rect x="3" y="4" width="18" height="16" rx="2" /><circle cx="9" cy="10" r="1.5" /><path d="M21 16l-5-5-8 8" /></svg>;
    case "grid":return <svg {...common}><rect x="3" y="3" width="7" height="7" rx="1" /><rect x="14" y="3" width="7" height="7" rx="1" /><rect x="3" y="14" width="7" height="7" rx="1" /><rect x="14" y="14" width="7" height="7" rx="1" /></svg>;
    case "pdf":return <svg {...common}><path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9l-6-6z" /><path d="M14 3v6h6" /><path d="M8 14h.01M11 14h.01M14 14h.01M8 17h8" strokeWidth="1.6" /></svg>;
    case "info":return <svg {...common}><circle cx="12" cy="12" r="9" /><path d="M12 8h.01M11 12h1v5h1" /></svg>;
    case "merge":return <svg {...common}><circle cx="6" cy="6" r="2" /><circle cx="6" cy="18" r="2" /><circle cx="18" cy="18" r="2" /><path d="M6 8v4a4 4 0 0 0 4 4h6" /></svg>;
    case "link":return <svg {...common}><path d="M10 14a4 4 0 0 0 5.66 0l3-3a4 4 0 0 0-5.66-5.66l-1.5 1.5" /><path d="M14 10a4 4 0 0 0-5.66 0l-3 3a4 4 0 0 0 5.66 5.66l1.5-1.5" /></svg>;
    case "globe":return <svg {...common}><circle cx="12" cy="12" r="9" /><path d="M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18" /></svg>;
    case "book":return <svg {...common}><path d="M4 4h11a3 3 0 0 1 3 3v13H7a3 3 0 0 1-3-3V4z" /><path d="M4 17a3 3 0 0 1 3-3h11" /></svg>;
    case "external":return <svg {...common}><path d="M14 4h6v6M20 4l-9 9M19 13v6a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h6" /></svg>;
    case "more-v":return <svg {...common}><circle cx="12" cy="5" r="1.4" fill="currentColor" /><circle cx="12" cy="12" r="1.4" fill="currentColor" /><circle cx="12" cy="19" r="1.4" fill="currentColor" /></svg>;
    case "edit-line":return <svg {...common}><path d="M12 20h9M16.5 3.5l4 4L8 20H4v-4l12.5-12.5z" /></svg>;
    case "copy":return <svg {...common}><rect x="8" y="8" width="13" height="13" rx="2" /><path d="M16 8V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h3" /></svg>;
    case "trash":return <svg {...common}><path d="M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M6 6l1 14a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-14" /><path d="M10 11v6M14 11v6" /></svg>;
    case "clock":return <svg {...common}><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>;
    case "calendar":return <svg {...common}><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 9h18M8 3v4M16 3v4"/></svg>;
    case "chevron-up":return <svg {...common}><path d="M6 15l6-6 6 6" /></svg>;
    case "code":return <svg {...common}><path d="M9 18l-6-6 6-6M15 6l6 6-6 6" /></svg>;
    case "pin":return <svg {...common}><path d="M12 2l3 6 5 1-4 4 1 6-5-3-5 3 1-6-4-4 5-1 3-6z" /></svg>;
    case "circle-dot":return <svg {...common}><circle cx="12" cy="12" r="9" /><circle cx="12" cy="12" r="3" fill="currentColor" /></svg>;
    case "json":return <svg {...common}><path d="M8 4c-2 0-3 1-3 4s-2 4-2 4 2 0 2 4 1 4 3 4M16 4c2 0 3 1 3 4s2 4 2 4-2 0-2 4-1 4-3 4" /></svg>;
    case "entity":return <svg {...common}><path d="M12 3l8 4.5v9L12 21l-8-4.5v-9L12 3z" /><path d="M12 12l8-4.5M12 12v9M12 12L4 7.5" /></svg>;
    case "source":return <svg {...common}><ellipse cx="12" cy="5" rx="8" ry="3" /><path d="M4 5v6c0 1.7 3.6 3 8 3s8-1.3 8-3V5M4 11v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6" /></svg>;
    case "shield":return <svg {...common}><path d="M12 2l8 3v6c0 5-3.5 9-8 11-4.5-2-8-6-8-11V5l8-3z" /></svg>;
    case "repo":return <svg {...common}><path d="M4 4a2 2 0 0 1 2-2h12v18H6a2 2 0 0 1-2-2V4z" /><path d="M4 16h14M9 2v14" /></svg>;
    case "confluence":return <svg {...common}><path d="M3 17c4-7 7-7 11 0M21 7c-4 7-7 7-11 0" /></svg>;
    case "jira":return <svg {...common}><path d="M11 2l9 9-9 9-3-3 6-6-6-6 3-3z" /></svg>;
    case "anthropic":return <svg {...common} stroke="none" fill="currentColor"><path d="M7.5 4h3.2l5 16h-3.2l-1-3.4H6.8L5.8 20H2.5l5-16zm.4 9.6h3l-1.5-5.2-1.5 5.2zM17.5 4h3.5l-3.5 16h-3.5l3.5-16z" /></svg>;
    case "openai":return <svg {...common}><path d="M12 3a4 4 0 0 1 7 2.7M19 5.7A4 4 0 0 1 21 9v6a4 4 0 0 1-2 3.3M19 18.3A4 4 0 0 1 12 21M12 21a4 4 0 0 1-7-2.7M5 18.3A4 4 0 0 1 3 15V9a4 4 0 0 1 2-3.3M5 5.7A4 4 0 0 1 12 3M8 9l4 2.3L16 9M12 11.3V16" /></svg>;
    case "gemini":return <svg {...common} stroke="none" fill="currentColor"><path d="M12 2c.4 5 4.6 9.2 9.6 9.6v.8c-5 .4-9.2 4.6-9.6 9.6h-.8C10.8 17 6.6 12.8 1.6 12.4v-.8C6.6 11.2 10.8 7 11.2 2h.8z" /></svg>;
    case "grok":return <svg {...common}><path d="M5 19l14-14M9 19l10-10M5 11l8-8" /></svg>;
    case "cerebras":return <svg {...common}><circle cx="12" cy="12" r="3" /><path d="M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1" /></svg>;
    case "more":return <svg {...common}><circle cx="5" cy="12" r="1.4" fill="currentColor" /><circle cx="12" cy="12" r="1.4" fill="currentColor" /><circle cx="19" cy="12" r="1.4" fill="currentColor" /></svg>;
    case "shield":return <svg {...common}><path d="M12 2l8 3v6c0 5-3.5 9-8 11-4.5-2-8-6-8-11V5l8-3z" /></svg>;
    case "globe":return <svg {...common}><circle cx="12" cy="12" r="9" /><path d="M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18" /></svg>;
    case "robot":return <svg {...common}><rect x="4" y="7" width="16" height="12" rx="2" /><path d="M12 7V4M9 12h.01M15 12h.01M9 16h6" /></svg>;
    case "hierarchy":return <svg {...common}><circle cx="12" cy="5" r="2.2" /><circle cx="5.5" cy="19" r="2.2" /><circle cx="18.5" cy="19" r="2.2" /><path d="M12 7.2v3.3M12 10.5l-5 7M12 10.5l5 7" /></svg>;
    default:return null;
  }
};

// ---------- BRAND LOGO ----------
const TeklensLogo = ({ collapsed = false }) =>
<div className="flex items-center gap-1.5" style={{ gap: "0px" }}>
    <span className="text-[18px] font-medium tracking-tight text-[#0e0e10]">teklens</span>
    {!collapsed &&
  <span className="text-[18px] font-medium tracking-tight bg-gradient-to-r from-[#3b5cf6] via-[#8b5cf6] to-[#ec4899] bg-clip-text text-transparent">.AI</span>
  }
  </div>;


// ---------- DATA ----------
const PROJECTS = ["Teklens AI", "Teklens PM", "Internal R&D"];

const CHATS = [
{ id: "c-risk", title: "Risk analysis for chat update", date: "today" },
{ id: "c-coll-dm", title: "Collateral for dark mode feature launch", date: "today" },
{ id: "c-supp-19", title: "Analyse issue TBG-019 — widget resize blocks scroll", date: "today" },
{ id: "c-q3", title: "Q3 roadmap prioritization", date: "yesterday" },
{ id: "c-tek-140", title: "Spec review — Allow attachments in Teklens.AI", date: "yesterday" },
{ id: "c-supp-03", title: "Hotfix narrative — TBG-003 Safari paste", date: "2d" },
{ id: "c-launch-roles", title: "Launch plan — Agent Team", date: "3d" },
{ id: "c-comp-watch", title: "Competitor release sweep — May", date: "1w" },
];


const ENTITY_CATEGORIES = [
{
  id: "pm", icon: "story", label: "Stories", tint: "#3b5cf6", source: "Jira · Project TEK",
  items: [
  { id: "story1", icon: "story", label: "TEK-140 · Allow to add attachments in Teklens.AI", virtual: true,
    chats: [
    { id: "p1", label: "Screenshot attachment story check" },
    { id: "p2", label: "Mobile upload flow review" },
    { id: "p3", label: "Backend storage spec" },
    { id: "p4", label: "QA acceptance criteria" }]
  },
  { id: "story2", icon: "story", label: "TEK-152 · Multi-tenant role permissions", virtual: true,
    chats: [
    { id: "p5", label: "RBAC matrix draft" },
    { id: "p6", label: "Migration plan" }]
  },
  { id: "story3", icon: "story", label: "TEK-166 · Inline comments on canvas", virtual: true,
    chats: [{ id: "p7", label: "Anchor model proposal" }] },
  { id: "story4", icon: "story", label: "TEK-178 · Audit log redesign", virtual: true,
    chats: [
    { id: "p8", label: "Schema discussion" },
    { id: "p9", label: "Retention policy" },
    { id: "p10", label: "UI mockups review" },
    { id: "p11", label: "Compliance check" },
    { id: "p12", label: "Performance test" },
    { id: "p13", label: "Rollout plan" }]
  }]

},
{
  id: "sprints", icon: "calendar", label: "Sprints", tint: "#8b5cf6", source: "Synchronized Jira · Teklens (TEK)",
  items: [
  { id: "sp-42", icon: "calendar", label: "Sprint 42 · current", virtual: true,
    chats: [
    { id: "sp42c1", label: "Mid-sprint pulse — May 22" },
    { id: "sp42c2", label: "Sprint 42 planning notes" },
    { id: "sp42c3", label: "Carry-overs from Sprint 41" }]
  },
  { id: "sp-41", icon: "calendar", label: "Sprint 41 · closed", virtual: true,
    chats: [
    { id: "sp41c1", label: "Sprint 41 retro" },
    { id: "sp41c2", label: "Delivered vs. committed" }]
  },
  { id: "sp-43", icon: "calendar", label: "Sprint 43 · planning", virtual: true,
    chats: [
    { id: "sp43c1", label: "Capacity for Sprint 43" }]
  }]
},
{
  id: "components", icon: "hierarchy", label: "Components", tint: "#a05a00", source: "Graph DB · contem/teklens-ai",
  items: [
  { id: "comp-chat-core", icon: "hierarchy", label: "Chat Core", virtual: true,
    chats: [
    { id: "cc-cco1", label: "Streaming refactor — risk sweep" },
    { id: "cc-cco2", label: "Virtualization scroll anchoring" },
    { id: "cc-cco3", label: "Tool-card expand jitter" }]
  },
  { id: "comp-composer", icon: "hierarchy", label: "Composer & Attachments", virtual: true,
    chats: [
    { id: "cc-co1", label: "Drag-drop vs. paste collision" },
    { id: "cc-co2", label: "AttachmentRail layout review" }]
  },
  { id: "comp-context-graph", icon: "hierarchy", label: "Context Graph", virtual: true,
    chats: [
    { id: "cc-cg1", label: "Schema migration backfill" },
    { id: "cc-cg2", label: "Restriction semantics for entities" }]
  },
  { id: "comp-streaming", icon: "hierarchy", label: "Streaming & Tools", virtual: true,
    chats: [
    { id: "cc-st1", label: "Reconnect correlation ids" },
    { id: "cc-st2", label: "Tool envelope v2 review" }]
  },
  { id: "comp-auth", icon: "hierarchy", label: "Auth & RBAC", virtual: true,
    chats: [
    { id: "cc-au1", label: "Role propagation on session refresh" }]
  },
  { id: "comp-knowledge", icon: "hierarchy", label: "Knowledge Indexer", virtual: true,
    chats: [
    { id: "cc-kn1", label: "Re-embed pipeline review" },
    { id: "cc-kn2", label: "Chunk offset determinism" }]
  },
  { id: "comp-plugin-host", icon: "hierarchy", label: "Plugin Host", virtual: true,
    chats: [
    { id: "cc-ph1", label: "Worker isolation hardening" }]
  },
  { id: "comp-telemetry", icon: "hierarchy", label: "Telemetry", virtual: true,
    chats: [
    { id: "cc-te1", label: "Edge PII redactor rollout" }]
  }]
},
{
  id: "knowledge", icon: "hash", label: "Know-how", tint: "#6b7280", source: "Knowledge Base",
  items: [
  { id: "k-coding", icon: "hash", label: "Coding guidelines", virtual: true,
    chats: [
    { id: "kc1", label: "TypeScript strictness rules" },
    { id: "kc2", label: "Naming conventions sweep" },
    { id: "kc3", label: "Server action patterns" }]
  },
  { id: "k-glossary", icon: "hash", label: "Glossary", virtual: true,
    chats: [
    { id: "kc4", label: "Entity vs. Source — definitions" },
    { id: "kc5", label: "Virtual chat terminology" }]
  },
  { id: "k-testing", icon: "hash", label: "Testing paradigms", virtual: true,
    chats: [
    { id: "kc6", label: "Component test pyramid" },
    { id: "kc7", label: "Contract testing for MCP" },
    { id: "kc8", label: "Snapshot policy" },
    { id: "kc9", label: "Flake quarantine workflow" }]
  },
  { id: "k-usecases", icon: "hash", label: "Use case directory", virtual: true,
    chats: [
    { id: "kc10", label: "Role-based onboarding flows" },
    { id: "kc11", label: "Attachments end-to-end" },
    { id: "kc12", label: "Event-triggered findings" }]
  }]
},
{
  id: "code", icon: "code", label: "Code", tint: "#10b981", source: "Repository · contem/teklens-ai",
  items: [
  { id: "cl1", icon: "code", label: "ChatThread.tsx", virtual: true,
    chats: [
    { id: "cc1", label: "Render perf review" },
    { id: "cc2", label: "Virtual chat composition" },
    { id: "cc3", label: "Streaming refactor" }]
  },
  { id: "cl2", icon: "code", label: "useEntityIndex hook", virtual: true,
    chats: [
    { id: "cc4", label: "Cache invalidation strategy" },
    { id: "cc5", label: "Test coverage gap" }]
  }]

}].
map((cat) => ({ ...cat, items: cat.items.filter((it) => it.chats.length > 0).map((it) => ({ ...it, count: it.chats.length })) }));

// Default thread — generic PM/eng recap (shown for chats without a bespoke conversation)
const MESSAGES = [
{ role: "user", text: "Where does this stand, and what's the next concrete step to move it forward?" },
{ role: "skill-loaded", skill: "Story Drafter" },
{ role: "tool", tool: "fetch_jira_issue", status: "completed", args: { project: "TEK" }, results: 1 },
{ role: "tool", tool: "rag_query", status: "completed", args: { sources: ["Engineering Wiki", "Product Specs"] }, results: 5 },
{ role: "assistant", body: "pmGeneric" },
{ role: "followups-risk" }];


// Chat messages — Risk analysis for chat update (TEK-345)
const RISK_MESSAGES = [
{ role: "user", text: "Run a full implementation risk analysis on TEK-345. I want to know what could derail the new chat frontend rollout — at the code level, not at the product level." },
{ role: "skill-loaded", skill: "Risk Analyzer v1.4" },
{ role: "skill-loaded", skill: "Component Analyzer" },
{ role: "tool", tool: "git_diff", status: "completed", args: { branch: "features/new-chat-frontend", base: "main" }, results: 38 },
{ role: "tool", tool: "graph-analysis", status: "completed", args: { paths: ["src/chat/", "src/composer/", "src/state/store.ts"] }, results: 12 },
{ role: "tool", tool: "rag_query", status: "completed", args: { sources: ["TEK-345", "ChatThread.tsx history", "Engineering Wiki / Streaming notes"] }, results: 9 },
{ role: "assistant", body: "riskMain" },
{ role: "followups-risk" }];


// ---------- ROOT ----------
function App() {
  const [iconActive, setIconActive] = useState(typeof window !== "undefined" && window.__initialView || "dashboard");
  const [activeRoleId, setActiveRoleId] = useState(typeof window !== "undefined" && window.__initialRoleId || null);
  const [sidePanelOpen, setSidePanelOpen] = useState(true);
  const [widgetOpen, setWidgetOpen] = useState(true);
  const [project, setProject] = useState(PROJECTS[0]);
  const [projectOpen, setProjectOpen] = useState(false);
  const [chatsOpen, setChatsOpen] = useState(true);
  const [openCats, setOpenCats] = useState({ pm: true, sprints: true, components: false, knowledge: false, code: false });
  const [openItems, setOpenItems] = useState({ story1: true });
  const [activeChat, setActiveChat] = useState("c-risk");
  const [virtualChat, setVirtualChat] = useState(null); // {entityId, label}
  // Per-chat context chips (DiNi chat = Researcher only; Simon virtual = Analyzer + entity)
  const CHAT_CHIPS = {
    "c-risk": [
    { id: "ra", kind: "skill", label: "Risk Analyzer" },
    { id: "ca", kind: "skill", label: "Component Analyzer" },
    { id: "tek-345", kind: "story", label: "TEK-345: Implement new chat frontend", linkedTo: "branch-newchat" },
    { id: "branch-newchat", kind: "branch", label: "features/new-chat-frontend", linkedTo: "tek-345" }]

    // other regular chats inherit a generic default
  };
  const VIRTUAL_CHIPS = {
    story1: [
    { id: "sd", kind: "skill", label: "Story Drafter" },
    { id: "ca", kind: "skill", label: "Component Analyzer" },
    { id: "tek-140", kind: "story", label: "TEK-140: Allow attachments in Teklens.AI" }],
    "comp-chat-core":      [{ id: "ca", kind: "skill", label: "Component Analyzer" }, { id: "comp-chat-core",      kind: "component", label: "Chat Core" }],
    "comp-composer":       [{ id: "ca", kind: "skill", label: "Component Analyzer" }, { id: "comp-composer",       kind: "component", label: "Composer & Attachments" }],
    "comp-context-graph":  [{ id: "ca", kind: "skill", label: "Component Analyzer" }, { id: "comp-context-graph",  kind: "component", label: "Context Graph" }],
    "comp-streaming":      [{ id: "ca", kind: "skill", label: "Component Analyzer" }, { id: "comp-streaming",      kind: "component", label: "Streaming & Tools" }],
    "comp-auth":           [{ id: "ca", kind: "skill", label: "Component Analyzer" }, { id: "comp-auth",           kind: "component", label: "Auth & RBAC" }],
    "comp-knowledge":      [{ id: "ca", kind: "skill", label: "Component Analyzer" }, { id: "comp-knowledge",      kind: "component", label: "Knowledge Indexer" }],
    "comp-plugin-host":    [{ id: "ca", kind: "skill", label: "Component Analyzer" }, { id: "comp-plugin-host",    kind: "component", label: "Plugin Host" }],
    "comp-telemetry":      [{ id: "ca", kind: "skill", label: "Component Analyzer" }, { id: "comp-telemetry",      kind: "component", label: "Telemetry" }],
  };
  const defaultChipsFor = (vc, chatId) => {
    if (vc) return VIRTUAL_CHIPS[vc.entityId] || [];
    return CHAT_CHIPS[chatId] || [];
  };
  const [contextChips, setContextChips] = useState(defaultChipsFor(null, "c-risk"));

  // Reset chips on chat / virtual-chat change (skipped immediately after a launch)
  const skipNextChipReset = useRef(false);
  useEffect(() => {
    if (skipNextChipReset.current) { skipNextChipReset.current = false; return; }
    setContextChips(defaultChipsFor(virtualChat, activeChat));
  }, [virtualChat, activeChat]);

  // Launch-chat handler: action cards dispatch "teklens:launch-chat" with {content, story, skill}
  useEffect(() => {
    const onLaunch = (e) => {
      const { content, story, skill } = e.detail || {};
      const chips = [];
      if (skill) chips.push({ id: `sk-${skill}`, kind: "skill", label: skill });
      if (story) chips.push({ id: `st-${story}`, kind: "story", label: story });
      skipNextChipReset.current = true;
      setContextChips(chips);
      setComposer(content || "");
      setVirtualChat(null);
      setActiveChat("new");
      setIconActive("ask");
      setActiveRoleId(null);
    };
    window.addEventListener("teklens:launch-chat", onLaunch);
    return () => window.removeEventListener("teklens:launch-chat", onLaunch);
  }, []);

  // Pin-as-context handler (fired by NodeDetailView's "Pin as context" button).
  useEffect(() => {
    const onAddChip = (e) => {
      const chip = e.detail;
      if (!chip || !chip.id) return;
      setContextChips(cs => cs.find(c => c.id === chip.id) ? cs : [...cs, chip]);
    };
    window.addEventListener("teklens:add-chip", onAddChip);
    return () => window.removeEventListener("teklens:add-chip", onAddChip);
  }, []);

  // Widgets are tied to the chat. DiNi chat (c1) + fresh "new" chat = no widgets.
  const widgetsByChat = {
    "c-risk": [{ id: 10, title: "Risk Analysis", subtitle: "TEK-345 · features/new-chat-frontend" }]
  };
  const widgetsByVirtual = {
    story1: [
      { id: 30, title: "Story Estimation", subtitle: "TEK-140 · Allow attachments in Teklens.AI" },
      { id: 31, title: "Story Update", subtitle: "TEK-140 · improve & enrich" },
    ],
    "sp-42": [
      { id: 50, title: "Sprint Pulse", subtitle: "Sprint 42 · burndown & scope" },
    ],
  };
  // One "Component Analysis" widget per domain component — opens the graph focused on it.
  if (window.COMP_WIDGET_IDS) {
    Object.entries(window.COMP_WIDGET_IDS).forEach(([cid, wid]) => {
      const comp = (window.GRAPH_COMPONENTS || []).find(c => c.id === cid);
      widgetsByVirtual["comp-" + cid] = [{ id: wid, title: "Component Analysis", subtitle: `${comp ? comp.name : cid} · contem/teklens-ai` }];
    });
  }
  const widgetsAvailable = virtualChat
    ? !!widgetsByVirtual[virtualChat.entityId]
    : !!widgetsByChat[activeChat];
  const messagesByChat = {
    "c-risk": RISK_MESSAGES,
    "new": []
  };
  const [megaOpen, setMegaOpen] = useState(false);
  const [megaTab, setMegaTab] = useState("entities");
  const [model, setModel] = useState("Gemini 3.1 Pro");
  const [widgetView, setWidgetView] = useState("widget"); // 'widget' | 'data'
  const [activeWidget, setActiveWidget] = useState(0);
  const [composer, setComposer] = useState("");
  const [theme, setTheme] = useState("light");

  // ----- Dashboard + Context Workspace areas -----
  const dashboardMode = iconActive === "dashboard";
  const workspaceMode = iconActive === "workspace";
  const settingsMode = iconActive === "settings";
  const [dashView, setDashView] = useState({ view: "board" }); // { view:'board' } | { view:'detail', id }
  const [pulseOpen, setPulseOpen] = useState(true);
  const [pulseW, setPulseW] = useState(340);
  const [artefactHome, setArtefactHome] = useState({}); // artId -> [{kind,id}, ...] (moves/copies)
  const onOpenContext = useCallback(() => { setIconActive("workspace"); }, []);
  const moveArtefact = useCallback((artId, from, to, copy) => {
    setArtefactHome((h) => {
      const cur = h[artId] || [from];
      const has = cur.some((x) => x.kind === to.kind && x.id === to.id);
      const next = copy ? (has ? cur : [...cur, to]) : [to];
      return { ...h, [artId]: next };
    });
  }, []);
  const openInitiative = useCallback((id) => { setIconActive("dashboard"); setDashView({ view: "detail", id }); }, []);

  // Resizable widths
  const [sidePanelW, setSidePanelW] = useState(280);
  const [widgetW, setWidgetW] = useState(420);

  // Tweaks panel
  const [tweaksOpen, setTweaksOpen] = useState(false);
  const [tweaks, setTweaks] = useState({ accent: "#1f3df6", density: "comfortable", iconBarStyle: "dark" });

  useEffect(() => {
    const onMsg = (e) => {
      if (e.data?.type === "__activate_edit_mode") setTweaksOpen(true);
      if (e.data?.type === "__deactivate_edit_mode") setTweaksOpen(false);
    };
    window.addEventListener("message", onMsg);
    window.parent.postMessage({ type: "__edit_mode_available" }, "*");
    return () => window.removeEventListener("message", onMsg);
  }, []);

  const toggleCat = (id) => setOpenCats((o) => ({ ...o, [id]: !o[id] }));
  const toggleItem = (id) => setOpenItems((o) => ({ ...o, [id]: !o[id] }));

  const widgets = (virtualChat && widgetsByVirtual[virtualChat.entityId]) || widgetsByChat[activeChat] || [];

  const activeMessages = messagesByChat[activeChat] || MESSAGES;

  // Code-analysis widget ids that support the component graph.
  const CODE_ANALYSIS_WIDGET_IDS = new Set([10, 30, 31, ...Object.values(window.COMP_WIDGET_IDS || {})]);
  const idx = Math.min(activeWidget, widgets.length - 1);
  const activeWidgetObj = widgets[idx] || widgets[0];
  const activeWidgetIsCodeAnalysis = activeWidgetObj && CODE_ANALYSIS_WIDGET_IDS.has(activeWidgetObj.id);

  // On chat / virtual-chat change, default the right panel back to the widget view.
  // (The component-chip effect below then re-opens the graph for component chats.)
  useEffect(() => {
    setWidgetView(v => (v === "data" ? "data" : "widget"));
  }, [virtualChat, activeChat]);

  // If a component chip is pinned + the active widget supports the graph, default to graph view.
  useEffect(() => {
    const hasComponentChip = contextChips.some(c => c.kind === "component");
    if (hasComponentChip && activeWidgetIsCodeAnalysis && widgetView === "widget") {
      setWidgetView("graph");
    }
    // If we're stuck on "graph" but the active widget no longer supports it, fall back.
    if (!activeWidgetIsCodeAnalysis && widgetView === "graph") {
      setWidgetView("widget");
    }
  }, [contextChips, activeWidgetIsCodeAnalysis, widgetView]);

  const accent = tweaks.accent;

  return (
    <div className="h-screen w-screen flex flex-col bg-[#f4f1ea] text-[#0e0e10] overflow-hidden font-sans" style={{ "--accent": accent }}>
      {/* Top: icon bar + main row */}
      <div className="flex flex-1 min-h-0">
        {/* ---- Icon Bar ---- */}
        <IconBar active={iconActive}
          onChange={(id) => { setIconActive(id); if (id === "roles") setActiveRoleId(null); if (id === "dashboard") setDashView({ view: "board" }); }}
          sidePanelOpen={sidePanelOpen} onToggleSide={() => setSidePanelOpen((s) => !s)}
          project={project} setProject={setProject} projectOpen={projectOpen} setProjectOpen={setProjectOpen} />

        {workspaceMode ? <ContextWorkspace sideOpen={sidePanelOpen} /> : <>
        {/* ---- Side Panel ---- */}
        {sidePanelOpen && !settingsMode &&
        <>
            <div style={{ width: sidePanelW }} className="shrink-0 h-full flex">
              {iconActive === "roles"
                ? <RolesSidePanel />
                : <SidePanel
                    mode={dashboardMode ? "dashboard" : "ask"}
                    project={project} setProject={setProject} projectOpen={projectOpen} setProjectOpen={setProjectOpen}
                    chatsOpen={chatsOpen} setChatsOpen={setChatsOpen}
                    openCats={openCats} toggleCat={toggleCat}
                    openItems={openItems} toggleItem={toggleItem}
                    activeChat={activeChat} setActiveChat={(id) => {setActiveChat(id);setVirtualChat(null);}}
                    virtualChat={virtualChat} setVirtualChat={setVirtualChat}
                    dashView={dashView} onOpenDashBoard={() => { setIconActive("dashboard"); setDashView({ view: "board" }); }} onOpenInitiative={openInitiative} />}
            </div>
            <ResizeHandle onResize={(dx) => setSidePanelW((w) => Math.max(220, Math.min(480, w + dx)))} />
          </>
        }

        {/* ---- Main column ---- */}
        <div className="flex flex-1 min-w-0 bg-white border-l border-[#e8e3d8]">
          {iconActive === "settings" ?
          <ArtefactSettings /> :
          iconActive === "components" ?
          <ComponentOverview /> :
          iconActive === "roles" ?
          (activeRoleId
            ? <RoleDetailPage roleId={activeRoleId} onBack={() => setActiveRoleId(null)} />
            : <RolesPage onOpenRole={(id) => setActiveRoleId(id)} />) :
          dashboardMode ? (
            /* ===== DASHBOARD VIEW ===== */
            <>
              {dashView.view === "detail"
                ? <InitiativeDetail initiativeId={dashView.id} onBack={() => setDashView({ view: "board" })} onOpenContext={onOpenContext} />
                : <DashboardView openInitiative={openInitiative} onOpenContext={onOpenContext} artefactHome={artefactHome} moveArtefact={moveArtefact} />}
              {pulseOpen ?
                <>
                  <ResizeHandle onResize={(dx) => setPulseW((w) => Math.max(280, Math.min(440, w - dx)))} />
                  <div style={{ width: pulseW }} className="shrink-0 h-full flex"><PulsePanel onClose={() => setPulseOpen(false)} onOpenContext={onOpenContext} /></div>
                </> :
                <PulseRail onExpand={() => setPulseOpen(true)} />}
            </>
          ) : (
          /* ===== ASK TEKLENS VIEW ===== */
          <>
              <ChatColumn
              virtualChat={virtualChat}
              messages={activeMessages}
              contextChips={contextChips} setContextChips={setContextChips}
              megaOpen={megaOpen} setMegaOpen={setMegaOpen} megaTab={megaTab} setMegaTab={setMegaTab}
              composer={composer} setComposer={setComposer}
              model={model} setModel={setModel}
              accent={accent} />
            
              {widgetsAvailable ? widgetOpen ?
            <>
                  <ResizeHandle onResize={(dx) => setWidgetW((w) => Math.max(320, Math.min(720, w - dx)))} />
                  <div style={{ width: widgetW }} className="shrink-0 h-full flex">
                    <WidgetPanel
                  widgets={widgets} active={activeWidget} setActive={setActiveWidget}
                  view={widgetView} setView={setWidgetView}
                  codeAnalysisIds={CODE_ANALYSIS_WIDGET_IDS}
                  onClose={() => setWidgetOpen(false)}
                  accent={accent} />
                
                  </div>
                </> :

            <CollapsedWidgetRail onExpand={() => setWidgetOpen(true)} count={widgets.length} active={activeWidget} setActive={setActiveWidget} widgets={widgets} /> :
            null}
            </>
          )}
        </div>
        </>}
      </div>

      {tweaksOpen &&
      <TweaksFloater tweaks={tweaks} setTweaks={setTweaks} onClose={() => {setTweaksOpen(false);window.parent.postMessage({ type: "__edit_mode_dismissed" }, "*");}} />
      }
    </div>);

}

// ---------- ICON BAR ----------
function IconBar({ active, onChange, sidePanelOpen, onToggleSide, project, setProject, projectOpen, setProjectOpen }) {
  const projectItems = [
  { id: "ask", icon: "sparkles", label: "Ask Teklens" },
  { id: "dashboard", icon: "grid", label: "Dashboard" },
  { id: "workspace", icon: "lab", label: "Context workspace" },
  { id: "roles", icon: "users", label: "Agents" },
  { id: "components", icon: "hierarchy", label: "Components" },
  { id: "settings", icon: "settings", label: "Settings" }];

  const hasProject = !!project;
  return (
    <div className="w-[52px] shrink-0 bg-[#1d1f26] flex flex-col items-center text-[#9ca3af]">
      {/* collapse */}
      <button onClick={onToggleSide} className="w-full h-12 flex items-center justify-center hover:bg-white/5 hover:text-white" title={sidePanelOpen ? "Collapse panel" : "Expand panel"}>
        <Icon name={sidePanelOpen ? "panel-left-close" : "panel-left-open"} size={18} />
      </button>

      <div className="h-px w-7 bg-white/10 my-1" />

      {/* project selector */}
      <div className="flex flex-col gap-0.5 w-full">
        <div className="relative">
          <button onClick={() => setProjectOpen((o) => !o)} title={project ? `Project: ${project}` : "Select a project"}
          className={`relative w-full h-12 flex items-center justify-center ${projectOpen ? "text-white bg-white/5" : "hover:text-white hover:bg-white/5"}`}>
            <span className="relative">
              <Icon name="folder" size={20} className={hasProject ? "text-[#e0b65a]" : ""} />
              <span className="absolute -bottom-1 -right-1.5 w-3.5 h-3.5 rounded-full bg-[#1d1f26] flex items-center justify-center">
                <Icon name="chevron-down" size={11} />
              </span>
            </span>
          </button>
          {projectOpen &&
          <>
              <div className="fixed inset-0 z-20" onClick={() => setProjectOpen(false)} />
              <div className="absolute left-full top-1 ml-1.5 w-56 bg-white rounded-lg border border-[#e8e3d8] shadow-xl z-30 py-1">
                <div className="px-2.5 py-1.5 text-[10.5px] font-semibold tracking-[0.06em] text-[#9aa0a6] uppercase">Projects</div>
                {PROJECTS.map((p) =>
              <button key={p} onClick={() => {setProject(p);setProjectOpen(false);}}
              className="w-full flex items-center gap-2 px-2.5 py-1.5 text-[13px] text-[#1f1f1f] hover:bg-black/[0.04]">
                    <Icon name="folder" size={14} className="text-[#9b8866]" />
                    <span className="flex-1 text-left">{p}</span>
                    {p === project && <Icon name="check" size={14} className="text-[var(--accent)]" />}
                  </button>
              )}
                {project &&
                <>
                  <div className="my-1 h-px bg-[#eee8d6]" />
                  <button onClick={() => {setProject(null);setProjectOpen(false);}}
                  className="w-full flex items-center gap-2 px-2.5 py-1.5 text-[12.5px] text-[#9aa0a6] hover:bg-black/[0.04] hover:text-[#0e0e10]">
                    <Icon name="x" size={13} /> Deselect project
                  </button>
                </>
                }
              </div>
            </>
          }
        </div>
      </div>

      <div className="h-px w-7 bg-white/10 my-1" />

      {/* project-dependent views */}
      <div className="flex flex-col gap-0.5 w-full">
        {projectItems.map((it) =>
        <button key={it.id} onClick={() => hasProject && onChange(it.id)}
        disabled={!hasProject}
        title={hasProject ? it.label : `${it.label} — select a project first`}
        className={`relative w-full h-12 flex items-center justify-center ${
        !hasProject ? "opacity-30 cursor-not-allowed" :
        active === it.id ? "text-white" : "hover:text-white hover:bg-white/5"}`
        }>
            {hasProject && active === it.id && <span className="absolute left-0 top-2 bottom-2 w-[2px] bg-white rounded-r" />}
            <Icon name={it.icon} size={20} />
          </button>
        )}
      </div>

      <div className="flex-1" />
      <button title="Workspace settings" className="w-full h-12 flex items-center justify-center hover:bg-white/5 hover:text-white">
        <Icon name="building" size={18} />
      </button>
    </div>);

}