<script lang="ts">
  import { onMount } from 'svelte';

  import { onDestroy } from 'svelte';

  interface BrainItem {
    id: string;
    type: string;
    title: string | null;
    url: string | null;
    raw_content: string | null;
    extracted_text: string | null;
    folder: string | null;
    tags: string[] | null;
    summary: string | null;
    confidence: number | null;
    processing_status: string;
    processing_error: string | null;
    metadata_json: any;
    created_at: string;
    updated_at: string;
    assets: { id: string; asset_type: string; filename: string; content_type: string | null }[];
  }

  let loading = $state(true);
  let items = $state<BrainItem[]>([]);
  let total = $state(0);
  let activeFolder = $state<string | null>(null);
  let searchQuery = $state('');
  let searching = $state(false);
  let folders = $state<string[]>([]);
  let tags = $state<string[]>([]);

  // Filter
  let activeTag = $state<string | null>(null);

  // Capture
  let captureInput = $state('');
  let capturing = $state(false);

  // Detail
  let selectedItem = $state<BrainItem | null>(null);
  let editingNote = $state(false);
  let editNoteContent = $state('');

  // Folder counts
  let folderCounts = $state<Record<string, number>>({});

  async function api(path: string, opts: RequestInit = {}) {
    const res = await fetch(`/api/brain${path}`, { credentials: 'include', ...opts });
    if (!res.ok) throw new Error(`${res.status}`);
    return res.json();
  }

  async function loadConfig() {
    try {
      const data = await api('/config');
      folders = data.folders || [];
      tags = data.tags || [];
    } catch { /* silent */ }
  }

  async function loadItems() {
    loading = true;
    try {
      const params = new URLSearchParams({ limit: '50' });
      if (activeFolder) params.set('folder', activeFolder);
      if (activeTag) params.set('tag', activeTag);
      const data = await api(`/items?${params}`);
      items = data.items || [];
      total = data.total || 0;

      // Count items per folder
      const counts: Record<string, number> = {};
      for (const item of items) {
        const f = item.folder || 'Uncategorized';
        counts[f] = (counts[f] || 0) + 1;
      }
      folderCounts = counts;
    } catch { /* silent */ }
    loading = false;
  }

  async function capture() {
    if (!captureInput.trim()) return;
    capturing = true;
    try {
      const isUrl = captureInput.trim().match(/^https?:\/\//);
      const body: any = isUrl
        ? { type: 'link', url: captureInput.trim() }
        : { type: 'note', raw_content: captureInput.trim() };

      await api('/items', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      });
      captureInput = '';
      await loadItems();
    } catch { /* silent */ }
    capturing = false;
  }

  async function search() {
    if (!searchQuery.trim()) {
      await loadItems();
      return;
    }
    searching = true;
    try {
      const data = await api('/search/hybrid', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ q: searchQuery, folder: activeFolder, limit: 30 }),
      });
      items = data.items || [];
      total = data.total || 0;
    } catch { /* silent */ }
    searching = false;
  }

  function startEditNote() {
    if (!selectedItem) return;
    editNoteContent = selectedItem.raw_content || '';
    editingNote = true;
  }

  async function saveNote() {
    if (!selectedItem) return;
    try {
      await api(`/items/${selectedItem.id}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ raw_content: editNoteContent }),
      });
      selectedItem.raw_content = editNoteContent;
      editingNote = false;
      await loadItems();
    } catch { /* silent */ }
  }

  async function deleteItem(id: string) {
    try {
      await api(`/items/${id}`, { method: 'DELETE' });
      selectedItem = null;
      await loadItems();
    } catch { /* silent */ }
  }

  async function reprocessItem(id: string) {
    try {
      await api(`/items/${id}/reprocess`, { method: 'POST' });
      await loadItems();
    } catch { /* silent */ }
  }

  function formatDate(d: string): string {
    try {
      const date = new Date(d);
      const now = new Date();
      const diff = Math.round((now.getTime() - date.getTime()) / 86400000);
      if (diff === 0) return 'Today';
      if (diff === 1) return 'Yesterday';
      if (diff < 7) return `${diff}d ago`;
      return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
    } catch { return ''; }
  }

  function getScreenshot(item: BrainItem): string | null {
    const asset = item.assets?.find(a => a.asset_type === 'screenshot');
    return asset ? `/api/brain/storage/${item.id}/screenshot/${asset.filename}` : null;
  }

  function typeIcon(type: string): string {
    switch (type) {
      case 'link': return '🔗';
      case 'note': return '📝';
      case 'pdf': return '📄';
      case 'image': return '🖼';
      default: return '📎';
    }
  }

  function handleCaptureKey(e: KeyboardEvent) {
    if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); capture(); }
  }

  function handleSearchKey(e: KeyboardEvent) {
    if (e.key === 'Enter') search();
  }

  // Poll for pending items
  let pollTimer: ReturnType<typeof setInterval> | null = null;

  function startPolling() {
    stopPolling();
    pollTimer = setInterval(async () => {
      const hasPending = items.some(i => i.processing_status === 'pending' || i.processing_status === 'processing');
      if (hasPending) {
        await loadItems();
        // Update selected item if it was pending
        if (selectedItem) {
          const updated = items.find(i => i.id === selectedItem!.id);
          if (updated) selectedItem = updated;
        }
      } else {
        stopPolling();
      }
    }, 3000);
  }

  function stopPolling() {
    if (pollTimer) { clearInterval(pollTimer); pollTimer = null; }
  }

  // Start polling after capture
  $effect(() => {
    const hasPending = items.some(i => i.processing_status === 'pending' || i.processing_status === 'processing');
    if (hasPending && !pollTimer) startPolling();
  });

  onMount(async () => {
    await loadConfig();
    await loadItems();
  });

  onDestroy(stopPolling);
</script>

<div class="page">
  <div class="app-surface">

    <!-- ═══ Hero ═══ -->
    <section class="brain-command reveal">
      <div class="command-copy">
        <div class="command-label">Second brain</div>
        <h1>Brain</h1>
        <p>Save anything. Links, notes, files. AI classifies everything automatically so you can find it later without thinking about where to put it.</p>
      </div>
      <div class="command-actions">
        <div class="command-kicker">Collection</div>
        <div class="command-stats">{total} saved · {Object.keys(folderCounts).length} folders</div>
      </div>
    </section>

    <!-- ═══ Capture bar ═══ -->
    <section class="capture-card reveal">
      <div class="capture-wrap">
        <svg class="capture-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
        <input
          class="capture-input"
          placeholder="Paste a URL or type a note to save..."
          bind:value={captureInput}
          onkeydown={handleCaptureKey}
          disabled={capturing}
        />
        {#if captureInput.trim()}
          <button class="capture-btn" onclick={capture} disabled={capturing}>
            {capturing ? 'Saving...' : 'Save'}
          </button>
        {/if}
      </div>
    </section>

    <!-- ═══ Folder signal strip ═══ -->
    <section class="signal-strip stagger">
      <button class="signal-card" class:active={activeFolder === null} onclick={() => { activeFolder = null; loadItems(); }}>
        <div class="signal-topline">
          <div class="signal-label">All</div>
          <div class="signal-value">{total}</div>
        </div>
        <div class="signal-note">Everything saved across all folders.</div>
      </button>
      {#each folders.slice(0, 5) as folder}
        <button class="signal-card" class:active={activeFolder === folder} onclick={() => { activeFolder = folder; loadItems(); }}>
          <div class="signal-topline">
            <div class="signal-label">{folder}</div>
            <div class="signal-value">{folderCounts[folder] || 0}</div>
          </div>
          <div class="signal-note">Items classified under {folder.toLowerCase()}.</div>
        </button>
      {/each}
    </section>

    <!-- ═══ Active tag filter ═══ -->
    {#if activeTag}
      <div class="active-filter">
        <span class="filter-label">Filtered by tag:</span>
        <span class="filter-tag">{activeTag}</span>
        <button class="filter-clear" onclick={() => { activeTag = null; loadItems(); }}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
          Clear
        </button>
      </div>
    {/if}

    <!-- ═══ Search bar ═══ -->
    <section class="search-section">
      <div class="search-wrap">
        <svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
        <input
          type="text"
          class="search-input"
          placeholder="Search your brain..."
          bind:value={searchQuery}
          onkeydown={handleSearchKey}
        />
        {#if searchQuery}
          <button class="search-clear" onclick={() => { searchQuery = ''; loadItems(); }}>
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
          </button>
        {/if}
      </div>
    </section>

    <!-- ═══ Masonry card grid ═══ -->
    {#if loading}
      <div class="masonry">
        {#each [1, 2, 3, 4, 5, 6] as _}
          <div class="card skeleton-card"></div>
        {/each}
      </div>
    {:else if items.length === 0}
      <div class="empty-state">
        <div class="empty-icon">
          <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
        </div>
        <div class="empty-title">Nothing saved yet</div>
        <div class="empty-desc">Paste a URL or type a note in the capture bar above.</div>
      </div>
    {:else}
      <div class="masonry">
        {#each items as item (item.id)}
          <div class="card" class:is-note={item.type === 'note'} class:is-processing={item.processing_status !== 'ready'}>
            <!-- Screenshot for links — clicking opens the URL -->
            {#if item.type === 'link' && item.assets?.some(a => a.asset_type === 'screenshot')}
              <a class="card-thumb" href={item.url} target="_blank" rel="noopener">
                <img src="/api/brain/storage/{item.id}/screenshot/screenshot.png" alt="" loading="lazy" />
                {#if item.processing_status !== 'ready'}
                  <div class="card-processing-overlay">
                    <span class="processing-dot"></span>
                    Processing...
                  </div>
                {/if}
              </a>
            {:else if item.type === 'note'}
              <!-- Note — clicking opens detail for editing -->
              <button class="card-note-body" onclick={() => { selectedItem = item; editingNote = false; }}>
                {(item.raw_content || '').slice(0, 200)}{(item.raw_content || '').length > 200 ? '...' : ''}
              </button>
            {:else if item.processing_status !== 'ready'}
              <div class="card-placeholder">
                <span class="processing-dot"></span>
                <span>Processing...</span>
              </div>
            {/if}

            <!-- Card content — click opens detail -->
            <button class="card-content" onclick={() => { selectedItem = item; editingNote = false; }}>
              <div class="card-title">{item.title || 'Untitled'}</div>
              {#if item.url}
                <div class="card-domain">{(() => { try { return new URL(item.url).hostname; } catch { return ''; } })()}</div>
              {/if}
              {#if item.summary && item.type !== 'note'}
                <div class="card-summary">{item.summary.slice(0, 100)}{item.summary.length > 100 ? '...' : ''}</div>
              {/if}
              <div class="card-footer">
                {#if item.tags && item.tags.length > 0}
                  <div class="card-tags">
                    {#each item.tags.slice(0, 3) as tag}
                      <button class="card-tag" onclick={(e) => { e.stopPropagation(); activeTag = tag; activeFolder = null; loadItems(); }}>{tag}</button>
                    {/each}
                  </div>
                {/if}
                <div class="card-meta">
                  {#if item.folder}<span class="card-folder">{item.folder}</span>{/if}
                  <span class="card-date">{formatDate(item.created_at)}</span>
                </div>
              </div>
            </button>
          </div>
        {/each}
      </div>
    {/if}

  </div>
</div>

<!-- ═══ Detail sheet ═══ -->
{#if selectedItem}
  <!-- svelte-ignore a11y_no_static_element_interactions -->
  <div class="detail-overlay" onclick={(e) => { if (e.target === e.currentTarget) selectedItem = null; }} onkeydown={(e) => { if (e.key === 'Escape') selectedItem = null; }}>
    <div class="detail-sheet">
      <div class="detail-header">
        <div>
          <div class="detail-type">{selectedItem.type}</div>
          <h2 class="detail-title">{selectedItem.title || 'Untitled'}</h2>
        </div>
        <button class="close-btn" onclick={() => selectedItem = null}>
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
        </button>
      </div>

      {#if selectedItem.url}
        <a class="detail-url" href={selectedItem.url} target="_blank" rel="noopener">{selectedItem.url}</a>
      {/if}

      {#if selectedItem.type === 'note'}
        <!-- Editable note content -->
        <div class="detail-content">
          {#if editingNote}
            <textarea
              class="note-editor"
              bind:value={editNoteContent}
              onkeydown={(e) => { if (e.key === 'Escape') editingNote = false; }}
            ></textarea>
            <div class="note-editor-actions">
              <button class="action-btn" onclick={saveNote}>Save</button>
              <button class="action-btn ghost" onclick={() => editingNote = false}>Cancel</button>
            </div>
          {:else}
            <button class="content-body clickable" onclick={startEditNote}>
              {selectedItem.raw_content || 'Empty note — click to edit'}
            </button>
          {/if}
        </div>
      {/if}

      {#if selectedItem.summary}
        <div class="detail-summary">{selectedItem.summary}</div>
      {/if}

      {#if selectedItem.tags && selectedItem.tags.length > 0}
        <div class="detail-tags">
          {#each selectedItem.tags as tag}
            <button class="detail-tag" onclick={() => { selectedItem = null; activeTag = tag; activeFolder = null; loadItems(); }}>{tag}</button>
          {/each}
        </div>
      {/if}

      <div class="detail-meta-line">
        {#if selectedItem.folder}<span>{selectedItem.folder}</span>{/if}
        <span>{formatDate(selectedItem.created_at)}</span>
      </div>

      <div class="detail-actions">
        {#if selectedItem.url}
          <a class="action-btn" href={selectedItem.url} target="_blank" rel="noopener">Open original</a>
        {/if}
        <button class="action-btn ghost" onclick={() => reprocessItem(selectedItem.id)}>Reclassify</button>
        <button class="action-btn ghost" onclick={() => { if (confirm('Delete this item?')) deleteItem(selectedItem.id); }}>Delete</button>
      </div>
    </div>
  </div>
{/if}

<style>
  .page { padding-top: 0; }
  .app-surface { max-width: 1360px; }

  /* ═══ Command hero ═══ */
  .brain-command {
    display: flex;
    justify-content: space-between;
    align-items: end;
    gap: 24px;
    padding: 8px 0 18px;
  }
  .command-copy { max-width: 640px; }
  .command-label {
    font-size: 11px; text-transform: uppercase;
    letter-spacing: 0.14em; color: #8c7b69; margin-bottom: 8px;
  }
  .command-copy h1 {
    margin: 0; font-size: clamp(2.1rem, 4.1vw, 3.5rem);
    line-height: 0.94; letter-spacing: -0.065em; color: #17120d;
  }
  .command-copy p {
    margin: 12px 0 0; max-width: 46ch;
    color: #5c5046; font-size: 1rem; line-height: 1.55;
  }
  .command-actions { min-width: 220px; display: grid; justify-items: end; gap: 8px; }
  .command-kicker { font-size: 11px; text-transform: uppercase; letter-spacing: 0.14em; color: #8c7b69; }
  .command-stats { font-size: 1.15rem; letter-spacing: -0.04em; color: #221a13; }

  /* ═══ Capture bar ═══ */
  .capture-card {
    border-radius: 28px; border: 1px solid rgba(35,26,17,0.08);
    background: rgba(255,252,248,0.68); backdrop-filter: blur(14px);
    padding: 14px 16px; margin-bottom: 18px;
  }
  .capture-wrap { display: flex; align-items: center; gap: 10px; }
  .capture-icon { width: 18px; height: 18px; color: #7f7365; flex-shrink: 0; }
  .capture-input {
    flex: 1; padding: 10px 0; border: none; background: none;
    color: #1e1812; font-size: 1rem; font-family: var(--font); outline: none;
  }
  .capture-input::placeholder { color: #8b7b6a; }
  .capture-btn {
    padding: 8px 18px; border-radius: 999px;
    background: #1e1812; color: white; border: none;
    font-size: 0.88rem; font-weight: 600; font-family: var(--font);
    transition: opacity 160ms;
  }
  .capture-btn:hover { opacity: 0.9; }

  /* ═══ Signal strip ═══ */
  .signal-strip { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; margin-bottom: 18px; }
  .signal-card {
    border-radius: 28px; border: 1px solid rgba(35,26,17,0.08);
    background: rgba(255,252,248,0.68); backdrop-filter: blur(14px);
    padding: 18px; text-align: left;
    transition: transform 160ms ease, background 160ms ease, border-color 160ms ease;
  }
  .signal-card:hover { transform: translateY(-2px); background: rgba(255,255,255,0.82); }
  .signal-card.active {
    border-color: rgba(179,92,50,0.2);
    background: linear-gradient(145deg, rgba(255,248,242,0.94), rgba(246,237,227,0.72));
  }
  .signal-topline { display: flex; align-items: end; justify-content: space-between; gap: 16px; margin-bottom: 12px; }
  .signal-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em; color: #7d6f61; }
  .signal-value { font-size: clamp(1.6rem, 3vw, 2.2rem); line-height: 0.95; letter-spacing: -0.05em; color: #1e1812; }
  .signal-note { color: #4f463d; line-height: 1.6; font-size: 0.85rem; }

  /* ═══ Active filter ═══ */
  .active-filter {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    margin-bottom: 12px;
    border-radius: 999px;
    background: rgba(179,92,50,0.08);
    border: 1px solid rgba(179,92,50,0.15);
    width: fit-content;
  }
  .filter-label { font-size: 0.82rem; color: #7d6f61; }
  .filter-tag { font-size: 0.82rem; font-weight: 700; color: #1e1812; }
  .filter-clear {
    display: flex; align-items: center; gap: 3px;
    font-size: 0.78rem; color: #8c7b69; background: none; border: none;
    font-family: var(--font); transition: color 160ms;
  }
  .filter-clear:hover { color: #1e1812; }

  /* ═══ Search ═══ */
  .search-section { margin-bottom: 18px; }
  .search-wrap { position: relative; }
  .search-icon { position: absolute; left: 16px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; color: #7f7365; pointer-events: none; }
  .search-input {
    width: 100%; padding: 14px 40px 14px 46px;
    border-radius: 28px; border: 1px solid rgba(35,26,17,0.08);
    background: rgba(255,252,248,0.68); backdrop-filter: blur(14px);
    color: #1e1812; font-size: 1rem; font-family: var(--font);
  }
  .search-input::placeholder { color: #8b7b6a; }
  .search-input:focus { outline: none; border-color: rgba(179,92,50,0.4); box-shadow: 0 0 0 4px rgba(179,92,50,0.06); background: rgba(255,255,255,0.9); }
  .search-clear { position: absolute; right: 14px; top: 50%; transform: translateY(-50%); background: none; border: none; color: #7f7365; }
  .search-clear svg { width: 16px; height: 16px; }

  /* ═══ Masonry grid ═══ */
  .masonry {
    columns: 3;
    column-gap: 14px;
  }

  .card {
    break-inside: avoid;
    display: flex;
    flex-direction: column;
    border-radius: 20px;
    border: 1px solid rgba(35,26,17,0.08);
    background: rgba(255,252,248,0.82);
    backdrop-filter: blur(10px);
    overflow: hidden;
    margin-bottom: 14px;
    width: 100%;
    text-align: left;
    transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease;
  }
  .card:hover {
    transform: translateY(-3px);
    box-shadow: 0 12px 32px rgba(42,30,19,0.08);
    border-color: rgba(35,26,17,0.14);
  }
  .card:active { transform: scale(0.985); }

  .card.is-processing { opacity: 0.7; }

  /* Card thumbnail — link opens URL */
  .card-thumb {
    display: block;
    width: 100%;
    position: relative;
    overflow: hidden;
    background: rgba(244,237,229,0.6);
    cursor: pointer;
  }
  .card-thumb img {
    width: 100%;
    height: auto;
    display: block;
    object-fit: cover;
    max-height: 240px;
  }
  .card-processing-overlay {
    position: absolute; inset: 0;
    background: rgba(30,24,18,0.6);
    display: flex; align-items: center; justify-content: center; gap: 6px;
    color: white; font-size: 0.85rem; font-weight: 600;
  }
  .processing-dot {
    width: 6px; height: 6px; border-radius: 50%; background: #f6a33a;
    animation: pulse 1.5s ease-in-out infinite;
  }
  @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

  /* Note card body — click opens detail */
  .card-note-body {
    padding: 18px 18px 0;
    font-size: 0.92rem;
    color: #3d342c;
    line-height: 1.65;
    white-space: pre-wrap;
    word-break: break-word;
    background: none;
    border: none;
    text-align: left;
    font-family: var(--font);
    cursor: pointer;
    width: 100%;
  }

  .card-placeholder {
    padding: 32px;
    display: flex; align-items: center; justify-content: center; gap: 6px;
    color: #8c7b69; font-size: 0.85rem;
    background: rgba(244,237,229,0.4);
  }

  /* Card content — button for detail click */
  .card-content {
    padding: 14px 18px 16px;
    background: none;
    border: none;
    text-align: left;
    font-family: var(--font);
    cursor: pointer;
    width: 100%;
    transition: background 160ms;
  }
  .card-content:hover { background: rgba(255,248,242,0.5); }

  .card-title {
    font-size: 0.95rem;
    font-weight: 700;
    color: #1e1812;
    line-height: 1.3;
    margin-bottom: 4px;
  }

  .card-domain {
    font-size: 0.8rem;
    color: #8c7b69;
    margin-bottom: 6px;
  }

  .card-summary {
    font-size: 0.82rem;
    color: #5c5046;
    line-height: 1.5;
    margin-bottom: 8px;
  }

  .card-footer {
    display: flex;
    flex-direction: column;
    gap: 6px;
  }

  .card-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
  }

  .card-tag {
    background: rgba(35,26,17,0.06);
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 0.72rem;
    color: #5d5248;
    font-weight: 500;
    border: none;
    font-family: var(--font);
    cursor: pointer;
    transition: background 160ms, color 160ms;
  }
  .card-tag:hover {
    background: rgba(179,92,50,0.12);
    color: #1e1812;
  }

  .card-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.75rem;
    color: #8c7b69;
  }

  .card-folder {
    font-weight: 600;
  }

  /* Skeleton cards */
  .skeleton-card {
    height: 200px;
    background: linear-gradient(90deg, rgba(244,237,229,0.5) 25%, rgba(255,252,248,0.8) 50%, rgba(244,237,229,0.5) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.5s infinite;
    margin-bottom: 14px;
    break-inside: avoid;
  }

  /* Empty state */
  .empty-state {
    padding: 64px 32px;
    text-align: center;
  }
  .empty-icon { color: #8c7b69; margin-bottom: 16px; }
  .empty-title { font-size: 1.2rem; font-weight: 700; color: #1e1812; margin-bottom: 6px; }
  .empty-desc { font-size: 0.95rem; color: #6a5d50; }

  /* ═══ Detail sheet ═══ */
  .detail-overlay {
    position: fixed; inset: 0;
    background: rgba(17,13,10,0.42); z-index: 60;
    display: flex; justify-content: flex-end;
    backdrop-filter: blur(12px);
  }
  .detail-sheet {
    width: 560px; max-width: 100%; height: 100%;
    background: linear-gradient(180deg, #f8f1e8 0%, #f3eadc 100%);
    overflow-y: auto; padding: 28px;
    box-shadow: -20px 0 50px rgba(18,13,10,0.16);
    border-left: 1px solid rgba(35,26,17,0.08);
    color: #1e1812;
    animation: sheetIn 220ms ease;
  }
  .detail-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 16px; }
  .detail-type { font-size: 11px; text-transform: uppercase; letter-spacing: 0.14em; color: #8c7b69; margin-bottom: 6px; }
  .detail-title { font-size: 1.5rem; font-weight: 700; color: #1e1812; line-height: 1.15; letter-spacing: -0.04em; margin: 0; }
  .close-btn { background: none; border: none; color: #7d6f61; padding: 4px; border-radius: 8px; }
  .close-btn:hover { background: rgba(35,26,17,0.08); color: #1e1812; }
  .close-btn svg { width: 20px; height: 20px; }

  .detail-url {
    display: block; font-size: 0.88rem; color: #8c7b69;
    margin-bottom: 16px; word-break: break-all;
    text-decoration: none;
  }
  .detail-url:hover { color: #1e1812; text-decoration: underline; }

  .detail-content {
    margin-bottom: 20px;
  }
  .content-body {
    display: block; width: 100%; text-align: left;
    font-size: 1rem; color: #1e1812; line-height: 1.7;
    white-space: pre-wrap; word-break: break-word;
    background: none; border: none; font-family: var(--font);
    padding: 14px 16px; border-radius: 14px;
    transition: background 160ms;
  }
  .content-body.clickable { cursor: text; }
  .content-body.clickable:hover { background: rgba(255,255,255,0.6); }

  .note-editor {
    width: 100%; min-height: 200px; padding: 14px 16px;
    border-radius: 14px; border: 1.5px solid rgba(179,92,50,0.3);
    background: rgba(255,255,255,0.8); color: #1e1812;
    font-size: 1rem; font-family: var(--font); line-height: 1.7;
    resize: vertical; outline: none;
  }
  .note-editor:focus { border-color: rgba(179,92,50,0.5); box-shadow: 0 0 0 4px rgba(179,92,50,0.06); }
  .note-editor-actions { display: flex; gap: 8px; margin-top: 10px; }

  .detail-summary {
    font-size: 0.92rem; color: #5c5046; line-height: 1.6;
    margin-bottom: 16px;
    font-style: italic;
  }

  .detail-meta-line {
    display: flex; gap: 12px; font-size: 0.8rem; color: #8c7b69;
    margin-bottom: 16px;
  }

  /* meta grid removed — folder/date shown inline */

  .detail-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 20px; }
  .detail-tag {
    background: rgba(35,26,17,0.06); padding: 4px 12px;
    border-radius: 999px; font-size: 0.85rem; color: #5d5248;
    border: none; font-family: var(--font); cursor: pointer;
    transition: background 160ms;
  }
  .detail-tag:hover { background: rgba(179,92,50,0.12); color: #1e1812; }

  .detail-actions { display: flex; gap: 8px; flex-wrap: wrap; }
  .action-btn {
    display: flex; align-items: center; gap: 5px;
    padding: 8px 14px; border-radius: 10px;
    background: rgba(255,255,255,0.8); border: 1px solid rgba(35,26,17,0.1);
    font-size: 0.88rem; color: #1e1812; text-decoration: none;
    font-family: var(--font); transition: background 160ms;
  }
  .action-btn:hover { background: rgba(255,255,255,0.95); }
  .action-btn.ghost { background: none; color: #6b6256; }

  /* ═══ Animations ═══ */
  .reveal { animation: riseIn 280ms ease; }
  .stagger .signal-card:nth-child(1) { animation: riseIn 220ms ease; }
  .stagger .signal-card:nth-child(2) { animation: riseIn 260ms ease; }
  .stagger .signal-card:nth-child(3) { animation: riseIn 300ms ease; }
  .stagger .signal-card:nth-child(4) { animation: riseIn 340ms ease; }
  .stagger .signal-card:nth-child(5) { animation: riseIn 380ms ease; }
  .stagger .signal-card:nth-child(6) { animation: riseIn 420ms ease; }
  @keyframes riseIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
  @keyframes sheetIn { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } }

  /* ═══ Mobile ═══ */
  @media (max-width: 1100px) {
    .masonry { columns: 2; }
  }
  @media (max-width: 768px) {
    .brain-command { display: grid; gap: 14px; }
    .command-actions { justify-items: start; }
    .signal-strip { grid-template-columns: 1fr 1fr; }
    .masonry { columns: 1; }
    .detail-sheet { width: 100%; padding: 20px; }
    /* detail meta grid removed */
  }
</style>
