← Notes results

Notes

ThinkingCap Qwen3.6 27B GGUF · typescript

Initial view of Notes

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 68,181 bytes · SHA-256 c40fe2e85d60
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Notes</title>
<style>
/* ── css: layout ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; overflow: hidden; }
body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  transition: background 0.2s, color 0.2s;
}

/* CSS Variables from custom properties */
:root {
  --bg: #ffffff;
  --bg-secondary: #f8f9fa;
  --bg-tertiary: #f0f1f3;
  --bg-hover: #e8eaed;
  --bg-active: #e3e6ea;
  --text: #1a1a1a;
  --text-secondary: #5f6368;
  --text-tertiary: #9aa0a6;
  --border: #e0e0e0;
  --border-light: #eee;
  --accent: #4285f4;
  --accent-light: #e8f0fe;
  --accent-dark: #2b6cb0;
  --danger: #ea4335;
  --danger-light: #fce8e6;
  --success: #34a853;
  --warning: #fbbc04;
  --editor-bg: #ffffff;
  --editor-text: #202124;
  --code-bg: #f5f5f5;
  --code-color: #c7254e;
  --quote-border: #4285f4;
  --hr-color: #e0e0e0;
  --checkbox-color: #4285f4;
  --tag-bg: #e8f0fe;
  --tag-text: #1967d2;
  --pin-color: #fbbc04;
  --shadow: rgba(0,0,0,0.08);
  --toolbar-bg: #fafafa;
  --divider-color: #e0e0e0;
  --font-ui: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-editor: 'Georgia', 'Times New Roman', serif;
  --font-mono: 'Consolas', 'Monaco', monospace;
}

body.dark-mode {
  --bg: #1e1e2e;
  --bg-secondary: #181825;
  --bg-tertiary: #11111b;
  --bg-hover: #313244;
  --bg-active: #45475a;
  --text: #cdd6f4;
  --text-secondary: #a6adc8;
  --text-tertiary: #6c7086;
  --border: #313244;
  --border-light: #2a2a3c;
  --accent: #89b4fa;
  --accent-light: #333353;
  --accent-dark: #74c7ec;
  --danger: #f38ba8;
  --danger-light: #3d2330;
  --success: #a6e3a1;
  --warning: #f9e2af;
  --editor-bg: #1e1e2e;
  --editor-text: #cdd6f4;
  --code-bg: #313244;
  --code-color: #f38ba8;
  --quote-border: #89b4fa;
  --hr-color: #313244;
  --checkbox-color: #89b4fa;
  --tag-bg: #333353;
  --tag-text: #89b4fa;
  --pin-color: #f9e2af;
  --shadow: rgba(0,0,0,0.3);
  --toolbar-bg: #181825;
  --divider-color: #313244;
}

/* Sidebar */
#sidebar-pane {
  width: 240px;
  min-width: 180px;
  max-width: 400px;
  background: var(--bg-secondary);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  transition: width 0.2s ease, opacity 0.2s ease;
  overflow: hidden;
}
#sidebar-pane.collapsed {
  width: 0 !important;
  min-width: 0;
  border-right: none;
  opacity: 0;
  pointer-events: none;
}
#sidebar-header {
  padding: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
#app-logo {
  font-size: 18px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: -0.5px;
}
#new-notebook-btn {
  margin-left: auto;
  width: 28px;
  height: 28px;
  border: none;
  background: var(--accent);
  color: white;
  border-radius: 6px;
  font-size: 18px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, transform 0.1s;
}
#new-notebook-btn:hover { background: var(--accent-dark); transform: scale(1.05); }
#sidebar-content {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
}
.sidebar-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.1s;
  user-select: none;
  margin-bottom: 2px;
}
.sidebar-item:hover { background: var(--bg-hover); }
.sidebar-item.active { background: var(--accent-light); color: var(--accent); }
.sidebar-icon { font-size: 16px; width: 22px; text-align: center; flex-shrink: 0; }
.sidebar-label {
  flex: 1;
  font-size: 13px;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sidebar-item .notebook-actions {
  display: flex;
  gap: 2px;
  opacity: 0;
  transition: opacity 0.1s;
}
.sidebar-item:hover .notebook-actions { opacity: 1; }
.notebook-actions button {
  width: 22px;
  height: 22px;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.notebook-actions button:hover { background: var(--bg-active); color: var(--text); }
.notebook-toggle {
  width: 20px;
  height: 20px;
  border: none;
  background: transparent;
  cursor: pointer;
  color: var(--text-tertiary);
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  flex-shrink: 0;
  transition: transform 0.15s;
}
.notebook-toggle.collapsed { transform: rotate(-90deg); }

/* Notebook notes list in sidebar */
.notebook-notes {
  padding-left: 16px;
  overflow: hidden;
  transition: max-height 0.2s ease;
}
.notebook-notes.collapsed { max-height: 0 !important; }
.notebook-note-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 12.5px;
  color: var(--text-secondary);
  transition: background 0.1s;
  margin-bottom: 1px;
}
.notebook-note-item:hover { background: var(--bg-hover); color: var(--text); }
.notebook-note-item.active { background: var(--accent-light); color: var(--accent); font-weight: 500; }
.notebook-note-item .pin-dot {
  color: var(--pin-color);
  font-size: 10px;
  flex-shrink: 0;
}

/* Resize handles */
.resize-handle {
  width: 4px;
  cursor: col-resize;
  background: transparent;
  transition: background 0.15s;
  flex-shrink: 0;
}
.resize-handle:hover, .resize-handle.active {
  background: var(--accent);
}
.resize-handle.hidden { display: none; }

/* Note List Pane */
#notelist-pane {
  width: 300px;
  min-width: 200px;
  max-width: 500px;
  background: var(--bg);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#notelist-header {
  padding: 12px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
#search-input {
  flex: 1;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
  background: var(--bg-secondary);
  color: var(--text);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
  font-family: var(--font-ui);
}
#search-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-light);
}
#notelist-actions {
  display: flex;
  gap: 4px;
}
#notelist-actions button {
  width: 30px;
  height: 30px;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.1s, color 0.1s;
}
#notelist-actions button:hover { background: var(--bg-hover); color: var(--text); }
#new-note-btn { background: var(--accent) !important; color: white !important; }
#new-note-btn:hover { background: var(--accent-dark) !important; }

/* Note filter bar */
#note-filter-bar {
  padding: 8px 12px;
  display: flex;
  gap: 6px;
  flex-shrink: 0;
  border-bottom: 1px solid var(--border-light);
}
.filter-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  background: var(--tag-bg);
  color: var(--tag-text);
  border-radius: 12px;
  font-size: 11px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.1s;
}
.filter-tag:hover { opacity: 0.8; }
.filter-tag .remove { font-size: 14px; line-height: 1; }

/* Note list */
#note-list {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
}
.note-card {
  padding: 12px;
  border-radius: 8px;
  cursor: pointer;
  margin-bottom: 4px;
  transition: background 0.1s, box-shadow 0.1s;
  border: 1px solid transparent;
}
.note-card:hover { background: var(--bg-secondary); }
.note-card.active {
  background: var(--accent-light);
  border-color: var(--accent);
  box-shadow: 0 1px 3px var(--shadow);
}
.note-card-title {
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 4px;
  display: flex;
  align-items: center;
  gap: 6px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.note-card-title .pin-icon {
  color: var(--pin-color);
  font-size: 12px;
  flex-shrink: 0;
}
.note-card-snippet {
  font-size: 12.5px;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-bottom: 4px;
}
.note-card-meta {
  font-size: 11px;
  color: var(--text-tertiary);
  display: flex;
  align-items: center;
  gap: 8px;
}
.note-card-tags {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-top: 6px;
}
.note-tag {
  padding: 1px 7px;
  background: var(--tag-bg);
  color: var(--tag-text);
  border-radius: 10px;
  font-size: 10.5px;
  font-weight: 500;
}

/* Editor Pane */
#editor-pane {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 300px;
  overflow: hidden;
  background: var(--editor-bg);
}
.editor-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--text-tertiary);
  gap: 12px;
  user-select: none;
}
.editor-empty-icon { font-size: 48px; opacity: 0.5; }
.editor-empty-text {
  font-size: 16px;
  font-weight: 400;
  letter-spacing: 0.2px;
}
#editor-container {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow: hidden;
}

