Q_WORKSPACE_V1.jsx
Design Mockups/Archived Mockups/DOC20 Mockups and Design/DOC20 Archived Mockups/DOC20 Workspace Redo/Q_WORKSPACE_V1.jsx
ELNOR REPO READER TEXT MIRROR
Original path: Design Mockups/Archived Mockups/DOC20 Mockups and Design/DOC20 Archived Mockups/DOC20 Workspace Redo/Q_WORKSPACE_V1.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 } from "react";
// === DESIGN TOKENS (matched to existing Q mockups) ===
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", textPri: "#1A1D21", textSec: "#5E6570", textTer: "#8B919A",
accentBtn: "#31588c", warn: "#D97706", error: "#B04040", border: "#E0E2E5",
borderLight: "#ECEEF0", green: "#2E8B57", agentAv: "#a1a7aa",
p1: "#B04040", p2: "#D97706", p3: "#31588c", p4: "#8B919A"
};
// === SHARED COMPONENTS ===
const Ic = ({ d, 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} /></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" />,
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 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" />,
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" />,
Bell: p => <Ic {...p} d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9 M13.73 21a2 2 0 01-3.46 0" />,
Clock: p => <Ic {...p} d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z M12 6v6l4 2" />,
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" />,
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" />,
Grip: p => <Ic {...p} d="M9 4v1 M9 11v1 M9 18v1 M15 4v1 M15 11v1 M15 18v1" sw={3} />,
Sun: p => <Ic {...p} d="M12 17a5 5 0 100-10 5 5 0 000 10z 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" />,
Zap: p => <Ic {...p} d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" />,
};
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, disabled, style: s }) => (
<button onClick={disabled ? undefined : onClick} style={{ padding: small ? "2px 8px" : "5px 14px", borderRadius: R.sm, border: primary ? "none" : ghost ? `1.5px solid ${c.border}` : `1px solid ${c.border}`, backgroundColor: primary ? (disabled ? c.accentBtn + "60" : c.accentBtn) : "transparent", color: primary ? "#fff" : c.textSec, fontSize: small ? 11 : 12.5, fontWeight: primary ? 550 : 450, cursor: disabled ? "not-allowed" : "pointer", fontFamily: font.sans, display: "flex", alignItems: "center", gap: 5, height: small ? 22 : 28, opacity: disabled ? .5 : 1, ...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>;
// === DATA ===
const briefCards = [
{ id: "b1", type: "system", icon: "Bell", title: "System", items: [
{ text: "DOC15 red-team review completed — 3 findings flagged", time: "2h ago", accent: c.green },
{ text: "OneDrive sync paused — re-auth needed", time: "6h ago", accent: c.warn },
]},
{ id: "b2", type: "elnor", icon: "Spark", title: "Elnor Overnight", items: [
{ text: "Reviewed 3 Henderson deposition transcripts — flagged 2 citation issues in Chen depo", time: "5h ago" },
{ text: "Updated Quark patent landscape analysis with 4 new filings", time: "4h ago" },
{ text: "Scanned SEC filings — no new Henderson-relevant 10-K amendments", time: "3h ago" },
]},
{ id: "b3", type: "calendar", icon: "Calendar", title: "Deadlines", items: [
{ text: "Expert disclosure deadline — Folb v. City of LA", time: "47 days", accent: c.error },
{ text: "Henderson MSJ response due", time: "12 days", accent: c.warn },
{ text: "Danny Christensen engagement call", time: "Tomorrow 2pm" },
]},
{ id: "b4", type: "mail", icon: "Mail", title: "Emails to Respond", items: [
{ text: "Sparacino — Narayanan local counsel agreement redline", time: "Yesterday" },
{ text: "Opposing counsel — Henderson discovery extension request", time: "2d ago", accent: c.warn },
]},
{ id: "b5", type: "news", icon: "Zap", title: "Watched Topics", items: [
{ text: "SEC announces new cybersecurity disclosure rules effective Q2", time: "Today" },
{ text: "9th Circuit: new opinion on securities fraud scienter standard", time: "Yesterday", accent: c.accentBtn },
]},
];
const initTodos = [
{ id: "t1", text: "Draft expert disclosure for Danny Christensen", done: false, priority: 1, due: "Apr 4", notes: "CCP § 2034 requirements. Need qualifications, opinions, basis.", project: "Folb v. City of LA", sub: [
{ id: "t1a", text: "Pull Christensen CV from engagement file", done: true },
{ id: "t1b", text: "List all opinions to be offered", done: false },
{ id: "t1c", text: "Identify documents reviewed", done: false },
]},
{ id: "t2", text: "Review Henderson MSJ opposition brief — Elnor's tracked changes", done: false, priority: 1, due: "Mar 20", project: "Henderson", sub: [] },
{ id: "t3", text: "Respond to Sparacino re: Narayanan local counsel agreement", done: false, priority: 2, due: "Mar 19", notes: "Check NY/CA choice-of-law for restrictive covenant.", sub: [] },
{ id: "t4", text: "Follow up with opposing counsel on discovery extension", done: false, priority: 2, due: "Mar 19", project: "Henderson", sub: [] },
{ id: "t5", text: "Review Quark patent analysis — new filings flagged overnight", done: false, priority: 3, due: null, project: "Quark", sub: [] },
{ id: "t6", text: "Update standing orders for new SEC cyber rules", done: false, priority: 3, due: null, sub: [] },
{ id: "t7", text: "File Folb trial exhibit list", done: true, priority: 2, due: "Mar 17", project: "Folb v. City of LA", sub: [] },
];
const noteContent = {
title: "Henderson MSJ — Work Notes",
body: [
{ 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_comment", 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." },
]
};
// === MAIN COMPONENT ===
export default function WorkspaceMockup() {
const [todos, setTodos] = useState(initTodos);
const [expandedTodo, setExpandedTodo] = useState("t1");
const [briefCollapsed, setBriefCollapsed] = useState(new Set());
const [briefDismissed, setBriefDismissed] = useState(new Set());
const [activeTab, setActiveTab] = useState("today"); // today | notes | viewer
const [rightPanel, setRightPanel] = useState(null); // null | "comments" | "ask"
const [newTodoText, setNewTodoText] = useState("");
const [showBrief, setShowBrief] = useState(true);
const [editingNote, setEditingNote] = useState(true);
const toggleTodo = (id) => setTodos(prev => prev.map(t => t.id === id ? { ...t, done: !t.done } : t));
const toggleSub = (parentId, subId) => setTodos(prev => prev.map(t => t.id === parentId ? { ...t, sub: t.sub.map(s => s.id === subId ? { ...s, done: !s.done } : s) } : t));
const toggleBriefCard = (id) => setBriefCollapsed(prev => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n; });
const dismissBrief = (id) => setBriefDismissed(prev => new Set([...prev, id]));
const priColor = (p) => p === 1 ? c.p1 : p === 2 ? c.p2 : p === 3 ? c.p3 : c.p4;
const priLabel = (p) => p === 1 ? "P1" : p === 2 ? "P2" : p === 3 ? "P3" : "P4";
const iconForBrief = (type) => {
if (type === "system") return <I.Bell size={12} color={c.warn} />;
if (type === "elnor") return <I.Spark size={12} color={c.agentAv} />;
if (type === "calendar") return <I.Calendar size={12} color={c.error} />;
if (type === "mail") return <I.Mail size={12} color={c.accentBtn} />;
if (type === "news") return <I.Zap size={12} color={c.green} />;
return <I.Bell size={12} />;
};
const activeTodos = todos.filter(t => !t.done);
const doneTodos = todos.filter(t => t.done);
const visibleBriefs = briefCards.filter(b => !briefDismissed.has(b.id));
return (
<div style={{ display: "flex", height: "100vh", fontFamily: font.sans, backgroundColor: c.bgApp, color: c.textPri, fontSize: 13 }}>
{/* === BROWSER COLUMN (left) === */}
<div style={{ width: 260, borderRight: `1px solid ${c.border}`, backgroundColor: c.bgPanel, display: "flex", flexDirection: "column", flexShrink: 0 }}>
<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} />
<span style={{ fontSize: 11.5, color: c.textTer }}>Search everything…</span>
</div>
</div>
{/* Scope chips */}
<div style={{ padding: "6px 8px 4px", borderBottom: `1px solid ${c.borderLight}` }}>
<div style={{ display: "flex", gap: 3, flexWrap: "wrap" }}>
{["Collection", "Project", "Bucket", "Folders"].map(s => (
<span key={s} style={{ padding: "2px 7px", borderRadius: R.sm, border: `1px solid ${c.borderLight}`, fontSize: 9.5, color: c.textTer, cursor: "pointer" }}>{s}</span>
))}
</div>
</div>
{/* Type chips */}
<div style={{ padding: "4px 8px 5px", borderBottom: `1px solid ${c.borderLight}` }}>
<div style={{ display: "flex", gap: 3, flexWrap: "wrap" }}>
{["Doc", "Chat", "Note", "Task", "Artifact", "Agent"].map(t => (
<span key={t} style={{ padding: "1px 6px", borderRadius: 3, fontSize: 9, color: c.textTer, border: `1px solid ${c.borderLight}`, cursor: "pointer" }}>{t}</span>
))}
<span style={{ padding: "1px 6px", fontSize: 9, color: c.textTer, cursor: "pointer" }}>+6</span>
</div>
</div>
{/* Browser items */}
<div style={{ flex: 1, overflowY: "auto" }}>
{[
{ title: "Henderson MSJ — Work Notes", type: "Note", time: "2h", pin: true },
{ title: "Henderson discovery analysis", type: "Chat", time: "2m", unread: true },
{ title: "MSJ Response Brief v3", type: "Artifact", time: "10m" },
{ title: "Weekly Task List", type: "Note", time: "4h", pin: true },
{ title: "Quark Patent Analysis", type: "Note", time: "1d" },
{ title: "Review batch #4", type: "Task", time: "2h", status: "running" },
{ title: "Henderson_Complaint.pdf", type: "Doc", time: "1d" },
{ title: "Judge Chen Conference Notes", type: "Note", time: "3d" },
{ title: "Privilege Log Summary v3", type: "Artifact", time: "3d" },
].map((item, i) => (
<div key={i} style={{ display: "flex", alignItems: "center", gap: 6, padding: "6px 8px", height: 32, borderBottom: `1px solid ${c.borderLight}`, cursor: "pointer" }}
onMouseEnter={e => e.currentTarget.style.backgroundColor = c.bgPanelAlt}
onMouseLeave={e => 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, color: c.textPri, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{item.title}</span>
{item.status && <span style={{ fontSize: 8.5, fontWeight: 600, color: c.accentBtn, textTransform: "uppercase" }}>{item.status}</span>}
<span style={{ fontSize: 9, color: c.textTer, flexShrink: 0 }}>{item.time}</span>
</div>
))}
</div>
<div style={{ padding: "3px 8px", borderTop: `1px solid ${c.borderLight}`, fontSize: 9, color: c.textTer }}>All · Modified · 9 items</div>
</div>
{/* === MAIN WORKSPACE (center) === */}
<div style={{ flex: 1, display: "flex", flexDirection: "column", minWidth: 0 }}>
{/* Workspace header */}
<div style={{ padding: "8px 16px", borderBottom: `1px solid ${c.border}`, backgroundColor: c.bgPanel, display: "flex", alignItems: "center", gap: 12 }}>
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
<I.Sun size={16} color={c.warn} />
<div>
<div style={{ fontSize: 15, fontWeight: 700 }}>Wednesday, March 18</div>
<div style={{ fontSize: 10, color: c.textTer }}>Good morning, Will</div>
</div>
</div>
<div style={{ flex: 1 }} />
{/* Tab bar */}
<div style={{ display: "flex", gap: 0, borderRadius: R.sm, border: `1px solid ${c.borderLight}`, overflow: "hidden" }}>
{[
{ id: "today", label: "Today" },
{ id: "notes", label: "Notes" },
{ id: "viewer", label: "Documents" },
].map(tab => (
<button key={tab.id} onClick={() => setActiveTab(tab.id)} style={{
padding: "4px 14px", border: "none", cursor: "pointer", fontFamily: font.sans,
fontSize: 11, fontWeight: activeTab === tab.id ? 650 : 450,
backgroundColor: activeTab === tab.id ? c.accentBtn + "0A" : "transparent",
color: activeTab === tab.id ? c.accentBtn : c.textSec,
borderBottom: activeTab === tab.id ? `2px solid ${c.accentBtn}` : "2px solid transparent",
}}>{tab.label}</button>
))}
</div>
<div style={{ display: "flex", gap: 4 }}>
<button onClick={() => setRightPanel(rightPanel === "comments" ? null : "comments")} style={{ padding: "3px 8px", borderRadius: R.sm, border: `1px solid ${rightPanel === "comments" ? c.accentBtn + "40" : c.borderLight}`, backgroundColor: rightPanel === "comments" ? c.accentBtn + "08" : "transparent", cursor: "pointer", display: "flex", alignItems: "center", gap: 4, fontFamily: font.sans, fontSize: 10.5, color: rightPanel === "comments" ? c.accentBtn : c.textSec }}>
<I.MsgCircle size={12} /> <span>3</span>
</button>
<button onClick={() => setRightPanel(rightPanel === "ask" ? null : "ask")} style={{ padding: "3px 8px", borderRadius: R.sm, border: `1px solid ${rightPanel === "ask" ? c.accentBtn + "40" : c.borderLight}`, backgroundColor: rightPanel === "ask" ? c.accentBtn + "08" : "transparent", cursor: "pointer", display: "flex", alignItems: "center", gap: 4, fontFamily: font.sans, fontSize: 10.5, color: rightPanel === "ask" ? c.accentBtn : c.textSec }}>
<I.Spark size={12} /> <span>Ask Elnor</span>
</button>
</div>
</div>
{/* Content area */}
<div style={{ flex: 1, display: "flex", overflow: "hidden" }}>
{/* Left: Note editor / Document viewer */}
<div style={{ flex: 1, display: "flex", flexDirection: "column", borderRight: `1px solid ${c.borderLight}`, minWidth: 0 }}>
{/* Editor toolbar */}
<div style={{ padding: "4px 12px", borderBottom: `1px solid ${c.borderLight}`, display: "flex", alignItems: "center", gap: 3, flexWrap: "wrap", backgroundColor: c.bgPanel }}>
<span style={{ fontSize: 9, fontWeight: 600, color: c.textTer, marginRight: 4 }}>EDITING</span>
<div style={{ width: 1, height: 16, backgroundColor: c.borderLight, margin: "0 4px" }} />
<button style={{ padding: "2px 6px", borderRadius: 3, border: `1px solid ${c.borderLight}`, backgroundColor: "transparent", cursor: "pointer", fontSize: 10, fontFamily: font.sans, color: c.textSec, fontWeight: 600 }}>B</button>
<button style={{ padding: "2px 6px", borderRadius: 3, border: `1px solid ${c.borderLight}`, backgroundColor: "transparent", cursor: "pointer", fontSize: 10, fontFamily: font.sans, color: c.textSec, fontStyle: "italic" }}>I</button>
<button style={{ padding: "2px 6px", borderRadius: 3, border: `1px solid ${c.borderLight}`, backgroundColor: "transparent", cursor: "pointer", fontSize: 10, fontFamily: font.sans, color: c.textSec, textDecoration: "underline" }}>U</button>
<div style={{ width: 1, height: 16, backgroundColor: c.borderLight, margin: "0 4px" }} />
<button style={{ padding: "2px 6px", borderRadius: 3, border: `1px solid ${c.borderLight}`, backgroundColor: "transparent", cursor: "pointer", fontSize: 10, fontFamily: font.sans, color: c.textSec }}>H1</button>
<button style={{ padding: "2px 6px", borderRadius: 3, border: `1px solid ${c.borderLight}`, backgroundColor: "transparent", cursor: "pointer", fontSize: 10, fontFamily: font.sans, color: c.textSec }}>H2</button>
<button style={{ padding: "2px 6px", borderRadius: 3, border: `1px solid ${c.borderLight}`, backgroundColor: "transparent", cursor: "pointer", fontSize: 10, fontFamily: font.sans, color: c.textSec }}>☐</button>
<div style={{ flex: 1 }} />
<span style={{ fontSize: 9, color: c.green }}>● Saved</span>
</div>
{/* Note content */}
<div style={{ flex: 1, overflowY: "auto", padding: "16px 24px 40px" }}>
<div contentEditable suppressContentEditableWarning style={{ fontSize: 21, fontWeight: 700, color: c.textPri, outline: "none", marginBottom: 16, borderBottom: `1px solid ${c.borderLight}`, paddingBottom: 8 }}>
{noteContent.title}
</div>
{noteContent.body.map((block, i) => {
if (block.type === "h2") return <h2 key={i} style={{ fontSize: 15, fontWeight: 700, color: c.textPri, margin: "20px 0 8px" }}>{block.text}</h2>;
if (block.type === "ai_comment") return (
<div key={i} style={{ margin: "12px 0", padding: "10px 14px", borderRadius: R.sm, border: `1px solid ${c.accentBtn}25`, backgroundColor: c.accentBtn + "05", display: "flex", gap: 10, alignItems: "flex-start" }}>
<Av letter="E" color={c.agentAv} size={22} />
<div style={{ flex: 1 }}>
<div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 4 }}>
<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: 8 }}>
<Btn small primary><I.Check size={10} color="#fff" /> Yes, pull them in</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: "6px 0", outline: "none" }}>{block.text}</p>;
})}
</div>
{/* Note metadata footer */}
<div style={{ padding: "4px 16px", borderTop: `1px solid ${c.borderLight}`, fontSize: 9.5, color: c.textTer, display: "flex", gap: 8, alignItems: "center", backgroundColor: c.bgPanel }}>
<Dot color={c.accentBtn} size={5} />
<span>Henderson v. DataCorp</span>
<span>·</span>
<span>Last edited 2h ago</span>
<span>·</span>
<span>3 comments</span>
<span>·</span>
<span>2 pending Elnor changes</span>
</div>
</div>
{/* Right: To-Do + Brief */}
<div style={{ width: 340, display: "flex", flexDirection: "column", backgroundColor: c.bgPanelAlt, flexShrink: 0 }}>
{/* To-Do header */}
<div style={{ padding: "8px 12px 6px", borderBottom: `1px solid ${c.borderLight}`, display: "flex", alignItems: "center", gap: 6, backgroundColor: c.bgPanel }}>
<span style={{ fontSize: 13, fontWeight: 700 }}>To Do</span>
<span style={{ fontSize: 10, color: c.textTer, backgroundColor: c.bgInput, padding: "1px 6px", borderRadius: 3 }}>{activeTodos.length}</span>
<div style={{ flex: 1 }} />
<button onClick={() => setShowBrief(!showBrief)} style={{ padding: "2px 7px", borderRadius: R.sm, border: `1px solid ${c.borderLight}`, backgroundColor: showBrief ? c.warn + "10" : "transparent", cursor: "pointer", fontSize: 9.5, fontFamily: font.sans, color: showBrief ? c.warn : c.textTer, display: "flex", alignItems: "center", gap: 3 }}>
<I.Bell size={10} /> Brief {visibleBriefs.length > 0 && <span style={{ backgroundColor: c.warn, color: "#fff", borderRadius: 3, padding: "0 4px", fontSize: 8, fontWeight: 700 }}>{visibleBriefs.reduce((a, b) => a + b.items.length, 0)}</span>}
</button>
</div>
<div style={{ flex: 1, overflowY: "auto" }}>
{/* === DAILY BRIEF CARDS === */}
{showBrief && visibleBriefs.length > 0 && (
<div style={{ padding: "8px 10px 4px", borderBottom: `1px solid ${c.borderLight}` }}>
{visibleBriefs.map(card => (
<div key={card.id} style={{ marginBottom: 6, borderRadius: R.sm, border: `1px solid ${c.borderLight}`, backgroundColor: c.bgCard, overflow: "hidden" }}>
<div onClick={() => toggleBriefCard(card.id)} style={{ display: "flex", alignItems: "center", gap: 6, padding: "6px 10px", cursor: "pointer", backgroundColor: c.bgPanelAlt }}>
{iconForBrief(card.type)}
<span style={{ flex: 1, fontSize: 10.5, fontWeight: 650, color: c.textPri }}>{card.title}</span>
<span style={{ fontSize: 9, color: c.textTer }}>{card.items.length}</span>
<button onClick={e => { e.stopPropagation(); dismissBrief(card.id); }} style={{ border: "none", background: "none", cursor: "pointer", padding: 0, display: "flex" }}><I.X size={10} color={c.textTer} /></button>
</div>
{!briefCollapsed.has(card.id) && (
<div style={{ padding: "2px 10px 6px" }}>
{card.items.map((item, i) => (
<div key={i} style={{ display: "flex", alignItems: "flex-start", gap: 6, padding: "4px 0", borderBottom: i < card.items.length - 1 ? `1px solid ${c.borderLight}` : "none" }}>
{item.accent && <Dot color={item.accent} size={5} />}
<span style={{ flex: 1, fontSize: 10.5, color: c.textSec, lineHeight: 1.4 }}>{item.text}</span>
<span style={{ fontSize: 9, color: c.textTer, flexShrink: 0, whiteSpace: "nowrap" }}>{item.time}</span>
</div>
))}
</div>
)}
</div>
))}
</div>
)}
{/* === TO-DO LIST === */}
<div style={{ padding: "6px 10px" }}>
{activeTodos.map(todo => (
<div key={todo.id} style={{ marginBottom: 2, borderRadius: R.sm, border: `1px solid ${expandedTodo === todo.id ? c.accentBtn + "30" : c.borderLight}`, backgroundColor: c.bgCard, overflow: "hidden" }}>
{/* Main row */}
<div style={{ display: "flex", alignItems: "flex-start", gap: 6, padding: "8px 10px", cursor: "pointer" }} onClick={() => setExpandedTodo(expandedTodo === todo.id ? null : todo.id)}>
<input type="checkbox" checked={todo.done} onChange={() => toggleTodo(todo.id)} onClick={e => e.stopPropagation()} style={{ width: 14, height: 14, accentColor: c.accentBtn, marginTop: 2, flexShrink: 0 }} />
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontSize: 12, fontWeight: 500, color: c.textPri, lineHeight: 1.4 }}>{todo.text}</div>
<div style={{ display: "flex", gap: 6, marginTop: 3, flexWrap: "wrap", alignItems: "center" }}>
<span style={{ fontSize: 8.5, fontWeight: 700, color: priColor(todo.priority), border: `1px solid ${priColor(todo.priority)}40`, borderRadius: 3, padding: "0 4px" }}>{priLabel(todo.priority)}</span>
{todo.due && <span style={{ fontSize: 9, color: c.textTer }}>{todo.due}</span>}
{todo.project && <span style={{ fontSize: 9, color: c.accentBtn }}>· {todo.project}</span>}
{todo.sub.length > 0 && <span style={{ fontSize: 9, color: c.textTer }}>{todo.sub.filter(s => s.done).length}/{todo.sub.length} subtasks</span>}
</div>
</div>
<div style={{ transform: expandedTodo === todo.id ? "rotate(90deg)" : "none", transition: "transform 0.15s" }}>
<I.ChevR size={10} color={c.textTer} />
</div>
</div>
{/* Expanded detail */}
{expandedTodo === todo.id && (
<div style={{ padding: "0 10px 10px 30px", borderTop: `1px solid ${c.borderLight}` }}>
{todo.notes && <div style={{ fontSize: 11, color: c.textSec, padding: "8px 0 4px", lineHeight: 1.5, fontStyle: "italic" }}>{todo.notes}</div>}
{/* Subtasks */}
{todo.sub.length > 0 && (
<div style={{ marginTop: 4 }}>
{todo.sub.map(sub => (
<div key={sub.id} style={{ display: "flex", alignItems: "center", gap: 6, padding: "3px 0" }}>
<input type="checkbox" checked={sub.done} onChange={() => toggleSub(todo.id, sub.id)} style={{ width: 12, height: 12, accentColor: c.accentBtn }} />
<span style={{ fontSize: 11, color: sub.done ? c.textTer : c.textSec, textDecoration: sub.done ? "line-through" : "none" }}>{sub.text}</span>
</div>
))}
</div>
)}
{/* Action row */}
<div style={{ display: "flex", gap: 4, marginTop: 8 }}>
<Btn small ghost><I.Spark size={10} color={c.agentAv} /> Ask Elnor</Btn>
<Btn small ghost><I.Plus size={10} /> Subtask</Btn>
<Btn small ghost><I.FileText size={10} /> Note</Btn>
</div>
</div>
)}
</div>
))}
{/* Add todo */}
<div style={{ display: "flex", alignItems: "center", gap: 6, padding: "8px 10px", borderRadius: R.sm, border: `1px dashed ${c.borderLight}`, marginTop: 6, cursor: "text" }}>
<I.Plus size={12} color={c.textTer} />
<input value={newTodoText} onChange={e => setNewTodoText(e.target.value)} placeholder="Add a task…" onKeyDown={e => {
if (e.key === "Enter" && newTodoText.trim()) {
setTodos(prev => [...prev, { id: "t" + Date.now(), text: newTodoText, done: false, priority: 3, due: null, sub: [] }]);
setNewTodoText("");
}
}} style={{ flex: 1, border: "none", outline: "none", fontSize: 11.5, fontFamily: font.sans, backgroundColor: "transparent", color: c.textPri }} />
</div>
{/* Completed section */}
{doneTodos.length > 0 && (
<div style={{ marginTop: 12 }}>
<div style={{ fontSize: 9.5, fontWeight: 650, color: c.textTer, textTransform: "uppercase", letterSpacing: ".06em", padding: "4px 0" }}>Completed ({doneTodos.length})</div>
{doneTodos.map(todo => (
<div key={todo.id} style={{ display: "flex", alignItems: "center", gap: 6, padding: "5px 10px", opacity: 0.5 }}>
<input type="checkbox" checked={todo.done} onChange={() => toggleTodo(todo.id)} style={{ width: 13, height: 13, accentColor: c.accentBtn }} />
<span style={{ fontSize: 11.5, color: c.textTer, textDecoration: "line-through" }}>{todo.text}</span>
</div>
))}
</div>
)}
</div>
</div>
</div>
{/* === RIGHT PANEL (Comments / Ask Elnor) === */}
{rightPanel && (
<div style={{ width: 280, 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: "8px 0", border: "none", cursor: "pointer", fontFamily: font.sans, fontSize: 10.5, fontWeight: rightPanel === "comments" ? 650 : 450, color: rightPanel === "comments" ? c.accentBtn : c.textTer, backgroundColor: rightPanel === "comments" ? c.accentBtn + "08" : "transparent", borderBottom: rightPanel === "comments" ? `2px solid ${c.accentBtn}` : "2px solid transparent" }}>💬 Comments (3)</button>
<button onClick={() => setRightPanel("ask")} style={{ flex: 1, padding: "8px 0", border: "none", cursor: "pointer", fontFamily: font.sans, fontSize: 10.5, fontWeight: rightPanel === "ask" ? 650 : 450, color: rightPanel === "ask" ? c.accentBtn : c.textTer, backgroundColor: rightPanel === "ask" ? c.accentBtn + "08" : "transparent", borderBottom: rightPanel === "ask" ? `2px solid ${c.accentBtn}` : "2px solid transparent" }}>✨ Ask Elnor</button>
<button onClick={() => setRightPanel(null)} style={{ padding: "8px 10px", border: "none", cursor: "pointer", backgroundColor: "transparent" }}><I.X size={12} color={c.textTer} /></button>
</div>
<div style={{ flex: 1, overflowY: "auto", padding: "8px" }}>
{rightPanel === "comments" && (
<>
{[
{ author: "You", body: "Need to strengthen scienter argument — Chen emails are key.", time: "2h ago", anchor: "CFO Chen's \"do NOT share\" email" },
{ author: "Elnor", body: "Found 3 additional Chen emails from July board prep. Also suggest cross-referencing Ex. 47 audit report for timeline support.", time: "2h ago", isAgent: true },
{ author: "You", body: "Check Vivendi cite — still good law?", time: "1h ago", anchor: "In re Vivendi Universal" },
].map((cm, i) => (
<div key={i} style={{ marginBottom: 8, 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: 4 }}>
<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: 4, 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: 6, 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 }}>✨</span>
</div>
</div>
))}
<div style={{ padding: "6px 8px", borderRadius: R.sm, border: `1px solid ${c.borderLight}`, cursor: "text", display: "flex", alignItems: "center", gap: 5 }}>
<I.Plus size={11} color={c.textTer} />
<span style={{ fontSize: 11, color: c.textTer }}>Add comment…</span>
</div>
</>
)}
{rightPanel === "ask" && (
<div>
<div style={{ marginBottom: 12 }}>
<div style={{ fontSize: 11, fontWeight: 600, color: c.textTer, marginBottom: 5 }}>Agent</div>
<div style={{ display: "flex", alignItems: "center", gap: 6, padding: "7px 10px", borderRadius: R.sm, border: `1px solid ${c.border}`, backgroundColor: c.bgCard }}>
<Av letter="E" color={c.agentAv} size={20} />
<span style={{ flex: 1, fontSize: 12, fontWeight: 600 }}>Elnor</span>
<I.ChevD size={11} color={c.textTer} />
</div>
</div>
<div style={{ marginBottom: 12 }}>
<div style={{ fontSize: 11, fontWeight: 600, color: c.textTer, marginBottom: 5 }}>Context</div>
<div style={{ fontSize: 10.5, color: c.textSec, padding: "6px 8px", borderRadius: R.sm, backgroundColor: c.bgPanelAlt, border: `1px solid ${c.borderLight}` }}>
Full note + to-do list visible to agent
</div>
</div>
<div style={{ marginBottom: 12 }}>
<div style={{ fontSize: 11, fontWeight: 600, color: c.textTer, marginBottom: 5 }}>Ask anything…</div>
<textarea placeholder="e.g. 'Check the Vivendi cite' or 'Add subtasks for the expert disclosure'" style={{ width: "100%", padding: "8px 10px", borderRadius: R.sm, border: `1px solid ${c.border}`, fontSize: 12, fontFamily: font.sans, outline: "none", minHeight: 80, resize: "vertical" }} />
</div>
<Btn primary style={{ width: "100%", justifyContent: "center" }}><I.Spark size={12} color="#fff" /> Ask Elnor</Btn>
<div style={{ fontSize: 9, color: c.textTer, marginTop: 8 }}>Elnor can see this note, your to-do list, and all comments. He can edit the note, add comments, update tasks, or respond in chat.</div>
</div>
)}
</div>
</div>
)}
</div>
</div>
{/* === CHAT PANEL INDICATOR (right edge) === */}
<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>
);
}