← Notes results

Notes

thinkingcap qwen3.6 27b · composer

Initial view of Notes

Browser check: Artifact runtime error. This is a technical check, not a quality review.

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 41,057 bytes · SHA-256 67abd22722dd
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Noteflow — Notes App</title>
<style>
/* ── css: base ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --bg-primary: #ffffff;
  --bg-secondary: #f8f9fa;
  --bg-tertiary: #f1f3f5;
  --bg-hover: #e9ecef;
  --bg-active: #dee2e6;
  --text-primary: #1a1a2e;
  --text-secondary: #495057;
  --text-tertiary: #868e96;
  --border-color: #e9ecef;
  --accent: #6c5ce7;
  --accent-hover: #5a4bd1;
  --accent-light: rgba(108, 92, 231, 0.1);
  --danger: #e74c3c;
  --danger-hover: #c0392b;
  --success: #2ecc71;
  --shadow-sm: 0 1px 3px rgba(0,0,0,0.08);
  --shadow-md: 0 4px 12px rgba(0,0,0,0.1);
  --shadow-lg: 0 8px 30px rgba(0,0,0,0.12);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --sidebar-width: 260px;
  --note-list-width: 300px;
  --transition: 0.2s ease;
}

[data-theme="dark"] {
  --bg-primary: #1a1b2e;
  --bg-secondary: #1e1f35;
  --bg-tertiary: #252640;
  --bg-hover: #2d2e48;
  --bg-active: #363756;
  --text-primary: #e8e8f0;
  --text-secondary: #b0b0c0;
  --text-tertiary: #7a7a90;
  --border-color: #2d2e48;
  --accent: #a29bfe;
  --accent-hover: #6c5ce7;
  --accent-light: rgba(162, 155, 254, 0.15);
  --shadow-sm: 0 1px 3px rgba(0,0,0,0.3);
  --shadow-md: 0 4px 12px rgba(0,0,0,0.4);
  --shadow-lg: 0 8px 30px rgba(0,0,0,0.5);
}

html { font-size: 15px; }

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Inter', sans-serif;
  background: var(--bg-primary);
  color: var(--text-primary);
  line-height: 1.6;
  overflow: hidden;
  height: 100vh;
}

#app-inner {
  display: flex;
  height: 100vh;
  width: 100vw;
}

.hidden { display: none !important; }
/* ── css: sidebar ── */
#sidebar {
  width: var(--sidebar-width);
  min-width: var(--sidebar-width);
  background: var(--bg-secondary);
  border-right: 1px solid var(--border-color);
  display: flex;
  flex-direction: column;
  padding: 20px 14px;
  gap: 8px;
  overflow-y: auto;
}

.sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}

.logo {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: -0.5px;
}

.icon-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px;
  border-radius: var(--radius-sm);
  color: var(--text-tertiary);
  transition: all var(--transition);
  display: flex;
  align-items: center;
  justify-content: center;
}

.icon-btn:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.btn-primary {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 16px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: var(--radius-md);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--transition);
  box-shadow: var(--shadow-sm);
}

.btn-primary:hover {
  background: var(--accent-hover);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}

.sidebar-search {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--bg-tertiary);
  border-radius: var(--radius-sm);
  color: var(--text-tertiary);
}

.sidebar-search svg { flex-shrink: 0; }

#search-input {
  border: none;
  background: transparent;
  outline: none;
  font-size: 0.85rem;
  color: var(--text-primary);
  width: 100%;
}

#search-input::placeholder { color: var(--text-tertiary); }

.sidebar-nav { display: flex; flex-direction: column; gap: 2px; margin-top: 4px; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
  color: var(--text-secondary);
  cursor: pointer;
  transition: all var(--transition);
  text-align: left;
  width: 100%;
}

.nav-item:hover { background: var(--bg-hover); color: var(--text-primary); }

.nav-item.active {
  background: var(--accent-light);
  color: var(--accent);
  font-weight: 600;
}

.sidebar-tags {
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--border-color);
}

.sidebar-tags h3 {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--text-tertiary);
  margin-bottom: 8px;
  font-weight: 600;
}

#tags-list { display: flex; flex-wrap: wrap; gap: 4px; }

.tag-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  background: var(--bg-tertiary);
  border-radius: 20px;
  font-size: 0.78rem;
  color: var(--text-secondary);
  cursor: pointer;
  transition: all var(--transition);
}

.tag-pill:hover {
  background: var(--accent-light);
  color: var(--accent);
}
/* ── css: note-list ── */
#note-list-panel {
  width: var(--note-list-width);
  min-width: var(--note-list-width);
  background: var(--bg-primary);
  border-right: 1px solid var(--border-color);
  display: flex;
  flex-direction: column;
}