/* Toolbar */
#editor-toolbar {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 6px 12px;
  background: var(--toolbar-bg);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
  flex-shrink: 0;
}
#editor-toolbar button {
  width: 32px;
  height: 30px;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  border-radius: 5px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.1s, color 0.1s;
  font-family: var(--font-ui);
}
#editor-toolbar button:hover { background: var(--bg-hover); color: var(--text); }
#editor-toolbar button.active { background: var(--accent-light); color: var(--accent); }
.toolbar-divider {
  width: 1px;
  height: 20px;
  background: var(--divider-color);
  margin: 0 4px;
}

/* Editor meta */
#editor-meta {
  padding: 16px 24px 8px;
  flex-shrink: 0;
}
#editor-title {
  width: 100%;
  border: none;
  font-size: 26px;
  font-weight: 700;
  background: transparent;
  color: var(--editor-text);
  outline: none;
  font-family: var(--font-ui);
  line-height: 1.3;
  letter-spacing: -0.5px;
}
#editor-title::placeholder { color: var(--text-tertiary); }
#editor-tags {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  flex-wrap: wrap;
}
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  background: var(--tag-bg);
  color: var(--tag-text);
  border-radius: 12px;
  font-size: 12px;
  font-weight: 500;
}
.tag-chip .tag-remove {
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  opacity: 0.6;
  transition: opacity 0.1s;
}
.tag-chip .tag-remove:hover { opacity: 1; }
#tag-input {
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  padding: 3px 8px;
  border-radius: 12px;
  font-size: 12px;
  outline: none;
  width: 100px;
  font-family: var(--font-ui);
}
#tag-input:focus { border-color: var(--accent); }

/* Editor content */
#editor-content {
  flex: 1;
  overflow-y: auto;
  padding: 12px 24px 100px;
  font-family: var(--font-editor);
  font-size: 16px;
  line-height: 1.75;
  color: var(--editor-text);
  outline: none;
  min-height: 200px;
}
#editor-content h1 { font-size: 2em; font-weight: 700; margin: 0.6em 0 0.3em; line-height: 1.3; letter-spacing: -0.5px; }
#editor-content h2 { font-size: 1.5em; font-weight: 600; margin: 0.5em 0 0.25em; line-height: 1.3; }
#editor-content h3 { font-size: 1.25em; font-weight: 600; margin: 0.4em 0 0.2em; }
#editor-content p { margin: 0.3em 0; }
#editor-content blockquote {
  border-left: 3px solid var(--quote-border);
  padding-left: 16px;
  margin: 0.5em 0;
  color: var(--text-secondary);
  font-style: italic;
}
#editor-content hr {
  border: none;
  border-top: 2px solid var(--hr-color);
  margin: 1em 0;
}
#editor-content code {
  background: var(--code-bg);
  color: var(--code-color);
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 0.9em;
  font-family: var(--font-mono);
}
#editor-content ul, #editor-content ol {
  padding-left: 24px;
  margin: 0.3em 0;
}
#editor-content li { margin: 0.15em 0; }
/* Checklist items */
.checklist-item {
  list-style: none;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0.15em 0;
  padding-left: 0;
}
.checklist-checkbox {
  width: 18px;
  height: 18px;
  border: 2px solid var(--accent);
  border-radius: 4px;
  cursor: pointer;
  flex-shrink: 0;
  margin-top: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.1s, border-color 0.1s;
}
.checklist-checkbox.checked {
  background: var(--accent);
  border-color: var(--accent);
}
.checklist-checkbox.checked::after {
  content: '✓';
  color: white;
  font-size: 12px;
  font-weight: 700;
}
.checklist-checkbox:hover { background: var(--accent-light); }
.checklist-text { flex: 1; }
.checklist-item.checked .checklist-text {
  text-decoration: line-through;
  color: var(--text-tertiary);
}

/* Editor status bar */
#editor-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 24px;
  border-top: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-tertiary);
  flex-shrink: 0;
}
#save-indicator {
  transition: opacity 0.3s;
  font-weight: 500;
}
#save-indicator.saving { color: var(--warning); }
#save-indicator.saved { color: var(--success); }

/* Note actions bar */
#note-actions-bar {
  display: flex;
  align-items: center;
  padding: 6px 12px;
  border-top: 1px solid var(--border);
  gap: 4px;
  flex-shrink: 0;
  background: var(--bg-secondary);
}
#note-actions-bar button {
  width: 32px;
  height: 28px;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  border-radius: 5px;
  cursor: pointer;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.1s;
}
#note-actions-bar button:hover { background: var(--bg-hover); }
#note-actions-bar .spacer { flex: 1; }
#note-actions-bar .danger-btn:hover { background: var(--danger-light); color: var(--danger); }

/* Move note dropdown */
.move-dropdown {
  position: absolute;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 12px var(--shadow);
  padding: 4px;
  z-index: 100;
  min-width: 180px;
}
.move-dropdown-item {
  padding: 8px 12px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 13px;
  transition: background 0.1s;
}
.move-dropdown-item:hover { background: var(--bg-hover); }

/* Dark mode toggle */
#dark-mode-toggle {
  position: fixed;
  bottom: 16px;
  right: 16px;
  width: 36px;
  height: 36px;
  border: none;
  background: var(--bg-secondary);
  color: var(--text);
  border-radius: 50%;
  cursor: pointer;
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 8px var(--shadow);
  transition: background 0.1s, transform 0.1s;
  z-index: 200;
}
#dark-mode-toggle:hover { transform: scale(1.1); }

/* Rename input */
.rename-input {
  border: 1px solid var(--accent);
  background: var(--bg);
  color: var(--text);
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 13px;
  outline: none;
  font-family: var(--font-ui);
  flex: 1;
  min-width: 0;
}

/* Search highlight */
.search-highlight {
  background: var(--warning);
  color: var(--text);
  border-radius: 2px;
  padding: 0 1px;
}

/* Scrollbar styling */
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--bg-hover); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--bg-active); }

