Elnor Repo Reader

Q_WORKSPACE_V5.jsx

Design Mockups/Archived Mockups/DOC20 Mockups and Design/DOC20 Archived Mockups/DOC20 Workspace Redo/Q_WORKSPACE_V5.jsx

Short text page f8b7de1676e6. Generated 2026-06-09T01:23:58.539Z from commit dbaa25962edc11ab30e8d4ca1715f9ae5bf77331. Worktree: clean.

Open readable HTML page · Open raw txt · Open path URL

ELNOR REPO READER TEXT MIRROR
Original path: Design Mockups/Archived Mockups/DOC20 Mockups and Design/DOC20 Archived Mockups/DOC20 Workspace Redo/Q_WORKSPACE_V5.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";
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"/>,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"/>,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}/>,Grid:p=><Ic {...p} d="M3 3h7v7H3z M14 3h7v7h-7z M3 14h7v7H3z M14 14h7v7h-7z"/>,};
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"}];

// Feed presets library
const feedPresets=[
  {id:"fp1",name:"System Activity",icon:"spark",desc:"Agent completions, chain results, memory updates",category:"system",cost:false},
  {id:"fp2",name:"System Notices",icon:"bell",desc:"Errors, warnings, sync issues, re-auth needed",category:"system",cost:false},
  {id:"fp3",name:"Gate Approvals",icon:"check",desc:"Pending chain gates and approval requests",category:"system",cost:false},
  {id:"fp4",name:"Active Operations",icon:"zap",desc:"Running agents, chains, and tasks",category:"system",cost:false},
  {id:"fp5",name:"Morning Summary",icon:"sun",desc:"Daily briefing from Elnor — overnight activity, priorities",category:"agent",cost:true},
  {id:"fp6",name:"Email Watch",icon:"mail",desc:"Flag important emails per your criteria",category:"agent",cost:true},
  {id:"fp7",name:"Deadline Tracker",icon:"calendar",desc:"Calendar deadlines from Outlook integration",category:"agent",cost:true},
];