.note-list-header {
  padding: 20px 18px 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--border-color);
}

.note-list-header h2 {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text-primary);
}

.badge {
  font-size: 0.75rem;
  padding: 3px 10px;
  background: var(--bg-tertiary);
  border-radius: 20px;
  color: var(--text-tertiary);
  font-weight: 600;
}

#note-list {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
}

.note-item {
  padding: 14px 14px;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: all var(--transition);
  margin-bottom: 2px;
  border: 1px solid transparent;
}

.note-item:hover { background: var(--bg-secondary); }

.note-item.active {
  background: var(--accent-light);
  border-color: rgba(108, 92, 231, 0.2);
}

.note-item-title {
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.note-item-preview {
  font-size: 0.8rem;
  color: var(--text-tertiary);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.5;
}

.note-item-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  font-size: 0.72rem;
  color: var(--text-tertiary);
}

.note-item-fav {
  color: #f39c12;
  font-size: 0.75rem;
}

.note-item-tag {
  padding: 1px 6px;
  background: var(--bg-tertiary);
  border-radius: 8px;
  font-size: 0.68rem;
}
/* ── css: editor ── */
#editor-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  background: var(--bg-primary);
  min-width: 0;
}

.empty-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--text-tertiary);
  gap: 16px;
}

.empty-state svg { opacity: 0.3; }
.empty-state p { font-size: 1rem; }

#editor-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  max-width: 820px;
  width: 100%;
  margin: 0 auto;
}

.toolbar {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 10px 24px;
  border-bottom: 1px solid var(--border-color);
  flex-wrap: wrap;
}

.tool-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-size: 0.85rem;
  transition: all var(--transition);
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
}

.tool-btn:hover { background: var(--bg-hover); color: var(--text-primary); }
.tool-btn.active { background: var(--accent-light); color: var(--accent); }

.divider {
  width: 1px;
  height: 20px;
  background: var(--border-color);
  margin: 0 4px;
}

.note-title-input {
  border: none;
  outline: none;
  font-size: 1.8rem;
  font-weight: 700;
  padding: 24px 36px 8px;
  background: transparent;
  color: var(--text-primary);
  width: 100%;
}

.note-title-input::placeholder { color: var(--text-tertiary); }

.tags-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 36px 8px;
  flex-wrap: wrap;
}

.tag-icon {
  color: var(--text-tertiary);
  font-size: 0.85rem;
}

.tag-input {
  border: none;
  background: transparent;
  outline: none;
  font-size: 0.82rem;
  color: var(--text-secondary);
  min-width: 100px;
}

.tag-input::placeholder { color: var(--text-tertiary); }

#note-tags { display: flex; gap: 4px; flex-wrap: wrap; }

.note-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 10px;
  background: var(--accent-light);
  color: var(--accent);
  border-radius: 20px;
  font-size: 0.78rem;
  font-weight: 500;
}

.note-tag .remove-tag {
  cursor: pointer;
  opacity: 0.6;
  font-size: 0.9rem;
  line-height: 1;
}

.note-tag .remove-tag:hover { opacity: 1; }

.editor-area {
  flex: 1;
  padding: 8px 36px 24px;
  overflow-y: auto;
  font-size: 0.95rem;
  line-height: 1.75;
  color: var(--text-primary);
  outline: none;
}

.editor-area:empty::before {
  content: attr(data-placeholder);
  color: var(--text-tertiary);
  pointer-events: none;
}

.editor-area h1 { font-size: 1.8rem; margin: 0.6em 0 0.3em; }
.editor-area h2 { font-size: 1.4rem; margin: 0.5em 0 0.25em; }
.editor-area h3 { font-size: 1.15rem; margin: 0.4em 0 0.2em; }
.editor-area blockquote {
  border-left: 3px solid var(--accent);
  padding-left: 16px;
  color: var(--text-secondary);
  margin: 0.5em 0;
}
.editor-area pre {
  background: var(--bg-tertiary);
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 0.85rem;
  overflow-x: auto;
}

.status-bar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 8px 36px;
  border-top: 1px solid var(--border-color);
  font-size: 0.75rem;
  color: var(--text-tertiary);
}

#note-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 36px;
  border-top: 1px solid var(--border-color);
}

.action-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px;
  border-radius: var(--radius-sm);
  color: var(--text-tertiary);
  transition: all var(--transition);
  display: flex;
  align-items: center;
}

.action-btn:hover { background: var(--bg-hover); color: var(--text-primary); }
.action-btn.danger:hover { background: rgba(231,76,60,0.1); color: var(--danger); }
.action-btn.favorited svg { fill: #f39c12; stroke: #f39c12; }

.action-select {
  padding: 5px 10px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-secondary);
  color: var(--text-primary);
  font-size: 0.82rem;
  outline: none;
  cursor: pointer;
}