/* Animations */
@keyframes fadeIn {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}
.note-card { animation: fadeIn 0.15s ease; }
</style>
</head>
<body>
<div id="app" style="display:flex;height:100vh;overflow:hidden;">
  <!-- Sidebar Pane -->
  <div id="sidebar-pane">
    <div id="sidebar-header">
      <span id="app-logo">Notes</span>
      <button id="new-notebook-btn" title="New Notebook">+</button>
    </div>
    <div id="sidebar-content">
      <div id="all-notes-item" class="sidebar-item" data-type="virtual-notebook" data-id="all">
        <span class="sidebar-icon">📋</span>
        <span class="sidebar-label">All Notes</span>
      </div>
      <div id="trash-item" class="sidebar-item" data-type="virtual-notebook" data-id="trash">
        <span class="sidebar-icon">🗑️</span>
        <span class="sidebar-label">Trash</span>
      </div>
      <div id="notebook-list"></div>
    </div>
  </div>
  <div id="sidebar-handle" class="resize-handle"></div>

  <!-- Note List Pane -->
  <div id="notelist-pane">
    <div id="notelist-header">
      <input id="search-input" type="text" placeholder="Search notes...">
      <div id="notelist-actions">
        <button id="sort-toggle" title="Sort order">⇅</button>
        <button id="new-note-btn" title="New Note">+</button>
      </div>
    </div>
    <div id="note-filter-bar"></div>
    <div id="note-list"></div>
  </div>
  <div id="notelist-handle" class="resize-handle"></div>

  <!-- Editor Pane -->
  <div id="editor-pane">
    <div id="editor-empty" class="editor-empty">
      <div class="editor-empty-icon">📝</div>
      <div class="editor-empty-text">Select or create a note</div>
    </div>
    <div id="editor-container" style="display:none;">
      <div id="editor-toolbar">
        <button data-cmd="bold" title="Bold (Ctrl+B)"><b>B</b></button>
        <button data-cmd="italic" title="Italic (Ctrl+I)"><i>I</i></button>
        <button data-cmd="underline" title="Underline (Ctrl+U)"><u>U</u></button>
        <button data-cmd="strikeThrough" title="Strikethrough"><s>S</s></button>
        <span class="toolbar-divider"></span>
        <button data-cmd="code" title="Inline Code">&lt;&gt;</button>
        <span class="toolbar-divider"></span>
        <button data-cmd="h1" title="Heading 1">H1</button>
        <button data-cmd="h2" title="Heading 2">H2</button>
        <button data-cmd="h3" title="Heading 3">H3</button>
        <span class="toolbar-divider"></span>
        <button data-cmd="ul" title="Bullet List">•</button>
        <button data-cmd="ol" title="Numbered List">1.</button>
        <button data-cmd="checklist" title="Checklist">☑</button>
        <button data-cmd="blockquote" title="Blockquote">❝</button>
        <button data-cmd="hr" title="Horizontal Rule">—</button>
      </div>
      <div id="editor-meta">
        <input id="editor-title" type="text" placeholder="Note title...">
        <div id="editor-tags"></div>
      </div>
      <div id="editor-content" contenteditable="true" spellcheck="true"></div>
      <div id="editor-status">
        <span id="save-indicator"></span>
        <span id="note-info"></span>
      </div>
    </div>
    <!-- Note action menu -->
    <div id="note-actions-bar">
      <button id="pin-note-btn" title="Pin/Unpin">📌</button>
      <button id="duplicate-note-btn" title="Duplicate">📋</button>
      <button id="move-note-btn" title="Move to notebook">↗</button>
      <button id="delete-note-btn" title="Delete">🗑</button>
      <span class="spacer"></span>
      <button id="restore-note-btn" title="Restore" style="display:none;">♻</button>
      <button id="permanent-delete-btn" title="Permanently delete" style="display:none;">✕</button>
    </div>
  </div>
