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

  import { onDestroy } from 'svelte';
  import PdfInlinePreview from '$lib/components/trips/PdfInlinePreview.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 }[];
  }

  interface SidebarFolder { id: string; name: string; slug: string; color?: string; icon?: string; is_active: boolean; item_count: number; }
  interface SidebarTag { id: string; name: string; slug: string; color?: string; icon?: string; is_active: boolean; item_count: number; }

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

  // Sidebar
  let sidebarFolders = $state<SidebarFolder[]>([]);
  let sidebarTags = $state<SidebarTag[]>([]);
  let sidebarView = $state<'folders' | 'tags'>('folders');
  let mobileSidebarOpen = $state(false);
  let showManage = $state(false);
  let newTaxName = $state('');

  // Capture
  let captureInput = $state('');
  let capturing = $state(false);
  let uploading = $state(false);
  let fileInput: HTMLInputElement;

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

  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 loadSidebar() {
    try {
      const data = await api('/taxonomy/sidebar');
      sidebarFolders = data.folders || [];
      sidebarTags = data.tags || [];
      total = data.total_items || 0;
    } 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;
    } catch { /* silent */ }
    loading = false;
  }

  async function addTaxonomy() {
    if (!newTaxName.trim()) return;
    try {
      const endpoint = sidebarView === 'folders' ? '/taxonomy/folders' : '/taxonomy/tags';
      await api(endpoint, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name: newTaxName.trim() }),
      });
      newTaxName = '';
      await loadSidebar();
    } catch { /* silent */ }
  }

  async function deleteTaxonomy(id: string) {
    try {
      const endpoint = sidebarView === 'folders' ? `/taxonomy/folders/${id}` : `/taxonomy/tags/${id}`;
      await api(endpoint, { method: 'DELETE' });
      await loadSidebar();
      await loadItems();
    } catch { /* silent */ }
  }

  function selectFolder(folder: SidebarFolder | null) {
    if (folder) {
      activeFolder = folder.name;
      activeFolderId = folder.id;
    } else {
      activeFolder = null;
      activeFolderId = null;
    }
    activeTag = null;
    activeTagId = null;
    loadItems();
  }

  function selectTag(tag: SidebarTag | null) {
    if (tag) {
      activeTag = tag.name;
      activeTagId = tag.id;
    } else {
      activeTag = null;
      activeTagId = null;
    }
    activeFolder = null;
    activeFolderId = null;
    loadItems();
  }

  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;
  }

  async function uploadFile(e: Event) {
    const input = e.target as HTMLInputElement;
    if (!input.files?.length) return;
    uploading = true;
    try {
      for (const file of input.files) {
        const formData = new FormData();
        formData.append('file', file);
        await fetch('/api/brain/items/upload', {
          method: 'POST',
          credentials: 'include',
          body: formData,
        });
      }
      input.value = '';
      await loadItems();
    } catch { /* silent */ }
    uploading = 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(); }
  }

  let searchTimer: ReturnType<typeof setTimeout>;

  function handleSearchInput() {
    clearTimeout(searchTimer);
    searchTimer = setTimeout(() => {
      search();
    }, 300);
  }

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

  function startPolling() {
    stopPolling();
    pollTimer = setInterval(async () => {
      const pendingIds = items
        .filter(i => i.processing_status === 'pending' || i.processing_status === 'processing')
        .map(i => i.id);

      if (pendingIds.length === 0) {
        stopPolling();
        return;
      }

      // Poll each pending item individually instead of reloading everything
      for (const id of pendingIds) {
        try {
          const updated = await api(`/items/${id}`);
          const idx = items.findIndex(i => i.id === id);
          if (idx !== -1) {
            items[idx] = updated;
            items = items; // trigger reactivity
          }
          if (selectedItem?.id === id) {
            selectedItem = updated;
          }
        } catch { /* item might be gone */ }
      }
    }, 4000);
  }

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

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

  onMount(async () => {
    // Read filters from URL params (set by AppShell sidebar links)
    const urlFolder = new URL(window.location.href).searchParams.get('folder');
    const urlTag = new URL(window.location.href).searchParams.get('tag');
    if (urlFolder) {
      activeFolder = urlFolder;
    }
    if (urlTag) {
      activeTag = urlTag;
    }

    await loadSidebar();
    await loadItems();
  });

  onDestroy(stopPolling);
</script>