/* Modal */
.modal { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; }

.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.5);
  backdrop-filter: blur(4px);
}

.modal-content {
  position: relative;
  background: var(--bg-primary);
  border-radius: var(--radius-lg);
  padding: 28px;
  max-width: 380px;
  width: 90%;
  box-shadow: var(--shadow-lg);
}

.modal-content h3 { margin-bottom: 10px; font-size: 1.1rem; }
.modal-content p { color: var(--text-secondary); font-size: 0.9rem; margin-bottom: 20px; line-height: 1.5; }

.modal-actions { display: flex; gap: 10px; justify-content: flex-end; }

.btn-secondary, .btn-danger {
  padding: 8px 20px;
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--transition);
  border: none;
}

.btn-secondary { background: var(--bg-tertiary); color: var(--text-primary); }
.btn-secondary:hover { background: var(--bg-hover); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-danger:hover { background: var(--danger-hover); }

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

/* Animations */
@keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }
.note-item { animation: fadeIn 0.2s ease; }
</style>
</head>
<body>
<div id="app-inner">
  <!-- Sidebar -->
  <aside id="sidebar">
    <div class="sidebar-header">
      <div class="logo">
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none"><rect x="3" y="3" width="18" height="18" rx="3" stroke="currentColor" stroke-width="2"></rect><path d="M8 8h8M8 12h5" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path></svg>
        <span>Noteflow</span>
      </div>
      <button id="theme-toggle" class="icon-btn" title="Toggle theme">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="5" stroke="currentColor" stroke-width="2"></circle><path d="M12 1v2m0 18v2M4.22 4.22l1.42 1.42m12.72 12.72l1.42 1.42M1 12h2m18 0h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path></svg>
      </button>
    </div>
    <button id="new-note-btn" class="btn-primary">
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M12 5v14m-7-7h14" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"></path></svg>
      New Note
    </button>
    <div class="sidebar-search">
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="2"></circle><path d="M16 16l5 5" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path></svg>
      <input type="text" id="search-input" placeholder="Search notes…">
    </div>
    <nav class="sidebar-nav">
      <button class="nav-item active" data-folder="all">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><path d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" stroke="currentColor" stroke-width="2"></path></svg>
        All Notes
      </button>
      <button class="nav-item" data-folder="favorites">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87L18.18 22 12 18.27 5.82 22 7 14.14 2 9.27l6.91-1.01z" stroke="currentColor" stroke-width="2"></path></svg>
        Favorites
      </button>
      <button class="nav-item" data-folder="personal">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2" stroke="currentColor" stroke-width="2"></path><circle cx="12" cy="7" r="4" stroke="currentColor" stroke-width="2"></circle></svg>
        Personal
      </button>
      <button class="nav-item" data-folder="work">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><rect x="2" y="7" width="20" height="14" rx="2" stroke="currentColor" stroke-width="2"></rect><path d="M16 7V5a2 2 0 00-2-2h-4a2 2 0 00-2 2v2" stroke="currentColor" stroke-width="2"></path></svg>
        Work
      </button>
      <button class="nav-item" data-folder="ideas">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><path d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.992-.442-1.927-1.212-2.586z" stroke="currentColor" stroke-width="2"></path></svg>
        Ideas
      </button>
    </nav>
    <div class="sidebar-tags">
      <h3>Tags</h3>
      <div id="tags-list"></div>
    </div>
  </aside>

  <!-- Note List -->
  <section id="note-list-panel">
    <div class="note-list-header">
      <h2 id="folder-title">All Notes</h2>
      <span id="note-count" class="badge">0 notes</span>
    </div>
    <div id="note-list"></div>
  </section>

  <!-- Editor -->
  <main id="editor-panel">
    <div id="empty-state" class="empty-state">
      <svg width="80" height="80" viewBox="0 0 24 24" fill="none"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z" stroke="currentColor" stroke-width="1.5"></path><path d="M14 2v6h6M16 13H8m8 4H8m2-8H8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path></svg>
      <p>Select a note or create a new one</p>
    </div>

    <div id="editor-container" class="hidden">
      <!-- Toolbar -->
      <div class="toolbar">
        <button class="tool-btn" data-action="bold" title="Bold"><strong>B</strong></button>
        <button class="tool-btn" data-action="italic" title="Italic"><em>I</em></button>
        <button class="tool-btn" data-action="underline" title="Underline"><u>U</u></button>
        <button class="tool-btn" data-action="strikethrough" title="Strikethrough"><s>S</s></button>
        <span class="divider"></span>
        <button class="tool-btn" data-action="h1" title="Heading 1">H1</button>
        <button class="tool-btn" data-action="h2" title="Heading 2">H2</button>
        <button class="tool-btn" data-action="h3" title="Heading 3">H3</button>
        <span class="divider"></span>
        <button class="tool-btn" data-action="ul" title="Bullet List">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><line x1="9" y1="6" x2="20" y2="6" stroke="currentColor" stroke-width="2"></line><line x1="9" y1="12" x2="20" y2="12" stroke="currentColor" stroke-width="2"></line><line x1="9" y1="18" x2="20" y2="18" stroke="currentColor" stroke-width="2"></line><circle cx="5" cy="6" r="1.5" fill="currentColor"></circle><circle cx="5" cy="12" r="1.5" fill="currentColor"></circle><circle cx="5" cy="18" r="1.5" fill="currentColor"></circle></svg>
        </button>
        <button class="tool-btn" data-action="ol" title="Numbered List">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><line x1="10" y1="6" x2="21" y2="6" stroke="currentColor" stroke-width="2"></line><line x1="10" y1="12" x2="21" y2="12" stroke="currentColor" stroke-width="2"></line><line x1="10" y1="18" x2="21" y2="18" stroke="currentColor" stroke-width="2"></line><text x="3" y="8" font-size="7" fill="currentColor">1</text><text x="3" y="14" font-size="7" fill="currentColor">2</text><text x="3" y="20" font-size="7" fill="currentColor">3</text></svg>
        </button>
        <button class="tool-btn" data-action="checklist" title="Checklist">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><rect x="3" y="5" width="6" height="6" rx="1" stroke="currentColor" stroke-width="2"></rect><path d="M5 8l1.5 1.5L9 7" stroke="currentColor" stroke-width="2"></path><line x1="12" y1="8" x2="21" y2="8" stroke="currentColor" stroke-width="2"></line><rect x="3" y="13" width="6" height="6" rx="1" stroke="currentColor" stroke-width="2"></rect><line x1="12" y1="16" x2="21" y2="16" stroke="currentColor" stroke-width="2"></line></svg>
        </button>
        <span class="divider"></span>
        <button class="tool-btn" data-action="quote" title="Quote">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V21z" stroke="currentColor" stroke-width="2"></path><path d="M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3z" stroke="currentColor" stroke-width="2"></path></svg>
        </button>
        <button class="tool-btn" data-action="code" title="Code Block">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><polyline points="16,18 22,12 16,6" stroke="currentColor" stroke-width="2"></polyline><polyline points="8,6 2,12 8,18" stroke="currentColor" stroke-width="2"></polyline></svg>
        </button>
        <span class="divider"></span>
        <button class="tool-btn" data-action="link" title="Insert Link">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71" stroke="currentColor" stroke-width="2"></path><path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71" stroke="currentColor" stroke-width="2"></path></svg>
        </button>
      </div>

      <!-- Title input -->
      <input type="text" id="note-title-input" class="note-title-input" placeholder="Untitled note…">

      <!-- Tags bar -->
      <div class="tags-bar">
        <span class="tag-icon">#</span>
        <input type="text" id="tag-input" class="tag-input" placeholder="Add tags…">
        <div id="note-tags"></div>
      </div>

      <!-- Content editor -->
      <div id="editor-content" contenteditable="true" class="editor-area" data-placeholder="Start writing…"></div>

      <!-- Status bar -->
      <div class="status-bar">
        <span id="word-count">0 words</span>
        <span id="char-count">0 characters</span>
        <span id="last-saved">Not saved yet</span>
      </div>
    </div>

    <!-- Note actions -->
    <div id="note-actions" class="hidden">
      <button id="favorite-btn" class="action-btn" title="Toggle favorite">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87L18.18 22 12 18.27 5.82 22 7 14.14 2 9.27l6.91-1.01z" stroke="currentColor" stroke-width="2"></path></svg>
      </button>
      <select id="folder-select" class="action-select">
        <option value="personal">Personal</option>
        <option value="work">Work</option>
        <option value="ideas">Ideas</option>
      </select>
      <button id="delete-btn" class="action-btn danger" title="Delete note">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><polyline points="3,6 5,6 21,6" stroke="currentColor" stroke-width="2"></polyline><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2" stroke="currentColor" stroke-width="2"></path></svg>
      </button>
    </div>
  </main>

  <!-- Delete confirmation modal -->
  <div id="delete-modal" class="modal hidden">
    <div class="modal-backdrop"></div>
    <div class="modal-content">
      <h3>Delete Note</h3>
      <p>Are you sure you want to delete this note? This action cannot be undone.</p>
      <div class="modal-actions">
        <button id="cancel-delete" class="btn-secondary">Cancel</button>
        <button id="confirm-delete" class="btn-danger">Delete</button>
      </div>
    </div>
  </div>