</div>
<button id="dark-mode-toggle" title="Toggle dark mode">🌙</button>
<script>
(function () {
'use strict';
var __mods = {};
var __cache = {};
var __map = {"src/main.ts":{"./state":"src/state.ts","./sidebar":"src/sidebar.ts","./notelist":"src/notelist.ts","./editor":"src/editor.ts"},"src/sidebar.ts":{"./state":"src/state.ts","./constants":"src/constants.ts"},"src/notelist.ts":{"./state":"src/state.ts","./constants":"src/constants.ts"},"src/editor.ts":{"./state":"src/state.ts","./constants":"src/constants.ts"}};
function __require(id) {
  if (__cache[id]) return __cache[id].exports;
  var module = __cache[id] = { exports: {} };
  var factory = __mods[id];
  if (!factory) throw new Error("Module not found: " + id);
  factory(module.exports, function (spec) {
    var target = (__map[id] && __map[id][spec]) || spec;
    return __require(target);
  }, module);
  return module.exports;
}

// ── module: src/main.ts ──
__mods["src/main.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const state_1 = require("./state");
const sidebar_1 = require("./sidebar");
const notelist_1 = require("./notelist");
const editor_1 = require("./editor");
function start() {
    (0, sidebar_1.initSidebar)();
    (0, notelist_1.initNoteList)();
    (0, editor_1.initEditor)();
    (0, state_1.onStateChange)(() => {
        (0, sidebar_1.render)();
        (0, notelist_1.render)();
        (0, editor_1.render)();
        applyDarkMode();
        applyPaneSizes();
    });
    initResizeHandles();
    applyDarkMode();
    applyPaneSizes();
    const darkToggle = document.getElementById('dark-mode-toggle');
    darkToggle?.addEventListener('click', () => {
        (0, state_1.setState)(s => { s.darkMode = !s.darkMode; });
    });
}
function applyDarkMode() {
    const state = (0, state_1.getState)();
    document.body.classList.toggle('dark-mode', state.darkMode);
    const toggle = document.getElementById('dark-mode-toggle');
    if (toggle)
        toggle.textContent = state.darkMode ? '☀️' : '🌙';
}
function applyPaneSizes() {
    const state = (0, state_1.getState)();
    const sidebarPane = document.getElementById('sidebar-pane');
    if (sidebarPane)
        sidebarPane.style.width = state.layout.sidebarWidth + 'px';
    const notelistPane = document.getElementById('notelist-pane');
    if (notelistPane)
        notelistPane.style.width = state.layout.noteListWidth + 'px';
}
function initResizeHandles() {
    const sidebarHandle = document.getElementById('sidebar-handle');
    const sidebarPane = document.getElementById('sidebar-pane');
    const notelistHandle = document.getElementById('notelist-handle');
    const notelistPane = document.getElementById('notelist-pane');
    if (sidebarHandle && sidebarPane) {
        makeResizable(sidebarHandle, sidebarPane, (delta) => {
            (0, state_1.setState)(s => {
                s.layout.sidebarWidth = Math.max(180, Math.min(400, s.layout.sidebarWidth + delta));
            });
        });
        sidebarHandle.addEventListener('dblclick', () => {
            (0, state_1.setState)(s => {
                s.layout.sidebarCollapsed = !s.layout.sidebarCollapsed;
            });
        });
    }
    if (notelistHandle && notelistPane) {
        makeResizable(notelistHandle, notelistPane, (delta) => {
            (0, state_1.setState)(s => {
                s.layout.noteListWidth = Math.max(200, Math.min(500, s.layout.noteListWidth + delta));
            });
        });
    }
}
function makeResizable(handle, target, onResize) {
    function onMouseMove(e) {
        onResize(e.clientX - handle._startX);
    }
    function onMouseUp() {
        document.removeEventListener('mousemove', onMouseMove);
        document.removeEventListener('mouseup', onMouseUp);
        handle.classList.remove('active');
        document.body.style.cursor = '';
        document.body.style.userSelect = '';
    }
    handle.addEventListener('mousedown', (e) => {
        e.preventDefault();
        handle._startX = e.clientX;
        handle.classList.add('active');
        document.body.style.cursor = 'col-resize';
        document.body.style.userSelect = 'none';
        document.addEventListener('mousemove', onMouseMove);
        document.addEventListener('mouseup', onMouseUp);
    });
}
start();
};

// ── module: src/constants.ts ──
__mods["src/constants.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CONSTANTS = void 0;
// Tunable constants
exports.CONSTANTS = {
    autosaveDebounce: 500,
    snippetLength: 80,
    minPaneWidth: 180,
    defaultSidebarWidth: 240,
    defaultNoteListWidth: 300,
    colors: {
        light: {
            bg: '#ffffff',
            bgSecondary: '#f8f9fa',
            bgTertiary: '#f0f1f3',
            bgHover: '#e8eaed',
            bgActive: '#e3e6ea',
            text: '#1a1a1a',
            textSecondary: '#5f6368',
            textTertiary: '#9aa0a6',
            border: '#e0e0e0',
            borderLight: '#eee',
            accent: '#4285f4',
            accentLight: '#e8f0fe',
            accentDark: '#2b6cb0',
            danger: '#ea4335',
            dangerLight: '#fce8e6',
            success: '#34a853',
            warning: '#fbbc04',
            editorBg: '#ffffff',
            editorText: '#202124',
            codeBg: '#f5f5f5',
            codeColor: '#c7254e',
            quoteBorder: '#4285f4',
            hrColor: '#e0e0e0',
            checkbox: '#4285f4',
            tagBg: '#e8f0fe',
            tagText: '#1967d2',
            pinColor: '#fbbc04',
            shadow: 'rgba(0,0,0,0.08)',
            toolbarBg: '#fafafa',
            dividerColor: '#e0e0e0',
        },
        dark: {
            bg: '#1e1e2e',
            bgSecondary: '#181825',
            bgTertiary: '#11111b',
            bgHover: '#313244',
            bgActive: '#45475a',
            text: '#cdd6f4',
            textSecondary: '#a6adc8',
            textTertiary: '#6c7086',
            border: '#313244',
            borderLight: '#2a2a3c',
            accent: '#89b4fa',
            accentLight: '#333353',
            accentDark: '#74c7ec',
            danger: '#f38ba8',
            dangerLight: '#3d2330',
            success: '#a6e3a1',
            warning: '#f9e2af',
            editorBg: '#1e1e2e',
            editorText: '#cdd6f4',
            codeBg: '#313244',
            codeColor: '#f38ba8',
            quoteBorder: '#89b4fa',
            hrColor: '#313244',
            checkbox: '#89b4fa',
            tagBg: '#333353',
            tagText: '#89b4fa',
            pinColor: '#f9e2af',
            shadow: 'rgba(0,0,0,0.3)',
            toolbarBg: '#181825',
            dividerColor: '#313244',
        },
    },
    fonts: {
        ui: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
        editor: "'Source Serif 4', 'Lora', 'Georgia', serif",
        mono: "'JetBrains Mono', 'Fira Code', 'Consolas', monospace",
    },
};
};

// ── module: src/state.ts ──
__mods["src/state.ts"] = function (exports, require, module) {
"use strict";
// Data model types and state
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultState = void 0;
exports.onStateChange = onStateChange;
exports.notifyChange = notifyChange;
exports.getState = getState;
exports.setState = setState;
exports.persist = persist;
exports.markUnsaved = markUnsaved;
exports.setSaving = setSaving;
exports.getNote = getNote;
exports.getNotebook = getNotebook;
exports.stripHtml = stripHtml;
let _listeners = [];
function onStateChange(fn) {
    _listeners.push(fn);
}
function notifyChange() {
    for (const fn of _listeners)
        fn();
}
function loadFromStorage() {
    try {
        const raw = localStorage.getItem('notes-app-state');
        if (!raw)
            return null;
        return JSON.parse(raw);
    }
    catch {
        return null;
    }
}
function generateId() {
    return Date.now().toString(36) + Math.random().toString(36).substring(2, 9);
}
exports.defaultState = {
    data: {
        notebooks: [
            { id: generateId(), name: 'Personal', collapsed: false, createdAt: Date.now() },
            { id: generateId(), name: 'Work', collapsed: false, createdAt: Date.now() },
        ],
        notes: [
            {
                id: generateId(),
                notebookId: '',
                title: 'Welcome to Notes',
                content: '<h1>Welcome to Notes!</h1><p>This is a <b>rich text editor</b>. Try the toolbar or keyboard shortcuts like <i>Ctrl+B</i> for bold.</p><p>Markdown shortcuts work too:</p><ul><li>Type <code># </code> for headings</li><li>Type <code>- </code> for lists</li><li>Type <code>[] </code> for checklists</li></ul><p>Enjoy!</p>',
                tags: ['welcome', 'tips'],
                pinned: true,
                createdAt: Date.now() - 100000,
                updatedAt: Date.now() - 100000,
            },
        ],
        trash: [],
    },
    layout: {
        sidebarWidth: 240,
        noteListWidth: 300,
        sidebarCollapsed: false,
    },
    activeNotebookId: 'all',
    activeNoteId: null,
    searchQuery: '',
    tagFilter: null,
    sortMode: 'modified',
    darkMode: false,
    saveStatus: 'saved',
};
const firstNoteId = exports.defaultState.data.notes[0].id;
const firstNotebookId = exports.defaultState.data.notebooks[0]?.id || '';
exports.defaultState.data.notes[0].notebookId = firstNotebookId;
let state = loadFromStorage() || { ...exports.defaultState, saveStatus: 'saved' };
function getState() {
    return state;
}
function setState(updater) {
    updater(state);
    persist();
    notifyChange();
}
function persist() {
    state.saveStatus = 'saved';
    try {
        localStorage.setItem('notes-app-state', JSON.stringify(state));
    }
    catch { /* storage full */ }
}
function markUnsaved() {
    state.saveStatus = 'unsaved';
    notifyChange();
}
function setSaving() {
    state.saveStatus = 'saving';
    notifyChange();
}
function getNote(id) {
    return state.data.notes.find(n => n.id === id)
        || state.data.trash.find(n => n.id === id);
}
function getNotebook(id) {
    return state.data.notebooks.find(n => n.id === id);
}
function stripHtml(html) {
    const tmp = document.createElement('div');
    tmp.innerHTML = html;
    return tmp.textContent || tmp.innerText || '';
}
};

// ── module: src/sidebar.ts ──
__mods["src/sidebar.ts"] = function (exports, require, module) {
"use strict";
// Sidebar rendering and interaction
Object.defineProperty(exports, "__esModule", { value: true });
exports.initSidebar = initSidebar;
exports.render = render;
const state_1 = require("./state");
let sidebarElement = null;
let notebookListElement = null;
function initSidebar() {
    sidebarElement = document.getElementById('sidebar-pane');
    notebookListElement = document.getElementById('notebook-list');
    render();
    bindEvents();
}
function render() {
    const state = (0, state_1.getState)();
    if (!notebookListElement)
        return;
    // Update active states for virtual items
    const allNotesItem = document.getElementById('all-notes-item');
    const trashItem = document.getElementById('trash-item');
    if (allNotesItem)
        allNotesItem.classList.toggle('active', state.activeNotebookId === 'all');
    if (trashItem)
        trashItem.classList.toggle('active', state.activeNotebookId === 'trash');
    // Render notebook list
    notebookListElement.innerHTML = '';
    for (const nb of state.data.notebooks) {
        const nbEl = document.createElement('div');
        nbEl.className = 'sidebar-item';
        nbEl.dataset.notebookId = nb.id;
        const notebookNotes = state.data.notes.filter(n => n.notebookId === nb.id);
        nbEl.innerHTML = `
      <button class="notebook-toggle ${nb.collapsed ? 'collapsed' : ''}" data-toggle="${nb.id}">▼</button>
      <span class="sidebar-icon">📁</span>
      <span class="sidebar-label">${escapeHtml(nb.name)}</span>
      <div class="notebook-actions">
        <button data-rename="${nb.id}" title="Rename">✎</button>
        <button data-delete-nb="${nb.id}" title="Delete">✕</button>
      </div>
    `;
        if (state.activeNotebookId === nb.id)
            nbEl.classList.add('active');
        notebookListElement.appendChild(nbEl);
        // Notes under this notebook
        if (!nb.collapsed) {
            const notesContainer = document.createElement('div');
            notesContainer.className = 'notebook-notes';
            for (const note of notebookNotes) {
                const noteItem = document.createElement('div');
                noteItem.className = 'notebook-note-item';
                if (state.activeNoteId === note.id)
                    noteItem.classList.add('active');
                noteItem.dataset.noteId = note.id;
                noteItem.innerHTML = `
          ${note.pinned ? '<span class="pin-dot">📌</span>' : ''}
          <span>${escapeHtml(note.title || 'Untitled')}</span>
        `;
                notesContainer.appendChild(noteItem);
            }
            notebookListElement.appendChild(notesContainer);
        }
    }
    // Update sidebar width
    if (sidebarElement) {
        sidebarElement.style.width = state.layout.sidebarWidth + 'px';
        sidebarElement.classList.toggle('collapsed', state.layout.sidebarCollapsed);
    }
}
function bindEvents() {
    const app = document.getElementById('app');
    if (!app)
        return;
    // Sidebar item clicks
    app.addEventListener('click', (e) => {
        const target = e.target;
        // Toggle notebook collapse
        const toggle = target.closest('[data-toggle]');
        if (toggle) {
            const nbId = toggle.dataset.toggle;
            (0, state_1.setState)(s => {
                const nb = s.data.notebooks.find(n => n.id === nbId);
                if (nb)
                    nb.collapsed = !nb.collapsed;
            });
            return;
        }
        // Rename notebook
        const renameBtn = target.closest('[data-rename]');
        if (renameBtn) {
            renameNotebook(renameBtn.dataset.rename);
            return;
        }
        // Delete notebook
        const deleteNbBtn = target.closest('[data-delete-nb]');
        if (deleteNbBtn) {
            deleteNotebook(deleteNbBtn.dataset.deleteNb);
            return;
        }
        // Virtual notebook (All Notes / Trash)
        const virtualItem = target.closest('[data-type="virtual-notebook"]');
        if (virtualItem) {
            (0, state_1.setState)(s => {
                s.activeNotebookId = virtualItem.dataset.id;
                s.activeNoteId = null;
                s.tagFilter = null;
            });
            return;
        }
        // Notebook selection
        const notebookItem = target.closest('.sidebar-item');
        if (notebookItem && notebookItem.dataset.notebookId) {
            (0, state_1.setState)(s => {
                s.activeNotebookId = notebookItem.dataset.notebookId;
                s.activeNoteId = null;
                s.tagFilter = null;
            });
            return;
        }
        // Notebook note selection
        const noteItem = target.closest('.notebook-note-item');
        if (noteItem && noteItem.dataset.noteId) {
            (0, state_1.setState)(s => {
                s.activeNoteId = noteItem.dataset.noteId;
                const note = (0, state_1.getNote)(noteItem.dataset.noteId);
                s.activeNotebookId = note?.notebookId || 'all';
                s.tagFilter = null;
            });
            return;
        }
    });
    // New notebook button
    document.getElementById('new-notebook-btn')?.addEventListener('click', () => {
        const name = prompt('Notebook name:');
        if (name?.trim()) {
            (0, state_1.setState)(s => {
                s.data.notebooks.push({
                    id: Date.now().toString(36) + Math.random().toString(36).substring(2, 9),
                    name: name.trim(),
                    collapsed: false,
                    createdAt: Date.now(),
                });
            });
        }
    });
}
function renameNotebook(nbId) {
    const state = (0, state_1.getState)();
    const nb = state.data.notebooks.find(n => n.id === nbId);
    if (!nb)
        return;
    const newName = prompt('Rename notebook:', nb.name);
    if (newName?.trim()) {
        (0, state_1.setState)(s => {
            const notebook = s.data.notebooks.find(n => n.id === nbId);
            if (notebook)
                notebook.name = newName.trim();
        });
    }
}
function deleteNotebook(nbId) {
    const state = (0, state_1.getState)();
    const nb = state.data.notebooks.find(n => n.id === nbId);
    if (!nb)
        return;
    if (!confirm(`Delete "${nb.name}" and all its notes?`))
        return;
    (0, state_1.setState)(s => {
        // Move notes to trash
        const notesInNb = s.data.notes.filter(n => n.notebookId === nbId);
        s.data.trash.push(...notesInNb);
        s.data.notes = s.data.notes.filter(n => n.notebookId !== nbId);
        s.data.notebooks = s.data.notebooks.filter(n => n.id !== nbId);
        if (s.activeNotebookId === nbId) {
            s.activeNotebookId = 'all';
            s.activeNoteId = null;
        }
    });
}
function escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
}
};

// ── module: src/notelist.ts ──
__mods["src/notelist.ts"] = function (exports, require, module) {
"use strict";
// Note list rendering and interaction
Object.defineProperty(exports, "__esModule", { value: true });
exports.initNoteList = initNoteList;
exports.render = render;
const state_1 = require("./state");
const constants_1 = require("./constants");
let noteListElement = null;
let searchInputElement = null;
let filterBarElement = null;
let sortToggleElement = null;
function initNoteList() {
    noteListElement = document.getElementById('note-list');
    searchInputElement = document.getElementById('search-input');
    filterBarElement = document.getElementById('note-filter-bar');
    sortToggleElement = document.getElementById('sort-toggle');
    render();
    bindEvents();
}
const SORT_MODES = ['modified', 'created', 'alphabetical'];
function render() {
    const state = (0, state_1.getState)();
    if (!noteListElement)
        return;
    // Filter notes based on active notebook
    let notes;
    if (state.activeNotebookId === 'all') {
        notes = state.data.notes;
    }
    else if (state.activeNotebookId === 'trash') {
        notes = state.data.trash;
    }
    else {
        notes = state.data.notes.filter(n => n.notebookId === state.activeNotebookId);
    }
    // Apply tag filter
    if (state.tagFilter) {
        notes = notes.filter(n => n.tags.includes(state.tagFilter));
    }
    // Apply search
    if (state.searchQuery) {
        const q = state.searchQuery.toLowerCase();
        notes = notes.filter(n => {
            const titleMatch = n.title.toLowerCase().includes(q);
            const bodyMatch = (0, state_1.stripHtml)(n.content || '').toLowerCase().includes(q);
            return titleMatch || bodyMatch;
        });
    }
    // Sort: pinned first, then by sort mode
    notes.sort((a, b) => {
        if (a.pinned && !b.pinned)
            return -1;
        if (!a.pinned && b.pinned)
            return 1;
        switch (state.sortMode) {
            case 'created': return b.createdAt - a.createdAt;
            case 'alphabetical': return a.title.localeCompare(b.title);
            case 'modified':
            default: return b.updatedAt - a.updatedAt;
        }
    });
    // Render
    noteListElement.innerHTML = '';
    if (notes.length === 0) {
        const empty = document.createElement('div');
        empty.style.cssText = 'padding:24px;text-align:center;color:var(--text-tertiary);font-size:13px;';
        empty.textContent = state.searchQuery ? 'No matching notes' : 'No notes here';
        noteListElement.appendChild(empty);
    }
    for (const note of notes) {
        const card = document.createElement('div');
        card.className = 'note-card';
        if (state.activeNoteId === note.id)
            card.classList.add('active');
        card.dataset.noteId = note.id;
        const snippet = (0, state_1.stripHtml)(note.content).substring(0, constants_1.CONSTANTS.snippetLength);
        const date = new Date(note.updatedAt);
        const dateStr = date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' }) +
            ' ' + date.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
        let html = '';
        html += `<div class="note-card-title">`;
        html += note.pinned ? '<span class="pin-icon">📌</span>' : '';
        html += escapeHtml(note.title || 'Untitled');
        html += `</div>`;
        // Search highlight in snippet
        if (state.searchQuery && snippet.toLowerCase().includes(state.searchQuery.toLowerCase())) {
            const highlighted = highlightText(snippet, state.searchQuery);
            html += `<div class="note-card-snippet">${highlighted}</div>`;
        }
        else {
            html += `<div class="note-card-snippet">${escapeHtml(snippet)}</div>`;
        }
        html += `<div class="note-card-meta"><span>${dateStr}</span></div>`;
        if (note.tags.length > 0) {
            html += `<div class="note-card-tags">`;
            for (const tag of note.tags) {
                html += `<span class="note-tag" data-tag="${escapeHtml(tag)}">${escapeHtml(tag)}</span>`;
            }
            html += `</div>`;
        }
        card.innerHTML = html;
        noteListElement.appendChild(card);
    }
    // Update filter bar
    if (filterBarElement) {
        filterBarElement.innerHTML = '';
        if (state.tagFilter) {
            const tag = document.createElement('span');
            tag.className = 'filter-tag';
            tag.innerHTML = `🏷 ${escapeHtml(state.tagFilter)} <span class="remove">×</span>`;
            filterBarElement.appendChild(tag);
        }
    }
    // Update sort toggle label
    if (sortToggleElement) {
        const labels = { modified: '↕ Mod', created: '↕ Cre', alphabetical: '↕ A-Z' };
        sortToggleElement.title = labels[state.sortMode] || '';
    }
}
function highlightText(text, query) {
    if (!query)
        return escapeHtml(text);
    const escaped = escapeHtml(text);
    const escapedQuery = escapeHtml(query);
    const regex = new RegExp(`(${escapeRegex(escapedQuery)})`, 'gi');
    return escaped.replace(regex, '<span class="search-highlight">$1</span>');
}
function escapeRegex(str) {
    return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
function escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
}
function bindEvents() {
    const app = document.getElementById('app');
    if (!app)
        return;
    // Note card click
    app.addEventListener('click', (e) => {
        const card = e.target.closest('.note-card');
        if (card) {
            (0, state_1.setState)(s => {
                s.activeNoteId = card.dataset.noteId;
                s.tagFilter = null;
            });
            return;
        }
        // Tag click
        const tag = e.target.closest('.note-tag');
        if (tag) {
            const tagFilter = tag.dataset.tag;
            (0, state_1.setState)(s => {
                s.tagFilter = s.tagFilter === tagFilter ? null : tagFilter;
            });
            return;
        }
        // Filter bar remove
        const removeBtn = e.target.closest('.filter-tag .remove');
        if (removeBtn) {
            (0, state_1.setState)(s => { s.tagFilter = null; });
            return;
        }
        // Filter tag click (click on the tag itself, not the remove)
        const filterTag = e.target.closest('.filter-tag');
        if (filterTag && !filterTag.querySelector('.remove')?.contains(e.target)) {
            (0, state_1.setState)(s => { s.tagFilter = null; });
            return;
        }
    });
    // Search input
    if (searchInputElement) {
        searchInputElement.addEventListener('input', () => {
            (0, state_1.setState)(s => { s.searchQuery = searchInputElement.value; });
        });
    }
    // Sort toggle
    if (sortToggleElement) {
        sortToggleElement.addEventListener('click', () => {
            (0, state_1.setState)(s => {
                const idx = SORT_MODES.indexOf(s.sortMode);
                s.sortMode = SORT_MODES[(idx + 1) % SORT_MODES.length];
            });
        });
    }
    // New note button
    document.getElementById('new-note-btn')?.addEventListener('click', () => {
        const state = (0, state_1.getState)();
        let notebookId = state.activeNotebookId;
        if (notebookId === 'all' || notebookId === 'trash') {
            notebookId = state.data.notebooks[0]?.id || 'all';
        }
        if (!notebookId || notebookId === 'all' || notebookId === 'trash') {
            alert('Create a notebook first');
            return;
        }
        const id = Date.now().toString(36) + Math.random().toString(36).substring(2, 9);
        (0, state_1.setState)(s => {
            s.data.notes.push({
                id,
                notebookId: notebookId,
                title: '',
                content: '',
                tags: [],
                pinned: false,
                createdAt: Date.now(),
                updatedAt: Date.now(),
            });
            s.activeNoteId = id;
        });
    });
}
};

// ── module: src/editor.ts ──
__mods["src/editor.ts"] = function (exports, require, module) {
"use strict";
// Rich text editor with contenteditable, toolbar, markdown shortcuts, paste sanitization
Object.defineProperty(exports, "__esModule", { value: true });
exports.initEditor = initEditor;
exports.render = render;
const state_1 = require("./state");
const constants_1 = require("./constants");
let editorEl = null;
let titleEl = null;
let tagsContainer = null;
let saveIndicator = null;
let noteInfoEl = null;
let emptyEl = null;
let containerEl = null;
let toolbarEl = null;
let pinBtn = null;
let dupBtn = null;
let moveBtn = null;
let delBtn = null;
let restoreBtn = null;
let permDelBtn = null;
let _saveTimer = null;
function initEditor() {
    editorEl = document.getElementById('editor-content');
    titleEl = document.getElementById('editor-title');
    tagsContainer = document.getElementById('editor-tags');
    saveIndicator = document.getElementById('save-indicator');
    noteInfoEl = document.getElementById('note-info');
    emptyEl = document.getElementById('editor-empty');
    containerEl = document.getElementById('editor-container');
    toolbarEl = document.getElementById('editor-toolbar');
    pinBtn = document.getElementById('pin-note-btn');
    dupBtn = document.getElementById('duplicate-note-btn');
    moveBtn = document.getElementById('move-note-btn');
    delBtn = document.getElementById('delete-note-btn');
    restoreBtn = document.getElementById('restore-note-btn');
    permDelBtn = document.getElementById('permanent-delete-btn');
    render();
    bindEvents();
}
function render() {
    const state = (0, state_1.getState)();
    const note = (0, state_1.getNote)(state.activeNoteId || '');
    const inTrash = state.activeNotebookId === 'trash';
    if (!containerEl || !emptyEl)
        return;
    if (!note) {
        containerEl.style.display = 'none';
        emptyEl.style.display = '';
        return;
    }
    containerEl.style.display = '';
    emptyEl.style.display = 'none';
    if (titleEl)
        titleEl.value = note.title;
    // Only set content if different — prevents cursor jumping during editing
    if (editorEl && editorEl.innerHTML !== note.content) {
        editorEl.innerHTML = note.content;
    }
    renderTags(note);
    updateSaveIndicator(state.saveStatus);
    if (noteInfoEl) {
        const created = new Date(note.createdAt).toLocaleDateString();
        const modified = new Date(note.updatedAt).toLocaleDateString();
        noteInfoEl.textContent = `Created: ${created} · Modified: ${modified}`;
    }
    if (pinBtn)
        pinBtn.style.display = inTrash ? 'none' : '';
    if (dupBtn)
        dupBtn.style.display = inTrash ? 'none' : '';
    if (moveBtn)
        moveBtn.style.display = inTrash ? 'none' : '';
    if (delBtn)
        delBtn.style.display = inTrash ? 'none' : '';
    if (restoreBtn)
        restoreBtn.style.display = inTrash ? '' : 'none';
    if (permDelBtn)
        permDelBtn.style.display = inTrash ? '' : 'none';
}
function renderTags(note) {
    if (!tagsContainer)
        return;
    tagsContainer.innerHTML = '';
    if (!note)
        return;
    for (const tag of note.tags) {
        const chip = document.createElement('span');
        chip.className = 'tag-chip';
        chip.innerHTML = `${escapeHtml(tag)} <span class="tag-remove">×</span>`;
        tagsContainer.appendChild(chip);
    }
    const input = document.createElement('input');
    input.id = 'tag-input';
    input.placeholder = 'Add tag...';
    input.addEventListener('keydown', (e) => {
        if (e.key === 'Enter' && input.value.trim()) {
            e.preventDefault();
            const t = input.value.trim().toLowerCase();
            (0, state_1.setState)(s => {
                const n = (0, state_1.getNote)(s.activeNoteId || '');
                if (n && !n.tags.includes(t)) {
                    n.tags.push(t);
                    n.updatedAt = Date.now();
                }
            });
            input.value = '';
        }
    });
    tagsContainer.appendChild(input);
}
function updateSaveIndicator(status) {
    if (!saveIndicator)
        return;
    saveIndicator.className = status;
    if (status === 'saved')
        saveIndicator.textContent = '✓ Saved';
    else if (status === 'saving')
        saveIndicator.textContent = '⏳ Saving...';
    else
        saveIndicator.textContent = '● Unsaved';
}
function escapeHtml(text) {
    const d = document.createElement('div');
    d.textContent = text;
    return d.innerHTML;
}
function bindEvents() {
    if (!editorEl || !titleEl)
        return;
    toolbarEl.addEventListener('click', (e) => {
        const btn = e.target.closest('button');
        if (!btn)
            return;
        const cmd = btn.dataset?.cmd;
        if (!cmd)
            return;
        editorEl.focus();
        handleToolbarCommand(cmd);
    });
    editorEl.addEventListener('input', () => {
        scheduleSave();
        updateToolbarState();
    });
    titleEl.addEventListener('input', () => { scheduleSave(); });
    tagsContainer.addEventListener('click', (e) => {
        const remove = e.target.closest('.tag-remove');
        if (!remove)
            return;
        const chip = remove.closest('.tag-chip');
        if (!chip)
            return;
        const tagText = chip.childNodes[0].textContent?.trim();
        if (!tagText)
            return;
        (0, state_1.setState)(s => {
            const n = (0, state_1.getNote)(s.activeNoteId || '');
            if (n) {
                n.tags = n.tags.filter(t => t !== tagText);
                n.updatedAt = Date.now();
            }
        });
    });
    editorEl.addEventListener('keydown', handleEditorKeyDown);
    editorEl.addEventListener('paste', handlePaste);
    document.addEventListener('selectionchange', () => { setTimeout(updateToolbarState, 0); });
    pinBtn.addEventListener('click', () => {
        (0, state_1.setState)(s => {
            const n = (0, state_1.getNote)(s.activeNoteId || '');
            if (n) {
                n.pinned = !n.pinned;
                n.updatedAt = Date.now();
            }
        });
    });
    dupBtn.addEventListener('click', () => {
        const state = (0, state_1.getState)();
        const note = (0, state_1.getNote)(state.activeNoteId || '');
        if (!note)
            return;
        const id = Date.now().toString(36) + Math.random().toString(36).substring(2, 9);
        (0, state_1.setState)(s => {
            s.data.notes.push({
                ...note, id, title: note.title + ' (copy)',
                createdAt: Date.now(), updatedAt: Date.now(),
            });
            s.activeNoteId = id;
        });
    });
    moveBtn.addEventListener('click', showMoveMenu);
    delBtn.addEventListener('click', () => {
        (0, state_1.setState)(s => {
            const idx = s.data.notes.findIndex(n => n.id === s.activeNoteId);
            if (idx >= 0) {
                s.data.trash.push(s.data.notes[idx]);
                s.data.notes.splice(idx, 1);
                s.activeNoteId = null;
            }
        });
    });
    restoreBtn.addEventListener('click', () => {
        (0, state_1.setState)(s => {
            const idx = s.data.trash.findIndex(n => n.id === s.activeNoteId);
            if (idx >= 0) {
                const note = s.data.trash[idx];
                s.data.notes.push(note);
                s.data.trash.splice(idx, 1);
                s.activeNotebookId = note.notebookId || 'all';
            }
        });
    });
    permDelBtn.addEventListener('click', () => {
        if (!confirm('Permanently delete this note?'))
            return;
        (0, state_1.setState)(s => {
            const idx = s.data.trash.findIndex(n => n.id === s.activeNoteId);
            if (idx >= 0) {
                s.data.trash.splice(idx, 1);
                s.activeNoteId = null;
            }
        });
    });
    // Drag and drop
    const sidebar = document.getElementById('sidebar-pane');
    sidebar.addEventListener('dragover', (e) => { e.preventDefault(); });
    sidebar.addEventListener('drop', (e) => {
        e.preventDefault();
        const item = e.target.closest('.sidebar-item');
        const nbId = item?.dataset?.notebookId;
        if (!nbId)
            return;
        const note = (0, state_1.getNote)((0, state_1.getState)().activeNoteId || '');
        if (!note)
            return;
        (0, state_1.setState)(s => {
            const n = s.data.notes.find(n => n.id === note.id);
            if (n)
                n.notebookId = nbId;
        });
    });
}
// ── Toolbar commands ──
function handleToolbarCommand(cmd) {
    if (!editorEl)
        return;
    switch (cmd) {
        case 'bold':
        case 'italic':
        case 'underline':
        case 'strikeThrough':
            document.execCommand(cmd, false);
            break;
        case 'code':
            wrapInlineTag('code');
            break;
        case 'h1':
        case 'h2':
        case 'h3':
            formatBlock(cmd.toUpperCase());
            break;
        case 'ul':
            formatBlock('ul');
            break;
        case 'ol':
            formatBlock('ol');
            break;
        case 'checklist':
            insertChecklistItem();
            break;
        case 'blockquote':
            formatBlock('blockquote');
            break;
        case 'hr':
            document.execCommand('insertHTML', false, '<hr>');
            break;
    }
    saveEditorContent();
    updateToolbarState();
}
function formatBlock(tag) {
    const sel = window.getSelection();
    if (!sel || !sel.rangeCount)
        return;
    let block = sel.getRangeAt(0).startContainer;
    while (block && block !== editorEl && block.nodeType !== 1)
        block = block.parentNode;
    if (block && block !== editorEl && block.nodeName === 'BODY')
        block = editorEl;
    const tagName = block?.tagName;
    if (tagName === tag.toUpperCase() && block !== editorEl) {
        unwrapElement(block);
    }
    else if (['H1', 'H2', 'H3', 'BLOCKQUOTE', 'UL', 'OL'].includes(tag.toUpperCase())) {
        document.execCommand('formatBlock', false, tag);
    }
}
function unwrapElement(el) {
    const parent = el.parentNode;
    if (!parent)
        return;
    while (el.firstChild)
        parent.insertBefore(el.firstChild, el);
    parent.removeChild(el);
}
function wrapInlineTag(tag) {
    const sel = window.getSelection();
    if (!sel || !sel.rangeCount || sel.isCollapsed)
        return;
    const range = sel.getRangeAt(0);
    const text = range.toString();
    if (!text)
        return;
    let parent = range.commonAncestorContainer;
    while (parent && parent.nodeType === 3)
        parent = parent.parentNode;
    if (!parent)
        return;
    if (parent.tagName === tag.toUpperCase()) {
        unwrapElement(parent);
        return;
    }
    document.execCommand('insertHTML', false, `<${tag}>${text}</${tag}>`);
}
function insertChecklistItem() {
    const sel = window.getSelection();
    if (!sel)
        return;
    const block = getCurrentBlock();
    if (block && block.classList?.contains('checklist-parent')) {
        unwrapElement(block);
        return;
    }
    document.execCommand('formatBlock', false, 'p');
    const checkbox = document.createElement('span');
    checkbox.className = 'checklist-checkbox';
    checkbox.contentEditable = 'false';
    checkbox.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        checkbox.classList.toggle('checked');
        const li = checkbox.closest('li');
        if (li)
            li.classList.toggle('checked');
        scheduleSave();
    });
    const textSpan = document.createElement('span');
    textSpan.className = 'checklist-text';
    textSpan.contentEditable = 'true';
    const li = document.createElement('li');
    li.className = 'checklist-item';
    li.contentEditable = 'true';
    li.appendChild(checkbox);
    li.appendChild(textSpan);
    const ul = document.createElement('ul');
    ul.className = 'checklist-parent';
    ul.appendChild(li);
    if (!editorEl)
        return;
    editorEl.appendChild(ul);
    const range = document.createRange();
    range.selectNodeContents(textSpan);
    range.collapse(false);
    sel.removeAllRanges();
    sel.addRange(range);
    textSpan.focus();
}
function getCurrentBlock() {
    const sel = window.getSelection();
    if (!sel || !sel.rangeCount)
        return null;
    let node = sel.anchorNode;
    while (node && node !== editorEl && node.nodeName !== 'BODY') {
        if (node.nodeType === 1) {
            const el = node;
            if (['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE', 'LI', 'DIV'].includes(el.tagName))
                return el;
        }
        node = node.parentNode;
    }
    return null;
}
// ── Keyboard handling ──
function handleEditorKeyDown(e) {
    if (!editorEl)
        return;
    if (e.key === 'Enter' && !e.shiftKey && !e.ctrlKey && !e.metaKey) {
        const block = getCurrentBlock();
        if (!block)
            return;
        if (block.tagName === 'LI' && block.classList.contains('checklist-item')) {
            const textSpan = block.querySelector('.checklist-text');
            if (textSpan && textSpan.textContent.trim() === '') {
                e.preventDefault();
                unwrapElement(block);
            }
            else {
                e.preventDefault();
                insertChecklistItem();
                scheduleSave();
            }
            return;
        }
        if (block.tagName === 'LI' && block.textContent?.trim() === '') {
            e.preventDefault();
            const ul = block.parentElement;
            if (ul)
                unwrapElement(ul);
            return;
        }
        return;
    }
    if (e.key === 'Tab') {
        e.preventDefault();
        return;
    }
    if (e.key === ' ' && handleMarkdownShortcut()) {
        e.preventDefault();
        scheduleSave();
        return;
    }
    scheduleSave();
}
function handleMarkdownShortcut() {
    if (!editorEl)
        return false;
    const sel = window.getSelection();
    if (!sel || !sel.rangeCount)
        return false;
    const block = getCurrentBlock();
    if (!block || block.tagName !== 'P')
        return false;
    const text = block.textContent || '';
    const selOffset = getCaretOffsetInBlock(block);
    const prefix = text.substring(0, selOffset);
    if (prefix === '# ') {
        block.innerHTML = text.substring(2);
        block.outerHTML = `<h1>${block.innerHTML || '&nbsp;'}</h1>`;
        scheduleSave();
        return true;
    }
    if (prefix === '## ') {
        block.innerHTML = text.substring(3);
        block.outerHTML = `<h2>${block.innerHTML || '&nbsp;'}</h2>`;
        scheduleSave();
        return true;
    }
    if (prefix === '### ') {
        block.innerHTML = text.substring(4);
        block.outerHTML = `<h3>${block.innerHTML || '&nbsp;'}</h3>`;
        scheduleSave();
        return true;
    }
    if (prefix === '- ') {
        const ul = document.createElement('ul');
        const li = document.createElement('li');
        li.textContent = text.substring(2);
        ul.appendChild(li);
        block.replaceWith(ul);
        scheduleSave();
        return true;
    }
    if (prefix === '[] ') {
        const ul = document.createElement('ul');
        ul.className = 'checklist-parent';
        const li = document.createElement('li');
        li.className = 'checklist-item';
        const cb = document.createElement('span');
        cb.className = 'checklist-checkbox';
        cb.contentEditable = 'false';
        cb.addEventListener('click', (ev) => {
            ev.preventDefault();
            ev.stopPropagation();
            cb.classList.toggle('checked');
            li.classList.toggle('checked');
            scheduleSave();
        });
        const ts = document.createElement('span');
        ts.className = 'checklist-text';
        ts.textContent = text.substring(3);
        li.appendChild(cb);
        li.appendChild(ts);
        ul.appendChild(li);
        block.replaceWith(ul);
        setTimeout(() => ts.focus(), 10);
        scheduleSave();
        return true;
    }
    if (prefix === '> ') {
        block.innerHTML = text.substring(2);
        block.outerHTML = `<blockquote>${block.innerHTML}</blockquote>`;
        scheduleSave();
        return true;
    }
    return false;
}
function getCaretOffsetInBlock(block) {
    const sel = window.getSelection();
    if (!sel || !sel.rangeCount)
        return 0;
    const range = sel.getRangeAt(0);
    const preRange = document.createRange();
    preRange.selectNodeContents(block);
    preRange.setEnd(range.startContainer, range.startOffset);
    return preRange.toString().length;
}
// ── Paste sanitization ──
function handlePaste(e) {
    e.preventDefault();
    const html = e.clipboardData?.getData('text/html');
    const plain = e.clipboardData?.getData('text/plain');
    let content;
    if (html) {
        content = sanitizeHtml(html);
    }
    else if (plain) {
        content = escapeHtml(plain).replace(/\n/g, '<br>');
    }
    else
        return;
    document.execCommand('insertHTML', false, content);
    scheduleSave();
}
function sanitizeHtml(html) {
    const allowed = new Set(['b', 'i', 'u', 's', 'strike', 'del', 'code', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'br', 'div', 'ul', 'ol', 'li', 'blockquote', 'hr', 'span', 'a', 'strong', 'em']);
    const parser = new DOMParser();
    const doc = parser.parseFromString(html, 'text/html');
    const body = doc.body;
    const toRemove = [];
    body.querySelectorAll('*').forEach(el => {
        if (!allowed.has(el.tagName.toLowerCase()))
            toRemove.push(el);
        Array.from(el.attributes).forEach(attr => {
            if (!['href', 'target', 'class', 'style'].includes(attr.name))
                el.removeAttribute(attr.name);
        });
        if (el.tagName.toLowerCase() === 'a') {
            const href = el.getAttribute('href');
            if (href && !href.startsWith('http'))
                el.removeAttribute('href');
        }
    });
    for (const node of toRemove) {
        const parent = node.parentNode;
        while (node.firstChild)
            parent?.insertBefore(node.firstChild, node);
        parent?.removeChild(node);
    }
    return body.innerHTML;
}
// ── Auto-save ──
function scheduleSave() {
    (0, state_1.markUnsaved)();
    if (_saveTimer)
        clearTimeout(_saveTimer);
    _saveTimer = setTimeout(() => { (0, state_1.setSaving)(); saveEditorContent(); }, constants_1.CONSTANTS.autosaveDebounce);
}
function saveEditorContent() {
    const state = (0, state_1.getState)();
    const note = (0, state_1.getNote)(state.activeNoteId || '');
    if (!note || !editorEl || !titleEl)
        return;
    note.content = editorEl.innerHTML;
    note.title = titleEl.value;
    note.updatedAt = Date.now();
}
// ── Toolbar state ──
function updateToolbarState() {
    if (!toolbarEl)
        return;
    toolbarEl.querySelectorAll('button[data-cmd]').forEach(btn => {
        const cmd = btn.dataset?.cmd;
        let active = false;
        if (!cmd) {
            btn.classList.remove('active');
            return;
        }
        if (cmd === 'bold')
            active = document.queryCommandState('bold');
        else if (cmd === 'italic')
            active = document.queryCommandState('italic');
        else if (cmd === 'underline')
            active = document.queryCommandState('underline');
        else if (cmd === 'strikeThrough')
            active = document.queryCommandState('strikeThrough');
        else if (['h1', 'h2', 'h3'].includes(cmd))
            active = document.queryCommandValue('formatBlock') === cmd.toUpperCase();
        else if (cmd === 'ul')
            active = document.queryCommandState('insertUnorderedList');
        else if (cmd === 'ol')
            active = document.queryCommandState('insertOrderedList');
        else if (cmd === 'blockquote')
            active = document.queryCommandValue('formatBlock') === 'BLOCKQUOTE';
        else if (cmd === 'code') {
            let n = window.getSelection()?.anchorNode;
            while (n && n !== editorEl) {
                if (n.nodeType === 1 && n.tagName === 'CODE') {
                    active = true;
                    break;
                }
                n = n.parentNode;
            }
        }
        else if (cmd === 'checklist')
            active = getCurrentBlock()?.classList?.contains('checklist-item') || false;
        btn.classList.toggle('active', active);
    });
}
// ── Move menu ──
function showMoveMenu() {
    const existing = document.querySelector('.move-dropdown');
    if (existing)
        existing.remove();
    const state = (0, state_1.getState)();
    if (state.data.notebooks.length === 0)
        return;
    const menu = document.createElement('div');
    menu.className = 'move-dropdown';
    for (const nb of state.data.notebooks) {
        const item = document.createElement('div');
        item.className = 'move-dropdown-item';
        item.textContent = nb.name;
        item.addEventListener('click', () => {
            (0, state_1.setState)(s => {
                const n = s.data.notes.find(n => n.id === s.activeNoteId);
                if (n)
                    n.notebookId = nb.id;
                s.activeNotebookId = nb.id;
            });
            menu.remove();
        });
        menu.appendChild(item);
    }
    const rect = moveBtn?.getBoundingClientRect();
    if (rect) {
        menu.style.left = rect.left + 'px';
        menu.style.top = (rect.bottom + 4) + 'px';
    }
    document.body.appendChild(menu);
    setTimeout(() => {
        document.addEventListener('click', (e) => { if (!menu.contains(e.target))
            menu.remove(); }, { once: true });
    }, 10);
}
};

// ── entry ──
__require("src/main.ts");
})();
</script>
</body>
</html>
<!-- agent-meta {"model":"ThinkingCap-Qwen3.6-27B-GGUF","provider":"brigid","persona":"typescript","sessionId":"088c3395-359d-4aed-81d5-4424146af4de","tokensIn":7161640,"tokensOut":56054,"tokensTotal":7217694,"cost":0,"turns":116,"toolCalls":116,"failedToolCalls":12,"timestamp":"2026-08-03T20:48:51.484Z"} -->