Q_WORKSPACE_V2.jsx
Design Mockups/Archived Mockups/DOC20 Mockups and Design/DOC20 Archived Mockups/DOC20 Workspace Redo/Q_WORKSPACE_V2.jsx
ELNOR REPO READER TEXT MIRROR
Original path: Design Mockups/Archived Mockups/DOC20 Mockups and Design/DOC20 Archived Mockups/DOC20 Workspace Redo/Q_WORKSPACE_V2.jsx
Source repo: /Users/OpenClaw1/Elnor/Elnor Specs
Git branch: main
Git commit: dbaa25962edc11ab30e8d4ca1715f9ae5bf77331
Generated: 2026-06-09T01:23:58.539Z
---
import { useState, useRef, useCallback, useEffect, useMemo } from "react";
// ─── DESIGN TOKENS (exact match to Q mockup suite) ───
const font = { sans: "'Söhne','Helvetica Neue',-apple-system,BlinkMacSystemFont,sans-serif" };
const R = { sm: "6px", md: "10px", full: "9999px" };
const c = {
bgApp: "#F8F8F6", bgPanel: "#FFFFFF", bgPanelAlt: "#F9FAFB", bgCard: "#FFFFFF",
bgInput: "#EFF1F3", bgSidebar: "#131820", textPri: "#1A1D21", textSec: "#5E6570",
textTer: "#8B919A", accentBtn: "#31588c", warn: "#D97706", error: "#B04040",
border: "#E0E2E5", borderLight: "#ECEEF0", green: "#2E8B57", neutral: "#6B7280",
agentAv: "#a1a7aa", borderDark: "#263040"
};
// ─── ICONS ───
const Ic = ({ d, d2, size = 18, color, sw = 1.75 }) => (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color || "currentColor"} strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round">
<path d={d} />{d2 && <path d={d2} />}
</svg>
);
const I = {
Plus: p => <Ic {...p} d="M12 5v14 M5 12h14" />,
X: p => <Ic {...p} d="M18 6L6 18 M6 6l12 12" />,
Check: p => <Ic {...p} d="M20 6L9 17l-5-5" />,
ChevD: p => <Ic {...p} d="M6 9l6 6 6-6" />,
ChevR: p => <Ic {...p} d="M9 18l6-6-6-6" />,
ChevL: p => <Ic {...p} d="M15 18l-6-6 6-6" />,
Search: p => <Ic {...p} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />,
Spark: p => <Ic {...p} d="M12 2l1.5 4.5L18 8l-4.5 1.5L12 14l-1.5-4.5L6 8l4.5-1.5L12 2z" d2="M12 14l1 3 3 1-3 1-1 3-1-3-3-1 3-1 1-3z" />,
MsgCircle: p => <Ic {...p} d="M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z" />,
Pin: p => <Ic {...p} d="M12 17v5 M9 2l.5 5L7 10l1.5 3h7L17 10l-2.5-3L15 2" />,
FileText: p => <Ic {...p} d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z M14 2v6h6 M16 13H8 M16 17H8" />,
Folder: p => <Ic {...p} d="M22 19a2 2 0 01-2 2H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2v11z" />,
File: p => <Ic {...p} d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z M14 2v6h6" />,
Save: p => <Ic {...p} d="M19 21H5a2 2 0 01-2-2V5a2 2 0 012-2h11l5 5v11a2 2 0 01-2 2z M17 21v-8H7v8 M7 3v5h8" />,
Copy: p => <Ic {...p} d="M20 9h-9a2 2 0 00-2 2v9a2 2 0 002 2h9a2 2 0 002-2v-9a2 2 0 00-2-2z M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" />,
Link: p => <Ic {...p} d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71 M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71" />,
Eye: p => <Ic {...p} d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z M12 9a3 3 0 100 6 3 3 0 000-6z" />,
Edit: p => <Ic {...p} d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7 M18.5 2.5a2.12 2.12 0 013 3L12 15l-4 1 1-4 9.5-9.5z" />,
Undo: p => <Ic {...p} d="M3 7v6h6 M21 17a9 9 0 00-9-9 9 9 0 00-6.69 3L3 13" />,
Redo: p => <Ic {...p} d="M21 7v6h-6 M3 17a9 9 0 019-9 9 9 0 016.69 3L21 13" />,
Maximize: p => <Ic {...p} d="M8 3H5a2 2 0 00-2 2v3m18 0V5a2 2 0 00-2-2h-3m0 18h3a2 2 0 002-2v-3M3 16v3a2 2 0 002 2h3" />,
Trash: p => <Ic {...p} d="M3 6h18 M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2" />,
Archive: p => <Ic {...p} d="M21 8v13H3V8 M1 3h22v5H1z M10 12h4" />,
Settings: p => <Ic {...p} d="M12 15a3 3 0 100-6 3 3 0 000 6z" d2="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 01-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z" />,
Bell: p => <Ic {...p} d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9" d2="M13.73 21a2 2 0 01-3.46 0" />,
Calendar: p => <Ic {...p} d="M19 4H5a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V6a2 2 0 00-2-2z M16 2v4 M8 2v4 M3 10h18" />,
Mail: p => <Ic {...p} d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z M22 6l-10 7L2 6" />,
Zap: p => <Ic {...p} d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" />,
List: p => <Ic {...p} d="M8 6h13 M8 12h13 M8 18h13 M3 6h.01 M3 12h.01 M3 18h.01" />,
Sun: p => <Ic {...p} d="M12 17a5 5 0 100-10 5 5 0 000 10z" d2="M12 1v2 M12 21v2 M4.22 4.22l1.42 1.42 M18.36 18.36l1.42 1.42 M1 12h2 M21 12h2 M4.22 19.78l1.42-1.42 M18.36 5.64l1.42-1.42" />,
};
// ─── SHARED COMPONENTS ───
const Dot = ({ color, size = 8 }) => <span style={{ display: "inline-flex", width: size, height: size, flexShrink: 0 }}><span style={{ display: "block", width: size, height: size, borderRadius: "50%", backgroundColor: color }} /></span>;
const Btn = ({ children, primary, ghost, small, onClick, style: s }) => (
<button onClick={onClick} style={{ padding: small ? "2px 8px" : "5px 14px", borderRadius: R.sm, border: primary ? "none" : `1px solid ${c.border}`, backgroundColor: primary ? c.accentBtn : "transparent", color: primary ? "#fff" : c.textSec, fontSize: small ? 10.5 : 12, fontWeight: primary ? 550 : 450, cursor: "pointer", fontFamily: font.sans, display: "flex", alignItems: "center", gap: 4, height: small ? 22 : 28, ...s }}>{children}</button>
);
const Av = ({ letter, color, size = 20 }) => <div style={{ width: size, height: size, borderRadius: R.sm, backgroundColor: color || c.accentBtn, color: "#fff", display: "flex", alignItems: "center", justifyContent: "center", fontSize: size * .42, fontWeight: 700, flexShrink: 0 }}>{letter}</div>;
const TBtn = ({ icon, title, active, onClick, label, dropdown }) => (
<button onClick={onClick} title={title} style={{ padding: label ? "3px 8px" : "3px 6px", borderRadius: R.sm, border: `1px solid ${active ? c.accentBtn + "40" : c.borderLight}`, backgroundColor: active ? c.accentBtn + "08" : "transparent", cursor: "pointer", display: "flex", alignItems: "center", gap: 4, color: active ? c.accentBtn : c.textSec, fontFamily: font.sans, fontSize: 10.5, fontWeight: active ? 600 : 450, height: 26 }}
onMouseEnter={e => { if (!active) e.currentTarget.style.backgroundColor = c.bgInput }}
onMouseLeave={e => { e.currentTarget.style.backgroundColor = active ? c.accentBtn + "08" : "transparent" }}>
{icon}{label && <span>{label}</span>}{dropdown && <I.ChevD size={8} />}
</button>
);
const Sep = () => <div style={{ width: 1, height: 18, backgroundColor: c.borderLight, margin: "0 3px", flexShrink: 0 }} />;
// ─── BROWSER DATA ───
const typeColors = { Note: c.accentBtn, Chat: c.green, Doc: c.textTer, Task: c.warn, Artifact: "#8B5CF6", Prompt: "#D97706" };
const projects = [{ id: 1, name: "Henderson v. DataCorp", color: "#31588c" }, { id: 2, name: "Quark Research", color: "#2E8B57" }];
const collections = [{ name: "Priority", color: "#B04040" }, { name: "Research", color: "#2E8B57" }, { name: "Draft", color: "#D97706" }, { name: "Archive", color: "#6B7280" }];
const scopeChips = ["Collection", "Project", "Bucket", "Places", "Folders", "Saved Views"];
const typeChips = ["Document", "Chat", "Preset", "Skill", "Task", "Agent", "Overlay", "Note", "Artifact", "Prompt"];
const sortOptions = ["Modified", "Alphabetical", "Type", "Created", "Last Used"];
const browserItems = [
{ type: "Note", title: "Henderson MSJ — Work Notes", time: "2h", pin: true, proj: 1, cols: ["Priority"] },
{ type: "Note", title: "Weekly Task List", time: "4h", pin: true, proj: 1 },
{ type: "Chat", title: "Henderson discovery analysis", time: "2m", unread: true, proj: 1 },
{ type: "Artifact", title: "MSJ Response Brief v3", time: "10m", proj: 1 },
{ type: "Doc", title: "Henderson_Complaint.pdf", time: "1d", proj: 1 },
{ type: "Note", title: "Quark Patent Analysis", time: "1d", proj: 2, cols: ["Research"] },
{ type: "Task", title: "Review batch #4", time: "2h", proj: 1, st: "running" },
{ type: "Chat", title: "Quark patent search", time: "1h", proj: 2 },
{ type: "Artifact", title: "Henderson Timeline Analysis", time: "2h", proj: 1 },
{ type: "Doc", title: "Patent_US20240001.pdf", time: "2d", proj: 2 },
{ type: "Note", title: "Judge Chen Conference Notes", time: "3d", proj: 1 },
{ type: "Task", title: "Draft motion response", time: "4h", proj: 1, st: "waiting" },
{ type: "Artifact", title: "Privilege Log Summary v3", time: "3d", proj: 1 },
{ type: "Prompt", title: "Discovery Review Template", time: "1w" },
];
// ─── NOTES SIDEBAR DATA ───
const noteFolders = [
{ id: "nf1", title: "Henderson Case", parent: null },
{ id: "nf2", title: "Privilege Issues", parent: "nf1" },
{ id: "nf3", title: "Motion Practice", parent: "nf1" },
{ id: "nf4", title: "Quark Patents", parent: null },
];
const noteList = [
{ id: "n1", title: "Henderson MSJ — Work Notes", folder: "nf3", mod: "2h", comments: 3, pinned: true, pending: 2, proj: "Henderson", projColor: c.accentBtn },
{ id: "n2", title: "Weekly Task List", folder: null, mod: "4h", comments: 0, pinned: true, proj: "Henderson", projColor: c.accentBtn },
{ id: "n3", title: "Judge Chen Conference Notes", folder: "nf3", mod: "3d", comments: 2, proj: "Henderson", projColor: c.accentBtn },
{ id: "n4", title: "Quark Patent Analysis", folder: "nf4", mod: "1d", comments: 1, proj: "Quark", projColor: c.green },
{ id: "n5", title: "Expert Disclosure Draft — Christensen", folder: "nf3", mod: "5d", comments: 0 },
{ id: "n6", title: "ELNOR Architecture Notes", folder: null, mod: "1w", comments: 0 },
];
const todoLists = [
{ id: "tl1", title: "Today", icon: "☀️", count: 5 },
{ id: "tl2", title: "Henderson Tasks", icon: "⚖️", count: 8 },
{ id: "tl3", title: "Weekly Review", icon: "📋", count: 3 },
];
// ─── TO-DO DATA ───
const initTodos = [
{ id: "t1", text: "Draft expert disclosure for Christensen", done: false, pri: 1, due: "Apr 4", proj: "Folb", sub: [
{ id: "s1", text: "Pull Christensen CV", done: true }, { id: "s2", text: "List opinions", done: false }, { id: "s3", text: "Identify docs reviewed", done: false }
]},
{ id: "t2", text: "Review Henderson MSJ brief — Elnor's tracked changes", done: false, pri: 1, due: "Mar 20", proj: "Henderson", sub: [] },
{ id: "t3", text: "Respond to Sparacino re: Narayanan agreement", done: false, pri: 2, due: "Mar 19", sub: [] },
{ id: "t4", text: "Follow up: opposing counsel discovery extension", done: false, pri: 2, due: "Mar 19", proj: "Henderson", sub: [] },
{ id: "t5", text: "Review Quark patent analysis — new filings", done: false, pri: 3, proj: "Quark", sub: [] },
{ id: "t6", text: "File Folb trial exhibit list", done: true, pri: 2, due: "Mar 17", proj: "Folb", sub: [] },
];
// ─── ELNOR FEED DATA ───
const elnorFeed = [
{ id: "e1", text: "Reviewed 3 Henderson deposition transcripts — flagged 2 citation issues in Chen depo", time: "5h ago", type: "task" },
{ id: "e2", text: "Updated Quark patent landscape — 4 new filings", time: "4h ago", type: "task" },
{ id: "e3", text: "Expert disclosure deadline — Folb v. City of LA", time: "47 days", type: "deadline", accent: c.error },
{ id: "e4", text: "Henderson MSJ response due", time: "12 days", type: "deadline", accent: c.warn },
{ id: "e5", text: "Sparacino — Narayanan agreement redline", time: "Yesterday", type: "email" },
{ id: "e6", text: "Opposing counsel — discovery extension request", time: "2d ago", type: "email", accent: c.warn },
{ id: "e7", text: "OneDrive sync paused — re-auth needed", time: "6h ago", type: "system", accent: c.warn },
{ id: "e8", text: "9th Cir: new opinion on scienter standard", time: "Yesterday", type: "news", accent: c.accentBtn },
];
// ─── NOTE CONTENT ───
const noteBody = [
{ type: "h2", text: "Key Arguments to Strengthen" },
{ type: "p", text: "1. Scienter — CFO Chen's \"do NOT share\" email is strongest evidence. Cross-ref with internal audit (Ex. 47). Elnor flagged additional Chen emails from July board prep." },
{ type: "p", text: "2. Loss causation — need Bloomberg data for exact trading window. Stock drop 34% on Oct 15 disclosure." },
{ type: "ai", author: "Elnor", text: "I found 3 additional Chen emails from the July board prep folder that strengthen scienter. Want me to pull the relevant excerpts into this note?", time: "2h ago" },
{ type: "h2", text: "Outstanding Research" },
{ type: "p", text: "- Check if Vivendi citation is still good law in 2d Cir — @Elnor reviewing" },
{ type: "p", text: "- PSLRA safe harbor scope after Omnicare — need to distinguish" },
{ type: "p", text: "- Damages calculation methodology — waiting on Christensen" },
{ type: "h2", text: "Deposition Notes" },
{ type: "p", text: "Chen depo key admissions: knew projections were stale by June 28, presented \"strong growth\" narrative anyway at July earnings call." },
];
const initComments = [
{ id: "c1", author: "You", color: c.accentBtn, body: "Strengthen scienter argument — Chen emails are key.", time: "2h", anchor: "CFO Chen's \"do NOT share\" email" },
{ id: "c2", author: "Elnor", color: c.agentAv, body: "Found 3 additional Chen emails from July board prep. Cross-ref Ex. 47 for timeline.", time: "2h", isAgent: true },
{ id: "c3", author: "You", color: c.accentBtn, body: "Check Vivendi cite — still good law?", time: "1h", anchor: "In re Vivendi Universal" },
];
// ═══════════════════════════════════════════════════════════════
// MAIN COMPONENT
// ═══════════════════════════════════════════════════════════════
export default function WorkspaceV2() {
// Browser state
const [activeScope, setActiveScope] = useState("Project");
const [activeProjIdx, setActiveProjIdx] = useState(0);
const [activeTypes, setActiveTypes] = useState(new Set());
const [selectedCollections, setSelectedCollections] = useState(new Set());
const [sortKey, setSortKey] = useState("Modified");
const [sortDrop, setSortDrop] = useState(false);
const [selectedBrowserIdx, setSelectedBrowserIdx] = useState(null);
const [searchQ, setSearchQ] = useState("");
// Notes sidebar
const [sidebarTab, setSidebarTab] = useState("notes"); // notes | todos
const [expandedFolders, setExpandedFolders] = useState(new Set(["nf1"]));
const [activeNoteId, setActiveNoteId] = useState("n1");
const [noteSearch, setNoteSearch] = useState("");
// Editor
const [rightPanel, setRightPanel] = useState(null); // null | comments | send
// To-do
const [todos, setTodos] = useState(initTodos);
const [expandedTodo, setExpandedTodo] = useState("t1");
const [todoCollapsed, setTodoCollapsed] = useState(false);
const [elnorCollapsed, setElnorCollapsed] = useState(true);
const [newTodoText, setNewTodoText] = useState("");
const [expandedElnor, setExpandedElnor] = useState(null);
const toggleTodo = id => setTodos(p => p.map(t => t.id === id ? { ...t, done: !t.done } : t));
const toggleSub = (pid, sid) => setTodos(p => p.map(t => t.id === pid ? { ...t, sub: t.sub.map(s => s.id === sid ? { ...s, done: !s.done } : s) } : t));
const toggleFolder = id => setExpandedFolders(p => { const n = new Set(p); n.has(id) ? n.delete(id) : n.add(id); return n; });
const priColor = p => p === 1 ? c.error : p === 2 ? c.warn : c.accentBtn;
const priLabel = p => p === 1 ? "P1" : p === 2 ? "P2" : "P3";
const activeTodos = todos.filter(t => !t.done);
const doneTodos = todos.filter(t => t.done);
const filtered = useMemo(() => {
let items = browserItems;
if (activeScope === "Project") items = items.filter(i => i.proj === projects[activeProjIdx].id);
if (activeTypes.size > 0) items = items.filter(i => activeTypes.has(i.type));
if (searchQ) items = items.filter(i => i.title.toLowerCase().includes(searchQ.toLowerCase()));
return items;
}, [activeScope, activeProjIdx, activeTypes, searchQ]);
// Render folder tree
const renderFolders = (parentId, depth = 0) => {
const children = noteFolders.filter(f => f.parent === parentId);
return children.map(f => (
<div key={f.id}>
<div onClick={() => toggleFolder(f.id)} style={{ display: "flex", alignItems: "center", gap: 4, padding: "4px 6px", paddingLeft: 6 + depth * 14, cursor: "pointer", borderRadius: R.sm, fontSize: 11.5, color: c.textPri, fontWeight: expandedFolders.has(f.id) ? 600 : 450 }}
onMouseEnter={e => e.currentTarget.style.backgroundColor = c.bgInput}
onMouseLeave={e => e.currentTarget.style.backgroundColor = "transparent"}>
<div style={{ transform: expandedFolders.has(f.id) ? "rotate(90deg)" : "none", transition: "transform 0.1s" }}>
<I.ChevR size={9} color={c.textTer} />
</div>
<I.Folder size={12} color={c.warn} />
<span style={{ flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{f.title}</span>
</div>
{expandedFolders.has(f.id) && renderFolders(f.id, depth + 1)}
</div>
));
};
const typeIcon = t => {
if (t === "task") return <I.Check size={9} color={c.green} />;
if (t === "deadline") return <I.Calendar size={9} color={c.error} />;
if (t === "email") return <I.Mail size={9} color={c.accentBtn} />;
if (t === "system") return <I.Bell size={9} color={c.warn} />;
if (t === "news") return <I.Zap size={9} color={c.green} />;
return <I.Spark size={9} />;
};
return (
<div style={{ display: "flex", height: "100vh", fontFamily: font.sans, backgroundColor: c.bgApp, color: c.textPri, fontSize: 13 }}>
{/* ═══ BROWSER COLUMN (full Q_BROWSER_R13 style) ═══ */}
<div style={{ width: 270, borderRight: `1px solid ${c.border}`, backgroundColor: c.bgPanel, display: "flex", flexDirection: "column", flexShrink: 0 }}>
{/* Search */}
<div style={{ padding: "8px 8px 6px", borderBottom: `1px solid ${c.borderLight}` }}>
<div style={{ display: "flex", alignItems: "center", gap: 4, padding: "5px 8px", borderRadius: R.sm, backgroundColor: c.bgInput }}>
<I.Search size={12} color={c.textTer} />
<input value={searchQ} onChange={e => setSearchQ(e.target.value)} placeholder="Search everything…" style={{ flex: 1, border: "none", outline: "none", backgroundColor: "transparent", fontSize: 11.5, fontFamily: font.sans, color: c.textPri }} />
{searchQ && <button onClick={() => setSearchQ("")} style={{ border: "none", background: "none", cursor: "pointer", padding: 0 }}><I.X size={10} color={c.textTer} /></button>}
</div>
</div>
{/* Scope row */}
<div style={{ padding: "5px 8px 3px", borderBottom: `1px solid ${c.borderLight}` }}>
<div style={{ display: "flex", gap: 3, flexWrap: "wrap" }}>
{scopeChips.map(s => (
<span key={s} onClick={() => setActiveScope(activeScope === s ? null : s)} style={{ padding: "2px 7px", borderRadius: R.sm, border: `1px solid ${activeScope === s ? c.accentBtn + "50" : c.borderLight}`, fontSize: 9.5, color: activeScope === s ? c.accentBtn : c.textTer, backgroundColor: activeScope === s ? c.accentBtn + "08" : "transparent", cursor: "pointer", fontWeight: activeScope === s ? 600 : 400 }}>{s}</span>
))}
</div>
</div>
{/* Scope detail */}
{activeScope === "Project" && (
<div style={{ padding: "4px 8px", borderBottom: `1px solid ${c.borderLight}`, backgroundColor: c.bgPanelAlt }}>
{projects.map((p, i) => (
<div key={p.id} onClick={() => setActiveProjIdx(i)} style={{ display: "flex", alignItems: "center", gap: 6, padding: "4px 8px", borderRadius: R.sm, cursor: "pointer", backgroundColor: i === activeProjIdx ? c.accentBtn + "08" : "transparent", fontWeight: i === activeProjIdx ? 600 : 400 }}
onMouseEnter={e => { if (i !== activeProjIdx) e.currentTarget.style.backgroundColor = c.bgInput }}
onMouseLeave={e => { e.currentTarget.style.backgroundColor = i === activeProjIdx ? c.accentBtn + "08" : "transparent" }}>
<Dot color={p.color} size={6} />
<span style={{ fontSize: 11, color: i === activeProjIdx ? c.accentBtn : c.textSec }}>{p.name}</span>
</div>
))}
</div>
)}
{/* Collection dots */}
<div style={{ padding: "4px 8px", borderBottom: `1px solid ${c.borderLight}`, display: "flex", gap: 4, alignItems: "center" }}>
{collections.map(col => (
<span key={col.name} onClick={() => setSelectedCollections(p => { const n = new Set(p); n.has(col.name) ? n.delete(col.name) : n.add(col.name); return n; })} title={col.name} style={{ width: 10, height: 10, borderRadius: "50%", backgroundColor: col.color, cursor: "pointer", border: selectedCollections.has(col.name) ? `2px solid ${c.textPri}` : "2px solid transparent", boxSizing: "border-box" }} />
))}
<span style={{ fontSize: 9, color: c.textTer, marginLeft: 4 }}>Collections</span>
</div>
{/* Type chips */}
<div style={{ padding: "4px 8px 5px", borderBottom: `1px solid ${c.borderLight}` }}>
<div style={{ display: "flex", gap: 3, flexWrap: "wrap" }}>
{typeChips.map(t => (
<span key={t} onClick={() => setActiveTypes(p => { const n = new Set(p); n.has(t) ? n.delete(t) : n.add(t); return n; })} style={{ padding: "1px 6px", borderRadius: 3, fontSize: 9, color: activeTypes.has(t) ? typeColors[t] || c.accentBtn : c.textTer, border: `1px solid ${activeTypes.has(t) ? (typeColors[t] || c.accentBtn) + "50" : c.borderLight}`, backgroundColor: activeTypes.has(t) ? (typeColors[t] || c.accentBtn) + "08" : "transparent", cursor: "pointer", fontWeight: activeTypes.has(t) ? 600 : 400 }}>{t}</span>
))}
{activeTypes.size > 0 && <span onClick={() => setActiveTypes(new Set())} style={{ fontSize: 9, color: c.textTer, cursor: "pointer", padding: "1px 4px" }}>clear</span>}
</div>
</div>
{/* Sort bar */}
<div style={{ padding: "3px 8px", borderBottom: `1px solid ${c.borderLight}`, display: "flex", alignItems: "center", gap: 4, fontSize: 9.5, color: c.textTer }}>
<span>{filtered.length} items</span>
<span style={{ flex: 1 }} />
<span style={{ position: "relative" }}>
<span onClick={() => setSortDrop(!sortDrop)} style={{ cursor: "pointer", display: "flex", alignItems: "center", gap: 2 }}>{sortKey} <I.ChevD size={8} /></span>
{sortDrop && <div style={{ position: "absolute", top: "100%", right: 0, backgroundColor: c.bgCard, border: `1px solid ${c.border}`, borderRadius: R.sm, boxShadow: "0 4px 12px rgba(0,0,0,0.1)", zIndex: 50, padding: 3, minWidth: 100 }}>
{sortOptions.map(s => <div key={s} onClick={() => { setSortKey(s); setSortDrop(false) }} style={{ padding: "4px 8px", fontSize: 10, cursor: "pointer", borderRadius: 3, backgroundColor: s === sortKey ? c.accentBtn + "08" : "transparent", fontWeight: s === sortKey ? 600 : 400, color: s === sortKey ? c.accentBtn : c.textSec }}
onMouseEnter={e => { if (s !== sortKey) e.currentTarget.style.backgroundColor = c.bgInput }}
onMouseLeave={e => { e.currentTarget.style.backgroundColor = s === sortKey ? c.accentBtn + "08" : "transparent" }}>{s}</div>)}
</div>}
</span>
</div>
{/* Results */}
<div style={{ flex: 1, overflowY: "auto" }}>
{filtered.map((item, i) => (
<div key={i} onClick={() => setSelectedBrowserIdx(i)} style={{ display: "flex", alignItems: "center", gap: 6, padding: "6px 8px", height: 32, borderBottom: `1px solid ${c.borderLight}`, cursor: "pointer", backgroundColor: selectedBrowserIdx === i ? c.accentBtn + "08" : "transparent" }}
onMouseEnter={e => { if (selectedBrowserIdx !== i) e.currentTarget.style.backgroundColor = c.bgPanelAlt }}
onMouseLeave={e => { if (selectedBrowserIdx !== i) e.currentTarget.style.backgroundColor = "transparent" }}>
{item.pin && <I.Pin size={8} color={c.warn} />}
{item.unread && <Dot color={c.accentBtn} size={4} />}
<span style={{ flex: 1, minWidth: 0, fontSize: 11.5, fontWeight: item.unread ? 600 : 450, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{item.title}</span>
{item.st && <span style={{ fontSize: 8.5, fontWeight: 600, color: item.st === "running" ? c.accentBtn : c.warn, textTransform: "uppercase" }}>{item.st}</span>}
<span style={{ fontSize: 8.5, fontWeight: 600, color: typeColors[item.type] || c.textTer, textTransform: "uppercase", letterSpacing: ".03em", flexShrink: 0 }}>{item.type}</span>
<span style={{ fontSize: 9, color: c.textTer, flexShrink: 0, minWidth: 18, textAlign: "right" }}>{item.time}</span>
</div>
))}
{filtered.length === 0 && <div style={{ padding: 16, fontSize: 11, color: c.textTer, textAlign: "center", fontStyle: "italic" }}>No items match</div>}
</div>
{/* Footer */}
<div style={{ padding: "3px 8px", borderTop: `1px solid ${c.borderLight}`, fontSize: 9, color: c.textTer, display: "flex", gap: 4 }}>
{activeScope && <span>{activeScope}</span>}
{activeScope === "Project" && <span>· {projects[activeProjIdx].name}</span>}
{selectedCollections.size > 0 && <span>· {[...selectedCollections].join(", ")}</span>}
<span style={{ marginLeft: "auto" }}>{sortKey}</span>
</div>
</div>
{/* ═══ NOTES SIDEBAR (from Q_NOTES_FULL) ═══ */}
<div style={{ width: 220, borderRight: `1px solid ${c.border}`, backgroundColor: c.bgPanelAlt, display: "flex", flexDirection: "column", flexShrink: 0 }}>
{/* Tab bar: Notes | To-Do Lists */}
<div style={{ display: "flex", borderBottom: `1px solid ${c.borderLight}` }}>
{[{ id: "notes", label: "Notes", icon: <I.FileText size={11} /> }, { id: "todos", label: "To-Do Lists", icon: <I.List size={11} /> }].map(tab => (
<button key={tab.id} onClick={() => setSidebarTab(tab.id)} style={{ flex: 1, padding: "7px 0", border: "none", cursor: "pointer", fontFamily: font.sans, fontSize: 10, fontWeight: sidebarTab === tab.id ? 650 : 450, color: sidebarTab === tab.id ? c.accentBtn : c.textTer, backgroundColor: sidebarTab === tab.id ? c.accentBtn + "06" : "transparent", borderBottom: sidebarTab === tab.id ? `2px solid ${c.accentBtn}` : "2px solid transparent", display: "flex", alignItems: "center", justifyContent: "center", gap: 4 }}>
{tab.icon}{tab.label}
</button>
))}
</div>
{sidebarTab === "notes" && <>
{/* Search + sort */}
<div style={{ padding: "6px 8px 4px", borderBottom: `1px solid ${c.borderLight}` }}>
<div style={{ display: "flex", alignItems: "center", gap: 4, padding: "4px 6px", borderRadius: R.sm, backgroundColor: c.bgInput, marginBottom: 4 }}>
<I.Search size={10} color={c.textTer} />
<input value={noteSearch} onChange={e => setNoteSearch(e.target.value)} placeholder="Search notes…" style={{ flex: 1, border: "none", outline: "none", backgroundColor: "transparent", fontSize: 10.5, fontFamily: font.sans }} />
</div>
<div style={{ display: "flex", gap: 4, alignItems: "center" }}>
<button style={{ padding: "2px 6px", borderRadius: 3, border: `1px solid ${c.borderLight}`, backgroundColor: "transparent", cursor: "pointer", fontSize: 9, fontFamily: font.sans, color: c.textTer, display: "flex", alignItems: "center", gap: 3 }}><I.Folder size={9} /> +Folder</button>
<button style={{ padding: "2px 6px", borderRadius: 3, border: `1px solid ${c.borderLight}`, backgroundColor: "transparent", cursor: "pointer", fontSize: 9, fontFamily: font.sans, color: c.textTer, display: "flex", alignItems: "center", gap: 3 }}><I.FileText size={9} /> +Note</button>
<span style={{ flex: 1 }} />
<span style={{ fontSize: 8.5, color: c.textTer }}>Modified ▾</span>
</div>
</div>
{/* Folder tree */}
<div style={{ flex: 1, overflowY: "auto" }}>
<div style={{ padding: "4px 4px" }}>{renderFolders(null)}</div>
{/* Note rows */}
{noteList.map(note => (
<div key={note.id} onClick={() => setActiveNoteId(note.id)} style={{ display: "flex", alignItems: "center", gap: 5, padding: "5px 8px", cursor: "pointer", borderLeft: activeNoteId === note.id ? `3px solid ${c.accentBtn}` : "3px solid transparent", backgroundColor: activeNoteId === note.id ? c.accentBtn + "06" : "transparent" }}
onMouseEnter={e => { if (activeNoteId !== note.id) e.currentTarget.style.backgroundColor = c.bgInput }}
onMouseLeave={e => { if (activeNoteId !== note.id) e.currentTarget.style.backgroundColor = "transparent" }}>
{note.pinned && <I.Pin size={8} color={c.warn} />}
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontSize: 11, fontWeight: activeNoteId === note.id ? 650 : 450, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{note.title}</div>
<div style={{ display: "flex", gap: 4, alignItems: "center", marginTop: 1 }}>
{note.proj && <><Dot color={note.projColor} size={4} /><span style={{ fontSize: 8.5, color: c.textTer }}>{note.proj}</span></>}
<span style={{ fontSize: 8.5, color: c.textTer }}>{note.mod}</span>
{note.comments > 0 && <span style={{ fontSize: 8.5, color: c.textTer }}>💬{note.comments}</span>}
{note.pending > 0 && <span style={{ fontSize: 8.5, color: c.warn }}>✏{note.pending}</span>}
</div>
</div>
</div>
))}
</div>
<div style={{ padding: "3px 8px", borderTop: `1px solid ${c.borderLight}`, fontSize: 8.5, color: c.textTer }}>{noteList.length} notes · Modified</div>
</>}
{sidebarTab === "todos" && <>
<div style={{ padding: "6px 8px 4px", borderBottom: `1px solid ${c.borderLight}`, display: "flex", alignItems: "center", gap: 4 }}>
<button style={{ padding: "2px 6px", borderRadius: 3, border: `1px solid ${c.borderLight}`, backgroundColor: "transparent", cursor: "pointer", fontSize: 9, fontFamily: font.sans, color: c.textTer, display: "flex", alignItems: "center", gap: 3 }}><I.Plus size={9} /> New List</button>
</div>
<div style={{ flex: 1, overflowY: "auto" }}>
{todoLists.map(list => (
<div key={list.id} style={{ display: "flex", alignItems: "center", gap: 6, padding: "7px 10px", cursor: "pointer", borderLeft: list.id === "tl1" ? `3px solid ${c.accentBtn}` : "3px solid transparent", backgroundColor: list.id === "tl1" ? c.accentBtn + "06" : "transparent" }}
onMouseEnter={e => { if (list.id !== "tl1") e.currentTarget.style.backgroundColor = c.bgInput }}
onMouseLeave={e => { if (list.id !== "tl1") e.currentTarget.style.backgroundColor = list.id === "tl1" ? c.accentBtn + "06" : "transparent" }}>
<span style={{ fontSize: 13 }}>{list.icon}</span>
<span style={{ flex: 1, fontSize: 11.5, fontWeight: list.id === "tl1" ? 650 : 450 }}>{list.title}</span>
<span style={{ fontSize: 9, color: c.textTer, backgroundColor: c.bgInput, padding: "1px 5px", borderRadius: 3 }}>{list.count}</span>
</div>
))}
</div>
</>}
</div>
{/* ═══ MAIN WORKSPACE ═══ */}
<div style={{ flex: 1, display: "flex", flexDirection: "column", minWidth: 0 }}>
{/* ─── FULL NOTES TOOLBAR (from Q_NOTES_FULL) ─── */}
<div style={{ padding: "0 8px", borderBottom: `1px solid ${c.border}`, display: "flex", alignItems: "center", gap: 3, flexWrap: "wrap", backgroundColor: c.bgPanel, minHeight: 34 }}>
{/* Paragraph selector */}
<TBtn label="Normal ▾" />
<Sep />
<TBtn icon={<span style={{ fontWeight: 700, fontSize: 11 }}>B</span>} title="Bold" />
<TBtn icon={<span style={{ fontStyle: "italic", fontSize: 11 }}>I</span>} title="Italic" />
<TBtn icon={<span style={{ textDecoration: "underline", fontSize: 11 }}>U</span>} title="Underline" />
<Sep />
<TBtn icon={<I.Undo size={13} />} title="Undo" />
<TBtn icon={<I.Redo size={13} />} title="Redo" />
<Sep />
<TBtn icon={<I.Copy size={12} />} title="Copy" />
<TBtn icon={<I.Save size={12} />} label="Save As…" dropdown />
<TBtn icon={<I.Link size={12} />} label="Ref" title="Copy reference" />
<TBtn icon={<I.Search size={12} />} title="Find (⌘F)" />
<TBtn icon={<I.Maximize size={12} />} title="Full Screen" />
<Sep />
<TBtn icon={<I.MsgCircle size={12} />} label="3" active={rightPanel === "comments"} onClick={() => setRightPanel(rightPanel === "comments" ? null : "comments")} />
<Sep />
<TBtn icon={<I.Eye size={12} />} label="Markup" active title="Markup / Clean toggle" />
<TBtn icon={<I.Edit size={12} />} label="2 ▾" title="Review: Accept All / Reject All" />
<div style={{ flex: 1 }} />
<TBtn icon={<I.Spark size={12} />} label="Send to Agent" active={rightPanel === "send"} onClick={() => setRightPanel(rightPanel === "send" ? null : "send")} />
<div style={{ marginLeft: 6, fontSize: 9, color: c.green }}>● Saved</div>
</div>
{/* ─── CONTENT SPLIT: Editor + ToDo/Elnor column ─── */}
<div style={{ flex: 1, display: "flex", overflow: "hidden" }}>
{/* ─── NOTE EDITOR ─── */}
<div style={{ flex: 1, display: "flex", flexDirection: "column", minWidth: 0 }}>
<div style={{ flex: 1, overflowY: "auto", padding: "16px 24px 40px" }}>
<div contentEditable suppressContentEditableWarning style={{ fontSize: 21, fontWeight: 700, outline: "none", marginBottom: 12, paddingBottom: 8, borderBottom: `1px solid ${c.borderLight}` }}>Henderson MSJ — Work Notes</div>
{noteBody.map((block, i) => {
if (block.type === "h2") return <h2 key={i} style={{ fontSize: 15, fontWeight: 700, margin: "18px 0 6px" }}>{block.text}</h2>;
if (block.type === "ai") return (
<div key={i} style={{ margin: "10px 0", padding: "10px 12px", borderRadius: R.sm, border: `1px solid ${c.accentBtn}20`, backgroundColor: c.accentBtn + "04", display: "flex", gap: 8 }}>
<Av letter="E" color={c.agentAv} size={22} />
<div style={{ flex: 1 }}>
<div style={{ display: "flex", alignItems: "center", gap: 5, marginBottom: 3 }}>
<span style={{ fontSize: 11, fontWeight: 650, color: c.agentAv }}>Elnor</span>
<span style={{ fontSize: 9, color: c.textTer }}>{block.time}</span>
</div>
<div style={{ fontSize: 12, color: c.textSec, lineHeight: 1.6 }}>{block.text}</div>
<div style={{ display: "flex", gap: 6, marginTop: 6 }}>
<Btn small primary><I.Check size={10} color="#fff" /> Yes</Btn>
<Btn small ghost>Dismiss</Btn>
<Btn small ghost>Reply</Btn>
</div>
</div>
</div>
);
return <p key={i} contentEditable suppressContentEditableWarning style={{ fontSize: 13, color: c.textSec, lineHeight: 1.7, margin: "5px 0", outline: "none" }}>{block.text}</p>;
})}
</div>
{/* Note footer */}
<div style={{ padding: "4px 16px", borderTop: `1px solid ${c.borderLight}`, fontSize: 9.5, color: c.textTer, display: "flex", gap: 8, backgroundColor: c.bgPanel }}>
<span style={{ display: "flex", alignItems: "center", gap: 3 }}><I.Spark size={9} color={c.agentAv} /> Elnor in Henderson discovery</span>
<span>·</span><Dot color={c.accentBtn} size={5} /><span>Henderson v. DataCorp</span>
<span>·</span><span>2h ago</span>
<span>·</span><span style={{ color: c.warn }}>2 pending changes</span>
</div>
</div>
{/* ─── TO-DO + ELNOR COLUMN ─── */}
<div style={{ width: 310, borderLeft: `1px solid ${c.border}`, display: "flex", flexDirection: "column", backgroundColor: c.bgPanelAlt, flexShrink: 0 }}>
{/* === MY TASKS === */}
<div style={{ borderBottom: `1px solid ${c.borderLight}` }}>
<div onClick={() => setTodoCollapsed(!todoCollapsed)} style={{ padding: "7px 10px", display: "flex", alignItems: "center", gap: 6, cursor: "pointer", backgroundColor: c.bgPanel }}>
<div style={{ transform: todoCollapsed ? "none" : "rotate(90deg)", transition: "transform 0.1s" }}><I.ChevR size={10} color={c.textTer} /></div>
<span style={{ fontSize: 12, fontWeight: 700, flex: 1 }}>Today</span>
<span style={{ fontSize: 9, color: c.textTer, backgroundColor: c.bgInput, padding: "1px 6px", borderRadius: 3 }}>{activeTodos.length}</span>
<button style={{ border: "none", background: "none", cursor: "pointer", padding: 0, display: "flex" }}><I.Settings size={12} color={c.textTer} /></button>
</div>
</div>
{!todoCollapsed && (
<div style={{ flex: 1, overflowY: "auto" }}>
<div style={{ padding: "4px 6px" }}>
{activeTodos.map(todo => (
<div key={todo.id} style={{ marginBottom: 1, borderRadius: R.sm, backgroundColor: c.bgCard, border: `1px solid ${expandedTodo === todo.id ? c.accentBtn + "25" : c.borderLight}` }}>
<div style={{ display: "flex", alignItems: "flex-start", gap: 5, padding: "5px 8px", cursor: "pointer" }} onClick={() => setExpandedTodo(expandedTodo === todo.id ? null : todo.id)}>
<input type="checkbox" checked={false} onChange={() => toggleTodo(todo.id)} onClick={e => e.stopPropagation()} style={{ width: 13, height: 13, accentColor: c.accentBtn, marginTop: 2, flexShrink: 0 }} />
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontSize: 11.5, fontWeight: 500, lineHeight: 1.35 }}>{todo.text}</div>
<div style={{ display: "flex", gap: 5, marginTop: 2, alignItems: "center", flexWrap: "wrap" }}>
<span style={{ fontSize: 8, fontWeight: 700, color: priColor(todo.pri), border: `1px solid ${priColor(todo.pri)}30`, borderRadius: 2, padding: "0 3px" }}>{priLabel(todo.pri)}</span>
{todo.due && <span style={{ fontSize: 8.5, color: c.textTer }}>{todo.due}</span>}
{todo.proj && <span style={{ fontSize: 8.5, color: c.accentBtn }}>{todo.proj}</span>}
{todo.sub.length > 0 && <span style={{ fontSize: 8.5, color: c.textTer }}>{todo.sub.filter(s => s.done).length}/{todo.sub.length}</span>}
</div>
</div>
<div style={{ transform: expandedTodo === todo.id ? "rotate(90deg)" : "none", transition: "transform 0.1s", marginTop: 3 }}><I.ChevR size={9} color={c.textTer} /></div>
</div>
{expandedTodo === todo.id && (
<div style={{ padding: "0 8px 6px 26px", borderTop: `1px solid ${c.borderLight}` }}>
{todo.sub.map(s => (
<div key={s.id} style={{ display: "flex", alignItems: "center", gap: 5, padding: "2px 0" }}>
<input type="checkbox" checked={s.done} onChange={() => toggleSub(todo.id, s.id)} style={{ width: 11, height: 11, accentColor: c.accentBtn }} />
<span style={{ fontSize: 10.5, color: s.done ? c.textTer : c.textSec, textDecoration: s.done ? "line-through" : "none" }}>{s.text}</span>
</div>
))}
<div style={{ display: "flex", gap: 4, marginTop: 4 }}>
<Btn small ghost><I.Spark size={9} color={c.agentAv} /> @Elnor</Btn>
<Btn small ghost><I.Plus size={9} /> Sub</Btn>
<Btn small ghost><I.FileText size={9} /> Note</Btn>
</div>
</div>
)}
</div>
))}
{/* Add task */}
<div style={{ display: "flex", alignItems: "center", gap: 5, padding: "5px 8px", borderRadius: R.sm, border: `1px dashed ${c.borderLight}`, marginTop: 4 }}>
<I.Plus size={10} color={c.textTer} />
<input value={newTodoText} onChange={e => setNewTodoText(e.target.value)} placeholder="Add task… (type @Elnor to assign)" onKeyDown={e => {
if (e.key === "Enter" && newTodoText.trim()) { setTodos(p => [...p, { id: "t" + Date.now(), text: newTodoText, done: false, pri: 3, sub: [] }]); setNewTodoText(""); }
}} style={{ flex: 1, border: "none", outline: "none", fontSize: 10.5, fontFamily: font.sans, backgroundColor: "transparent" }} />
</div>
{/* Done */}
{doneTodos.length > 0 && (
<div style={{ marginTop: 8 }}>
<div style={{ fontSize: 9, fontWeight: 650, color: c.textTer, textTransform: "uppercase", letterSpacing: ".05em", padding: "3px 0" }}>Done ({doneTodos.length})</div>
{doneTodos.map(t => (
<div key={t.id} style={{ display: "flex", alignItems: "center", gap: 5, padding: "3px 8px", opacity: 0.45 }}>
<input type="checkbox" checked onChange={() => toggleTodo(t.id)} style={{ width: 12, height: 12, accentColor: c.accentBtn }} />
<span style={{ fontSize: 10.5, textDecoration: "line-through", color: c.textTer }}>{t.text}</span>
</div>
))}
</div>
)}
</div>
{/* === ELNOR FEED === */}
<div style={{ borderTop: `1px solid ${c.borderLight}`, marginTop: 4 }}>
<div onClick={() => setElnorCollapsed(!elnorCollapsed)} style={{ padding: "7px 10px", display: "flex", alignItems: "center", gap: 6, cursor: "pointer", backgroundColor: c.bgPanel }}>
<div style={{ transform: elnorCollapsed ? "none" : "rotate(90deg)", transition: "transform 0.1s" }}><I.ChevR size={10} color={c.textTer} /></div>
<I.Spark size={12} color={c.agentAv} />
<span style={{ fontSize: 12, fontWeight: 700, flex: 1 }}>Elnor</span>
<span style={{ fontSize: 9, color: c.textTer, backgroundColor: c.bgInput, padding: "1px 6px", borderRadius: 3 }}>{elnorFeed.length}</span>
</div>
{!elnorCollapsed && (
<div style={{ padding: "2px 6px 6px" }}>
{elnorFeed.map(item => (
<div key={item.id} onClick={() => setExpandedElnor(expandedElnor === item.id ? null : item.id)} style={{ display: "flex", alignItems: "flex-start", gap: 5, padding: "4px 6px", borderRadius: R.sm, cursor: "pointer", marginBottom: 1 }}
onMouseEnter={e => e.currentTarget.style.backgroundColor = c.bgInput}
onMouseLeave={e => e.currentTarget.style.backgroundColor = "transparent"}>
{typeIcon(item.type)}
{item.accent && <Dot color={item.accent} size={4} />}
<span style={{ flex: 1, fontSize: 10.5, color: c.textSec, lineHeight: 1.35 }}>{item.text}</span>
<span style={{ fontSize: 8.5, color: c.textTer, flexShrink: 0, whiteSpace: "nowrap" }}>{item.time}</span>
</div>
))}
</div>
)}
</div>
</div>
)}
</div>
{/* ─── RIGHT PANEL (Comments / Send to Agent) ─── */}
{rightPanel && (
<div style={{ width: 260, borderLeft: `1px solid ${c.border}`, display: "flex", flexDirection: "column", backgroundColor: c.bgPanel, flexShrink: 0 }}>
<div style={{ display: "flex", borderBottom: `1px solid ${c.borderLight}` }}>
<button onClick={() => setRightPanel("comments")} style={{ flex: 1, padding: "7px 0", border: "none", cursor: "pointer", fontFamily: font.sans, fontSize: 10, fontWeight: rightPanel === "comments" ? 650 : 450, color: rightPanel === "comments" ? c.accentBtn : c.textTer, backgroundColor: "transparent", borderBottom: rightPanel === "comments" ? `2px solid ${c.accentBtn}` : "2px solid transparent" }}>💬 Comments (3)</button>
<button onClick={() => setRightPanel("send")} style={{ flex: 1, padding: "7px 0", border: "none", cursor: "pointer", fontFamily: font.sans, fontSize: 10, fontWeight: rightPanel === "send" ? 650 : 450, color: rightPanel === "send" ? c.accentBtn : c.textTer, backgroundColor: "transparent", borderBottom: rightPanel === "send" ? `2px solid ${c.accentBtn}` : "2px solid transparent" }}>✨ Send to Agent</button>
<button onClick={() => setRightPanel(null)} style={{ padding: "7px 8px", border: "none", cursor: "pointer", backgroundColor: "transparent" }}><I.X size={11} color={c.textTer} /></button>
</div>
<div style={{ flex: 1, overflowY: "auto", padding: 8 }}>
{rightPanel === "comments" && initComments.map((cm, i) => (
<div key={cm.id} style={{ marginBottom: 6, padding: "8px 10px", borderRadius: R.sm, border: `1px solid ${c.borderLight}`, backgroundColor: cm.isAgent ? c.accentBtn + "04" : c.bgCard }}>
<div style={{ display: "flex", alignItems: "center", gap: 5, marginBottom: 3 }}>
<Av letter={cm.isAgent ? "E" : "W"} color={cm.isAgent ? c.agentAv : c.accentBtn} size={18} />
<span style={{ fontSize: 11, fontWeight: 650, color: cm.isAgent ? c.agentAv : c.accentBtn }}>{cm.author}</span>
<span style={{ fontSize: 9, color: c.textTer }}>{cm.time}</span>
</div>
{cm.anchor && <div style={{ fontSize: 9.5, color: c.accentBtn, backgroundColor: c.accentBtn + "08", padding: "2px 6px", borderRadius: 3, marginBottom: 3, fontStyle: "italic" }}>"{cm.anchor}"</div>}
<div style={{ fontSize: 11.5, color: c.textSec, lineHeight: 1.5 }}>{cm.body}</div>
<div style={{ display: "flex", gap: 8, marginTop: 5, fontSize: 10, color: c.textTer }}>
<span style={{ cursor: "pointer" }}>Reply</span>
<span style={{ cursor: "pointer" }}>Resolve</span>
<span style={{ flex: 1 }} />
<span style={{ cursor: "pointer", color: c.agentAv }}>✨ Send</span>
</div>
</div>
))}
{rightPanel === "comments" && (
<div style={{ padding: "6px 8px", borderRadius: R.sm, border: `1px solid ${c.borderLight}`, display: "flex", alignItems: "center", gap: 5, cursor: "text" }}>
<I.Plus size={10} color={c.textTer} /><span style={{ fontSize: 10.5, color: c.textTer }}>Add comment… (type @Elnor)</span>
</div>
)}
{rightPanel === "send" && (
<div style={{ padding: 4 }}>
<div style={{ marginBottom: 10 }}>
<div style={{ fontSize: 10.5, fontWeight: 600, color: c.textTer, marginBottom: 4 }}>Agent</div>
<div style={{ display: "flex", alignItems: "center", gap: 6, padding: "6px 8px", borderRadius: R.sm, border: `1px solid ${c.border}`, backgroundColor: c.bgCard }}>
<Av letter="E" color={c.agentAv} size={18} /><span style={{ flex: 1, fontSize: 11.5, fontWeight: 600 }}>Elnor</span><I.ChevD size={10} color={c.textTer} />
</div>
</div>
<div style={{ marginBottom: 10 }}>
<div style={{ fontSize: 10.5, fontWeight: 600, color: c.textTer, marginBottom: 4 }}>Output mode</div>
{[{ l: "Respond in chat", d: "Opens chat with context" }, { l: "Send with instructions", d: "Agent processes result" }].map((o, i) => (
<div key={i} style={{ display: "flex", alignItems: "center", gap: 5, padding: "5px 8px", borderRadius: R.sm, border: `1px solid ${i === 0 ? c.accentBtn + "50" : c.border}`, marginBottom: 3, cursor: "pointer", backgroundColor: i === 0 ? c.accentBtn + "06" : "transparent" }}>
<span style={{ width: 10, height: 10, borderRadius: "50%", border: `2px solid ${i === 0 ? c.accentBtn : c.border}`, backgroundColor: i === 0 ? c.accentBtn : "transparent" }} />
<div><div style={{ fontSize: 10.5, fontWeight: i === 0 ? 600 : 450, color: i === 0 ? c.accentBtn : c.textPri }}>{o.l}</div><div style={{ fontSize: 8.5, color: c.textTer }}>{o.d}</div></div>
</div>
))}
</div>
<Btn primary style={{ width: "100%", justifyContent: "center", marginTop: 8 }}><I.Spark size={12} color="#fff" /> Open in Chat</Btn>
</div>
)}
</div>
</div>
)}
</div>
</div>
{/* ═══ CHAT COLUMN INDICATOR ═══ */}
<div style={{ width: 40, borderLeft: `1px solid ${c.border}`, backgroundColor: c.bgPanel, display: "flex", flexDirection: "column", alignItems: "center", paddingTop: 12, gap: 8, flexShrink: 0 }}>
<div style={{ writingMode: "vertical-rl", fontSize: 10, fontWeight: 600, color: c.accentBtn, letterSpacing: ".05em", cursor: "pointer", padding: "8px 4px" }}>CHAT →</div>
<Dot color={c.green} size={6} />
<div style={{ fontSize: 8, color: c.textTer, writingMode: "vertical-rl" }}>Henderson</div>
</div>
</div>
);
}