</div>
<script>
'use strict';

// ── const: STORAGE_KEY ──
const STORAGE_KEY = 'noteflow_notes';

// ── const: THEME_KEY ──
const THEME_KEY = 'noteflow_theme';

// ── function: loadNotes ──
function loadNotes() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (raw) return JSON.parse(raw);
  } catch (e) {}
  return getDefaultNotes();
}

// ── function: saveNotes ──
function saveNotes(notes) {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(notes));
}

// ── function: loadTheme ──
function loadTheme() {
  return localStorage.getItem(THEME_KEY) || 'light';
}

// ── function: saveTheme ──
function saveTheme(theme) {
  localStorage.setItem(THEME_KEY, theme);
}

// ── function: generateId ──
function generateId() {
  return Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
}

// ── function: formatDate ──
function formatDate(ts) {
  const d = new Date(ts);
  const now = new Date();
  if (d.toDateString() === now.toDateString()) {
    return 'Today at ' + d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
  }
  const yesterday = new Date(now);
  yesterday.setDate(yesterday.getDate() - 1);
  if (d.toDateString() === yesterday.toDateString()) {
    return 'Yesterday';
  }
  return d.toLocaleDateString([], { month: 'short', day: 'numeric' });
}

// ── function: stripHtml ──
function stripHtml(html) {
  const tmp = document.createElement('div');
  tmp.innerHTML = html;
  return tmp.textContent || '';
}

