Notes
GPT 6 Luna · full

Reviews & generation details
Reviews
No human review yet. Unreviewed does not mean unsuccessful.
Generation context
Imported historical artifact. Its exact original instructions and lineage are not known.
Generation prompt · exact text unavailable
See the current prompt for reference. It may differ from the instructions used to generate this artifact.
Inspect original source 46,611 bytes · SHA-256 2522c2229e9d
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Folio — Notes</title>
<style>
/* Tunable design constants */
:root{--bg:#f7f5f0;--panel:#fbfaf7;--paper:#fffefa;--ink:#292923;--muted:#89877e;--line:#e9e6dd;--accent:#7d8060;--accent-strong:#65694a;--accent-wash:#eff0e7;--hover:#f1efe9;--danger:#b45c4e;--shadow:0 14px 40px #302d2012;--serif:Georgia,'Times New Roman',serif;--sans:Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;--mono:'SFMono-Regular',Consolas,monospace;--save-delay:650ms;--snippet-length:104}
*{box-sizing:border-box}html,body{height:100%;margin:0}body{font-family:var(--sans);background:var(--bg);color:var(--ink);font-size:13px;overflow:hidden}button,input{font:inherit;color:inherit}button{border:0;background:none;cursor:pointer}button:focus-visible,input:focus-visible,[contenteditable]:focus-visible{outline:2px solid #a3a77a;outline-offset:2px}#app{height:100%;display:flex;flex-direction:column}.topbar{height:57px;flex:none;display:flex;align-items:center;padding:0 20px;border-bottom:1px solid var(--line);background:var(--panel);gap:16px;z-index:3}.brand{display:flex;align-items:center;gap:10px;width:194px;flex:none}.brand-mark{width:27px;height:27px;border-radius:8px;background:var(--accent);color:white;display:grid;place-items:center;font:italic bold 16px var(--serif);box-shadow:inset 0 0 0 1px #ffffff44}.brand-name{font:600 16px var(--serif);letter-spacing:.2px}.top-center{display:flex;align-items:center;gap:11px;flex:1;min-width:0}.crumb{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.crumb strong{color:#55564c;font-weight:550}.top-actions{display:flex;align-items:center;gap:7px}.icon-btn{width:32px;height:32px;border-radius:8px;display:grid;place-items:center;color:#77776e;transition:.16s ease}.icon-btn:hover{background:var(--hover);color:var(--ink)}.icon-btn svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}.save-state{font-size:11px;color:var(--muted);min-width:46px;text-align:right}.save-state:before{content:'';display:inline-block;width:6px;height:6px;border-radius:50%;background:#9da77b;margin:0 6px 1px 0}.save-state.saving:before{background:#c79d57;animation:pulse .8s infinite alternate}@keyframes pulse{to{opacity:.25}}
.workspace{display:flex;flex:1;min-height:0;overflow:hidden}.sidebar{width:236px;min-width:170px;max-width:360px;flex:none;background:#f3f1eb;border-right:1px solid var(--line);display:flex;flex-direction:column;transition:width .22s ease,min-width .22s ease;overflow:hidden}.sidebar.collapsed{width:0!important;min-width:0;border:0}.side-scroll{overflow:auto;padding:20px 12px 16px;flex:1}.side-top{display:flex;align-items:center;justify-content:space-between;padding:0 7px 17px}.section-label{font-size:10px;letter-spacing:1.15px;text-transform:uppercase;color:#99968a;font-weight:650}.nav-row,.notebook-row{height:34px;border-radius:7px;display:flex;align-items:center;gap:9px;padding:0 9px;color:#626259;cursor:pointer;transition:background .15s,color .15s;position:relative}.nav-row:hover,.notebook-row:hover{background:#eae8df;color:var(--ink)}.nav-row.active,.notebook-row.active{background:#e5e6d9;color:#45483a;font-weight:550}.nav-row .glyph,.notebook-row .glyph{width:16px;text-align:center;color:#898b70;font-size:14px}.count{margin-left:auto;color:#a09e93;font-size:10px}.side-divider{height:1px;background:#e4e1d8;margin:16px 4px}.notebook-heading{display:flex;align-items:center;justify-content:space-between;padding:0 7px 8px}.small-add{width:24px;height:24px;border-radius:6px;color:#8b897f;font-size:18px;line-height:1}.small-add:hover{background:#e7e5dc;color:var(--ink)}.notebook-list{display:flex;flex-direction:column;gap:2px}.book-actions{display:none;margin-left:auto;gap:1px}.notebook-row:hover .book-actions,.notebook-row.active .book-actions{display:flex}.mini-action{width:20px;height:20px;border-radius:5px;color:#85847b;font-size:14px;display:grid;place-items:center}.mini-action:hover{background:#dcdace;color:var(--ink)}.sidebar-bottom{border-top:1px solid var(--line);padding:12px;display:flex;gap:6px}.side-bottom-btn{flex:1;height:31px;border-radius:7px;color:#77766c;text-align:left;padding:0 9px;font-size:11px}.side-bottom-btn:hover{background:#eae8df}.side-bottom-btn span{margin-right:7px}
.resizer{width:5px;flex:none;cursor:col-resize;position:relative;z-index:2;margin:0 -2px}.resizer:hover:after,.resizer.dragging:after{content:'';position:absolute;top:0;bottom:0;left:2px;width:2px;background:#aeb18a}.notelist{width:310px;min-width:230px;max-width:480px;flex:none;background:var(--panel);border-right:1px solid var(--line);display:flex;flex-direction:column;min-height:0}.list-head{padding:22px 18px 14px}.list-head-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:15px}.list-title{font:600 21px var(--serif);letter-spacing:-.35px}.new-note{height:31px;border-radius:7px;background:var(--accent);color:white;padding:0 11px;font-size:11px;font-weight:550;display:flex;gap:6px;align-items:center;box-shadow:0 2px 5px #40432617;transition:.16s}.new-note:hover{background:var(--accent-strong);transform:translateY(-1px)}.new-note b{font-size:17px;font-weight:400;line-height:10px}.searchbox{height:34px;display:flex;align-items:center;gap:8px;padding:0 10px;background:#f2f0ea;border:1px solid transparent;border-radius:8px;color:#929087}.searchbox:focus-within{background:var(--paper);border-color:#c9cbb3;box-shadow:0 0 0 3px #969b6715}.searchbox svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:1.8}.searchbox input{border:0;outline:0;background:none;width:100%;font-size:11px}.searchbox input::placeholder{color:#a6a398}.list-tools{height:38px;display:flex;align-items:center;justify-content:space-between;padding:0 18px;border-bottom:1px solid var(--line);font-size:10px;color:#97948a}.sort-select{background:transparent;border:0;color:#76756c;font-size:10px;outline:none;cursor:pointer}.notes-scroll{overflow:auto;flex:1;padding:9px 9px 18px}.note-card{position:relative;padding:12px 12px 11px;border-radius:8px;margin-bottom:3px;cursor:pointer;transition:background .15s,border-color .15s;border:1px solid transparent}.note-card:hover{background:#f3f1eb}.note-card.selected{background:#eff0e8;border-color:#e8e9dd}.note-card-top{display:flex;align-items:center;gap:6px}.note-card h3{font-size:12px;font-weight:600;margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}.pin-icon{font-size:10px;color:#96956e}.note-date{font-size:9px;color:#aaa79d;white-space:nowrap}.note-preview{font-size:10px;color:#8a887e;line-height:1.45;margin-top:6px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.note-meta{display:flex;gap:4px;margin-top:7px;overflow:hidden}.tag-pill{font-size:9px;background:#eeede6;color:#85836f;padding:2px 6px;border-radius:4px;white-space:nowrap}.note-card.selected .tag-pill{background:#e4e5d9}.note-empty{padding:35px 20px;text-align:center;color:#99968b;line-height:1.7;font-size:11px}.note-empty .empty-icon{font:30px var(--serif);color:#b3b19f;margin-bottom:8px}
.editor-pane{flex:1;min-width:300px;display:flex;flex-direction:column;background:var(--paper);position:relative}.editor-top{height:52px;flex:none;border-bottom:1px solid #f0eee8;display:flex;align-items:center;padding:0 26px;gap:8px}.editor-top .spacer{flex:1}.editor-actions{display:flex;gap:2px}.editor-body-wrap{overflow:auto;flex:1;scrollbar-gutter:stable}.editor-inner{max-width:790px;margin:0 auto;padding:38px 60px 100px;min-height:100%}.title-field{font:600 31px/1.24 var(--serif);letter-spacing:-.6px;border:0;outline:none;width:100%;resize:none;background:transparent;color:var(--ink);padding:0;margin:0 0 10px;display:block;min-height:40px}.title-field::placeholder{color:#c7c4b8}.note-info{display:flex;align-items:center;gap:8px;color:#aaa79c;font-size:10px;padding:0 0 23px;border-bottom:1px solid #efede7}.info-dot{width:3px;height:3px;border-radius:50%;background:#c0bdb1}.tag-editor{display:flex;align-items:center;gap:5px;flex-wrap:wrap;margin-top:14px;min-height:20px}.tag-editor .tag-pill{background:#efeee7}.tag-remove{margin-left:3px;cursor:pointer;color:#aaa}.tag-input{min-width:65px;width:95px;border:0;outline:0;background:transparent;font-size:10px;color:#77776c}.tag-input::placeholder{color:#b5b2a7}.format-toolbar{height:40px;flex:none;background:var(--paper);border-bottom:1px solid #f0eee8;display:flex;align-items:center;gap:3px;padding:0 max(20px,calc((100% - 790px)/2 + 60px));position:sticky;top:0;z-index:2}.tool{width:29px;height:28px;border-radius:5px;display:grid;place-items:center;color:#77766e;font-size:13px;transition:.13s}.tool:hover{background:#f0eee8;color:var(--ink)}.tool.active{background:#e8e9dd;color:#555a3e}.tool svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}.tool strong{font-weight:700}.tool-sep{height:17px;width:1px;background:#e8e5dd;margin:0 5px}.editor{font:15px/1.78 var(--serif);color:#45443d;min-height:280px;outline:none;overflow-wrap:anywhere}.editor:empty:before{content:'Begin with a thought…';color:#c4c1b5;pointer-events:none}.editor h1,.editor h2,.editor h3{font-family:var(--sans);color:var(--ink);line-height:1.3;letter-spacing:-.4px;margin:1.35em 0 .5em}.editor h1{font-size:25px}.editor h2{font-size:20px}.editor h3{font-size:16px}.editor p{margin:.65em 0}.editor ul,.editor ol{padding-left:25px;margin:.65em 0}.editor li{padding-left:3px}.editor blockquote{border-left:3px solid #b9bc9b;padding:2px 0 2px 17px;margin:1em 0;color:#77766a}.editor code{font:13px var(--mono);background:#f2f0e9;border-radius:4px;padding:2px 5px;color:#70734f}.editor hr{border:0;border-top:1px solid #e5e2d9;margin:24px 0}.editor [data-checklist] li{list-style:none;margin-left:-21px;display:flex;align-items:flex-start;gap:8px}.editor [data-checklist] input[type=checkbox]{appearance:none;flex:none;width:15px;height:15px;border:1px solid #c9c7b8;border-radius:4px;margin:7px 0 0;cursor:pointer;position:relative}.editor [data-checklist] input:checked{background:var(--accent);border-color:var(--accent)}.editor [data-checklist] input:checked:after{content:'✓';position:absolute;inset:-2px 0 0;color:white;font:11px var(--sans);text-align:center}.editor [data-checklist] li.checked{color:#aaa99e;text-decoration:line-through}.editor [data-checklist] li.checked input{text-decoration:none}.empty-editor{flex:1;display:grid;place-items:center;color:#a7a499;text-align:center}.empty-card{transform:translateY(-15px)}.empty-card .symbol{width:56px;height:56px;border:1px solid #eeece4;border-radius:17px;margin:0 auto 15px;display:grid;place-items:center;font:italic 26px var(--serif);color:#a7a88a;background:#faf9f5}.empty-card h2{font:500 17px var(--serif);color:#77766d;margin:0 0 6px}.empty-card p{font-size:11px;margin:0;color:#aaa79d}.toast{position:fixed;bottom:22px;left:50%;transform:translate(-50%,12px);background:#34352c;color:#fff;padding:9px 14px;border-radius:8px;font-size:11px;box-shadow:var(--shadow);opacity:0;pointer-events:none;transition:.2s;z-index:20}.toast.show{opacity:1;transform:translate(-50%,0)}.modal-backdrop{position:fixed;inset:0;background:#24241e55;display:grid;place-items:center;z-index:30;backdrop-filter:blur(2px)}.modal{width:min(370px,calc(100vw - 34px));background:var(--paper);border-radius:13px;padding:23px;box-shadow:0 18px 60px #0003}.modal h2{font:600 20px var(--serif);margin:0 0 17px}.modal input{width:100%;height:39px;border:1px solid var(--line);border-radius:7px;padding:0 11px;background:var(--bg);outline:none}.modal input:focus{border-color:#a6a985;box-shadow:0 0 0 3px #969b6715}.modal-actions{display:flex;justify-content:flex-end;gap:7px;margin-top:18px}.btn{height:32px;padding:0 12px;border-radius:7px;font-size:11px}.btn:hover{background:var(--hover)}.btn.primary{background:var(--accent);color:white}.btn.primary:hover{background:var(--accent-strong)}.context-menu{position:fixed;z-index:25;background:var(--paper);border:1px solid var(--line);box-shadow:var(--shadow);border-radius:9px;padding:5px;min-width:165px}.context-menu button{display:block;width:100%;height:31px;text-align:left;border-radius:5px;padding:0 9px;font-size:11px;color:#55554d}.context-menu button:hover{background:var(--hover)}.context-menu button.danger{color:var(--danger)}.menu-sep{height:1px;background:var(--line);margin:4px}.drop-hint{position:absolute;inset:5px;border:1px dashed #959a6d;border-radius:7px;pointer-events:none}.highlight{background:#f2e3a6;color:inherit;border-radius:2px}.trash-note .note-preview{opacity:.65}
body.dark{--bg:#20211e;--panel:#252622;--paper:#292a25;--ink:#e9e7dd;--muted:#a09e91;--line:#393a33;--accent:#a2a77b;--accent-strong:#bbc08d;--accent-wash:#393c30;--hover:#34352f;--danger:#df8979;color-scheme:dark}body.dark .sidebar{background:#23241f}body.dark .nav-row.active,body.dark .notebook-row.active,body.dark .note-card.selected{background:#383a30;color:#e1e0d5;border-color:#414337}body.dark .searchbox,body.dark .editor code{background:#33342e}body.dark .note-card:hover,body.dark .side-bottom-btn:hover,body.dark .nav-row:hover,body.dark .notebook-row:hover{background:#30312b}body.dark .note-card.selected .tag-pill,body.dark .tag-pill{background:#393a32}body.dark .editor{color:#d0cec3}body.dark .crumb strong{color:#d2d0c5}body.dark .format-toolbar{background:var(--paper)}body.dark .editor-top,body.dark .format-toolbar{border-color:#35362f}body.dark .editor-toolbar .tool.active{background:#414337}body.dark .editor [data-checklist] input:checked{background:var(--accent)}
@media(max-width:800px){.sidebar{width:190px}.notelist{width:270px}.brand{width:auto}.topbar{padding:0 12px}.editor-inner{padding:30px 28px 80px}.format-toolbar{padding-left:28px;padding-right:15px}}@media(max-width:620px){.sidebar{width:0!important;min-width:0;border:0}.notelist{width:42%;min-width:150px}.editor-pane{min-width:200px}.editor-inner{padding:25px 18px}.editor-top{padding:0 14px}.list-head{padding:17px 12px 12px}.list-tools{padding:0 12px}.notes-scroll{padding:7px 5px}.topbar{height:50px}.brand{width:auto}.brand-name{display:none}.save-state{display:none}}
</style></head>
<body><div id="app">
<header class="topbar"><div class="brand"><div class="brand-mark">f</div><span class="brand-name">folio</span></div><div class="top-center"><button class="icon-btn" id="collapseBtn" title="Toggle sidebar" aria-label="Toggle sidebar"><svg viewBox="0 0 24 24"><rect x="3.5" y="4" width="17" height="16" rx="2"/><path d="M9 4v16"/></svg></button><div class="crumb" id="crumb"><strong>All Notes</strong></div></div><div class="top-actions"><span class="save-state" id="saveState">Saved</span><button class="icon-btn" id="themeBtn" title="Toggle theme" aria-label="Toggle theme"><svg viewBox="0 0 24 24"><path d="M20.2 15.4A8 8 0 0 1 8.6 3.8 8.2 8.2 0 1 0 20.2 15.4Z"/></svg></button></div></header>
<main class="workspace"><aside class="sidebar" id="sidebar"><div class="side-scroll"><div class="side-top"><span class="section-label">Library</span></div><div id="virtualNav"></div><div class="side-divider"></div><div class="notebook-heading"><span class="section-label">Notebooks</span><button class="small-add" id="addNotebook" title="New notebook">+</button></div><div class="notebook-list" id="notebookList"></div></div><div class="sidebar-bottom"><button class="side-bottom-btn" id="trashNav"><span>♲</span>Trash <span class="count" id="trashCount"></span></button></div></aside><div class="resizer" data-resize="side"></div>
<section class="notelist"><div class="list-head"><div class="list-head-top"><div class="list-title" id="listTitle">All Notes</div><button class="new-note" id="newNote"><b>+</b> New note</button></div><label class="searchbox"><svg viewBox="0 0 24 24"><circle cx="10.8" cy="10.8" r="6.7"/><path d="m16 16 4.3 4.3"/></svg><input id="searchInput" placeholder="Search all notes…" autocomplete="off"><span style="font-size:9px;color:#aaa">⌘K</span></label></div><div class="list-tools"><span id="noteCount">0 notes</span><select id="sortSelect" class="sort-select" aria-label="Sort notes"><option value="modified">Modified</option><option value="created">Created</option><option value="alpha">Alphabetical</option></select></div><div class="notes-scroll" id="notesList"></div></section><div class="resizer" data-resize="list"></div>
<section class="editor-pane" id="editorPane"><div class="editor-top"><span class="crumb" id="editorNotebook"></span><span class="spacer"></span><span class="save-state" id="editorSaved">Saved</span><div class="editor-actions"><button class="icon-btn" id="pinBtn" title="Pin note" aria-label="Pin note"><svg viewBox="0 0 24 24"><path d="m8 4 8 0-1.5 6 3 3v1H6.5v-1l3-3L8 4Z"/><path d="M12 14v7"/></svg></button><button class="icon-btn" id="moveBtn" title="Move note" aria-label="Move note"><svg viewBox="0 0 24 24"><path d="M4 7h7l2 2h7v10H4z"/><path d="M12 11v5m-2-2 2 2 2-2"/></svg></button><button class="icon-btn" id="moreBtn" title="More actions" aria-label="More actions"><svg viewBox="0 0 24 24"><circle cx="5" cy="12" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/></svg></button></div></div><div class="format-toolbar" id="toolbar" style="display:none">
<button class="tool" data-cmd="bold" title="Bold (Ctrl+B)"><strong>B</strong></button><button class="tool" data-cmd="italic" title="Italic (Ctrl+I)"><em>I</em></button><button class="tool" data-cmd="underline" title="Underline (Ctrl+U)"><u>U</u></button><button class="tool" data-cmd="strikeThrough" title="Strikethrough"><s>S</s></button><button class="tool" data-cmd="code" title="Inline code">‹›</button><span class="tool-sep"></span><button class="tool" data-cmd="formatBlock" data-value="H1" title="Heading 1">H1</button><button class="tool" data-cmd="formatBlock" data-value="H2" title="Heading 2">H2</button><button class="tool" data-cmd="formatBlock" data-value="H3" title="Heading 3">H3</button><span class="tool-sep"></span><button class="tool" data-cmd="insertUnorderedList" title="Bulleted list">☷</button><button class="tool" data-cmd="insertOrderedList" title="Numbered list">1.</button><button class="tool" data-cmd="checklist" title="Checklist">☑</button><button class="tool" data-cmd="formatBlock" data-value="BLOCKQUOTE" title="Quote">❝</button><button class="tool" data-cmd="insertHorizontalRule" title="Horizontal rule">―</button></div>
<div id="editorContent" class="editor-body-wrap"><div class="empty-editor"><div class="empty-card"><div class="symbol">f</div><h2>Select or create a note</h2><p>Your ideas deserve a little space.</p></div></div></div></section></main></div><div class="toast" id="toast"></div><div id="modalRoot"></div>
<script>
/* Folio — model, persistence, and interaction */
(()=>{'use strict';
const KEY='folio.notes.v1', DEBOUNCE=650, SNIPPET=104;
const uid=()=>Math.random().toString(36).slice(2,9)+Date.now().toString(36).slice(-3), now=()=>Date.now();
const defaultData=()=>{const id=uid(),nid=uid(),t=now();return {notebooks:[{id:nid,name:'Personal',created:t}],notes:[{id,notebookId:nid,title:'A place for your thoughts',html:'<p>Welcome to <strong>Folio</strong> — a quieter place to collect ideas.</p><p>Use the toolbar to shape your thoughts, or try a few shortcuts:</p><ul><li>Type <code># </code> to make a heading</li><li>Type <code>[] </code> to start a checklist</li></ul><blockquote>Small notes become big ideas.</blockquote>',tags:['welcome'],pinned:false,created:t,updated:t,deleted:false}],selection:id,view:'all',sort:'modified',sidebarWidth:236,listWidth:310,collapsed:false,theme:'light'}};
let data;try{data=JSON.parse(localStorage.getItem(KEY))||defaultData()}catch(e){data=defaultData()}
if(!Array.isArray(data.notebooks)||!Array.isArray(data.notes))data=defaultData();
// Repair the built-in welcome note if an interrupted browser edit left only an empty heading.
const welcome=data.notes.find(n=>n.title==='A place for your thoughts'&&!n.deleted);if(welcome&&!(welcome.html||'').replace(/<[^>]*>/g,'').trim())welcome.html='<p>Welcome to <strong>Folio</strong> — a quieter place to collect ideas.</p><p>Use the toolbar to shape your thoughts, or try a few shortcuts:</p><ul><li>Type <code># </code> to make a heading</li><li>Type <code>[] </code> to start a checklist</li></ul><blockquote>Small notes become big ideas.</blockquote>';
let query='',activeTag='',saveTimer=null,toastTimer=null,undoStack=[],redoStack=[],lastHtml='',suppressHistory=false,dragNote=null,modalResolve=null;
const $=s=>document.querySelector(s), $$=s=>[...document.querySelectorAll(s)], esc=s=>String(s??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
const editorWrap=$('#editorContent');
function textOf(html){const d=document.createElement('div');d.innerHTML=html||'';return (d.innerText||d.textContent||'').replace(/\u00a0/g,' ').replace(/\s+/g,' ').trim()}
function sanitize(html){const doc=new DOMParser().parseFromString('<body>'+html+'</body>','text/html'),allowed=new Set(['P','DIV','BR','STRONG','B','EM','I','U','S','STRIKE','CODE','H1','H2','H3','UL','OL','LI','BLOCKQUOTE','HR','INPUT']);function clean(node){[...node.childNodes].forEach(ch=>{if(ch.nodeType===8){ch.remove();return}if(ch.nodeType!==1)return;const tag=ch.tagName;if(tag==='SCRIPT'||tag==='STYLE'||tag==='IFRAME'||tag==='OBJECT'||tag==='SVG'){ch.remove();return}clean(ch);if(!allowed.has(tag)){ch.replaceWith(...ch.childNodes);return}for(const a of [...ch.attributes])ch.removeAttribute(a.name);if(tag==='INPUT'){ch.type='checkbox';ch.checked=ch.hasAttribute('checked')||ch.defaultChecked;ch.setAttribute('contenteditable','false');ch.disabled=false}if(tag==='UL'&&ch.dataset.checklist==='true')ch.setAttribute('data-checklist','true');if(tag==='LI'&&ch.classList.contains('checked'))ch.setAttribute('class','checked');if(tag==='UL'&&ch.getAttribute('data-checklist')==='true'){} });}clean(doc.body);return doc.body.innerHTML.replace(/<div>/g,'<p>').replace(/<\/div>/g,'</p>')}
// Sanitizer preserving only supported semantic markup and checklist state.
function cleanHtml(html){const doc=new DOMParser().parseFromString('<body>'+html+'</body>','text/html');const allowed=new Set('P DIV BR STRONG B EM I U S STRIKE CODE H1 H2 H3 UL OL LI BLOCKQUOTE HR INPUT'.split(' '));function walk(parent){for(const el of [...parent.children]){let tag=el.tagName;if(['SCRIPT','STYLE','IFRAME','OBJECT','SVG','FORM'].includes(tag)){el.remove();continue}walk(el);if(!allowed.has(tag)){el.replaceWith(...el.childNodes);continue}const checklist=el.hasAttribute('data-checklist'),checked=el.classList.contains('checked');[...el.attributes].forEach(a=>el.removeAttribute(a.name));if(tag==='UL'&&checklist)el.setAttribute('data-checklist','true');if(tag==='LI'&&checked)el.classList.add('checked');if(tag==='INPUT'){const isChecked=el.checked||el.hasAttribute('checked');el.type='checkbox';el.checked=isChecked;el.setAttribute('contenteditable','false');if(isChecked)el.setAttribute('checked','');}}}walk(doc.body);return doc.body.innerHTML.replace(/<div>/g,'<p>').replace(/<\/div>/g,'</p>')}
function persist(){try{localStorage.setItem(KEY,JSON.stringify(data))}catch(e){toast('Could not save changes — storage is full.')}$('#saveState').textContent='Saved';$('#saveState').classList.remove('saving');$('#editorSaved').textContent='Saved';$('#editorSaved').classList.remove('saving')}
function scheduleSave(){['#saveState','#editorSaved'].forEach(s=>{$(s).textContent='Saving';$(s).classList.add('saving')});clearTimeout(saveTimer);saveTimer=setTimeout(persist,DEBOUNCE)}
function toast(msg){const el=$('#toast');el.textContent=msg;el.classList.add('show');clearTimeout(toastTimer);toastTimer=setTimeout(()=>el.classList.remove('show'),2100)}
function current(){return data.notes.find(n=>n.id===data.selection&&!n.deleted)}function notebook(id){return data.notebooks.find(n=>n.id===id)}
function setView(view){data.view=view;activeTag='';render()}
function visibleNotes(){let list=data.notes.filter(n=>data.view==='trash'?n.deleted:!n.deleted);if(data.view==='book')list=list.filter(n=>n.notebookId===data.bookId);if(data.view==='tag')list=list.filter(n=>n.tags?.includes(activeTag));if(query.trim()){const q=query.trim().toLowerCase();list=list.filter(n=>(n.title+' '+textOf(n.html)+' '+(n.tags||[]).join(' ')).toLowerCase().includes(q))}if(data.sort==='alpha')list.sort((a,b)=>(a.title||'').localeCompare(b.title||''));else if(data.sort==='created')list.sort((a,b)=>b.created-a.created);else list.sort((a,b)=>b.updated-a.updated);if(data.view!=='trash')list.sort((a,b)=>Number(!!b.pinned)-Number(!!a.pinned));return list}
function dateLabel(ts){if(!ts)return'';const d=new Date(ts),today=new Date();if(d.toDateString()===today.toDateString())return d.toLocaleTimeString([],{hour:'numeric',minute:'2-digit'});const diff=Date.now()-ts;if(diff<6*864e5)return d.toLocaleDateString([],{weekday:'short'});return d.toLocaleDateString([],{month:'short',day:'numeric'})}
function highlightText(s,q){if(!q)return esc(s);const i=s.toLowerCase().indexOf(q.toLowerCase());if(i<0)return esc(s);return esc(s.slice(0,i))+'<mark class="highlight">'+esc(s.slice(i,i+q.length))+'</mark>'+esc(s.slice(i+q.length))}
function renderSidebar(){const v=$('#virtualNav');v.innerHTML=`<div class="nav-row ${data.view==='all'?'active':''}" data-view="all"><span class="glyph">▤</span>All Notes<span class="count">${data.notes.filter(n=>!n.deleted).length}</span></div>`;const books=$('#notebookList');books.innerHTML='';data.notebooks.forEach(b=>{const row=document.createElement('div');row.className='notebook-row '+(data.view==='book'&&data.bookId===b.id?'active':'');row.dataset.book=b.id;row.innerHTML=`<span class="glyph">▱</span><span class="book-name">${esc(b.name)}</span><span class="count">${data.notes.filter(n=>!n.deleted&&n.notebookId===b.id).length}</span><span class="book-actions"><button class="mini-action rename-book" title="Rename">···</button></span>`;books.appendChild(row)});$('#trashCount').textContent=data.notes.filter(n=>n.deleted).length||'';$('#trashNav').classList.toggle('active',data.view==='trash')}
function viewTitle(){if(data.view==='trash')return'Trash';if(data.view==='book')return notebook(data.bookId)?.name||'Notebook';if(data.view==='tag')return'# '+activeTag;return query?'Search results':'All Notes'}
function renderList(){const list=visibleNotes(),root=$('#notesList');$('#listTitle').textContent=viewTitle();$('#noteCount').textContent=`${list.length} ${list.length===1?'note':'notes'}`;$('#sortSelect').value=data.sort;root.innerHTML='';if(!list.length){root.innerHTML=`<div class="note-empty"><div class="empty-icon">${data.view==='trash'?'♲':'✳'}</div>${query?'No notes found. Try another search.':data.view==='trash'?'Your deleted notes will appear here.':'A fresh page is waiting for you.'}</div>`;return}list.forEach(n=>{const card=document.createElement('article');card.className='note-card '+(n.id===data.selection?'selected ':'')+(n.deleted?'trash-note':'');card.dataset.id=n.id;card.draggable=!n.deleted;const title=n.title||'Untitled';let preview=textOf(n.html).slice(0,SNIPPET);card.innerHTML=`<div class="note-card-top"><h3>${highlightText(title,query)}</h3>${n.pinned&&!n.deleted?'<span class="pin-icon">◆</span>':''}<time class="note-date">${dateLabel(n.updated)}</time></div><div class="note-preview">${highlightText(preview,query)||'No additional text'}</div>${n.tags?.length?`<div class="note-meta">${n.tags.slice(0,3).map(t=>`<span class="tag-pill" data-tag="${esc(t)}">${esc(t)}</span>`).join('')}</div>`:''}`;root.appendChild(card)})}
function renderEditor(){const n=current(),toolbar=$('#toolbar'),content=$('#editorContent');if(!n){toolbar.style.display='none';$('#pinBtn').style.display='none';$('#moveBtn').style.display='none';$('#moreBtn').style.display='none';$('#editorNotebook').textContent='';content.innerHTML='<div class="empty-editor"><div class="empty-card"><div class="symbol">f</div><h2>Select or create a note</h2><p>Your ideas deserve a little space.</p></div></div>';return}$('#pinBtn').style.display=$('#moveBtn').style.display=$('#moreBtn').style.display='grid';$('#pinBtn').classList.toggle('active',!!n.pinned);$('#pinBtn').title=n.pinned?'Unpin note':'Pin note';$('#editorNotebook').textContent=notebook(n.notebookId)?.name||'';toolbar.style.display='flex';content.innerHTML=`<div class="editor-inner"><textarea class="title-field" id="titleField" rows="1" placeholder="Untitled note" aria-label="Note title"></textarea><div class="note-info"><span id="createdInfo">Created ${new Date(n.created).toLocaleDateString([],{month:'long',day:'numeric',year:'numeric'})}</span><i class="info-dot"></i><span id="updatedInfo">Edited ${dateLabel(n.updated)}</span></div><div class="tag-editor" id="tagEditor"></div><div class="editor" id="editor" contenteditable="true" spellcheck="true" role="textbox" aria-multiline="true"></div></div>`;const title=$('#titleField');title.value=n.title||'';const ed=$('#editor');ed.innerHTML=cleanHtml(n.html||'');lastHtml=ed.innerHTML;undoStack=[];redoStack=[];renderTags();}
function renderTags(){const n=current(),box=$('#tagEditor');if(!n||!box)return;box.innerHTML=(n.tags||[]).map((t,i)=>`<span class="tag-pill">${esc(t)}<span class="tag-remove" data-index="${i}" title="Remove tag">×</span></span>`).join('')+'<input class="tag-input" id="tagInput" placeholder="+ Add tag" aria-label="Add tag">'}
function render(){renderSidebar();renderList();renderEditor();$('#crumb').innerHTML=`<strong>${esc(viewTitle())}</strong>`;$('#sidebar').classList.toggle('collapsed',!!data.collapsed);$('#sidebar').style.width=data.sidebarWidth+'px';$('.notelist').style.width=data.listWidth+'px';document.body.classList.toggle('dark',data.theme==='dark');scheduleSave()}
function selectNote(id){data.selection=id;renderList();renderEditor();scheduleSave()}
function createNote(){let nb=data.view==='book'?data.bookId:data.notebooks[0]?.id;if(!nb){createNotebook();return}const n={id:uid(),notebookId:nb,title:'',html:'<p><br></p>',tags:[],pinned:false,created:now(),updated:now(),deleted:false};data.notes.unshift(n);data.selection=n.id;if(data.view==='trash')data.view='all';render();setTimeout(()=>$('#titleField')?.focus(),50)}
function createNotebook(renameId){const old=notebook(renameId);openModal(old?'Rename notebook':'New notebook',old?.name||'',name=>{if(!name)return;if(old)old.name=name;else{const b={id:uid(),name,created:now()};data.notebooks.push(b);data.view='book';data.bookId=b.id}render()})}
function openModal(title,value,done){const root=$('#modalRoot');root.innerHTML=`<div class="modal-backdrop"><form class="modal"><h2>${esc(title)}</h2><input id="modalInput" maxlength="40" placeholder="Notebook name" value="${esc(value)}"><div class="modal-actions"><button type="button" class="btn" id="modalCancel">Cancel</button><button class="btn primary" type="submit">Save</button></div></form></div>`;const input=$('#modalInput');input.focus();input.select();const close=()=>root.innerHTML='';$('#modalCancel').onclick=()=>{close();done('')};$('.modal-backdrop').onclick=e=>{if(e.target.classList.contains('modal-backdrop')){close();done('')}};$('.modal').onsubmit=e=>{e.preventDefault();const v=input.value.trim();close();done(v)}}
function pushUndo(html){undoStack.push(html);if(undoStack.length>80)undoStack.shift();redoStack=[]}
function syncEditor(fromInput=false){const ed=$('#editor'),n=current();if(!ed||!n)return;const clean=cleanHtml(ed.innerHTML);if(clean!==ed.innerHTML)ed.innerHTML=clean;if(fromInput){if(clean!==lastHtml&&!suppressHistory)pushUndo(lastHtml);suppressHistory=false}if(clean!==lastHtml){n.html=clean;lastHtml=clean;n.updated=now();scheduleSave();renderList();$('#updatedInfo').textContent='Edited just now'} }
function updateTitle(){const n=current();if(!n)return;n.title=$('#titleField').value;n.updated=now();scheduleSave();renderList()}
function restoreHtml(html){const ed=$('#editor');if(!ed)return;ed.innerHTML=cleanHtml(html);lastHtml=ed.innerHTML;const n=current();if(n){n.html=ed.innerHTML;n.updated=now();scheduleSave();renderList()}updateToolbar()}
function doUndo(redo=false){const from=redo?undoStack:redoStack,to=redo?redoStack:undoStack;if(!from.length)return;to.push($('#editor')?.innerHTML||lastHtml);restoreHtml(from.pop())}
function focusEditor(){const ed=$('#editor');if(ed)ed.focus()}
function command(cmd,value){const ed=$('#editor');if(!ed)return;ed.focus();const before=ed.innerHTML;pushUndo(before);suppressHistory=true;const sel=getSelection();if(cmd==='code'){document.execCommand('insertHTML',false,'<code>'+((sel?.toString())||'code')+'</code>')}else if(cmd==='checklist'){insertChecklist()}else document.execCommand(cmd,false,value||null);syncEditor(false);lastHtml=cleanHtml(ed.innerHTML);const n=current();if(n)n.html=lastHtml;updateToolbar()}
function insertChecklist(){const sel=getSelection();let li=sel?.anchorNode?.parentElement?.closest('li');if(li){const ul=li.parentElement;ul.setAttribute('data-checklist','true');li.insertAdjacentHTML('afterbegin','<input type="checkbox" contenteditable="false">');return}document.execCommand('insertHTML',false,'<ul data-checklist="true"><li><input type="checkbox" contenteditable="false"> </li></ul><p><br></p>');placeCaretEnd($('#editor').querySelector('ul li'))}
function placeCaretEnd(el){if(!el)return;const r=document.createRange(),s=getSelection();r.selectNodeContents(el);r.collapse(false);s.removeAllRanges();s.addRange(r)}
function updateToolbar(){const ed=$('#editor');if(!ed)return;const state={bold:document.queryCommandState('bold'),italic:document.queryCommandState('italic'),underline:document.queryCommandState('underline'),strikeThrough:document.queryCommandState('strikeThrough'),insertUnorderedList:document.queryCommandState('insertUnorderedList'),insertOrderedList:document.queryCommandState('insertOrderedList')};$$('#toolbar [data-cmd]').forEach(b=>{const c=b.dataset.cmd;b.classList.toggle('active',!!state[c])})}
function insertShortcut(blockType,marker){const sel=getSelection();if(!sel||!sel.anchorNode)return false;const node=sel.anchorNode;if(node.nodeType!==3)return false;const block=node.parentElement.closest('p,div,h1,h2,h3,blockquote,li')||node.parentElement;if(!block||block.closest('li'))return false;const prefixRange=document.createRange();prefixRange.selectNodeContents(block);prefixRange.setEnd(node,sel.anchorOffset);if(prefixRange.toString()!==marker||block.textContent!==marker)return false;let replacement;if(blockType==='ul'||blockType==='check'){replacement=document.createElement('ul');if(blockType==='check')replacement.setAttribute('data-checklist','true');const li=document.createElement('li');if(blockType==='check'){const inp=document.createElement('input');inp.type='checkbox';inp.setAttribute('contenteditable','false');li.append(inp)}li.append(document.createElement('br'));replacement.append(li)}else{replacement=document.createElement(blockType);replacement.innerHTML='<br>'}block.replaceWith(replacement);const target=replacement.tagName==='UL'?replacement.querySelector('li'):replacement;placeCaretEnd(target);syncEditor(false);lastHtml=cleanHtml($('#editor').innerHTML);return true}
function handleEnter(e){const sel=getSelection(),li=sel?.anchorNode?.parentElement?.closest('li'),ed=$('#editor');if(!li||!ed.contains(li))return;const list=li.parentElement,isCheck=list.hasAttribute('data-checklist'),empty=textOf(li.innerHTML.replace(/<input[^>]*>/g,''))==='';if(empty){e.preventDefault();if(isCheck){const p=document.createElement('p');p.innerHTML='<br>';list.after(p);li.remove();if(!list.children.length)list.remove();placeCaretEnd(p)}else{document.execCommand('insertParagraph');}syncEditor(false);return}if(isCheck){e.preventDefault();const next=document.createElement('li'),inp=document.createElement('input');inp.type='checkbox';inp.setAttribute('contenteditable','false');next.append(inp,document.createTextNode(''));li.after(next);placeCaretEnd(next);syncEditor(false)}}
function handleMarkdown(e){if(e.key!==' ')return;const sel=getSelection();if(!sel||sel.rangeCount===0)return;const node=sel.anchorNode;if(node?.nodeType!==3)return;const before=node.textContent.slice(0,sel.anchorOffset),map={'#':'H1','##':'H2','###':'H3','-':'ul','[]':'check','>':'BLOCKQUOTE'};if(map[before]){e.preventDefault();insertShortcut(map[before],before);syncEditor(false)}}
function handlePaste(e){const ed=$('#editor');if(!ed)return;e.preventDefault();const html=e.clipboardData.getData('text/html'),plain=e.clipboardData.getData('text/plain');let safe;if(html)safe=cleanHtml(html);else safe=esc(plain).replace(/\r?\n/g,'<br>');document.execCommand('insertHTML',false,safe);syncEditor(false)}
function moveNote(id,nb){const n=data.notes.find(x=>x.id===id);if(!n||!nb)return;n.notebookId=nb;n.updated=now();scheduleSave();render();toast('Note moved')}
function deleteNote(n){if(!n)return;n.deleted=true;n.deletedAt=now();n.originalNotebookId=n.notebookId;data.selection=null;render();toast('Moved to Trash')}
function duplicateNote(n){if(!n)return;const copy={...n,id:uid(),title:(n.title||'Untitled')+' copy',created:now(),updated:now(),tags:[...(n.tags||[])],deleted:false};data.notes.push(copy);data.selection=copy.id;render();toast('Note duplicated')}
function noteMenu(anchor,n){closeMenu();const m=document.createElement('div');m.className='context-menu';m.innerHTML=n.deleted?'<button data-action="restore">Restore note</button><button data-action="purge" class="danger">Delete permanently</button>':'<button data-action="pin">'+(n.pinned?'Unpin note':'Pin note')+'</button><button data-action="duplicate">Duplicate</button><div class="menu-sep"></div><button data-action="delete" class="danger">Move to Trash</button>';document.body.append(m);const r=anchor.getBoundingClientRect();m.style.top=Math.min(innerHeight-m.offsetHeight-8,r.bottom+4)+'px';m.style.left=Math.max(8,Math.min(innerWidth-m.offsetWidth-8,r.right-m.offsetWidth))+'px';m.onclick=e=>{const a=e.target.dataset.action;if(!a)return;closeMenu();if(a==='pin'){n.pinned=!n.pinned;render()}if(a==='duplicate')duplicateNote(n);if(a==='delete')deleteNote(n);if(a==='restore'){n.deleted=false;n.notebookId=n.originalNotebookId||n.notebookId;data.view='book';data.bookId=n.notebookId;data.selection=n.id;render()}if(a==='purge'){data.notes=data.notes.filter(x=>x.id!==n.id);data.selection=null;render()}};setTimeout(()=>document.addEventListener('pointerdown',outsideMenu,{once:true}),0)}
function bookMenu(anchor,id){closeMenu();const m=document.createElement('div');m.className='context-menu';m.innerHTML='<button data-act="rename">Rename notebook</button><button data-act="delete" class="danger">Delete notebook</button>';document.body.append(m);const r=anchor.getBoundingClientRect();m.style.top=Math.min(innerHeight-m.offsetHeight-8,r.bottom+3)+'px';m.style.left=Math.min(innerWidth-m.offsetWidth-8,r.left)+'px';m.onclick=e=>{const act=e.target.dataset.act;if(!act)return;closeMenu();if(act==='rename')createNotebook(id);else{const b=notebook(id);if(!b)return;const remaining=data.notebooks.filter(x=>x.id!==id);if(!remaining.length){toast('Keep at least one notebook');return}const fallback=remaining[0].id;data.notes.forEach(n=>{if(n.notebookId===id)n.notebookId=fallback;if(n.originalNotebookId===id)n.originalNotebookId=fallback});data.notebooks=remaining;if(data.view==='book'&&data.bookId===id){data.view='all';data.bookId=null}render();toast('Notebook removed')}};setTimeout(()=>document.addEventListener('pointerdown',outsideMenu,{once:true}),0)}
function outsideMenu(e){if(!e.target.closest('.context-menu'))closeMenu()}function closeMenu(){$$('.context-menu').forEach(x=>x.remove())}
function moveMenu(anchor){const n=current();if(!n)return;const m=document.createElement('div');m.className='context-menu';m.innerHTML=data.notebooks.map(b=>`<button data-id="${b.id}">${esc(b.name)}${n.notebookId===b.id?' ✓':''}</button>`).join('');document.body.append(m);const r=anchor.getBoundingClientRect();m.style.top=Math.min(innerHeight-m.offsetHeight-8,r.bottom+3)+'px';m.style.left=Math.max(8,r.left-m.offsetWidth+30)+'px';m.onclick=e=>{const id=e.target.dataset.id;if(id)moveNote(n.id,id);closeMenu()};setTimeout(()=>document.addEventListener('pointerdown',outsideMenu,{once:true}),0)}
// Event delegation and editor behavior.
$('#virtualNav').onclick=e=>{const row=e.target.closest('[data-view]');if(row)setView(row.dataset.view)};
$('#notebookList').onclick=e=>{const row=e.target.closest('.notebook-row');if(!row)return;if(e.target.closest('.rename-book')){bookMenu(e.target.closest('.rename-book'),row.dataset.book);return}data.view='book';data.bookId=row.dataset.book;activeTag='';render()};
$('#notebookList').ondragover=e=>{if(e.target.closest('.notebook-row')){e.preventDefault();e.target.closest('.notebook-row').style.outline='1px dashed #969b67'}};$('#notebookList').ondragleave=e=>{const r=e.target.closest('.notebook-row');if(r)r.style.outline=''};$('#notebookList').ondrop=e=>{const r=e.target.closest('.notebook-row');if(!r||!dragNote)return;e.preventDefault();r.style.outline='';moveNote(dragNote,r.dataset.book);dragNote=null};
$('#notesList').onclick=e=>{const card=e.target.closest('.note-card');if(!card)return;const n=data.notes.find(x=>x.id===card.dataset.id);if(!n)return;if(n.deleted){data.selection=n.id;noteMenu(card,n);return}selectNote(n.id)};
$('#notesList').oncontextmenu=e=>{const c=e.target.closest('.note-card');if(!c)return;e.preventDefault();const n=data.notes.find(x=>x.id===c.dataset.id);if(n)noteMenu(c,n)};
$('#notesList').ondragstart=e=>{const c=e.target.closest('.note-card');if(c){dragNote=c.dataset.id;e.dataTransfer.setData('text/plain',dragNote);e.dataTransfer.effectAllowed='move'}};
$('#notesList').ondragend=()=>dragNote=null;
$('#newNote').onclick=createNote;$('#addNotebook').onclick=()=>createNotebook();$('#trashNav').onclick=()=>setView('trash');$('#sortSelect').onchange=e=>{data.sort=e.target.value;renderList();scheduleSave()};$('#searchInput').oninput=e=>{query=e.target.value;renderList();$('#listTitle').textContent=viewTitle()};$('#searchInput').onkeydown=e=>{if(e.key==='Escape'){e.target.value='';query='';renderList()}};
$('#collapseBtn').onclick=()=>{data.collapsed=!data.collapsed;$('#sidebar').classList.toggle('collapsed',data.collapsed);scheduleSave()};$('#themeBtn').onclick=()=>{data.theme=data.theme==='dark'?'light':'dark';document.body.classList.toggle('dark',data.theme==='dark');scheduleSave()};$('#pinBtn').onclick=()=>{const n=current();if(n){n.pinned=!n.pinned;renderList();$('#pinBtn').classList.toggle('active',n.pinned);scheduleSave()}};$('#moveBtn').onclick=e=>moveMenu(e.currentTarget);$('#moreBtn').onclick=e=>{const n=current();if(n)noteMenu(e.currentTarget,n)};
$('#toolbar').onclick=e=>{const b=e.target.closest('[data-cmd]');if(b)command(b.dataset.cmd,b.dataset.value)};
$('#editorContent').addEventListener('input',e=>{if(e.target.id==='titleField')updateTitle();else if(e.target.id==='editor')syncEditor(true)});
$('#editorContent').addEventListener('keydown',e=>{if(e.target.id==='titleField'){if(e.key==='Enter'){e.preventDefault();focusEditor()}return}if(e.target.id!=='editor'&&!e.target.closest('#editor'))return;if((e.metaKey||e.ctrlKey)&&!e.altKey){const k=e.key.toLowerCase();if(k==='b'||k==='i'||k==='u'){e.preventDefault();command({b:'bold',i:'italic',u:'underline'}[k]);return}if(k==='z'){e.preventDefault();doUndo(e.shiftKey);return}if(k==='y'){e.preventDefault();doUndo(true);return}}if(e.key==='Enter')handleEnter(e);else if(e.key===' ')handleMarkdown(e)});
$('#editorContent').addEventListener('paste',handlePaste);
$('#editorContent').addEventListener('click',e=>{if(e.target.matches('input[type=checkbox]')){const li=e.target.closest('li');if(li){li.classList.toggle('checked',e.target.checked);if(e.target.checked)e.target.setAttribute('checked','');else e.target.removeAttribute('checked');syncEditor(false)}}});
$('#editorContent').addEventListener('keydown',e=>{if(e.target.classList.contains('tag-input')&&e.key==='Enter'){e.preventDefault();const val=e.target.value.trim().replace(/^#/,'');const n=current();if(val&&n&&!n.tags.includes(val)){n.tags.push(val);renderTags();scheduleSave();$('#tagInput')?.focus()}}if(e.target.classList.contains('tag-input')&&e.key==='Backspace'&&!e.target.value){const n=current();if(n?.tags.length){n.tags.pop();renderTags();scheduleSave();$('#tagInput')?.focus()}}});
$('#editorContent').addEventListener('click',e=>{if(e.target.classList.contains('tag-remove')){const n=current();n.tags.splice(+e.target.dataset.index,1);renderTags();scheduleSave()}if(e.target.classList.contains('tag-pill')&&!e.target.classList.contains('tag-remove')){activeTag=e.target.textContent.replace('×','');data.view='tag';renderList()}});
document.addEventListener('selectionchange',updateToolbar);document.addEventListener('keydown',e=>{if((e.metaKey||e.ctrlKey)&&e.key.toLowerCase()==='k'){e.preventDefault();$('#searchInput').focus()}if(e.key==='Escape')closeMenu()});
// Drag dividers persist pane dimensions; pointer movement is clamped for usable panes.
$$('.resizer').forEach(handle=>handle.addEventListener('pointerdown',e=>{e.preventDefault();handle.classList.add('dragging');const startX=e.clientX,side=$('#sidebar'),list=$('.notelist'),startSide=side.getBoundingClientRect().width,startList=list.getBoundingClientRect().width;const move=ev=>{if(handle.dataset.resize==='side'){data.sidebarWidth=Math.max(170,Math.min(360,startSide+ev.clientX-startX));side.style.width=data.sidebarWidth+'px'}else{data.listWidth=Math.max(230,Math.min(480,startList+ev.clientX-startX));list.style.width=data.listWidth+'px'}};const up=()=>{handle.classList.remove('dragging');window.removeEventListener('pointermove',move);window.removeEventListener('pointerup',up);scheduleSave()};window.addEventListener('pointermove',move);window.addEventListener('pointerup',up,{once:true})}));
// Initial state restoration
if(data.theme==='dark')document.body.classList.add('dark');if(!data.selection||!data.notes.some(n=>n.id===data.selection&&!n.deleted)){data.selection=data.notes.find(n=>!n.deleted)?.id||null}$('#searchInput').value='';render();
})();
</script></body></html>
<!-- agent-meta {"model":"openai/gpt-6-luna","provider":"openrouter","persona":"full","sessionId":"af117c88-e697-4b03-99f9-a3c98b83b803","tokensIn":380322,"tokensOut":22620,"tokensTotal":402942,"cost":0.018351839999999998,"turns":17,"toolCalls":16,"failedToolCalls":1,"timestamp":"2026-09-23T00:14:54.549Z"} -->