// Block data
const initBlocks=[
  {id:"b0",type:"bar",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."},
  {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 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."},
  {id:"b5",type:"feed",title:"Activity Brief",collapsed:false,preset:"fp1",sections:[
    {key:"elnor",icon:"spark",label:"Elnor",items:[
      {text:"Reviewed 3 Henderson depo transcripts — flagged 2 citation issues",time:"5h"},{text:"Updated Quark patent landscape — 4 new filings",time:"4h"},{text:"Scanned SEC filings — no Henderson-relevant amendments",time:"3h"},
    ]},
    {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",time:"2h",accent:c.green},
    ]},
  ]},
  {id:"b6",type:"text",content:""},
];
const feedIcons={spark:<I.Spark size={11} color={c.agentAv}/>,bell:<I.Bell size={11} color={c.warn}/>,check:<I.Check size={11} color={c.green}/>,zap:<I.Zap size={11} color={c.accentBtn}/>,sun:<I.Sun size={11} color={c.warn}/>,mail:<I.Mail size={11} color={c.accentBtn}/>,calendar:<I.Calendar size={11} color={c.error}/>};

export default function WorkspaceV5(){
  const idC=useRef(500);const nid=()=>"x"+(++idC.current);
  const [browserOpen,setBrowserOpen]=useState(false);
  const [commentsOpen,setCommentsOpen]=useState(false);
  const [rightTab,setRightTab]=useState("comments");
  const [showMarkup,setShowMarkup]=useState(true);
  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({});
  const [collapsedFeeds,setCollapsedFeeds]=useState(new Set());
  const [editingTitle,setEditingTitle]=useState(null);
  // Module picker state
  const [pickerOpen,setPickerOpen]=useState(false);
  const [pickerStep,setPickerStep]=useState("choose"); // "choose" | "feed_presets" | "feed_custom"
  const [pickerTab,setPickerTab]=useState("system");
  const [customName,setCustomName]=useState("");
  const [customInstruction,setCustomInstruction]=useState("");

  const editorRef=useRef(null);const agent=agents[0];const flash=msg=>setToast(msg);
  const toggleBlock=(id)=>setBlocks(p=>p.map(b=>b.id===id?{...b,collapsed:!b.collapsed}:b));
  const toggleTask=(bid,tid)=>setBlocks(p=>p.map(b=>b.id===bid?{...b,tasks:b.tasks.map(t=>t.id===tid?{...t,done:!t.done}:t)}:b));
  const toggleSub=(bid,tid,sid)=>setBlocks(p=>p.map(b=>b.id===bid?{...b,tasks:b.tasks.map(t=>t.id===tid?{...t,sub:t.sub.map(s=>s.id===sid?{...s,done:!s.done}:s)}:t)}:b));
  const deleteBlock=id=>setBlocks(p=>p.filter(b=>b.id!==id));
  const toggleFeedSection=key=>{const s=new Set(collapsedFeeds);s.has(key)?s.delete(key):s.add(key);setCollapsedFeeds(s)};
  const addTask=(bid,text)=>{if(!text.trim())return;setBlocks(p=>p.map(b=>b.id===bid?{...b,tasks:[...b.tasks,{id:nid(),text:text.trim(),done:false,sub:[]}]}:b));setNewTaskText("")};
  const addSubtask=(bid,tid,text)=>{if(!text.trim())return;setBlocks(p=>p.map(b=>b.id===bid?{...b,tasks:b.tasks.map(t=>t.id===tid?{...t,sub:[...t.sub,{id:nid(),text:text.trim(),done:false}]}:t)}:b));setNewSubText(p=>({...p,[tid]:""}))};
  const addThreadReply=(bid)=>{if(!threadReplyText.trim())return;setBlocks(p=>p.map(b=>b.id===bid?{...b,messages:[...b.messages,{id:nid(),author:"You",color:c.accentBtn,body:threadReplyText.trim(),time:"now"}]}:b));setThreadReplyId(null);setThreadReplyText("")};

  // Insert block at end (toolbar button inserts at cursor position in real impl)
  const insertBlock=(type,preset)=>{
    const newId=nid();let block;
    if(type==="tasks")block={id:newId,type:"tasks",title:"New Task List",collapsed:false,tasks:[]};
    else if(type==="feed"){
      const p=preset||{name:"Custom Feed",sections:[]};
      block={id:newId,type:"feed",title:p.name,collapsed:false,preset:p.id,sections:
        p.id==="fp1"?[{key:"activity",icon:"spark",label:"Activity",items:[{text:"Waiting for events…",time:"now"}]}]:
        p.id==="fp2"?[{key:"notices",icon:"bell",label:"Notices",items:[{text:"No active notices",time:"now"}]}]:
        p.id==="fp5"?[{key:"morning",icon:"sun",label:"Summary",items:[{text:"Generating morning brief…",time:"now"}]}]:
        [{key:"custom",icon:"spark",label:p.name,items:[{text:"Configure this feed via the gear icon or @Elnor",time:"now"}]}]
      };
    }
    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",title:"New notice — click Elnor to configure",accent:c.warn};
    else return;
    setBlocks(p=>[...p.slice(0,-1),block,...p.slice(-1)]); // insert before last empty text
    setPickerOpen(false);setPickerStep("choose");
    flash(`${type==="feed"?(preset?.name||"Feed"):type} block added`);
  };

  const DragHandle=()=><div style={{width:14,display:"flex",alignItems:"center",justifyContent:"center",cursor:"grab",opacity:0.18,flexShrink:0,marginRight:2}} onMouseEnter={e=>e.currentTarget.style.opacity=0.55} onMouseLeave={e=>e.currentTarget.style.opacity=0.18}><I.Grip size={12} color={c.textTer}/></div>;

  const renderBlock=(block)=>{
    // BAR
    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",margin:"14px 0"}}>
      <DragHandle/>
      <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 ref to block:${block.id}`)} title="Ask Elnor" 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={()=>deleteBlock(block.id)} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}><I.X size={11}/></button>
    </div>;
    // TEXT
    if(block.type==="text") return <div key={block.id} style={{display:"flex",alignItems:"flex-start",margin:"4px 0",position:"relative"}} onMouseEnter={e=>{const d=e.currentTarget.querySelector("[data-del]");if(d)d.style.opacity=0.4}} onMouseLeave={e=>{const d=e.currentTarget.querySelector("[data-del]");if(d)d.style.opacity=0}}>
      <div style={{paddingTop:6}}><DragHandle/></div>
      <p contentEditable suppressContentEditableWarning style={{flex:1,fontSize:14,lineHeight:1.75,color:block.content?c.textPri:c.textTer,outline:"none",minHeight:28,padding:"4px 0"}}>{block.content||"Type here… @Elnor to ask, /todo /feed /ask for modules"}</p>
      <button data-del="1" onClick={()=>deleteBlock(block.id)} style={{opacity:0,border:"none",background:"none",cursor:"pointer",padding:2,display:"flex",color:c.textTer,flexShrink:0,marginTop:6,transition:"opacity 0.1s"}}><I.X size={11}/></button>
    </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={{margin:"14px 0"}}><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"}}><DragHandle/><I.ChevR size={10} color={c.textTer}/><I.List size={12} color={c.warn}/><span style={{fontSize:12,fontWeight:650}}>{block.title}</span><span style={{fontSize:9.5,color:c.textTer,backgroundColor:c.bgInput,padding:"1px 6px",borderRadius:3}}>{active.length} open</span><span style={{flex:1}}/><button onClick={e=>{e.stopPropagation();deleteBlock(block.id)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}><I.X size={11}/></button></div></div>;
      return <div key={block.id} style={{margin:"14px 0",borderRadius:R.sm,border:`1px solid ${c.borderLight}`,overflow:"hidden"}}>
        <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}`}}>
          <DragHandle/><I.ChevD size={10} color={c.textTer}/><I.List size={12} color={c.warn}/>
          {editingTitle===block.id?<input autoFocus defaultValue={block.title} onBlur={e=>{setBlocks(p=>p.map(b=>b.id===block.id?{...b,title:e.target.value||block.title}:b));setEditingTitle(null)}} onKeyDown={e=>{if(e.key==="Enter"){setBlocks(p=>p.map(b=>b.id===block.id?{...b,title:e.target.value||block.title}:b));setEditingTitle(null)}if(e.key==="Escape")setEditingTitle(null)}} onClick={e=>e.stopPropagation()} style={{flex:1,fontSize:12.5,fontWeight:700,border:`1px solid ${c.accentBtn}40`,borderRadius:3,padding:"1px 6px",outline:"none",fontFamily:font.sans,backgroundColor:c.bgCard}}/>
          :<span style={{fontSize:12.5,fontWeight:700,flex:1,cursor:"text"}} onClick={e=>{e.stopPropagation();setEditingTitle(block.id)}}>{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…")}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}}><I.Settings size={11}/></button>
          <button onClick={e=>{e.stopPropagation();deleteBlock(block.id)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}><I.X size={11}/></button>
        </div>
        <div style={{padding:"4px 8px"}}>
          {active.map(task=><div key={task.id} style={{borderBottom:`1px solid ${c.borderLight}`,paddingBottom:expandedTask===task.id?6:0}}>
            <div style={{display:"flex",alignItems:"center",gap:8,padding:"6px 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 style={{transform:expandedTask===task.id?"rotate(90deg)":"none",transition:"transform 0.1s"}}><I.ChevR size={9} color={c.textTer}/></div>
              </div>
            </div>
            {expandedTask===task.id&&<div style={{padding:"2px 0 4px 30px"}}>
              {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.textPri,textDecoration:s.done?"line-through":"none"}}>{s.text}</span>
              </div>)}
              <div style={{display:"flex",alignItems:"center",gap:6,padding:"3px 0"}}>
                <input type="checkbox" disabled style={{width:13,height:13,opacity:0.2}}/>
                <input value={newSubText[task.id]||""} onChange={e=>setNewSubText(p=>({...p,[task.id]:e.target.value}))} placeholder="Add subtask…" onKeyDown={e=>{if(e.key==="Enter")addSubtask(block.id,task.id,newSubText[task.id]||"")}} style={{flex:1,border:"none",borderBottom:`1px solid ${c.borderLight}`,outline:"none",fontSize:12,fontFamily:font.sans,color:c.textPri,backgroundColor:"transparent",padding:"2px 0"}}/>
              </div>
              <div style={{display:"flex",gap:4,marginTop:6}}>
                <Btn small ghost onClick={()=>flash("@Elnor…")}><I.Spark size={9} color={c.agentAv}/>@Elnor</Btn>
                <Btn small ghost onClick={()=>flash(task.link?`Open "${task.link}"`:"Link note…")}><I.Link size={9}/>{task.link?"Open Note":"Link Note"}</Btn>
              </div>
            </div>}
          </div>)}
          <div style={{display:"flex",alignItems:"center",gap:8,padding:"6px 4px"}}>
            <input type="checkbox" disabled style={{width:15,height:15,opacity:0.2}}/>
            <input value={newTaskText} onChange={e=>setNewTaskText(e.target.value)} placeholder="Add task…" onKeyDown={e=>{if(e.key==="Enter")addTask(block.id,newTaskText)}} style={{flex:1,border:"none",borderBottom:`1px solid ${c.borderLight}`,outline:"none",fontSize:13.5,fontFamily:font.sans,color:c.textPri,backgroundColor:"transparent",padding:"2px 0"}}/>
          </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={{margin:"14px 0"}}><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"}}><DragHandle/><I.ChevR size={10} color={c.textTer}/><I.Spark size={12} color={c.agentAv}/><span style={{fontSize:12,fontWeight:650}}>{block.title}</span><span style={{fontSize:9,color:c.green,fontWeight:600}}>● live</span><span style={{fontSize:9.5,color:c.textTer,backgroundColor:c.bgInput,padding:"1px 6px",borderRadius:3}}>{totalItems}</span><span style={{flex:1}}/><button onClick={e=>{e.stopPropagation();deleteBlock(block.id)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}><I.X size={11}/></button></div></div>;
      return <div key={block.id} style={{margin:"14px 0",borderRadius:R.sm,border:`1px solid ${c.borderLight}`,overflow:"hidden"}}>
        <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}`}}>
          <DragHandle/><I.ChevD size={10} color={c.textTer}/><I.Spark size={12} color={c.agentAv}/>
          {editingTitle===block.id?<input autoFocus defaultValue={block.title} onBlur={e=>{setBlocks(p=>p.map(b=>b.id===block.id?{...b,title:e.target.value||block.title}:b));setEditingTitle(null)}} onKeyDown={e=>{if(e.key==="Enter"){setBlocks(p=>p.map(b=>b.id===block.id?{...b,title:e.target.value||block.title}:b));setEditingTitle(null)}if(e.key==="Escape")setEditingTitle(null)}} onClick={e=>e.stopPropagation()} style={{flex:1,fontSize:12.5,fontWeight:700,border:`1px solid ${c.accentBtn}40`,borderRadius:3,padding:"1px 6px",outline:"none",fontFamily:font.sans,backgroundColor:c.bgCard}}/>
          :<span style={{fontSize:12.5,fontWeight:700,flex:1,cursor:"text"}} onClick={e=>{e.stopPropagation();setEditingTitle(block.id)}}>{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…")}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}}><I.Settings size={11}/></button>
          <button onClick={e=>{e.stopPropagation();deleteBlock(block.id)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}><I.X 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.textPri,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={{margin:"14px 0"}}><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"}}><DragHandle/><I.ChevR size={10} color={c.textTer}/><Av letter="E" color={c.agentAv} size={16}/><span style={{fontSize:11.5,color:c.textPri,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><button onClick={e=>{e.stopPropagation();deleteBlock(block.id)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}><I.X size={11}/></button></div></div>;
      return <div key={block.id} style={{margin:"14px 0",borderRadius:R.sm,border:`1px solid ${c.accentBtn}20`,backgroundColor:c.accentBtn+"03",overflow:"hidden"}}>
        <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`}}>
          <DragHandle/><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>}
          <button onClick={e=>{e.stopPropagation();deleteBlock(block.id)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}><I.X size={11}/></button>
        </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.textPri,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);if(pickerOpen&&pickerStep==="choose")setPickerOpen(false)}}>
      <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={()=>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:270,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}}>Browser with Notes scope<br/>from V4.5</div></div></div>}

      {/* MAIN */}
      <div style={{flex:1,display:"flex",flexDirection:"column",overflow:"hidden"}}>
        {/* TOOLBAR */}
        <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/>
          {/* ═══ ADD MODULE BUTTON ═══ */}
          <div style={{position:"relative"}}>
            <TBtn icon={<I.Grid size={13}/>} label="Add Module" dropdown active={pickerOpen} onClick={e=>{e.stopPropagation();setPickerOpen(!pickerOpen);setPickerStep("choose")}}/>
            {pickerOpen&&<div onClick={e=>e.stopPropagation()} style={{position:"absolute",top:30,left:0,backgroundColor:c.bgCard,border:`1px solid ${c.border}`,borderRadius:R.sm,boxShadow:"0 8px 28px rgba(0,0,0,0.15)",zIndex:999,width:pickerStep==="choose"?220:380,padding:0,overflow:"hidden"}}>
              {/* STEP 1: Choose block type */}
              {pickerStep==="choose"&&<div style={{padding:6}}>
                <div style={{padding:"6px 10px",fontSize:10,fontWeight:600,color:c.textTer,textTransform:"uppercase",letterSpacing:".05em"}}>Insert Module</div>
                <DItem onClick={()=>{insertBlock("tasks");}}><I.List size={14} color={c.warn}/><div><div style={{fontWeight:600}}>Task List</div><div style={{fontSize:9.5,color:c.textTer}}>Checkboxes, subtasks, due dates</div></div></DItem>
                <DItem onClick={()=>{setPickerStep("feed_presets");setPickerTab("system")}}><I.Spark size={14} color={c.agentAv}/><div><div style={{fontWeight:600}}>Activity Feed</div><div style={{fontSize:9.5,color:c.textTer}}>System events or Elnor-powered</div></div></DItem>
                <DItem onClick={()=>insertBlock("thread")}><I.MsgCircle size={14} color={c.accentBtn}/><div><div style={{fontWeight:600}}>@Elnor Thread</div><div style={{fontSize:9.5,color:c.textTer}}>Inline conversation</div></div></DItem>
                <DItem onClick={()=>insertBlock("bar")}><I.Bell size={14} color={c.warn}/><div><div style={{fontWeight:600}}>Notice Bar</div><div style={{fontSize:9.5,color:c.textTer}}>Alert, reminder, status</div></div></DItem>
              </div>}

              {/* STEP 2: Feed preset picker */}
              {pickerStep==="feed_presets"&&<div>
                <div style={{display:"flex",alignItems:"center",padding:"8px 10px",borderBottom:`1px solid ${c.borderLight}`,gap:6}}>
                  <button onClick={()=>setPickerStep("choose")} style={{border:"none",background:"none",cursor:"pointer",display:"flex",color:c.textTer,padding:0}}><I.ChevR size={12} style={{transform:"rotate(180deg)"}}/></button>
                  <span style={{fontSize:12,fontWeight:650,flex:1}}>Choose Feed Preset</span>
                </div>
                {/* Tabs */}
                <div style={{display:"flex",borderBottom:`1px solid ${c.borderLight}`}}>
                  {[{id:"system",label:"System",desc:"No AI cost"},{id:"agent",label:"Agent",desc:"Elnor-powered"},{id:"custom",label:"My Presets",desc:"Saved"}].map(tab=>(
                    <button key={tab.id} onClick={()=>setPickerTab(tab.id)} style={{flex:1,padding:"8px 4px",border:"none",cursor:"pointer",fontFamily:font.sans,fontSize:10,fontWeight:pickerTab===tab.id?650:400,color:pickerTab===tab.id?c.accentBtn:c.textTer,backgroundColor:"transparent",borderBottom:pickerTab===tab.id?`2px solid ${c.accentBtn}`:"2px solid transparent",display:"flex",flexDirection:"column",alignItems:"center",gap:1}}>
                      <span>{tab.label}</span>
                      <span style={{fontSize:8,color:c.textTer}}>{tab.desc}</span>
                    </button>
                  ))}
                </div>
                {/* Preset cards */}
                <div style={{padding:6,maxHeight:260,overflowY:"auto"}}>
                  {feedPresets.filter(p=>p.category===pickerTab||(pickerTab==="custom")).map(preset=>(
                    <div key={preset.id} onClick={()=>insertBlock("feed",preset)} style={{display:"flex",alignItems:"center",gap:10,padding:"8px 10px",borderRadius:R.sm,cursor:"pointer",marginBottom:2}} onMouseEnter={e=>e.currentTarget.style.backgroundColor=c.bgInput} onMouseLeave={e=>e.currentTarget.style.backgroundColor="transparent"}>
                      <div style={{width:32,height:32,borderRadius:R.sm,backgroundColor:preset.cost?c.warn+"15":c.green+"15",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0}}>
                        {feedIcons[preset.icon]||<I.Spark size={14}/>}
                      </div>
                      <div style={{flex:1,minWidth:0}}>
                        <div style={{fontSize:12,fontWeight:600,color:c.textPri}}>{preset.name}</div>
                        <div style={{fontSize:10,color:c.textTer,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{preset.desc}</div>
                      </div>
                      {preset.cost&&<span style={{fontSize:8,padding:"1px 5px",borderRadius:3,backgroundColor:c.warn+"15",color:c.warn,fontWeight:700}}>AI</span>}
                      {!preset.cost&&<span style={{fontSize:8,padding:"1px 5px",borderRadius:3,backgroundColor:c.green+"15",color:c.green,fontWeight:700}}>FREE</span>}
                    </div>
                  ))}
                  {pickerTab==="custom"&&<div style={{padding:"12px 10px",textAlign:"center",color:c.textTer,fontSize:11,fontStyle:"italic"}}>No saved presets yet.<br/>Configure a feed block and click "Save as Preset"</div>}
                </div>
                {/* Create custom */}
                <div style={{borderTop:`1px solid ${c.borderLight}`,padding:6}}>
                  <DItem onClick={()=>setPickerStep("feed_custom")}><I.Plus size={12} color={c.accentBtn}/><span style={{color:c.accentBtn,fontWeight:600}}>Create Custom Feed…</span></DItem>
                </div>
              </div>}

              {/* STEP 3: Custom feed configuration */}
              {pickerStep==="feed_custom"&&<div>
                <div style={{display:"flex",alignItems:"center",padding:"8px 10px",borderBottom:`1px solid ${c.borderLight}`,gap:6}}>
                  <button onClick={()=>setPickerStep("feed_presets")} style={{border:"none",background:"none",cursor:"pointer",display:"flex",color:c.textTer,padding:0}}><I.ChevR size={12} style={{transform:"rotate(180deg)"}}/></button>
                  <span style={{fontSize:12,fontWeight:650,flex:1}}>Create Custom Feed</span>
                </div>
                <div style={{padding:"10px 12px"}}>
                  <div style={{marginBottom:10}}>
                    <div style={{fontSize:11,fontWeight:600,color:c.textTer,marginBottom:4}}>Feed name</div>
                    <input value={customName} onChange={e=>setCustomName(e.target.value)} placeholder="e.g., Henderson Email Watch" style={{width:"100%",padding:"6px 8px",borderRadius:R.sm,border:`1px solid ${c.border}`,fontSize:12,fontFamily:font.sans,outline:"none"}}/>
                  </div>
                  <div style={{marginBottom:10}}>
                    <div style={{fontSize:11,fontWeight:600,color:c.textTer,marginBottom:4}}>Source type</div>
                    <div style={{display:"flex",gap:4}}>
                      <button style={{flex:1,padding:"8px 6px",borderRadius:R.sm,border:`2px solid ${c.green}40`,backgroundColor:c.green+"08",cursor:"pointer",fontFamily:font.sans,textAlign:"left"}}>
                        <div style={{fontSize:11,fontWeight:600,color:c.green}}>System Events</div>
                        <div style={{fontSize:9,color:c.textTer}}>Subscribe to real-time events. No AI cost.</div>
                      </button>
                      <button style={{flex:1,padding:"8px 6px",borderRadius:R.sm,border:`2px solid ${c.warn}40`,backgroundColor:c.warn+"08",cursor:"pointer",fontFamily:font.sans,textAlign:"left"}}>
                        <div style={{fontSize:11,fontWeight:600,color:c.warn}}>Agent Instruction</div>
                        <div style={{fontSize:9,color:c.textTer}}>Tell Elnor what to track. Runs on schedule.</div>
                      </button>
                    </div>
                  </div>
                  <div style={{marginBottom:10}}>
                    <div style={{fontSize:11,fontWeight:600,color:c.textTer,marginBottom:4}}>Instruction to Elnor</div>
                    <textarea value={customInstruction} onChange={e=>setCustomInstruction(e.target.value)} placeholder="e.g., Monitor Outlook for emails from opposing counsel. Summarize each in one line." style={{width:"100%",padding:"6px 8px",borderRadius:R.sm,border:`1px solid ${c.border}`,fontSize:12,fontFamily:font.sans,outline:"none",minHeight:60,resize:"vertical"}}/>
                  </div>
                  <div style={{marginBottom:10}}>
                    <div style={{fontSize:11,fontWeight:600,color:c.textTer,marginBottom:4}}>Schedule</div>
                    <div style={{display:"flex",gap:4}}>
                      {["Continuous","Hourly","Daily","Manual"].map(s=><button key={s} style={{padding:"4px 10px",borderRadius:R.sm,border:`1px solid ${s==="Daily"?c.accentBtn+"50":c.borderLight}`,backgroundColor:s==="Daily"?c.accentBtn+"08":"transparent",fontSize:10,fontFamily:font.sans,color:s==="Daily"?c.accentBtn:c.textTer,cursor:"pointer",fontWeight:s==="Daily"?600:400}}>{s}</button>)}
                    </div>
                  </div>
                  <div style={{display:"flex",gap:6,marginTop:12}}>
                    <Btn primary onClick={()=>{insertBlock("feed",{id:nid(),name:customName||"Custom Feed"});setCustomName("");setCustomInstruction("")}} style={{flex:1,justifyContent:"center"}}>Create Feed</Btn>
                    <Btn ghost onClick={()=>{setPickerStep("feed_presets")}}>Cancel</Btn>
                  </div>
                </div>
              </div>}
            </div>}
          </div>
          <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={showMarkup?"Markup":"Clean"} active={showMarkup} onClick={()=>setShowMarkup(!showMarkup)}/>
          <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",userSelect:"text"}}>
              {/* 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 19</div>
              </div>
              <div style={{fontSize:10.5,color:c.textTer,marginBottom:8,display:"flex",alignItems:"center",gap:4}}>
                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>

              {/* Blocks with natural spacing */}
              {blocks.map(block=>renderBlock(block))}

              {/* Slash command hint */}
              <div style={{marginTop:30,padding:"8px 12px",borderRadius:R.sm,border:`1px dashed ${c.borderLight}`,backgroundColor:c.bgPanelAlt,display:"flex",alignItems:"center",gap:8}}>
                <I.Grid size={12} color={c.accentBtn}/>
                <span style={{fontSize:11,color:c.textTer}}>Use <strong style={{color:c.accentBtn}}>Add Module</strong> in toolbar · Type <strong style={{color:c.accentBtn}}>/todo</strong> <strong style={{color:c.accentBtn}}>/feed</strong> <strong style={{color:c.accentBtn}}>/ask</strong> anywhere · Type <strong style={{color:c.accentBtn}}>@Elnor</strong> on any line</span>
              </div>
            </div>
          </div>

          {/* COMMENTS 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</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>
  );
}