// ── function: countWords ──
function countWords(text) {
  const clean = text.trim();
  if (!clean) return 0;
  return clean.split(/\s+/).length;
}

// ── function: getDefaultNotes ──
function getDefaultNotes() {
  return [
    {
      id: generateId(), title: 'Welcome to Noteflow ✨', folder: 'personal', favorite: true, tags: ['welcome'],
      content: '<h1>Welcome to Noteflow</h1><p>Your beautiful new notes application. Here are some things you can do:</p><ul><li>Create and organize notes into folders</li><li>Use the rich text toolbar for formatting</li><li>Add tags to categorize your notes</li><li>Favorite important notes</li><li>Search across all your notes</li><li>Toggle dark mode with the sun icon</li></ul><blockquote>All your notes are saved locally in your browser.</blockquote>',
      created: Date.now() - 86400000, modified: Date.now() - 3600000
    },
    {
      id: generateId(), title: 'Project Roadmap Q1', folder: 'work', favorite: false, tags: ['planning', 'work'],
      content: '<h2>Q1 Goals</h2><p>Prioritize the following initiatives:</p><ol><li>User onboarding redesign</li><li>Performance optimization sprint</li><li>New dashboard widgets</li></ol><p><strong>Deadline:</strong> March 31st</p>',
      created: Date.now() - 172800000, modified: Date.now() - 7200000
    },
    {
      id: generateId(), title: 'App Ideas Brainstorm', folder: 'ideas', favorite: true, tags: ['ideas'],
      content: '<p>Some app ideas to explore:</p><ul><li>Habit tracker with streaks and social accountability</li><li>Recipe organizer that generates weekly meal plans</li><li>Meditation timer with ambient soundscapes</li><li>Book notes with highlight export</li></ul>',
      created: Date.now() - 259200000, modified: Date.now() - 86400000
    },
    {
      id: generateId(), title: 'Meeting Notes — Design Review', folder: 'work', favorite: false, tags: ['meeting'],
      content: '<p><strong>Date:</strong> Monday</p><h3>Attendees</h3><ul><li>Sarah (Design Lead)</li><li>Marcus (Engineering)</li><li>Jen (Product)</li></ul><h3>Action Items</h3><ul><li>Update component library by Friday</li><li>Schedule user testing sessions</li><li>Review accessibility audit results</li></ul>',
      created: Date.now() - 345600000, modified: Date.now() - 172800000
    },
    {
      id: generateId(), title: 'Reading List', folder: 'personal', favorite: false, tags: ['books'],
      content: '<h3>To Read</h3><ul><li>Atomic Habits — James Clear</li><li>Deep Work — Cal Newport</li><li>The Design of Everyday Things — Don Norman</li></ul><h3>In Progress</h3><p>Thinking, Fast and Slow — Daniel Kahneman (ch. 12)</p>',
      created: Date.now() - 432000000, modified: Date.now() - 259200000
    }
  ];
}

// ── let: state ──
let state = {
  notes: [],
  activeNoteId: null,
  currentFolder: 'all',
  searchQuery: '',
  theme: 'light'
};

// ── function: getActiveNote ──
function getActiveNote() {
  return state.notes.find(n => n.id === state.activeNoteId) || null;
}

