Q_WORKSPACE_V4_1 (1).jsx
Design Mockups/Archived Mockups/DOC20 Mockups and Design/DOC20 Archived Mockups/DOC20 Workspace Redo/Q_WORKSPACE_V4_1 (1).jsx
import { useState, useRef, useCallback, useEffect } from "react";
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",agentAv:"#a1a7aa",borderDark:"#263040"};
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"/>,Pin:p=><Ic {...p} d="M12 17v5 M9 2l.5 5L7 10l1.5 3h7L17 10l-2.5-3L15 2"/>,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"/>,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"/>,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"/>,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"/>,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"/>,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"/>,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"/>,Settings:p=><Ic {...p} d="M12 15a3 3 0 100-6 3 3 0 000 6z"/>,List:p=><Ic {...p} d="M8 6h13 M8 12h13 M8 18h13 M3 6h.01 M3 12h.01 M3 18h.01"/>,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"/>,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"/>,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"/>,Grip:p=><Ic {...p} d="M9 4h.01M9 9h.01M9 14h.01M9 19h.01M15 4h.01M15 9h.01M15 14h.01M15 19h.01" sw={3}/>,};
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>;
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}}/>;
const Toast=({msg,onDone})=>{useEffect(()=>{const t=setTimeout(onDone,2200);return()=>clearTimeout(t)},[onDone]);return <div style={{position:"fixed",bottom:24,left:"50%",transform:"translateX(-50%)",backgroundColor:c.textPri,color:"#fff",padding:"8px 18px",borderRadius:R.sm,fontSize:12,fontWeight:500,fontFamily:font.sans,zIndex:9999,boxShadow:"0 4px 16px rgba(0,0,0,0.2)"}}>{msg}</div>};
const DItem=({children,onClick,active})=><button onClick={onClick} style={{display:"flex",alignItems:"center",gap:6,width:"100%",padding:"6px 10px",border:"none",cursor:"pointer",backgroundColor:active?c.accentBtn+"08":"transparent",fontSize:11.5,color:c.textPri,textAlign:"left",borderRadius:R.sm,fontFamily:font.sans,fontWeight:active?600:400}} onMouseEnter={e=>{if(!active)e.currentTarget.style.backgroundColor=c.bgInput}} onMouseLeave={e=>{if(!active)e.currentTarget.style.backgroundColor=active?c.accentBtn+"08":"transparent"}}>{children}</button>;
const agents=[{name:"Elnor",color:c.agentAv,letter:"E"}];
// ═══ BLOCK DATA ═══
const initBlocks=[
{id:"b0",type:"bar",icon:"mail",title:"📧 Email from Sparacino received — Narayanan agreement redline",time:"2:15 PM",accent:c.accentBtn},
{id:"b1",type:"text",content:"Quick note: need to confirm with Danny that he's available for the May trial week before filing the expert disclosure. Call him today."},
{id:"b2",type:"tasks",title:"To Do",collapsed:false,tasks:[
{id:"t1",text:"Draft expert disclosure for Christensen",done:false,due:"Apr 4",link:"Expert Depo Prep",sub:[{id:"s1",text:"Pull Christensen CV",done:true},{id:"s2",text:"List opinions to be offered",done:false},{id:"s3",text:"Identify documents reviewed",done:false}]},
{id:"t2",text:"Review Henderson MSJ brief — Elnor's tracked changes",done:false,due:"Mar 20",link:"Henderson Discovery Priorities"},
{id:"t3",text:"Respond to Sparacino re: Narayanan agreement",done:false,due:"Mar 19"},
{id:"t4",text:"Follow up: opposing counsel on discovery extension",done:false,due:"Mar 19"},
{id:"t5",text:"Review Quark patent analysis — new filings",done:false,link:"Quark Patent Analysis"},
{id:"t6",text:"File Folb trial exhibit list",done:true,due:"Mar 17"},
]},
{id:"b3",type:"thread",collapsed:false,contextQuote:"opposing counsel on discovery extension",messages:[
{id:"m1",author:"You",color:c.accentBtn,body:"@Elnor draft a response declining the extension, cite the scheduling order deadline and the prejudice from further delay",time:"45m"},
{id:"m2",author:"Elnor",color:c.agentAv,body:"Draft ready. Key points: scheduling order set discovery cutoff March 28, extension would prejudice plaintiff's expert disclosure timeline, defendant has had 4 months to complete discovery. Want me to open it in a new note or paste below?",time:"40m"},
]},
{id:"b4",type:"text",content:"Call with Sparacino re: Narayanan — need to confirm NY vs CA choice of law for the restrictive covenant. NY probably governs but CA may void it entirely under Bus & Prof Code § 16600."},
{id:"b5",type:"feed",title:"Activity Brief",collapsed:false,sections:[
{key:"elnor",icon:"spark",label:"Elnor",items:[
{text:"Reviewed 3 Henderson depo transcripts — flagged 2 citation issues in Chen depo",time:"5h"},
{text:"Updated Quark patent landscape — 4 new filings",time:"4h"},
{text:"Scanned SEC filings — no new Henderson-relevant 10-K amendments",time:"3h"},
]},
{key:"calendar",icon:"calendar",label:"Deadlines",items:[
{text:"Expert disclosure deadline — Folb v. City of LA",time:"47d",accent:c.error},
{text:"Henderson MSJ response due",time:"12d",accent:c.warn},
{text:"Danny Christensen engagement call",time:"Tomorrow 2pm"},
]},
{key:"email",icon:"mail",label:"Email",items:[
{text:"Sparacino — Narayanan agreement redline",time:"Yesterday"},
{text:"Opposing counsel — discovery extension request",time:"2d",accent:c.warn},
]},
{key:"system",icon:"bell",label:"System",items:[
{text:"OneDrive sync paused — re-auth needed",time:"6h",accent:c.warn},
{text:"DOC15 red-team review completed — 3 findings flagged",time:"2h",accent:c.green},
]},
]},
{id:"b6",type:"text",content:""},
];
const feedIcons={spark:<I.Spark size={11} color={c.agentAv}/>,calendar:<I.Calendar size={11} color={c.error}/>,mail:<I.Mail size={11} color={c.accentBtn}/>,bell:<I.Bell size={11} color={c.warn}/>,zap:<I.Zap size={11} color={c.green}/>};
// ═══ MAIN ═══
export default function WorkspaceV4_1(){
const idC=useRef(500);const nid=()=>"x"+(++idC.current);
const [browserOpen,setBrowserOpen]=useState(true);
const [noteListOpen,setNoteListOpen]=useState(true);
const [commentsOpen,setCommentsOpen]=useState(false);
const [rightTab,setRightTab]=useState("comments");
const [findBar,setFindBar]=useState(false);
const [fullScreen,setFullScreen]=useState(false);
const [openDrop,setOpenDrop]=useState(null);
const [toast,setToast]=useState(null);
const [blocks,setBlocks]=useState(initBlocks);
const [expandedTask,setExpandedTask]=useState(null);
const [threadReplyId,setThreadReplyId]=useState(null);
const [threadReplyText,setThreadReplyText]=useState("");
const [newTaskText,setNewTaskText]=useState("");
const [newSubText,setNewSubText]=useState({});// keyed by taskId
const [inserterAt,setInserterAt]=useState(null); // index where + was clicked
const [bubbleMenu,setBubbleMenu]=useState(null);
const [collapsedFeeds,setCollapsedFeeds]=useState(new Set());
const editorRef=useRef(null);
const agent=agents[0];const flash=msg=>setToast(msg);
const toggleBlock=(id,field="collapsed")=>setBlocks(p=>p.map(b=>b.id===id?{...b,[field]:!b[field]}:b));
const toggleTask=(blockId,taskId)=>setBlocks(p=>p.map(b=>b.id===blockId?{...b,tasks:b.tasks.map(t=>t.id===taskId?{...t,done:!t.done}:t)}:b));
const toggleSub=(blockId,taskId,subId)=>setBlocks(p=>p.map(b=>b.id===blockId?{...b,tasks:b.tasks.map(t=>t.id===taskId?{...t,sub:t.sub.map(s=>s.id===subId?{...s,done:!s.done}:s)}:t)}:b));
const dismissAlert=id=>setBlocks(p=>p.filter(b=>b.id!==id));
const addThreadReply=(blockId)=>{if(!threadReplyText.trim())return;setBlocks(p=>p.map(b=>b.id===blockId?{...b,messages:[...b.messages,{id:nid(),author:"You",color:c.accentBtn,body:threadReplyText.trim(),time:"now"}]}:b));setThreadReplyId(null);setThreadReplyText("")};
const toggleFeedSection=key=>{const s=new Set(collapsedFeeds);s.has(key)?s.delete(key):s.add(key);setCollapsedFeeds(s)};
const insertBlock=(idx,type)=>{const newId=nid();let block;
if(type==="tasks")block={id:newId,type:"tasks",title:"New Task List",collapsed:false,tasks:[]};
else if(type==="feed")block={id:newId,type:"feed",title:"New Feed",collapsed:false,sections:[{key:"custom",icon:"spark",label:"Custom",items:[]}]};
else if(type==="thread")block={id:newId,type:"thread",collapsed:false,contextQuote:"",messages:[{id:nid(),author:"You",color:c.accentBtn,body:"@Elnor ",time:"now"}]};
else if(type==="bar")block={id:newId,type:"bar",icon:"bell",title:"New notice — click Elnor to configure",accent:c.warn};
else block={id:newId,type:"text",content:""};
setBlocks(p=>{const n=[...p];n.splice(idx,0,block);return n});setInserterAt(null);flash(`${type} block added`)};
const handleMouseUp=useCallback(e=>{if(e.target.closest("[data-bubble]"))return;const sel=window.getSelection();if(!sel||sel.isCollapsed||!sel.toString().trim()){setBubbleMenu(null);return}const text=sel.toString().trim();if(text.length<3)return;const rect=sel.getRangeAt(0).getBoundingClientRect();const er=editorRef.current?.getBoundingClientRect();if(!er)return;setBubbleMenu({x:rect.left-er.left+rect.width/2,y:rect.top-er.top-8,text})},[]);
const dismissBubble=()=>{setBubbleMenu(null);window.getSelection()?.removeAllRanges()};
// ─── Block Inserter ───
const BlockInserter=({idx})=>{
const [hover,setHover]=useState(false);
return <div style={{position:"relative",height:hover||inserterAt===idx?20:8,display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",transition:"height 0.1s"}} onMouseEnter={()=>setHover(true)} onMouseLeave={()=>{if(inserterAt!==idx)setHover(false)}}>
{(hover||inserterAt===idx)&&<><div style={{position:"absolute",left:0,right:0,top:"50%",height:1,backgroundColor:c.accentBtn+"30"}}/><button onClick={()=>setInserterAt(inserterAt===idx?null:idx)} style={{position:"relative",zIndex:2,width:20,height:20,borderRadius:"50%",border:`1.5px solid ${c.accentBtn}40`,backgroundColor:c.bgCard,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 1px 4px rgba(0,0,0,0.08)"}}><I.Plus size={11} color={c.accentBtn}/></button></>}
{inserterAt===idx&&<div style={{position:"absolute",top:22,left:"50%",transform:"translateX(-50%)",backgroundColor:c.bgCard,border:`1px solid ${c.border}`,borderRadius:R.sm,boxShadow:"0 6px 20px rgba(0,0,0,0.12)",zIndex:100,padding:4,minWidth:160}}>
<DItem onClick={()=>insertBlock(idx,"text")}><I.FileText size={12} color={c.textTer}/>Text</DItem>
<DItem onClick={()=>insertBlock(idx,"tasks")}><I.List size={12} color={c.warn}/>Task List</DItem>
<DItem onClick={()=>insertBlock(idx,"feed")}><I.Spark size={12} color={c.agentAv}/>Activity Feed</DItem>
<DItem onClick={()=>insertBlock(idx,"thread")}><I.MsgCircle size={12} color={c.accentBtn}/>@Elnor Thread</DItem>
<DItem onClick={()=>insertBlock(idx,"bar")}><I.Bell size={12} color={c.warn}/>Notice / Alert Bar</DItem>
</div>}
</div>;
};
// ─── Drag Handle ───
const DragHandle=()=><div style={{position:"absolute",left:-20,top:4,width:14,height:20,display:"flex",alignItems:"center",justifyContent:"center",cursor:"grab",opacity:0.25,borderRadius:2}} onMouseEnter={e=>e.currentTarget.style.opacity=0.6} onMouseLeave={e=>e.currentTarget.style.opacity=0.25}><I.Grip size={12} color={c.textTer}/></div>;
// ─── Module Header Bar (for collapsed state) ───
const ModuleBar=({block,icon,count,extra})=><div onClick={()=>toggleBlock(block.id)} style={{display:"flex",alignItems:"center",gap:6,padding:"6px 10px",borderRadius:R.sm,border:`1px solid ${c.borderLight}`,backgroundColor:c.bgPanelAlt,cursor:"pointer",position:"relative"}} onMouseEnter={e=>e.currentTarget.style.borderColor=c.accentBtn+"30"} onMouseLeave={e=>e.currentTarget.style.borderColor=c.borderLight}>
<DragHandle/>
<div style={{transform:block.collapsed?"none":"rotate(90deg)",transition:"transform 0.1s"}}><I.ChevR size={10} color={c.textTer}/></div>
{icon}
<span style={{fontSize:12,fontWeight:650,color:c.textPri}}>{block.title}</span>
{count!==undefined&&<span style={{fontSize:9.5,color:c.textTer,backgroundColor:c.bgInput,padding:"1px 6px",borderRadius:3}}>{count}</span>}
{extra}
<span style={{flex:1}}/>
<button onClick={e=>{e.stopPropagation();flash(`Configure "${block.title}"…`)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}}><I.Settings size={11}/></button>
</div>;
// ─── Render blocks ───
const renderBlock=(block,idx)=>{
// CONFIGURABLE BAR — generic block with Ask Elnor to configure/update
if(block.type==="bar") return <div key={block.id} style={{display:"flex",alignItems:"center",gap:8,padding:"7px 12px",borderRadius:R.sm,border:`1px solid ${block.accent||c.accentBtn}30`,backgroundColor:(block.accent||c.accentBtn)+"06",marginBottom:4,position:"relative"}}>
<DragHandle/>
{block.icon==="mail"&&<I.Mail size={13} color={c.accentBtn}/>}
{block.icon==="bell"&&<I.Bell size={13} color={c.warn}/>}
{block.icon==="zap"&&<I.Zap size={13} color={c.green}/>}
{block.icon==="calendar"&&<I.Calendar size={13} color={c.error}/>}
{!block.icon&&<Dot color={block.accent||c.accentBtn} size={6}/>}
<span style={{flex:1,fontSize:13,color:c.textPri,lineHeight:1.4}}>{block.title}</span>
{block.time&&<span style={{fontSize:10,color:c.textTer,flexShrink:0}}>{block.time}</span>}
<button onClick={()=>flash(`Opening chat with reference to block:${block.id} — Elnor can update this bar per your instructions`)} title="Ask Elnor about this block" style={{padding:"2px 7px",borderRadius:R.sm,border:`1px solid ${c.agentAv}40`,backgroundColor:c.agentAv+"10",cursor:"pointer",display:"flex",alignItems:"center",gap:3,fontSize:10,fontFamily:font.sans,color:c.agentAv,fontWeight:600}}><I.Spark size={10}/>Elnor</button>
<button onClick={()=>dismissAlert(block.id)} title="Dismiss" style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}}><I.X size={12}/></button>
</div>;
// TEXT
if(block.type==="text") return <div key={block.id} style={{position:"relative",marginBottom:2}}>
<DragHandle/>
<p contentEditable suppressContentEditableWarning style={{fontSize:14,lineHeight:1.75,color:block.content?c.textSec:c.textTer,outline:"none",minHeight:24,padding:"2px 0"}} onBlur={e=>setBlocks(p=>p.map(b=>b.id===block.id?{...b,content:e.target.textContent}:b))}>{block.content||"Type here… @Elnor to ask, /slash for commands"}</p>
</div>;
// TASKS
if(block.type==="tasks"){
const active=block.tasks.filter(t=>!t.done);const done=block.tasks.filter(t=>t.done);
if(block.collapsed) return <div key={block.id} style={{marginBottom:4}}><ModuleBar block={block} icon={<I.List size={13} color={c.warn}/>} count={`${active.length} open`}/></div>;
return <div key={block.id} style={{marginBottom:4,borderRadius:R.sm,border:`1px solid ${c.borderLight}`,overflow:"hidden",position:"relative"}}>
<DragHandle/>
<div onClick={()=>toggleBlock(block.id)} style={{display:"flex",alignItems:"center",gap:6,padding:"7px 10px",backgroundColor:c.bgPanelAlt,cursor:"pointer",borderBottom:`1px solid ${c.borderLight}`}}>
<I.ChevD size={10} color={c.textTer}/><I.List size={12} color={c.warn}/>
<span style={{fontSize:12.5,fontWeight:700,flex:1}}>{block.title}</span>
<span style={{fontSize:9.5,color:c.textTer,backgroundColor:c.bgInput,padding:"1px 6px",borderRadius:3}}>{active.length} open</span>
<button onClick={e=>{e.stopPropagation();flash(`Configure "${block.title}"…`)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}}><I.Settings size={11}/></button>
</div>
<div style={{padding:"4px 8px"}}>
{active.map(task=><div key={task.id}>
<div style={{display:"flex",alignItems:"center",gap:8,padding:"5px 4px",cursor:"pointer"}} onClick={()=>setExpandedTask(expandedTask===task.id?null:task.id)}>
<input type="checkbox" checked={false} onChange={()=>toggleTask(block.id,task.id)} onClick={e=>e.stopPropagation()} style={{width:15,height:15,accentColor:c.accentBtn,flexShrink:0}}/>
<span style={{flex:1,fontSize:13.5,lineHeight:1.45,color:c.textPri}}>{task.text}</span>
<div style={{display:"flex",gap:5,alignItems:"center",flexShrink:0}}>
{task.due&&<span style={{fontSize:10,color:c.textTer}}>{task.due}</span>}
{task.link&&<span style={{fontSize:10,color:c.accentBtn,cursor:"pointer",display:"flex",alignItems:"center",gap:2}} onClick={e=>{e.stopPropagation();flash(`Open "${task.link}"`)}}><I.Link size={9}/>Note</span>}
{task.sub?.length>0&&<span style={{fontSize:10,color:c.textTer}}>{task.sub.filter(s=>s.done).length}/{task.sub.length}</span>}
</div>
</div>
{expandedTask===task.id&&task.sub?.length>0&&<div style={{padding:"2px 0 6px 28px"}}>
{task.sub.map(s=><div key={s.id} style={{display:"flex",alignItems:"center",gap:6,padding:"3px 0"}}>
<input type="checkbox" checked={s.done} onChange={()=>toggleSub(block.id,task.id,s.id)} style={{width:13,height:13,accentColor:c.accentBtn}}/>
<span style={{fontSize:12.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 onClick={()=>flash("@Elnor…")}><I.Spark size={9} color={c.agentAv}/>@Elnor</Btn>
<Btn small ghost><I.Plus size={9}/>Subtask</Btn>
<Btn small ghost onClick={()=>flash(task.link?`Open "${task.link}"`:"Link note…")}><I.Link size={9}/>{task.link?"Open":"Link"}</Btn>
</div>
</div>}
</div>)}
{/* Add task */}
<div style={{display:"flex",alignItems:"center",gap:8,padding:"4px 4px",opacity:0.5}}>
<input type="checkbox" disabled style={{width:15,height:15}}/>
<span contentEditable suppressContentEditableWarning style={{flex:1,fontSize:13,color:c.textTer,outline:"none"}} onFocus={e=>{if(e.target.textContent==="Add task…")e.target.textContent=""}} onBlur={e=>{if(!e.target.textContent.trim())e.target.textContent="Add task…"}}>Add task…</span>
</div>
{done.length>0&&<details style={{padding:"2px 4px 4px"}}><summary style={{fontSize:10,fontWeight:600,color:c.textTer,cursor:"pointer",padding:"4px 0"}}>Done ({done.length})</summary>
{done.map(t=><div key={t.id} style={{display:"flex",alignItems:"center",gap:8,padding:"3px 4px",opacity:.4}}>
<input type="checkbox" checked onChange={()=>toggleTask(block.id,t.id)} style={{width:14,height:14,accentColor:c.accentBtn}}/>
<span style={{fontSize:12.5,textDecoration:"line-through",color:c.textTer}}>{t.text}</span>
</div>)}
</details>}
</div>
</div>;
}
// FEED
if(block.type==="feed"){
const totalItems=block.sections.reduce((a,s)=>a+s.items.length,0);
if(block.collapsed) return <div key={block.id} style={{marginBottom:4}}><ModuleBar block={block} icon={<I.Spark size={13} color={c.agentAv}/>} count={`${totalItems} items`} extra={<span style={{fontSize:9,color:c.green,fontWeight:600}}>● live</span>}/></div>;
return <div key={block.id} style={{marginBottom:4,borderRadius:R.sm,border:`1px solid ${c.borderLight}`,overflow:"hidden",position:"relative"}}>
<DragHandle/>
<div onClick={()=>toggleBlock(block.id)} style={{display:"flex",alignItems:"center",gap:6,padding:"7px 10px",backgroundColor:c.bgPanelAlt,cursor:"pointer",borderBottom:`1px solid ${c.borderLight}`}}>
<I.ChevD size={10} color={c.textTer}/><I.Spark size={12} color={c.agentAv}/>
<span style={{fontSize:12.5,fontWeight:700,flex:1}}>{block.title}</span>
<span style={{fontSize:9,color:c.green,fontWeight:600}}>● auto-updating</span>
<span style={{fontSize:9.5,color:c.textTer,backgroundColor:c.bgInput,padding:"1px 6px",borderRadius:3}}>{totalItems}</span>
<button onClick={e=>{e.stopPropagation();flash(`Configure "${block.title}"…`)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}}><I.Settings size={11}/></button>
</div>
<div style={{maxHeight:280,overflowY:"auto",padding:"6px 8px"}}>
{block.sections.map(sec=><div key={sec.key} style={{marginBottom:4}}>
<div onClick={()=>toggleFeedSection(sec.key)} style={{display:"flex",alignItems:"center",gap:5,padding:"3px 4px",cursor:"pointer"}}>
<div style={{transform:collapsedFeeds.has(sec.key)?"none":"rotate(90deg)",transition:"transform 0.1s"}}><I.ChevR size={8} color={c.textTer}/></div>
{feedIcons[sec.icon]||<I.Spark size={11}/>}
<span style={{fontSize:11.5,fontWeight:700,color:c.textSec}}>{sec.label}</span>
<span style={{fontSize:9,color:c.textTer}}>({sec.items.length})</span>
</div>
{!collapsedFeeds.has(sec.key)&&sec.items.map((item,i)=><div key={i} style={{display:"flex",alignItems:"flex-start",gap:6,padding:"4px 4px 4px 22px"}}>
<span style={{color:c.textTer,fontSize:10,marginTop:2,flexShrink:0}}>▹</span>
{item.accent&&<Dot color={item.accent} size={5}/>}
<span style={{flex:1,fontSize:12.5,color:c.textSec,lineHeight:1.45}}>{item.text}</span>
<span style={{fontSize:9.5,color:c.textTer,flexShrink:0,whiteSpace:"nowrap"}}>{item.time}</span>
</div>)}
</div>)}
</div>
</div>;
}
// THREAD
if(block.type==="thread"){
if(block.collapsed) return <div key={block.id} style={{marginBottom:4}}>
<div onClick={()=>toggleBlock(block.id)} style={{display:"flex",alignItems:"center",gap:6,padding:"6px 10px",borderRadius:R.sm,border:`1px solid ${c.borderLight}`,backgroundColor:c.bgPanelAlt,cursor:"pointer",position:"relative"}} onMouseEnter={e=>e.currentTarget.style.borderColor=c.accentBtn+"30"} onMouseLeave={e=>e.currentTarget.style.borderColor=c.borderLight}>
<DragHandle/><I.ChevR size={10} color={c.textTer}/><Av letter="E" color={c.agentAv} size={16}/>
<span style={{fontSize:11.5,color:c.textSec,flex:1}}><strong style={{color:c.agentAv}}>Elnor</strong> · {block.messages.length} messages</span>
<span style={{fontSize:9.5,color:c.textTer}}>{block.messages[block.messages.length-1]?.time}</span>
</div>
</div>;
return <div key={block.id} style={{marginBottom:4,borderRadius:R.sm,border:`1px solid ${c.accentBtn}20`,backgroundColor:c.accentBtn+"03",overflow:"hidden",position:"relative"}}>
<DragHandle/>
<div onClick={()=>toggleBlock(block.id)} style={{padding:"5px 12px",display:"flex",alignItems:"center",gap:6,cursor:"pointer",backgroundColor:c.accentBtn+"06",borderBottom:`1px solid ${c.accentBtn}15`}}>
<I.ChevD size={10} color={c.accentBtn}/><I.MsgCircle size={11} color={c.accentBtn}/>
<span style={{fontSize:10.5,fontWeight:600,color:c.accentBtn,flex:1}}>Thread · {block.messages.length}</span>
{block.contextQuote&&<span style={{fontSize:9,color:c.textTer,fontStyle:"italic"}}>re: "{block.contextQuote}"</span>}
</div>
{block.messages.map((msg,i)=><div key={msg.id} style={{padding:"7px 14px",borderBottom:i<block.messages.length-1?`1px solid ${c.borderLight}`:"none",backgroundColor:msg.author==="You"?"transparent":c.agentAv+"06"}}>
<div style={{display:"flex",alignItems:"center",gap:6,marginBottom:3}}>
<Av letter={msg.author[0]} color={msg.color} size={16}/>
<span style={{fontSize:11,fontWeight:650,color:msg.color}}>{msg.author}</span>
<span style={{fontSize:9,color:c.textTer}}>{msg.time}</span>
{msg.author==="You"&&<><span style={{fontSize:9,color:c.textTer,cursor:"pointer",marginLeft:"auto"}}>edit</span><span style={{fontSize:9,color:c.error+"80",cursor:"pointer"}}>delete</span></>}
</div>
<div style={{fontSize:12.5,lineHeight:1.55,color:c.textSec,paddingLeft:22}}>{msg.body}</div>
</div>)}
{threadReplyId===block.id?<div style={{padding:"7px 14px",borderTop:`1px solid ${c.borderLight}`,backgroundColor:c.bgPanelAlt}}>
<textarea value={threadReplyText} onChange={e=>setThreadReplyText(e.target.value)} placeholder="Reply… @Elnor" autoFocus onKeyDown={e=>{if(e.key==="Enter"&&!e.shiftKey){e.preventDefault();addThreadReply(block.id)}}} style={{width:"100%",padding:"6px 8px",borderRadius:R.sm,border:`1px solid ${c.border}`,fontSize:12,fontFamily:font.sans,outline:"none",minHeight:36,resize:"vertical"}}/>
<div style={{display:"flex",gap:4,marginTop:4}}><Btn small primary onClick={()=>addThreadReply(block.id)} disabled={!threadReplyText.trim()}>Send</Btn><Btn small ghost onClick={()=>{setThreadReplyId(null);setThreadReplyText("")}}>Cancel</Btn></div>
</div>:<div style={{padding:"5px 14px",borderTop:`1px solid ${c.borderLight}`,backgroundColor:c.bgPanelAlt}}>
<div onClick={()=>{setThreadReplyId(block.id);setThreadReplyText("")}} style={{display:"flex",alignItems:"center",gap:5,padding:"4px 8px",borderRadius:R.sm,border:`1px solid ${c.border}`,backgroundColor:c.bgCard,cursor:"text"}}><I.Plus size={10} color={c.textTer}/><span style={{fontSize:11,color:c.textTer}}>Reply… @Elnor</span></div>
</div>}
</div>;
}
return null;
};
return (
<div style={{display:"flex",width:"100%",height:"100vh",fontFamily:font.sans,color:c.textPri,backgroundColor:c.bgApp}} onClick={()=>{setOpenDrop(null);setInserterAt(null)}}>
<style>{`*{box-sizing:border-box;margin:0;padding:0}::-webkit-scrollbar{width:4px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:transparent;border-radius:2px}*:hover::-webkit-scrollbar-thumb{background:#d1d5db}::selection{background:${c.accentBtn}22}details>summary{list-style:none}details>summary::-webkit-details-marker{display:none}`}</style>
{toast&&<Toast msg={toast} onDone={()=>setToast(null)}/>}
{/* SIDEBAR RAIL */}
<div style={{width:44,flexShrink:0,backgroundColor:c.bgSidebar,borderRight:`1px solid ${c.borderDark}`,display:"flex",flexDirection:"column",alignItems:"center",paddingTop:10,gap:6}}>
<div style={{width:26,height:26,borderRadius:R.sm,backgroundColor:c.accentBtn,color:"#fff",display:"flex",alignItems:"center",justifyContent:"center",fontSize:11,fontWeight:700,marginBottom:6}}>Q</div>
<button onClick={()=>setBrowserOpen(!browserOpen)} title="Browser (⌘B)" style={{width:28,height:28,borderRadius:R.sm,border:"none",cursor:"pointer",backgroundColor:browserOpen?"#ffffff18":"transparent",color:browserOpen?"#fff":"#777",display:"flex",alignItems:"center",justifyContent:"center"}}><I.Search size={15}/></button>
<button onClick={()=>setNoteListOpen(!noteListOpen)} title="Notes" style={{width:28,height:28,borderRadius:R.sm,border:"none",cursor:"pointer",backgroundColor:noteListOpen?"#ffffff18":"transparent",color:noteListOpen?"#fff":"#777",display:"flex",alignItems:"center",justifyContent:"center"}}><I.FileText size={15}/></button>
<button onClick={()=>setCommentsOpen(!commentsOpen)} title="Comments" style={{width:28,height:28,borderRadius:R.sm,border:"none",cursor:"pointer",backgroundColor:commentsOpen?"#ffffff18":"transparent",color:commentsOpen?"#fff":"#777",display:"flex",alignItems:"center",justifyContent:"center"}}><I.MsgCircle size={15}/></button>
</div>
{/* BROWSER placeholder */}
{browserOpen&&<div style={{width:260,flexShrink:0,backgroundColor:c.bgPanel,borderRight:`1px solid ${c.border}`,display:"flex",flexDirection:"column"}}>
<div style={{padding:"10px 12px",borderBottom:`1px solid ${c.borderLight}`,display:"flex",alignItems:"center",justifyContent:"space-between"}}><span style={{fontSize:12,fontWeight:650}}>Browser</span><button onClick={()=>setBrowserOpen(false)} style={{border:"none",background:"none",cursor:"pointer",display:"flex",color:c.textTer}}><I.X size={12}/></button></div>
<div style={{flex:1,display:"flex",alignItems:"center",justifyContent:"center",padding:20}}><div style={{textAlign:"center",fontSize:11,color:c.textTer,fontStyle:"italic",lineHeight:1.6}}>Q_BROWSER_R13.jsx<br/>plugs in here<br/><span style={{fontSize:10}}>260px · collapsible</span></div></div>
</div>}
{/* NOTES SIDEBAR placeholder */}
{noteListOpen&&!fullScreen&&<div style={{width:220,flexShrink:0,backgroundColor:c.bgPanel,borderRight:`1px solid ${c.border}`,display:"flex",flexDirection:"column"}}>
<div style={{padding:"8px 10px",borderBottom:`1px solid ${c.borderLight}`,display:"flex",alignItems:"center",justifyContent:"space-between"}}><span style={{fontSize:12.5,fontWeight:650}}>Notes</span><button onClick={()=>setNoteListOpen(false)} style={{border:"none",background:"none",cursor:"pointer",display:"flex",color:c.textTer}}><I.X size={12}/></button></div>
<div style={{flex:1,overflowY:"auto"}}>
{/* Pinned Today */}
<div style={{padding:"7px 10px",borderBottom:`1px solid ${c.borderLight}`,borderLeft:`2px solid ${c.accentBtn}`,backgroundColor:c.accentBtn+"06"}}>
<div style={{display:"flex",alignItems:"center",gap:3,marginBottom:2}}><I.Pin size={8} color={c.warn}/><I.Sun size={10} color={c.warn}/><span style={{fontSize:12,fontWeight:600}}>Today — Wed, Mar 18</span></div>
<div style={{fontSize:9.5,color:c.textTer}}>just now · 5 tasks · live</div>
</div>
<div style={{padding:"4px 8px",borderBottom:`1px solid ${c.borderLight}`,backgroundColor:c.bgPanelAlt}}><div style={{display:"flex",alignItems:"center",gap:4}}><I.ChevD size={9} color={c.textTer}/><I.Folder size={11} color={c.warn}/><span style={{fontSize:11.5,fontWeight:600}}>To-Do Lists</span></div></div>
{["Henderson Tasks","Weekly Review"].map((n,i)=><div key={i} style={{padding:"6px 10px 6px 28px",borderBottom:`1px solid ${c.borderLight}`,cursor:"pointer"}} onMouseEnter={e=>e.currentTarget.style.backgroundColor=c.bgInput} onMouseLeave={e=>e.currentTarget.style.backgroundColor="transparent"}><div style={{fontSize:11.5}}>{n}</div><div style={{fontSize:9.5,color:c.textTer}}>{["1d","3d"][i]}</div></div>)}
<div style={{padding:"4px 8px",borderBottom:`1px solid ${c.borderLight}`,backgroundColor:c.bgPanelAlt}}><div style={{display:"flex",alignItems:"center",gap:4}}><I.ChevR size={9} color={c.textTer}/><I.Folder size={11} color={c.textTer}/><span style={{fontSize:11.5,fontWeight:600}}>Daily Notes</span><span style={{fontSize:9,color:c.textTer}}>14</span></div></div>
<div style={{padding:"4px 8px",borderBottom:`1px solid ${c.borderLight}`,backgroundColor:c.bgPanelAlt}}><div style={{display:"flex",alignItems:"center",gap:4}}><I.ChevD size={9} color={c.textTer}/><I.Folder size={11} color={c.warn}/><span style={{fontSize:11.5,fontWeight:600}}>Henderson Case</span></div></div>
{["Henderson Discovery Priorities","Judge Chen Notes","Privilege Checklist"].map((n,i)=><div key={i} style={{padding:"6px 10px 6px 28px",borderBottom:`1px solid ${c.borderLight}`,cursor:"pointer"}} onMouseEnter={e=>e.currentTarget.style.backgroundColor=c.bgInput} onMouseLeave={e=>e.currentTarget.style.backgroundColor="transparent"}><div style={{fontSize:11.5}}>{n}</div><div style={{fontSize:9.5,color:c.textTer}}>{["2h","3d","1d"][i]}{i===0&&" · 💬2"}</div></div>)}
</div>
<div style={{padding:"3px 8px",borderTop:`1px solid ${c.borderLight}`,fontSize:9,color:c.textTer}}>12 notes · Modified</div>
</div>}
{/* MAIN WORKSPACE */}
<div style={{flex:1,display:"flex",flexDirection:"column",overflow:"hidden"}}>
{/* Toolbar (from Q_NOTES_FULL) */}
<div style={{display:"flex",alignItems:"center",gap:3,padding:"4px 10px",borderBottom:`1px solid ${c.border}`,backgroundColor:c.bgPanel,flexWrap:"wrap"}}>
<select style={{padding:"2px 4px",borderRadius:3,border:`1px solid ${c.borderLight}`,fontSize:10.5,fontFamily:font.sans,color:c.textSec,backgroundColor:"transparent",height:24}}><option>Paragraph</option><option>H1</option><option>H2</option></select>
<TBtn icon={<span style={{fontWeight:700,fontSize:12}}>B</span>}/><TBtn icon={<span style={{fontStyle:"italic",fontSize:12}}>I</span>}/><TBtn icon={<span style={{textDecoration:"underline",fontSize:12}}>U</span>}/>
<Sep/><TBtn icon={<I.Undo size={13}/>}/><TBtn icon={<I.Redo size={13}/>}/>
<Sep/><TBtn icon={<I.Copy size={13}/>} title="Copy" onClick={()=>flash("Copied")}/>
<div style={{position:"relative"}}><TBtn icon={<I.Save size={13}/>} label="Save As…" dropdown onClick={e=>{e.stopPropagation();setOpenDrop(openDrop==="save"?null:"save")}}/>
{openDrop==="save"&&<div onClick={e=>e.stopPropagation()} style={{position:"absolute",top:28,left:0,backgroundColor:c.bgCard,border:`1px solid ${c.border}`,borderRadius:R.sm,boxShadow:"0 8px 24px rgba(0,0,0,0.12)",zIndex:999,minWidth:180,padding:4}}>
<DItem onClick={()=>{flash("Export MD");setOpenDrop(null)}}>Export as Markdown</DItem>
<DItem onClick={()=>{flash("Export DOCX");setOpenDrop(null)}}>Export as DOCX</DItem>
<DItem onClick={()=>{flash("Export PDF");setOpenDrop(null)}}>Export as PDF</DItem>
<div style={{borderTop:`1px solid ${c.borderLight}`,margin:"2px 0"}}/>
<DItem onClick={()=>{flash("Save as Prompt");setOpenDrop(null)}}>Save as Prompt</DItem>
</div>}</div>
<TBtn icon={<I.Link size={13}/>} label="Ref" onClick={()=>flash("Ref copied")}/>
<Sep/><TBtn icon={<I.Search size={13}/>} active={findBar} onClick={()=>setFindBar(!findBar)}/><TBtn icon={<I.Maximize size={13}/>} active={fullScreen} onClick={()=>setFullScreen(!fullScreen)}/>
<Sep/><TBtn icon={<I.MsgCircle size={13}/>} label="2" active={commentsOpen&&rightTab==="comments"} onClick={()=>{if(commentsOpen&&rightTab==="comments")setCommentsOpen(false);else{setCommentsOpen(true);setRightTab("comments")}}}/>
<Sep/><TBtn icon={<I.Eye size={13}/>} label="Markup" active/>
<TBtn icon={<I.Edit size={13}/>} label="0 ▾"/>
<div style={{flex:1}}/><span style={{fontSize:10,color:c.green,fontWeight:500}}>Saved just now</span>
<Sep/><button onClick={()=>{if(commentsOpen&&rightTab==="send")setCommentsOpen(false);else{setCommentsOpen(true);setRightTab("send")}}} style={{padding:"3px 10px",borderRadius:R.sm,border:`1px solid ${c.accentBtn}40`,backgroundColor:(commentsOpen&&rightTab==="send")?c.accentBtn:c.accentBtn+"08",cursor:"pointer",display:"flex",alignItems:"center",gap:4,color:(commentsOpen&&rightTab==="send")?"#fff":c.accentBtn,fontFamily:font.sans,fontSize:10.5,fontWeight:600,height:26}}><I.Spark size={12}/>Send to Agent</button>
</div>
{findBar&&<div style={{display:"flex",alignItems:"center",gap:6,padding:"5px 12px",borderBottom:`1px solid ${c.borderLight}`,backgroundColor:c.bgPanelAlt}}><I.Search size={12} color={c.textTer}/><input placeholder="Find…" autoFocus style={{flex:1,border:"none",backgroundColor:"transparent",fontSize:12,fontFamily:font.sans,outline:"none",maxWidth:250}}/><span style={{fontSize:10,color:c.textTer}}>0/0</span><button onClick={()=>setFindBar(false)} style={{padding:2,border:"none",cursor:"pointer",backgroundColor:"transparent",display:"flex",color:c.textTer}}><I.X size={12}/></button></div>}
{/* CONTENT */}
<div style={{flex:1,display:"flex",overflow:"hidden"}}>
<div style={{flex:1,display:"flex",flexDirection:"column",overflow:"hidden",minWidth:0}}>
<div ref={editorRef} style={{flex:1,overflowY:"auto",padding:"16px 32px 60px",position:"relative",userSelect:"text"}} onMouseUp={handleMouseUp} onMouseDown={e=>{if(bubbleMenu&&!e.target.closest("[data-bubble]"))setBubbleMenu(null)}}>
{/* Title */}
<div style={{display:"flex",alignItems:"center",gap:8,marginBottom:3}}>
<I.Sun size={20} color={c.warn}/>
<div style={{fontSize:22,fontWeight:700}} contentEditable suppressContentEditableWarning>Today — Wednesday, March 18</div>
</div>
<div style={{fontSize:10.5,color:c.textTer,marginBottom:16,display:"flex",alignItems:"center",gap:4}}>
<I.Pin size={9} color={c.warn}/> Pinned · Auto-updating · Configurable modules
<button onClick={()=>flash("Configure workspace template…")} style={{border:`1px solid ${c.borderLight}`,borderRadius:3,backgroundColor:"transparent",cursor:"pointer",padding:"1px 6px",fontSize:9,color:c.textTer,fontFamily:font.sans,display:"flex",alignItems:"center",gap:2,marginLeft:4}}><I.Settings size={9}/>Configure</button>
</div>
{/* Render all blocks with inserters between them */}
{blocks.map((block,idx)=><div key={block.id}>
<BlockInserter idx={idx}/>
{renderBlock(block,idx)}
</div>)}
<BlockInserter idx={blocks.length}/>
{/* Slash command hint */}
<div style={{marginTop:20,padding:"8px 12px",borderRadius:R.sm,border:`1px dashed ${c.borderLight}`,backgroundColor:c.bgPanelAlt,display:"flex",alignItems:"center",gap:8}}>
<I.Plus size={12} color={c.accentBtn}/>
<span style={{fontSize:11,color:c.textTer}}>Hover between blocks to insert · Type <strong style={{color:c.accentBtn}}>/todo</strong> <strong style={{color:c.accentBtn}}>/feed</strong> <strong style={{color:c.accentBtn}}>/thread</strong> · Type <strong style={{color:c.accentBtn}}>@Elnor</strong> anywhere</span>
</div>
{/* Bubble menu */}
{bubbleMenu&&<div data-bubble="1" style={{position:"absolute",left:Math.max(10,Math.min(bubbleMenu.x-140,(editorRef.current?.clientWidth||500)-300)),top:bubbleMenu.y-44,backgroundColor:c.bgCard,border:`1px solid ${c.border}`,borderRadius:R.sm,boxShadow:"0 4px 16px rgba(0,0,0,0.12)",padding:"4px 6px",display:"flex",gap:2,zIndex:100,alignItems:"center"}}>
<button onClick={()=>{flash("Comment…");dismissBubble()}} style={{padding:"5px 10px",borderRadius:R.sm,border:"none",cursor:"pointer",backgroundColor:c.accentBtn,color:"#fff",fontSize:11,fontWeight:600,fontFamily:font.sans,display:"flex",alignItems:"center",gap:4}}><I.MsgCircle size={11}/>Comment</button><Sep/>
<div style={{display:"flex",alignItems:"center",gap:2,padding:"2px 6px",borderRadius:R.sm,border:`1px solid ${c.borderLight}`,cursor:"pointer"}}><Dot color={agent.color} size={6}/><span style={{fontSize:10,fontWeight:500}}>{agent.name}</span></div>
<button onClick={()=>{flash(`Ask ${agent.name} inline…`);dismissBubble()}} style={{padding:"5px 8px",borderRadius:R.sm,border:"none",cursor:"pointer",backgroundColor:"transparent",color:c.textSec,fontSize:11,fontFamily:font.sans,display:"flex",alignItems:"center",gap:3}} onMouseEnter={e=>e.currentTarget.style.backgroundColor=c.bgInput} onMouseLeave={e=>e.currentTarget.style.backgroundColor="transparent"}><I.Spark size={11}/>Ask inline</button>
{["Rewrite","Expand","Shorten"].map(a=><button key={a} onClick={()=>{flash(`${agent.name}: ${a}…`);dismissBubble()}} style={{padding:"5px 8px",borderRadius:R.sm,border:"none",cursor:"pointer",backgroundColor:"transparent",color:c.textSec,fontSize:11,fontFamily:font.sans}} onMouseEnter={e=>e.currentTarget.style.backgroundColor=c.bgInput} onMouseLeave={e=>e.currentTarget.style.backgroundColor="transparent"}>{a}</button>)}
<button onClick={dismissBubble} style={{padding:3,border:"none",cursor:"pointer",backgroundColor:"transparent",color:c.textTer,display:"flex"}}><I.X size={11}/></button>
</div>}
</div>
</div>
{/* COMMENTS PANEL placeholder */}
{commentsOpen&&!fullScreen&&<div style={{width:rightTab==="send"?290:260,flexShrink:0,borderLeft:`1px solid ${c.border}`,display:"flex",flexDirection:"column",backgroundColor:c.bgPanelAlt}}>
<div style={{display:"flex",borderBottom:`1px solid ${c.borderLight}`,flexShrink:0}}>
<button onClick={()=>setRightTab("comments")} style={{flex:1,padding:"7px 0",border:"none",cursor:"pointer",backgroundColor:rightTab==="comments"?c.bgPanelAlt:c.bgInput,color:rightTab==="comments"?c.accentBtn:c.textTer,fontSize:10.5,fontWeight:rightTab==="comments"?650:450,fontFamily:font.sans,borderBottom:rightTab==="comments"?`2px solid ${c.accentBtn}`:"2px solid transparent",display:"flex",alignItems:"center",justifyContent:"center",gap:3}}><I.MsgCircle size={10}/>Comments</button>
<button onClick={()=>setRightTab("send")} style={{flex:1,padding:"7px 0",border:"none",cursor:"pointer",backgroundColor:rightTab==="send"?c.bgPanel:c.bgInput,color:rightTab==="send"?c.accentBtn:c.textTer,fontSize:10.5,fontWeight:rightTab==="send"?650:450,fontFamily:font.sans,borderBottom:rightTab==="send"?`2px solid ${c.accentBtn}`:"2px solid transparent",display:"flex",alignItems:"center",justifyContent:"center",gap:3}}><I.Spark size={10}/>Send to Agent</button>
<button onClick={()=>setCommentsOpen(false)} style={{width:26,border:"none",cursor:"pointer",backgroundColor:"transparent",display:"flex",alignItems:"center",justifyContent:"center",color:c.textTer}}><I.X size={11}/></button>
</div>
<div style={{flex:1,display:"flex",alignItems:"center",justifyContent:"center",padding:16}}>
<div style={{textAlign:"center",fontSize:11,color:c.textTer,fontStyle:"italic",lineHeight:1.6}}>Comments + Send to Agent<br/>from Q_NOTES_FULL.jsx<br/>plugs in here<br/><span style={{fontSize:10}}>@mention support in specs</span></div>
</div>
</div>}
</div>
</div>
{/* CHAT 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>
);
}