<div class="brain-layout">

      <!-- Second sidebar (like Reader) -->
      <!-- svelte-ignore a11y_no_static_element_interactions -->
      {#if mobileSidebarOpen}
        <div class="mobile-sidebar-overlay" onclick={() => mobileSidebarOpen = false}></div>
      {/if}
      <aside class="brain-sidebar" class:mobile-open={mobileSidebarOpen}>
        <div class="sidebar-header">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><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>
          <span class="sidebar-title">Brain</span>
          <button class="sidebar-settings" onclick={() => showManage = !showManage} title={showManage ? 'Done editing' : 'Manage'}>
            {#if showManage}
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M20 6L9 17l-5-5"/></svg>
            {:else}
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z"/></svg>
            {/if}
          </button>
        </div>

        <nav class="sidebar-nav">
          <button class="nav-item" class:active={!activeFolder && !activeTag} onclick={() => { activeFolder = null; activeTag = null; activeFolderId = null; activeTagId = null; mobileSidebarOpen = false; loadItems(); }}>
            <span class="nav-label">All items</span>
            <span class="nav-count">{total}</span>
          </button>
        </nav>

        <!-- Folders -->
        <div class="sidebar-separator"></div>
        <div class="sidebar-section-head">
          <div class="sidebar-section-label">Folders</div>
        </div>
        {#if showManage}
          <div class="sidebar-add-row">
            <input class="sidebar-add-input" placeholder="New folder..." bind:value={newTaxName} onkeydown={(e) => { if (e.key === 'Enter') { sidebarView = 'folders'; addTaxonomy(); } }} />
            <button class="sidebar-add-go" onclick={() => { sidebarView = 'folders'; addTaxonomy(); }}>+</button>
          </div>
        {/if}
        <nav class="sidebar-nav">
          {#each sidebarFolders.filter(f => f.is_active) as folder}
            <button class="nav-item" class:active={activeFolder === folder.name} onclick={() => { activeFolder = folder.name; activeFolderId = folder.id; activeTag = null; activeTagId = null; mobileSidebarOpen = false; loadItems(); }}>
              {#if folder.color}<span class="nav-dot" style="background: {folder.color}"></span>{/if}
              <span class="nav-label">{folder.name}</span>
              {#if showManage}
                <!-- svelte-ignore a11y_no_static_element_interactions --><span class="nav-delete" onclick={(e) => { e.stopPropagation(); if (confirm(`Delete "${folder.name}"? Items will be moved.`)) deleteTaxonomy(folder.id); }}>×</span>
              {:else if folder.item_count > 0}
                <span class="nav-count">{folder.item_count}</span>
              {/if}
            </button>
          {/each}
        </nav>

        <!-- Tags -->
        <div class="sidebar-separator"></div>
        <div class="sidebar-section-head">
          <div class="sidebar-section-label">Tags</div>
        </div>
        {#if showManage}
          <div class="sidebar-add-row">
            <input class="sidebar-add-input" placeholder="New tag..." bind:value={newTaxName} onkeydown={(e) => { if (e.key === 'Enter') { sidebarView = 'tags'; addTaxonomy(); } }} />
            <button class="sidebar-add-go" onclick={() => { sidebarView = 'tags'; addTaxonomy(); }}>+</button>
          </div>
          <nav class="sidebar-nav">
            {#each sidebarTags.filter(t => t.is_active) as tag}
              <button class="nav-item" class:active={activeTag === tag.name} onclick={() => { activeTag = tag.name; activeTagId = tag.id; activeFolder = null; activeFolderId = null; mobileSidebarOpen = false; loadItems(); }}>
                <span class="nav-label">{tag.name}</span>
                <!-- svelte-ignore a11y_no_static_element_interactions --><span class="nav-delete" onclick={(e) => { e.stopPropagation(); if (confirm(`Delete tag "${tag.name}"?`)) deleteTaxonomy(tag.id); }}>×</span>
              </button>
            {/each}
          </nav>
        {:else}
          <nav class="sidebar-nav">
            {#each sidebarTags.filter(t => t.is_active && t.item_count > 0) as tag}
              <button class="nav-item" class:active={activeTag === tag.name} onclick={() => { activeTag = tag.name; activeTagId = tag.id; activeFolder = null; activeFolderId = null; mobileSidebarOpen = false; loadItems(); }}>
                <span class="nav-label">{tag.name}</span>
                <span class="nav-count">{tag.item_count}</span>
              </button>
            {/each}
          </nav>
        {/if}
      </aside>

      <!-- Main content -->
      <div class="brain-content">
        <!-- 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.</p>
          </div>
          <div class="command-actions">
            <div class="command-kicker">Collection</div>
            <div class="command-stats">{total} saved</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} />
            <button class="upload-btn" onclick={() => fileInput?.click()} disabled={uploading} title="Upload file">
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
            </button>
            {#if captureInput.trim()}
              <button class="capture-btn" onclick={capture} disabled={capturing}>{capturing ? 'Saving...' : 'Save'}</button>
            {/if}
          </div>
          <input bind:this={fileInput} type="file" class="hidden-input" accept=".pdf,.png,.jpg,.jpeg,.gif,.webp,.txt,.md,.csv" onchange={uploadFile} multiple />
          {#if uploading}<div class="upload-status">Uploading...</div>{/if}
        </section>

        <!-- Mobile: horizontal pill filters -->
        <div class="mobile-pills">
          <button class="pill" class:active={!activeFolder && !activeTag} onclick={() => { activeFolder = null; activeTag = null; activeFolderId = null; activeTagId = null; loadItems(); }}>
            All
          </button>
          {#each sidebarFolders.filter(f => f.is_active) as folder}
            <button class="pill" class:active={activeFolder === folder.name} onclick={() => { activeFolder = folder.name; activeFolderId = folder.id; activeTag = null; activeTagId = null; loadItems(); }}
              style={folder.color ? `--pill-color: ${folder.color}` : ''}>
              {#if folder.color}<span class="pill-dot" style="background: {folder.color}"></span>{/if}
              {folder.name}
              {#if folder.item_count > 0}<span class="pill-count">{folder.item_count}</span>{/if}
            </button>
          {/each}
          <span class="pill-separator"></span>
          {#each sidebarTags.filter(t => t.is_active) as tag}
            <button class="pill pill-tag" class:active={activeTag === tag.name} onclick={() => { activeTag = tag.name; activeTagId = tag.id; activeFolder = null; activeFolderId = null; loadItems(); }}>
              #{tag.name}
            </button>
          {/each}
        </div>

        <!-- Active filter indicator -->
        {#if activeFolder || activeTag}
        <div class="active-filter">
          <span class="filter-label">Filtered by {activeFolder ? 'folder' : 'tag'}:</span>
          <span class="filter-tag">{activeFolder || activeTag}</span>
          <button class="filter-clear" onclick={() => { activeFolder = null; activeTag = null; activeFolderId = null; activeTagId = null; mobileSidebarOpen = false; 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 -->
      <div 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} oninput={handleSearchInput} />
          {#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>
        </div>

        <!-- 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'}>
            <!-- Thumbnail: screenshot for links/PDFs, original image for images -->
            {#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 === 'pdf' && item.assets?.some(a => a.asset_type === 'screenshot')}
              <button class="card-thumb" onclick={() => { selectedItem = item; editingNote = false; }}>
                <img src="/api/brain/storage/{item.id}/screenshot/screenshot.png" alt="" loading="lazy" />
                <div class="card-type-badge">PDF</div>
              </button>
            {:else if item.type === 'image' && item.assets?.some(a => a.asset_type === 'original_upload')}
              {@const imgAsset = item.assets.find(a => a.asset_type === 'original_upload')}
              <button class="card-thumb" onclick={() => { selectedItem = item; editingNote = false; }}>
                <img src="/api/brain/storage/{item.id}/original_upload/{imgAsset?.filename}" alt="" loading="lazy" />
              </button>
            {:else if item.type === 'note'}
              <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>
              {:else if item.type === 'pdf'}
                <div class="card-domain">PDF document{item.metadata_json?.page_count ? ` · ${item.metadata_json.page_count} page${item.metadata_json.page_count !== 1 ? 's' : ''}` : ''}</div>
              {:else if item.type === 'image'}
                <div class="card-domain">Image</div>
              {/if}
              {#if item.type === 'pdf' && item.extracted_text}
                <div class="card-summary">{item.extracted_text.slice(0, 120)}{item.extracted_text.length > 120 ? '...' : ''}</div>
              {:else 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><!-- .brain-content -->
</div><!-- .brain-layout -->

<!-- ═══ PDF/Image full-screen viewer ═══ -->
{#if selectedItem && (selectedItem.type === 'pdf' || selectedItem.type === 'image')}
  <!-- svelte-ignore a11y_no_static_element_interactions -->
  <div class="viewer-overlay" onclick={(e) => { if (e.target === e.currentTarget) selectedItem = null; }} onkeydown={(e) => { if (e.key === 'Escape') selectedItem = null; }}>
    <div class="viewer-layout">
      <!-- Main viewer area -->
      <div class="viewer-main">
        {#if selectedItem.type === 'pdf'}
          {@const pdfAsset = selectedItem.assets?.find(a => a.asset_type === 'original_upload')}
          {#if pdfAsset}
            <iframe
              src="/api/brain/storage/{selectedItem.id}/original_upload/{pdfAsset.filename}#zoom=page-fit"
              title={selectedItem.title || 'PDF'}
              class="viewer-iframe"
            ></iframe>
          {/if}
        {:else if selectedItem.type === 'image'}
          {@const imgAsset = selectedItem.assets?.find(a => a.asset_type === 'original_upload')}
          {#if imgAsset}
            <div class="viewer-image-wrap">
              <img src="/api/brain/storage/{selectedItem.id}/original_upload/{imgAsset.filename}" alt={selectedItem.title || ''} class="viewer-image" />
            </div>
          {/if}
        {/if}
      </div>

      <!-- Sidebar with details -->
      <div class="viewer-sidebar">
        <div class="viewer-sidebar-header">
          <div>
            <div class="detail-type">{selectedItem.type === 'pdf' ? 'PDF Document' : 'Image'}</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.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 class="meta-folder-pill">{selectedItem.folder}</span>{/if}
          <span>{formatDate(selectedItem.created_at)}</span>
          {#if selectedItem.metadata_json?.page_count}
            <span>{selectedItem.metadata_json.page_count} page{selectedItem.metadata_json.page_count !== 1 ? 's' : ''}</span>
          {/if}
        </div>

        {#if selectedItem.extracted_text}
          <div class="detail-extracted">
            <div class="extracted-label">Extracted text</div>
            <div class="extracted-body">{selectedItem.extracted_text.slice(0, 1000)}{selectedItem.extracted_text.length > 1000 ? '...' : ''}</div>
          </div>
        {/if}

        <div class="detail-actions">
          {#if selectedItem.assets?.some(a => a.asset_type === 'original_upload')}
            <a class="action-btn" href="/api/brain/storage/{selectedItem.id}/original_upload/{selectedItem.assets.find(a => a.asset_type === 'original_upload')?.filename}" target="_blank" rel="noopener">Download</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>
  </div>

<!-- ═══ Detail sheet for links/notes ═══ -->
{:else 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.type === 'link' && selectedItem.assets?.some(a => a.asset_type === 'screenshot')}
        <a class="detail-screenshot" href={selectedItem.url} target="_blank" rel="noopener">
          <img src="/api/brain/storage/{selectedItem.id}/screenshot/screenshot.png" alt="" />
        </a>
      {/if}

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

      {#if selectedItem.summary && selectedItem.type !== 'note'}
        <div class="detail-summary">{selectedItem.summary}</div>
      {/if}

      {#if selectedItem.type === 'note'}
        <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.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 class="meta-folder-pill">{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>
  /* No .page wrapper — brain-layout is the root */

  /* ═══ 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: 140px; display: grid; justify-items: end; gap: 6px; }
  .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; }
  .upload-btn {
    flex-shrink: 0;
    width: 36px; height: 36px;
    border-radius: 10px;
    border: 1px solid rgba(35,26,17,0.1);
    background: rgba(255,255,255,0.6);
    color: #7f7365;
    display: flex; align-items: center; justify-content: center;
    transition: all 160ms;
  }
  .upload-btn:hover { background: rgba(255,255,255,0.9); color: #1e1812; border-color: rgba(35,26,17,0.2); }
  .upload-btn:active { transform: scale(0.95); }

  .hidden-input { display: none; }

  .upload-status {
    font-size: 0.82rem; color: #8c7b69;
    margin-top: 8px; padding-left: 28px;
  }

  .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; }

  /* ═══ Layout: Sidebar + Content (Reader pattern) ═══ */
  .brain-layout {
    display: flex;
    min-height: calc(100vh - 60px);
  }

  .brain-sidebar {
    width: 248px;
    flex-shrink: 0;
    min-height: 0;
    background: rgba(245, 237, 228, 0.82);
    border-right: 1px solid rgba(35,26,17,0.1);
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    padding: 16px 0 12px;
    backdrop-filter: blur(16px);
  }
  .sidebar-header { display: flex; align-items: center; gap: 8px; padding: 0 18px 14px; }
  .sidebar-header > svg { color: #7f5f3d; }
  .sidebar-title { font-size: 1rem; font-weight: 700; color: #1f1811; letter-spacing: -0.03em; flex: 1; }
  .sidebar-settings {
    width: 28px; height: 28px; border-radius: 8px; border: none;
    background: none; color: #8c7b69; display: flex; align-items: center;
    justify-content: center; cursor: pointer; transition: all 140ms; flex-shrink: 0;
  }
  .sidebar-settings:hover { background: rgba(255,248,241,0.72); color: #1f1811; }

  .sidebar-nav { display: flex; flex-direction: column; gap: 2px; padding: 0 12px; }
  .nav-item {
    display: flex; align-items: center; gap: var(--sp-2, 8px);
    padding: 10px 12px; border-radius: 14px; background: none; border: none;
    font-size: var(--text-sm, 0.85rem); color: #65584c; cursor: pointer;
    transition: all var(--transition, 160ms); text-align: left; width: 100%; font-family: var(--font);
  }
  .nav-item:hover { background: rgba(255,248,241,0.72); color: #1f1811; }
  .nav-item.active { background: rgba(255,248,241,0.92); color: #1f1811; font-weight: 600; box-shadow: inset 0 0 0 1px rgba(35,26,17,0.08); }
  .nav-label { flex: 1; }
  .nav-count { font-size: var(--text-xs, 0.72rem); color: #8a7a68; font-family: var(--mono); }
  .nav-item.active .nav-count { color: #7f5f3d; opacity: 0.8; }

  .sidebar-separator { height: 1px; background: rgba(35,26,17,0.08); margin: 12px 18px; }

  .sidebar-section-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 4px 18px 6px;
  }
  .sidebar-section-label {
    font-size: 0.68rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.14em; color: #8c7b69;
  }
  .sidebar-section-add {
    width: 20px; height: 20px; border-radius: 6px;
    border: none; background: rgba(35,26,17,0.06);
    color: #7f5f3d; font-size: 0.85rem; font-weight: 700;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer; transition: all 140ms;
  }
  .sidebar-section-add:hover { background: rgba(35,26,17,0.12); }

  .sidebar-add-row {
    display: flex; gap: 4px; padding: 0 12px; margin-bottom: 6px;
  }
  .sidebar-add-input {
    flex: 1; min-width: 0; padding: 6px 8px; border-radius: 10px;
    border: 1px solid rgba(35,26,17,0.12); background: rgba(255,255,255,0.7);
    font-size: 0.78rem; font-family: var(--font); color: #1e1812; outline: none;
  }
  .sidebar-add-input:focus { border-color: rgba(179,92,50,0.4); }
  .sidebar-add-input::placeholder { color: #8c7b69; }
  .sidebar-add-go {
    flex-shrink: 0; padding: 6px 8px; border-radius: 10px; border: none;
    background: #1e1812; color: white; font-size: 0.72rem; font-weight: 600;
    font-family: var(--font); cursor: pointer;
  }

  .nav-delete {
    width: 22px; height: 22px; border-radius: 6px;
    border: none; background: none; color: #8c7b69;
    font-size: 0.9rem; display: flex; align-items: center; justify-content: center;
    cursor: pointer; transition: all 140ms; flex-shrink: 0;
  }
  .nav-delete:hover { background: rgba(220,38,38,0.1); color: #DC2626; }

  /* manage button removed — settings icon in header */

  .brain-content {
    flex: 1;
    min-width: 0;
    padding: 16px 28px 28px;
    overflow-x: hidden;
  }

  /* ═══ Mobile pills ═══ */
  .mobile-pills {
    display: none;
    gap: 6px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 4px;
    margin-bottom: 12px;
  }
  .mobile-pills::-webkit-scrollbar { display: none; }

  .pill {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 6px 12px;
    border-radius: 999px;
    border: 1px solid rgba(35,26,17,0.1);
    background: rgba(255,252,248,0.7);
    color: #5c5046;
    font-size: 0.78rem;
    font-weight: 500;
    font-family: var(--font);
    cursor: pointer;
    white-space: nowrap;
    flex-shrink: 0;
    transition: all 160ms;
  }
  .pill:hover { background: rgba(255,248,241,0.9); }
  .pill.active {
    background: rgba(255,248,241,0.95);
    color: #1e1812;
    font-weight: 600;
    border-color: var(--pill-color, rgba(35,26,17,0.2));
    box-shadow: inset 0 0 0 1px var(--pill-color, transparent);
  }
  .pill-dot {
    width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
  }
  .pill-count {
    font-size: 0.65rem; font-family: var(--mono); color: #8c7b69;
  }

  .pill-separator {
    width: 1px; height: 20px; background: rgba(35,26,17,0.12); flex-shrink: 0; align-self: center;
  }
  .pill-tag { color: #7d6f61; font-style: italic; }

  .nav-dot {
    width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
  }

  @media (max-width: 768px) {
    .mobile-pills { display: flex; }
  }

  /* ═══ 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;
    object-position: top;
    max-height: 240px;
  }
  .card-type-badge {
    position: absolute;
    top: 10px;
    right: 10px;
    background: rgba(30,24,18,0.75);
    color: white;
    font-size: 0.7rem;
    font-weight: 700;
    padding: 3px 8px;
    border-radius: 6px;
    letter-spacing: 0.04em;
    backdrop-filter: blur(4px);
  }

  .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; }

  /* ═══ Document viewer popup ═══ */
  .viewer-overlay {
    position: fixed; inset: 0; z-index: 60;
    background: rgba(17,13,10,0.5);
    backdrop-filter: blur(6px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 32px;
    animation: fadeIn 200ms ease;
  }
  @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

  .viewer-layout {
    display: grid;
    grid-template-columns: 1fr 440px;
    width: 94vw;
    max-width: 1300px;
    height: 85vh;
    border-radius: 24px;
    overflow: hidden;
    box-shadow: 0 32px 80px rgba(18,13,10,0.3);
    animation: sheetIn 220ms ease;
  }

  .viewer-main {
    overflow: auto;
    background: #f5f0ea;
  }

  .viewer-iframe {
    width: 100%;
    height: 100%;
    border: none;
    background: white;
  }

  .viewer-image-wrap {
    padding: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    overflow: auto;
  }

  .viewer-image {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 8px;
  }

  .viewer-sidebar {
    background: linear-gradient(180deg, #f8f1e8 0%, #f3eadc 100%);
    border-left: 1px solid rgba(35,26,17,0.08);
    padding: 28px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 18px;
  }

  .viewer-sidebar-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 12px;
  }

  /* ═══ Detail sheet (links/notes) ═══ */
  .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-screenshot {
    display: block; border-radius: 14px; overflow: hidden;
    margin-bottom: 16px; border: 1px solid rgba(35,26,17,0.08);
  }
  .detail-screenshot img {
    width: 100%; height: auto; display: block; max-height: 300px; object-fit: cover;
  }
  .detail-screenshot:hover { opacity: 0.95; }

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

  .meta-folder-pill {
    background: rgba(35,26,17,0.06); padding: 2px 10px;
    border-radius: 999px; font-weight: 600;
  }

  .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-extracted {
    margin-bottom: 16px;
    padding: 14px 16px;
    background: rgba(255,255,255,0.5);
    border-radius: 14px;
    border: 1px solid rgba(35,26,17,0.06);
  }
  .extracted-label {
    font-size: 10px; text-transform: uppercase;
    letter-spacing: 0.1em; color: #8c7b69;
    margin-bottom: 8px;
  }
  .extracted-body {
    font-size: 0.88rem; color: #3d342c; line-height: 1.6;
    white-space: pre-wrap; word-break: break-word;
    font-family: var(--mono);
  }

  .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; }
    .brain-sidebar {
      display: none;
      position: fixed; left: 0; top: 0; bottom: 0; z-index: 50;
      width: 280px; box-shadow: 8px 0 24px rgba(0,0,0,0.1);
    }
    .brain-sidebar.mobile-open { display: flex; }
    .mobile-sidebar-overlay {
      position: fixed; inset: 0; z-index: 49;
      background: rgba(17,13,10,0.3);
    }
    .brain-layout { margin: 0; }
    .masonry { columns: 1; }
    .detail-sheet { width: 100%; padding: 20px; }
    .viewer-overlay { padding: 0; }
    .viewer-layout { grid-template-columns: 1fr; grid-template-rows: 55vh 1fr; width: 100%; height: 100vh; border-radius: 0; max-width: 100%; }
    .viewer-sidebar { max-height: none; border-left: none; border-top: 1px solid rgba(35,26,17,0.08); overflow-y: auto; }
  }
</style>