// ── function: getFilteredNotes ──
function getFilteredNotes() {
  let filtered = [...state.notes];
  if (state.currentFolder === 'favorites') {
    filtered = filtered.filter(n => n.favorite);
  } else if (state.currentFolder !== 'all') {
    filtered = filtered.filter(n => n.folder === state.currentFolder);
  }
  if (state.searchQuery) {
    const q = state.searchQuery.toLowerCase();
    filtered = filtered.filter(n =>
      n.title.toLowerCase().includes(q) ||
      stripHtml(n.content).toLowerCase().includes(q) ||
      n.tags.some(t => t.toLowerCase().includes(q))
    );
  }
  return filtered.sort((a, b) => b.modified - a.modified);
}

// ── function: getAllTags ──
function getAllTags() {
  const tagMap = {};
  state.notes.forEach(n => {
    n.tags.forEach(t => { tagMap[t] = (tagMap[t] || 0) + 1; });
  });
  return Object.entries(tagMap).sort((a, b) => b[1] - a[1]);
}

// ── function: getFolderName ──
function getFolderName(folder) {
  const names = { all: 'All Notes', favorites: 'Favorites', personal: 'Personal', work: 'Work', ideas: 'Ideas' };
  return names[folder] || folder;
}

// ── function: renderNoteList ──
function renderNoteList() {
  const list = document.getElementById('note-list');
  const filtered = getFilteredNotes();
  document.getElementById('folder-title').textContent = getFolderName(state.currentFolder);
  document.getElementById('note-count').textContent = `${filtered.length} note${filtered.length !== 1 ? 's' : ''}`;

  if (!filtered.length) {
    list.innerHTML = `<div style="text-align:center;padding:40px 20px;color:var(--text-tertiary);font-size:0.85rem;">No notes found</div>`;
    return;
  }

  list.innerHTML = filtered.map(note => {
    const preview = stripHtml(note.content).slice(0, 100);
    const isActive = note.id === state.activeNoteId;
    return `
      <div class="note-item${isActive ? ' active' : ''}" data-id="${note.id}">
        <div class="note-item-title">${note.title || 'Untitled'}</div>
        <div class="note-item-preview">${preview || 'Empty note'}</div>
        <div class="note-item-meta">
          ${note.favorite ? '<span class="note-item-fav">★</span>' : ''}
          <span>${formatDate(note.modified)}</span>
          ${note.tags.slice(0, 2).map(t => `<span class="note-item-tag">${t}</span>`).join('')}
        </div>
      </div>
    `;
  }).join('');

  list.querySelectorAll('.note-item').forEach(el => {
    el.addEventListener('click', () => selectNote(el.dataset.id));
  });
}

// ── function: renderSidebarTags ──
function renderSidebarTags() {
  const container = document.getElementById('tags-list');
  const tags = getAllTags();
  container.innerHTML = tags.map(([tag, count]) =>
    `<span class="tag-pill" data-tag="${tag}">${tag} (${count})</span>`
  ).join('');

  container.querySelectorAll('.tag-pill').forEach(el => {
    el.addEventListener('click', () => {
      state.searchQuery = el.dataset.tag;
      document.getElementById('search-input').value = '#' + el.dataset.tag;
      renderNoteList();
    });
  });
}

// ── function: renderEditor ──
function renderEditor() {
  const note = getActiveNote();
  const emptyState = document.getElementById('empty-state');
  const editorContainer = document.getElementById('editor-container');
  const noteActions = document.getElementById('note-actions');

  if (!note) {
    emptyState.classList.remove('hidden');
    editorContainer.classList.add('hidden');
    noteActions.classList.add('hidden');
    return;
  }

  emptyState.classList.add('hidden');
  editorContainer.classList.remove('hidden');
  noteActions.classList.remove('hidden');

  document.getElementById('note-title-input').value = note.title;
  document.getElementById('editor-content').innerHTML = note.content;
  document.getElementById('folder-select').value = note.folder;

  // Favorite button state
  const favBtn = document.getElementById('favorite-btn');
  if (note.favorite) {
    favBtn.classList.add('favorited');
  } else {
    favBtn.classList.remove('favorited');
  }

  renderNoteTags(note);
  updateWordCount();
}

// ── function: renderNoteTags ──
function renderNoteTags(note) {
  const container = document.getElementById('note-tags');
  container.innerHTML = note.tags.map(tag =>
    `<span class="note-tag">${tag}<span class="remove-tag" data-tag="${tag}">×</span></span>`
  ).join('');

  container.querySelectorAll('.remove-tag').forEach(el => {
    el.addEventListener('click', (e) => {
      e.stopPropagation();
      const n = getActiveNote();
      if (!n) return;
      n.tags = n.tags.filter(t => t !== el.dataset.tag);
      n.modified = Date.now();
      saveNotes(state.notes);
      renderEditor();
      renderNoteList();
      renderSidebarTags();
    });
  });
}

// ── function: updateWordCount ──
function updateWordCount() {
  const editor = document.getElementById('editor-content');
  const text = stripHtml(editor.innerHTML);
  const words = countWords(text);
  const chars = text.length;
  document.getElementById('word-count').textContent = `${words} word${words !== 1 ? 's' : ''}`;
  document.getElementById('char-count').textContent = `${chars} character${chars !== 1 ? 's' : ''}`;
}

// ── function: updateLastSaved ──
function updateLastSaved() {
  const el = document.getElementById('last-saved');
  if (el) {
    el.textContent = `Saved ${new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;
  }
}

// ── function: selectNote ──
function selectNote(id) {
  state.activeNoteId = id;
  renderEditor();
  renderNoteList();
}

// ── function: createNewNote ──
function createNewNote() {
  const note = {
    id: generateId(),
    title: '',
    folder: state.currentFolder === 'all' || state.currentFolder === 'favorites' ? 'personal' : state.currentFolder,
    favorite: false,
    tags: [],
    content: '',
    created: Date.now(),
    modified: Date.now()
  };
  state.notes.unshift(note);
  saveNotes(state.notes);
  selectNote(note.id);
  renderSidebarTags();
  setTimeout(() => document.getElementById('note-title-input').focus(), 50);
}

// ── function: deleteActiveNote ──
function deleteActiveNote() {
  if (!state.activeNoteId) return;
  state.notes = state.notes.filter(n => n.id !== state.activeNoteId);
  saveNotes(state.notes);
  state.activeNoteId = null;
  renderEditor();
  renderNoteList();
  renderSidebarTags();
}

// ── function: toggleFavorite ──
function toggleFavorite() {
  const note = getActiveNote();
  if (!note) return;
  note.favorite = !note.favorite;
  note.modified = Date.now();
  saveNotes(state.notes);
  renderEditor();
  renderNoteList();
}

// ── function: switchFolder ──
function switchFolder(folder) {
  state.currentFolder = folder;
  document.querySelectorAll('.nav-item').forEach(el => {
    el.classList.toggle('active', el.dataset.folder === folder);
  });
  renderNoteList();
}

// ── function: filterByTag ──
function filterByTag(tag) {
  state.searchQuery = tag;
  document.getElementById('search-input').value = '#' + tag;
  renderNoteList();
}

// ── function: saveCurrentNote ──
function saveCurrentNote() {
  const note = getActiveNote();
  if (!note) return;
  note.title = document.getElementById('note-title-input').value;
  note.content = document.getElementById('editor-content').innerHTML;
  note.modified = Date.now();
  saveNotes(state.notes);
  updateLastSaved();
  renderNoteList();
}

// ── function: executeToolbarAction ──
function executeToolbarAction(action) {
  const editor = document.getElementById('editor-content');
  editor.focus();

  switch (action) {
    case 'bold':
      document.execCommand('bold', false, null);
      break;
    case 'italic':
      document.execCommand('italic', false, null);
      break;
    case 'underline':
      document.execCommand('underline', false, null);
      break;
    case 'strikethrough':
      document.execCommand('strikeThrough', false, null);
      break;
    case 'h1':
      document.execCommand('formatBlock', false, '<h1>');
      break;
    case 'h2':
      document.execCommand('formatBlock', false, '<h2>');
      break;
    case 'h3':
      document.execCommand('formatBlock', false, '<h3>');
      break;
    case 'ul':
      document.execCommand('insertUnorderedList', false, null);
      break;
    case 'ol':
      document.execCommand('insertOrderedList', false, null);
      break;
    case 'checklist':
      insertChecklist();
      break;
    case 'quote':
      document.execCommand('formatBlock', false, '<blockquote>');
      break;
    case 'code':
      insertCodeBlock();
      break;
    case 'link':
      const url = prompt('Enter URL:');
      if (url) {
        document.execCommand('createLink', false, url);
      }
      break;
  }
  saveCurrentNote();
}

// ── function: insertChecklist ──
function insertChecklist() {
  const html = '<div style="display:flex;align-items:center;gap:8px;margin:4px 0;"><input type="checkbox" style="width:16px;height:16px;accent-color:var(--accent);"><span>Task item</span></div>';
  document.execCommand('insertHTML', false, html);
}

// ── function: insertCodeBlock ──
function insertCodeBlock() {
  const code = prompt('Enter code:');
  if (code) {
    document.execCommand('insertHTML', false, `<pre><code>${code.replace(/</g, '&lt;').replace(/>/g, '&gt;')}</code></pre><p><br></p>`);
  }
}

// ── function: addTagToNote ──
function addTagToNote(tag) {
  const note = getActiveNote();
  if (!note || !tag.trim()) return;
  tag = tag.trim().toLowerCase().replace(/[^a-z0-9-_]/g, '');
  if (tag && !note.tags.includes(tag)) {
    note.tags.push(tag);
    note.modified = Date.now();
    saveNotes(state.notes);
    renderEditor();
    renderSidebarTags();
  }
}

// ── function: toggleTheme ──
function toggleTheme() {
  state.theme = state.theme === 'light' ? 'dark' : 'light';
  document.documentElement.setAttribute('data-theme', state.theme);
  saveTheme(state.theme);
}

// ── main ──
// Initialize theme
state.theme = loadTheme();
document.documentElement.setAttribute('data-theme', state.theme);

// Load notes
state.notes = loadNotes();

// Initial render
renderNoteList();
renderSidebarTags();
renderEditor();

// Event: New note button
document.getElementById('new-note-btn').addEventListener('click', createNewNote);

// Event: Theme toggle
document.getElementById('theme-toggle').addEventListener('click', toggleTheme);

// Event: Folder navigation
document.querySelectorAll('.nav-item').forEach(el => {
  el.addEventListener('click', () => switchFolder(el.dataset.folder));
});

// Event: Search input
let searchTimeout;
document.getElementById('search-input').addEventListener('input', (e) => {
  clearTimeout(searchTimeout);
  searchTimeout = setTimeout(() => {
    state.searchQuery = e.target.value.replace(/^#/, '').trim();
    renderNoteList();
  }, 200);
});

// Event: Note title change
document.getElementById('note-title-input').addEventListener('input', () => {
  saveCurrentNote();
});

// Event: Editor content change (debounced)
let editorTimeout;
document.getElementById('editor-content').addEventListener('input', () => {
  clearTimeout(editorTimeout);
  editorTimeout = setTimeout(() => {
    saveCurrentNote();
    updateWordCount();
  }, 500);
});

// Event: Word count on keyup for responsiveness
document.getElementById('editor-content').addEventListener('keyup', updateWordCount);

// Event: Toolbar buttons
document.querySelectorAll('.tool-btn').forEach(btn => {
  btn.addEventListener('click', () => executeToolbarAction(btn.dataset.action));
});

// Event: Tag input
document.getElementById('tag-input').addEventListener('keydown', (e) => {
  if (e.key === 'Enter') {
    e.preventDefault();
    addTagToNote(e.target.value);
    e.target.value = '';
  }
});

// Event: Folder select change
document.getElementById('folder-select').addEventListener('change', (e) => {
  const note = getActiveNote();
  if (!note) return;
  note.folder = e.target.value;
  note.modified = Date.now();
  saveNotes(state.notes);
  renderNoteList();
});

// Event: Favorite button
document.getElementById('favorite-btn').addEventListener('click', toggleFavorite);

// Event: Delete button (show modal)
document.getElementById('delete-btn').addEventListener('click', () => {
  document.getElementById('delete-modal').classList.remove('hidden');
});

// Event: Cancel delete
document.getElementById('cancel-delete').addEventListener('click', () => {
  document.getElementById('delete-modal').classList.add('hidden');
});

// Event: Confirm delete
document.getElementById('confirm-delete').addEventListener('click', () => {
  deleteActiveNote();
  document.getElementById('delete-modal').classList.add('hidden');
});

// Event: Modal backdrop click to close
document.querySelector('.modal-backdrop').addEventListener('click', () => {
  document.getElementById('delete-modal').classList.add('hidden');
});

// Keyboard shortcuts
document.addEventListener('keydown', (e) => {
  // Ctrl/Cmd + N = new note
  if ((e.ctrlKey || e.metaKey) && e.key === 'n') {
    e.preventDefault();
    createNewNote();
  }
  // Escape to deselect
  if (e.key === 'Escape' && state.activeNoteId) {
    const activeEl = document.activeElement;
    if (activeEl && (activeEl.tagName === 'INPUT' || activeEl.contentEditable === 'true')) return;
    state.activeNoteId = null;
    renderEditor();
    renderNoteList();
  }
});

// Auto-save on page unload
window.addEventListener('beforeunload', () => {
  saveCurrentNote();
});

console.log('%c📝 Noteflow loaded!', 'color: #6c5ce7; font-size: 14px; font-weight: bold;');
</script>
</body>
</html>
<!-- agent-meta {"model":"thinkingcap-qwen3.6-27b","provider":"lmstudio","persona":"composer","sessionId":"dad3018d-603b-4227-8cf2-d704802f380b","tokensIn":567107,"tokensOut":20875,"tokensTotal":587982,"turns":27,"toolCalls":26,"failedToolCalls":2,"timestamp":"2026-07-18T18:05:38.578Z"} -->