threadshelf 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +185 -0
  2. package/LICENSE +21 -0
  3. package/README.md +763 -0
  4. package/SECURITY.md +75 -0
  5. package/bin/threadshelf-mcp.js +12 -0
  6. package/bin/threadshelf.js +87 -0
  7. package/dist/mcp/server.js +388 -0
  8. package/dist/src/chunking.js +72 -0
  9. package/dist/src/cli.js +24 -0
  10. package/dist/src/embedding.js +59 -0
  11. package/dist/src/env.js +2 -0
  12. package/dist/src/generation/config.js +344 -0
  13. package/dist/src/generation/downloader.js +172 -0
  14. package/dist/src/generation/error-log.js +34 -0
  15. package/dist/src/generation/filesystem-browser.js +83 -0
  16. package/dist/src/generation/gguf-metadata.js +179 -0
  17. package/dist/src/generation/hardware.js +87 -0
  18. package/dist/src/generation/llama-install.js +563 -0
  19. package/dist/src/generation/llama-process.js +576 -0
  20. package/dist/src/generation/llama-profile.js +136 -0
  21. package/dist/src/generation/master-prompts.js +155 -0
  22. package/dist/src/generation/model-catalog.js +276 -0
  23. package/dist/src/generation/model-discovery.js +60 -0
  24. package/dist/src/generation/model-download.js +151 -0
  25. package/dist/src/generation/openai-compatible.js +231 -0
  26. package/dist/src/generation/providers/llama-cpp.js +97 -0
  27. package/dist/src/generation/providers/openrouter.js +106 -0
  28. package/dist/src/generation/quick-setup.js +215 -0
  29. package/dist/src/generation/registry.js +23 -0
  30. package/dist/src/generation/service.js +100 -0
  31. package/dist/src/generation/threads.js +311 -0
  32. package/dist/src/generation/types.js +1 -0
  33. package/dist/src/ingest-cli.js +95 -0
  34. package/dist/src/ingest.js +257 -0
  35. package/dist/src/load-env.js +17 -0
  36. package/dist/src/model-label.js +15 -0
  37. package/dist/src/parser.js +811 -0
  38. package/dist/src/paths.js +79 -0
  39. package/dist/src/routes/collections.js +97 -0
  40. package/dist/src/routes/files.js +136 -0
  41. package/dist/src/routes/generation.js +536 -0
  42. package/dist/src/routes/health.js +6 -0
  43. package/dist/src/routes/index.js +21 -0
  44. package/dist/src/routes/ingest.js +300 -0
  45. package/dist/src/routes/insights.js +24 -0
  46. package/dist/src/routes/loopback.js +15 -0
  47. package/dist/src/routes/model-catalog.js +178 -0
  48. package/dist/src/routes/search.js +57 -0
  49. package/dist/src/routes/stream-abort.js +23 -0
  50. package/dist/src/routes/thread.js +43 -0
  51. package/dist/src/search-cli.js +93 -0
  52. package/dist/src/server.js +78 -0
  53. package/dist/src/services/collections.js +58 -0
  54. package/dist/src/services/insights.js +111 -0
  55. package/dist/src/services/search.js +68 -0
  56. package/dist/src/services/stats.js +35 -0
  57. package/dist/src/services/thread.js +140 -0
  58. package/dist/src/store.js +1138 -0
  59. package/dist/src/validation.js +250 -0
  60. package/dist/src/watch.js +83 -0
  61. package/package.json +103 -0
  62. package/public/assets/index-CIm_Idqi.js +38 -0
  63. package/public/assets/index-Dv09K2vS.css +1 -0
  64. package/public/favicon.svg +6 -0
  65. package/public/index.html +28 -0
  66. package/scripts/openrouter-export-all.js +228 -0
  67. package/scripts/openrouter-export-browser.js +153 -0
@@ -0,0 +1 @@
1
+ :root{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--bg-0:oklch(15.5% .005 240);--bg-1:oklch(18% .006 240);--bg-2:oklch(21.5% .007 240);--bg-3:oklch(25% .008 240);--bg-hover:oklch(23.5% .008 240);--border-0:oklch(27% .008 240);--border-1:oklch(33% .01 240);--border-2:oklch(42% .012 240);--text-0:oklch(96.5% .005 240);--text-1:oklch(82% .008 240);--text-2:oklch(62% .01 240);--text-3:oklch(46% .01 240);--text-4:oklch(34% .01 240);--accent:oklch(78% .13 215);--accent-soft:oklch(78% .13 215/.14);--accent-border:oklch(78% .13 215/.35);--accent-ink:oklch(18% .04 240);--danger:oklch(70% .16 25);--danger-soft:oklch(70% .16 25/.14);--success:oklch(74% .13 155);--success-soft:oklch(74% .13 155/.14);--warning:oklch(78% .15 75);--warning-soft:oklch(78% .15 75/.14);--role-user:oklch(78% .1 230);--role-reasoning:oklch(80% .13 75);--role-response:oklch(76% .11 155);--p-google:oklch(70% .13 250);--p-openrouter:oklch(72% .15 320);--p-openai:oklch(74% .13 155);--p-claude:oklch(76% .13 55);--p-lmstudio:oklch(72% .12 200);--p-grok:oklch(70% .02 260);--sidebar-bg:oklch(16% .005 240/.6);--sidebar-rail-bg:oklch(15.5% .005 240/.7);--topbar-bg:oklch(16.5% .005 240/.85);--thread-bar-bg:oklch(16% .005 240/.88);--thread-glow-2:oklch(20% .02 240/.4);--empty-bg:oklch(17% .005 240/.5);--overlay-bg:oklch(8% .004 240/.58);--scrim-bg:oklch(10% .005 240/.55);--code-bg:oklch(0% 0 0/.25);--dialog-shadow:0 30px 80px -20px oklch(0% 0 0/.7);--reasoning-bg:oklch(18% .012 75/.3);--reasoning-bg-strong:oklch(18% .012 75/.45);--reasoning-bg-pill:oklch(18% .012 75/.6);--reasoning-border:oklch(80% .13 75/.18);--reasoning-border-strong:oklch(80% .13 75/.35);--reasoning-border-active:oklch(80% .13 75/.5);--glow-1:oklch(22% .04 230/.5);--glow-2:oklch(20% .04 280/.35);--glow-reading:oklch(21% .03 250/.4);--font-sans:Aptos, "Segoe UI Variable", "Segoe UI", ui-sans-serif, system-ui, sans-serif;--font-mono:"Cascadia Code", "SFMono-Regular", Consolas, ui-monospace, monospace;--fs-micro:11px;--fs-meta:11.5px;--r-xs:4px;--r-sm:6px;--r-md:8px;--r-lg:12px;--r-xl:16px;--row-h:32px;--pad-x:14px;--pad-y:10px}[data-theme=light]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--bg-0:oklch(98.5% .002 240);--bg-1:oklch(96.5% .003 240);--bg-2:oklch(94% .004 240);--bg-3:oklch(91% .005 240);--bg-hover:oklch(94.5% .005 240);--border-0:oklch(90% .005 240);--border-1:oklch(84% .007 240);--border-2:oklch(74% .01 240);--text-0:oklch(23% .012 240);--text-1:oklch(34% .012 240);--text-2:oklch(48% .012 240);--text-3:oklch(60% .012 240);--text-4:oklch(72% .01 240);--accent:oklch(60% .13 220);--accent-soft:oklch(60% .13 220/.12);--accent-border:oklch(60% .13 220/.4);--accent-ink:oklch(99% .01 220);--danger:oklch(55% .19 25);--danger-soft:oklch(55% .19 25/.12);--success:oklch(52% .13 155);--success-soft:oklch(52% .13 155/.13);--warning:oklch(60% .15 75);--warning-soft:oklch(60% .15 75/.14);--role-user:oklch(55% .13 230);--role-reasoning:oklch(58% .14 75);--role-response:oklch(52% .12 155);--p-google:oklch(52% .15 250);--p-openrouter:oklch(55% .18 320);--p-openai:oklch(52% .13 155);--p-claude:oklch(55% .14 55);--p-lmstudio:oklch(54% .13 200);--p-grok:oklch(50% .03 260);--sidebar-bg:oklch(97.5% .003 240/.75);--sidebar-rail-bg:oklch(97% .003 240/.82);--topbar-bg:oklch(98.5% .003 240/.85);--thread-bar-bg:oklch(98.5% .003 240/.92);--thread-glow-2:oklch(93% .03 240/.9);--empty-bg:oklch(97% .006 240/.9);--overlay-bg:oklch(38% .02 240/.18);--scrim-bg:oklch(40% .02 240/.18);--code-bg:oklch(94% .01 240/.95);--dialog-shadow:0 24px 64px -28px oklch(38% .02 240/.28);--reasoning-bg:oklch(95% .03 85/.72);--reasoning-bg-strong:oklch(94% .035 85/.84);--reasoning-bg-pill:oklch(91% .05 85/.92);--reasoning-border:oklch(82% .06 85/.45);--reasoning-border-strong:oklch(78% .07 85/.62);--reasoning-border-active:oklch(72% .08 85/.78);--glow-1:oklch(86% .06 230/.5);--glow-2:oklch(86% .06 285/.4);--glow-reading:oklch(88% .05 250/.45)}*,:before,:after{box-sizing:border-box}html,body,#root{height:100%}body{background:var(--bg-0);color:var(--text-0);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;margin:0;font-size:15px;line-height:1.5;overflow:hidden}button{cursor:pointer;font-family:inherit}input,textarea,select{color:inherit;font-family:inherit}::selection{background:var(--accent-soft);color:var(--text-0)}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--border-0);background-clip:padding-box;border:2px solid #0000;border-radius:99px}::-webkit-scrollbar-thumb:hover{background:var(--border-2);background-clip:padding-box;border:2px solid #0000}.mono{font-family:var(--font-mono)}[hidden]{display:none!important}.app{background:radial-gradient(1200px 600px at 80% -10%, var(--glow-1), transparent 60%), radial-gradient(900px 500px at -10% 110%, var(--glow-2), transparent 60%), var(--bg-0);grid-template-columns:248px 1fr;width:100%;height:100dvh;transition:grid-template-columns .22s cubic-bezier(.4,0,.2,1);display:grid}.app[data-reading=true]{background:radial-gradient(1400px 700px at 50% -10%, var(--glow-reading), transparent 65%), var(--bg-0)}.sidebar-scrim{display:none}.sidebar.rail{background:var(--sidebar-rail-bg);border-right:1px solid var(--border-0);flex-direction:column;padding:0;display:flex}.rail-brand{border-bottom:1px solid var(--border-0);align-items:center;gap:9px;height:52px;padding:0 12px;display:flex}.rail-brand .name{letter-spacing:-.005em;color:var(--text-1);font-size:12.5px;font-weight:500}.rail-nav{flex-direction:column;flex:none;gap:1px;padding:8px 8px 4px;display:flex}.rail-item{border-radius:var(--r-sm);height:30px;color:var(--text-2);cursor:pointer;text-align:left;background:0 0;border:0;grid-template-columns:18px 1fr;align-items:center;gap:9px;padding:0 9px;font-size:12.5px;display:grid;position:relative}.rail-item .ico-wrap{color:var(--text-2);place-items:center;display:grid}.rail-item:hover{background:var(--bg-1);color:var(--text-0)}.rail-item:hover .ico-wrap{color:var(--text-0)}.rail-item[data-active=true]{background:var(--bg-2);color:var(--text-0)}.rail-item[data-active=true] .ico-wrap{color:var(--accent)}.rail-item[data-active=true]:before{content:"";background:var(--accent);border-radius:99px;width:2px;position:absolute;top:6px;bottom:6px;left:-8px}.rail-sep-h{font-family:var(--font-mono);font-size:var(--fs-meta);text-transform:uppercase;letter-spacing:.1em;color:var(--text-4);padding:10px 14px 4px}.rail-colls{flex-direction:column;flex:1;gap:1px;padding:0 8px 12px;display:flex;overflow:auto}.rail-coll-row{grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:4px;display:grid}.rail-coll{border-radius:var(--r-sm);cursor:pointer;text-align:left;height:28px;color:var(--text-2);background:0 0;border:0;grid-template-columns:8px 1fr;align-items:center;gap:10px;padding:0 9px;font-size:12px;display:grid;position:relative}.rail-coll i{background:var(--border-2);border-radius:99px;width:8px;height:8px;display:block}.rail-coll span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.rail-coll:hover{background:var(--bg-1);color:var(--text-0)}.rail-coll[data-active=true]{background:var(--bg-2);color:var(--text-0)}.rail-coll-delete{width:26px;height:26px;color:var(--text-3);background:0 0;border:0;border-radius:4px;place-items:center;padding:0;display:grid}.rail-coll-delete:hover{background:var(--danger-soft);color:var(--danger)}.rail-foot{border-top:1px solid var(--border-0);font-size:var(--fs-meta);color:var(--text-3);font-family:var(--font-mono);justify-content:space-between;align-items:center;margin-top:auto;padding:10px 12px;display:flex}.sidebar{border-right:1px solid var(--border-0);background:var(--sidebar-bg);-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);flex-direction:column;min-width:0;display:flex}.sb-brand{border-bottom:1px solid var(--border-0);align-items:center;gap:9px;height:40px;padding:0 12px;display:flex}.sb-logo{background:linear-gradient(140deg, var(--accent), oklch(55% .16 280));width:26px;height:26px;box-shadow:0 6px 20px -10px var(--accent), inset 0 0 0 1px oklch(100% 0 0/.1);border-radius:7px;flex-shrink:0;place-items:center;display:grid;position:relative}.sb-logo:after{content:"";border:1.5px solid var(--accent-ink);border-bottom-color:#0000;border-radius:99px;width:10px;height:10px;transform:rotate(-30deg)}.sb-name{flex-direction:column;gap:0;min-width:0;line-height:1.15;display:flex}.sb-name b{letter-spacing:-.01em;font-weight:600}.sb-name span{font-size:var(--fs-meta);color:var(--text-3);font-family:var(--font-mono)}.sb-chat-panel{border:1px solid var(--border-0);border-radius:var(--r-lg);background:color-mix(in oklch, var(--bg-1) 82%, transparent);min-width:0;margin:10px 8px 2px;overflow:hidden}.sb-chat-create{grid-template-columns:minmax(0,1fr) 36px;gap:6px;margin:6px;display:grid}.sb-new-chat{border:1px solid var(--accent-border);border-radius:var(--r-md);background:var(--accent);min-height:36px;color:var(--accent-ink);text-align:left;box-shadow:0 10px 28px -18px var(--accent);grid-template-columns:16px minmax(0,1fr);align-items:center;gap:9px;padding:0 10px;font-size:13px;font-weight:600;display:grid}.sb-new-chat span{min-width:0}.sb-new-chat:hover{filter:brightness(1.06)}.sb-private-chat{border:1px solid var(--border-1);border-radius:var(--r-md);background:var(--bg-1);width:36px;height:36px;color:var(--text-1);place-items:center;padding:0;display:grid}.sb-private-chat:hover{border-color:var(--accent-border);background:var(--accent-soft);color:var(--accent-ink)}.sb-chat-history{min-width:0;margin:0 4px 4px}.sb-chat-history-toggle{border-radius:var(--r-sm);width:100%;min-height:34px;color:var(--text-2);text-align:left;background:0 0;border:1px solid #0000;grid-template-columns:18px minmax(0,1fr) auto 14px;align-items:center;gap:7px;padding:0 7px;display:grid}.sb-chat-history-toggle .ico{place-items:center;display:grid}.sb-chat-history-toggle .label{min-width:0;font-size:12.5px;font-weight:500}.sb-chat-history-toggle em{min-width:18px;color:var(--text-3);text-align:right;font:var(--fs-meta) var(--font-mono);font-style:normal}.sb-chat-history-toggle:hover,.sb-chat-history-toggle[aria-expanded=true]{border-color:var(--border-0);background:var(--bg-1);color:var(--text-0)}.sb-chat-chevron{color:var(--text-3);place-items:center;font-size:13px;transition:transform .16s;display:grid}.sb-chat-history-toggle[aria-expanded=true] .sb-chat-chevron{transform:rotate(180deg)}.sb-chat-history-list{flex-direction:column;gap:2px;min-height:0;max-height:min(30dvh,260px);margin-top:2px;padding:3px;display:flex;overflow-y:auto}.sb-chat-item{border-radius:var(--r-sm);min-width:0;color:var(--text-2);text-align:left;background:0 0;border:1px solid #0000;flex-direction:column;gap:3px;padding:7px 8px;display:flex}.sb-chat-item:hover{background:var(--bg-2)}.sb-chat-item[data-active=true]{border-color:var(--accent-border);background:var(--accent-soft)}.sb-chat-item strong{color:var(--text-1);overflow-wrap:anywhere;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:12.5px;font-weight:500;line-height:1.3;display:-webkit-box;overflow:hidden}.sb-chat-item span{color:var(--text-3);font:var(--fs-micro) var(--font-mono);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sb-chat-history-empty{color:var(--text-4);font:var(--fs-meta) var(--font-mono);padding:10px 8px}.sb-cmdk{border:1px solid var(--border-0);background:var(--bg-1);border-radius:var(--r-sm);height:30px;color:var(--text-2);white-space:nowrap;align-items:center;gap:8px;margin:8px 12px 4px;padding:0 8px 0 9px;font-size:12px;display:flex}.sb-cmdk>span{text-align:left;text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.sb-cmdk svg{flex:none}.sb-cmdk:hover{border-color:var(--border-1);background:var(--bg-2);color:var(--text-1)}.sb-cmdk kbd{font-family:var(--font-mono);font-size:var(--fs-meta);border:1px solid var(--border-0);background:var(--bg-2);color:var(--text-2);border-radius:4px;margin-left:auto;padding:2px 5px}.sb-section{font-size:var(--fs-meta);font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;color:var(--text-3);justify-content:space-between;align-items:center;padding:12px 14px 4px;display:flex}.sb-section button{color:var(--text-2);background:0 0;border:0;border-radius:4px;place-items:center;width:18px;height:18px;padding:0;display:grid}.sb-section button:hover{background:var(--bg-2);color:var(--text-0)}.sb-list{flex-direction:column;flex:none;gap:1px;padding:2px 8px;display:flex;overflow:auto}.sb-collections{scrollbar-gutter:stable;flex:0 auto;min-height:0;max-height:min(36dvh,360px);padding-bottom:8px;overflow-y:auto}.sb-manage-section{border-top:1px solid var(--border-0);margin-top:auto}.sb-manage-list{padding-bottom:8px}.sb-item{height:var(--row-h);border-radius:var(--r-sm);color:var(--text-1);text-align:left;cursor:pointer;background:0 0;border:0;grid-template-columns:16px 1fr auto;align-items:center;gap:9px;padding:0 8px;font-size:12.8px;display:grid;position:relative}.sb-item:hover{background:var(--bg-1);color:var(--text-0)}.sb-item[data-active=true]{background:var(--bg-2);color:var(--text-0)}.sb-item[data-active=true]:before{content:"";background:var(--accent);border-radius:99px;width:2px;position:absolute;top:6px;bottom:6px;left:-8px}.sb-item[data-active=true] .ico{color:var(--accent)}.sb-item .ico{width:14px;height:14px;color:var(--text-2);display:inline-flex}.sb-item .label{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.sb-item .count{font-family:var(--font-mono);font-size:var(--fs-meta);color:var(--text-3)}.sb-coll-row{grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:4px;display:grid}.sb-coll{border-radius:var(--r-sm);cursor:pointer;text-align:left;color:var(--text-1);background:0 0;border:0;grid-template-columns:14px 1fr auto;align-items:center;gap:9px;width:100%;padding:6px 10px 6px 8px;display:grid;position:relative}.sb-coll:hover{background:var(--bg-1);color:var(--text-0)}.sb-coll[data-active=true]{background:var(--bg-2);color:var(--text-0)}.sb-coll[data-active=true]:before{content:"";background:var(--accent);border-radius:99px;width:2px;position:absolute;top:8px;bottom:8px;left:-8px}.sb-coll-dot{background:var(--border-2);border-radius:99px;flex-shrink:0;width:8px;height:8px}.sb-coll-meta{flex-direction:column;gap:1px;min-width:0;display:flex}.sb-coll-meta b{text-overflow:ellipsis;white-space:nowrap;font-size:12.8px;font-weight:500;overflow:hidden}.sb-coll-meta span{font-size:var(--fs-meta);color:var(--text-3);font-family:var(--font-mono);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sb-coll-delete{width:26px;height:26px;color:var(--text-3);background:0 0;border:0;border-radius:4px;place-items:center;padding:0;display:grid}.sb-coll-delete:hover{background:var(--danger-soft);color:var(--danger)}.sb-coll-providers{align-items:center;gap:3px;display:flex}.sb-coll-providers i{background:var(--border-2);border-radius:99px;width:6px;height:6px;display:block}.sb-coll-providers i.google{background:var(--p-google)}.sb-coll-providers i.openrouter{background:var(--p-openrouter)}.sb-coll-providers i.openai{background:var(--p-openai)}.sb-coll-providers i.claude{background:var(--p-claude)}.sb-footer{border-top:1px solid var(--border-0);font-size:var(--fs-meta);color:var(--text-3);font-family:var(--font-mono);flex-direction:column;gap:6px;margin-top:auto;padding:10px 12px;display:flex}.sb-footer-row{justify-content:space-between;align-items:center;gap:8px;display:flex}.sb-status{color:var(--text-2);align-items:center;gap:6px;display:inline-flex}.sb-status:before{content:"";background:var(--success);width:6px;height:6px;box-shadow:0 0 0 3px var(--success-soft);border-radius:99px}.sb-status.offline:before{background:var(--danger);box-shadow:0 0 0 3px var(--danger-soft)}.topbar{z-index:10;border-bottom:1px solid var(--border-0);background:var(--topbar-bg);-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);flex:none;align-items:center;gap:12px;height:48px;padding:0 16px;display:flex;position:relative}.crumbs{color:var(--text-2);align-items:center;gap:6px;font-size:12.5px;display:flex}.crumbs b{color:var(--text-0);font-weight:500}.crumbs .sep{color:var(--text-4)}.topbar-spacer{flex:1}.topbar-actions{align-items:center;gap:6px;display:flex}.topbar-action{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-1);height:30px;color:var(--text-2);white-space:nowrap;align-items:center;gap:7px;padding:0 10px;font-size:12px;display:inline-flex}.topbar-action em{color:var(--text-4);font:var(--fs-micro) var(--font-mono);font-style:normal}.topbar-action:hover,.topbar-action[aria-expanded=true]{border-color:var(--border-1);background:var(--bg-2);color:var(--text-0)}.topbar-action.primary{border-color:var(--accent-border);background:var(--accent-soft);color:var(--accent)}.topbar-action.icon-only{justify-content:center;width:30px;padding:0}.icon-btn{border-radius:var(--r-sm);width:32px;height:32px;color:var(--text-2);background:0 0;border:1px solid #0000;place-items:center;padding:0;display:grid}.icon-btn:hover{background:var(--bg-2);color:var(--text-0);border-color:var(--border-0)}.icon-btn.mobile-menu-btn{flex:none;display:none}.main{flex-direction:column;min-width:0;height:100%;min-height:0;display:flex;overflow:hidden}.main-scroll{flex:1;min-height:0;overflow:auto}.view{flex-direction:column;gap:18px;width:100%;max-width:1040px;margin:0 auto;padding:clamp(22px,3vw,44px) clamp(24px,4vw,56px) 96px;display:flex}.btn{background:var(--bg-2);height:32px;color:var(--text-0);border:1px solid var(--border-1);border-radius:var(--r-sm);white-space:nowrap;cursor:pointer;align-items:center;gap:7px;padding:0 12px;font-family:inherit;font-size:12.5px;display:inline-flex}.btn:hover{background:var(--bg-3);border-color:var(--border-2)}.btn svg{width:13px;height:13px}.btn.primary{background:var(--accent);color:var(--accent-ink);box-shadow:0 8px 20px -10px var(--accent);border-color:oklch(85% .13 215);font-weight:500}.btn.primary:hover{background:oklch(82% .13 215)}.btn.ghost{color:var(--text-2);background:0 0;border-color:#0000}.btn.ghost:hover{background:var(--bg-2);color:var(--text-0);border-color:var(--border-0)}.btn.danger{color:var(--danger);background:0 0;border-color:oklch(70% .16 25/.3)}.btn.danger:hover{background:var(--danger-soft);border-color:oklch(70% .16 25/.5)}.btn.sm{gap:5px;height:26px;padding:0 9px;font-size:11.5px}.btn[disabled]{opacity:.4;pointer-events:none}.section-h{align-items:baseline;gap:12px;display:flex}.section-h h2{letter-spacing:-.015em;margin:0;font-size:18px;font-weight:500}.section-h .desc{color:var(--text-2);font-size:12.5px}.panel{border:1px solid var(--border-0);background:var(--bg-1);border-radius:var(--r-lg);overflow:hidden}.panel-head{border-bottom:1px solid var(--border-0);background:linear-gradient(180deg, var(--bg-2), transparent);align-items:center;gap:10px;padding:12px 16px;display:flex}.panel-head h3{letter-spacing:-.005em;margin:0;font-size:13.5px;font-weight:500}.panel-head .sub{color:var(--text-3);font-size:11.5px;font-family:var(--font-mono)}.panel-body{padding:16px}.stat-grid{background:var(--border-0);border-bottom:1px solid var(--border-0);grid-template-columns:repeat(4,1fr);gap:1px;display:grid}.stat{background:var(--bg-1);flex-direction:column;gap:4px;padding:14px 16px;display:flex}.stat .k{font-family:var(--font-mono);font-size:var(--fs-meta);text-transform:uppercase;letter-spacing:.08em;color:var(--text-3)}.stat .v{font-family:var(--font-mono);letter-spacing:-.02em;color:var(--text-0);font-variant-numeric:tabular-nums;font-size:22px}.stat .d{color:var(--text-3);font-size:11px;font-family:var(--font-mono)}.banner{border-radius:var(--r-md);border:1px solid;align-items:center;gap:10px;padding:9px 14px;font-size:12.5px;display:flex}.banner.warn{background:var(--warning-soft);color:oklch(85% .1 75);border-color:oklch(78% .15 75/.3)}.banner.info{background:var(--accent-soft);border-color:var(--accent-border);color:var(--text-0)}.banner.err{background:var(--danger-soft);color:oklch(85% .1 25);border-color:oklch(70% .16 25/.35)}.banner .grow{flex:1}.banner code{font-family:var(--font-mono);background:var(--code-bg);border-radius:4px;padding:1px 5px;font-size:11.5px}.scrim{background:var(--scrim-bg);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);z-index:100;place-items:start center;padding-top:14vh;display:grid;position:fixed;inset:0}.scrim[hidden]{display:none}.cmdk{background:var(--bg-1);border:1px solid var(--border-1);border-radius:var(--r-lg);width:min(640px,92vw);box-shadow:var(--dialog-shadow);flex-direction:column;display:flex;overflow:hidden}.cmdk-input{border-bottom:1px solid var(--border-0);grid-template-columns:38px 1fr auto;align-items:center;height:48px;display:grid}.cmdk-input svg{width:17px;height:17px;color:var(--text-2);justify-self:center}.cmdk-input input{color:var(--text-0);background:0 0;border:0;outline:0;font-family:inherit;font-size:15px}.cmdk-input kbd{font-family:var(--font-mono);font-size:var(--fs-meta);border:1px solid var(--border-0);color:var(--text-2);border-radius:4px;margin-right:12px;padding:2px 6px}.cmdk-list{max-height:50vh;padding:6px;overflow:auto}.cmdk-group-h{font-family:var(--font-mono);font-size:var(--fs-meta);text-transform:uppercase;letter-spacing:.08em;color:var(--text-3);padding:8px 10px 4px}.cmdk-item{border-radius:var(--r-sm);text-align:left;width:100%;height:34px;color:var(--text-1);cursor:pointer;background:0 0;border:0;grid-template-columns:18px 1fr auto;align-items:center;gap:10px;padding:0 10px;font-family:inherit;font-size:13px;display:grid}.cmdk-item:hover,.cmdk-item[data-active=true]{background:var(--bg-2);color:var(--text-0)}.cmdk-item svg{color:var(--text-2);width:14px;height:14px}.cmdk-item .meta{font-family:var(--font-mono);font-size:var(--fs-meta);color:var(--text-3)}.modal-card{background:var(--bg-1);border:1px solid var(--border-1);border-radius:var(--r-lg);width:min(480px,92vw);box-shadow:var(--dialog-shadow);overflow:hidden}.modal-head{border-bottom:1px solid var(--border-0);padding:14px 16px}.modal-head h3{margin:0;font-size:15px;font-weight:500}.modal-head p{color:var(--text-2);margin:4px 0 0;font-size:12.5px}.modal-body{flex-direction:column;gap:10px;padding:14px 16px;display:flex}.modal-body label{color:var(--text-2);font-size:12px}.modal-body input{border-radius:var(--r-sm);border:1px solid var(--border-0);background:var(--bg-2);outline:0;height:32px;padding:0 10px;font-size:12.5px}.modal-body input:focus{border-color:var(--accent-border)}.modal-foot{border-top:1px solid var(--border-0);justify-content:flex-end;gap:8px;padding:12px 16px;display:flex}.theme-toggle{border-radius:var(--r-sm);color:var(--text-2);cursor:pointer;background:0 0;border:1px solid #0000;align-items:center;gap:7px;font-family:inherit;display:inline-flex}.theme-toggle .tt-ico{place-items:center;display:grid}.theme-toggle:hover{background:var(--bg-2);color:var(--text-0);border-color:var(--border-0)}.theme-toggle.icon{place-content:center;width:26px;height:26px;padding:0}.theme-toggle.full{height:28px;padding:0 10px;font-size:12px}.toaster{z-index:200;flex-direction:column;gap:8px;max-width:min(380px,92vw);display:flex;position:fixed;bottom:18px;right:18px}.toast{border-radius:var(--r-md);border:1px solid var(--border-1);background:var(--bg-2);color:var(--text-0);text-align:left;grid-template-columns:18px 1fr;align-items:center;gap:10px;padding:11px 14px;font-size:12.5px;animation:.18s cubic-bezier(.2,.8,.2,1) toast-in;display:grid;box-shadow:0 16px 40px -16px oklch(0% 0 0/.6)}.toast .toast-ico{color:var(--text-2);place-items:center;display:grid}.toast .toast-text{min-width:0}.toast[data-type=success]{border-color:var(--success)}.toast[data-type=success] .toast-ico{color:var(--success)}.toast[data-type=error]{border-color:var(--danger)}.toast[data-type=error] .toast-ico{color:var(--danger)}.toast[data-type=info]{border-color:var(--accent-border)}.toast[data-type=info] .toast-ico{color:var(--accent)}@keyframes toast-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.role-dist{border-top:1px solid var(--border-0);padding:12px 16px}.role-bar{border-radius:99px;gap:2px;height:6px;display:flex;overflow:hidden}.role-bar i{min-width:2px;display:block}.role-bar i.user{background:var(--role-user);border-radius:99px 0 0 99px}.role-bar i.thinking{background:var(--role-reasoning)}.role-bar i.ai{background:var(--role-response);border-radius:0 99px 99px 0}.role-legend{font-size:11px;font-family:var(--font-mono);color:var(--text-2);gap:16px;margin-top:8px;display:flex}.role-legend span{align-items:center;gap:5px;display:inline-flex}.role-legend i{border-radius:99px;width:6px;height:6px}.role-legend i.user{background:var(--role-user)}.role-legend i.thinking{background:var(--role-reasoning)}.role-legend i.ai{background:var(--role-response)}.file-list{max-height:300px;overflow:auto}.file-list-empty{color:var(--text-3);padding:16px;font-size:12px}.file-row{border-bottom:1px solid var(--border-0);grid-template-columns:auto 1fr;align-items:center;gap:12px;padding:8px 16px;font-size:12.5px;display:grid}.file-row i{background:var(--border-2);border-radius:99px;width:6px;height:6px}.file-row .name{font-family:var(--font-mono);color:var(--text-1);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.danger-row{border:1px solid var(--border-0);border-radius:var(--r-md);grid-template-columns:1fr auto;align-items:center;gap:16px;padding:12px 14px;display:grid}.danger-row .title{color:var(--text-0);font-size:13px;font-weight:500}.danger-row .desc{color:var(--text-2);margin-top:3px;font-size:12px}.search-card{background:var(--bg-1);border:1px solid var(--border-0);border-radius:var(--r-md);grid-template-columns:38px 1fr auto;align-items:center;min-height:50px;padding-right:6px;transition:border-color .15s,box-shadow .15s;display:grid}.search-card:focus-within{border-color:var(--accent-border);box-shadow:0 0 0 4px var(--accent-soft)}.search-card .search-ico{width:16px;height:16px;color:var(--text-2);justify-self:center}.search-card input{color:var(--text-0);letter-spacing:-.005em;background:0 0;border:0;outline:0;min-width:0;font-family:inherit;font-size:16px}.search-card input::placeholder{color:var(--text-3)}.search-card .search-clear{border-radius:var(--r-sm);width:30px;height:30px;color:var(--text-3);cursor:pointer;background:0 0;border:0;place-items:center;padding:0;display:grid}.search-card .search-clear:hover,.search-card .search-clear:focus-visible{background:var(--bg-2);color:var(--text-0)}.search-toolbar{flex-wrap:wrap;align-items:center;gap:10px;padding:0 2px;display:flex}.mode-toggle{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-1);display:inline-flex;overflow:hidden}.mode-btn{min-height:28px;color:var(--text-3);cursor:pointer;background:0 0;border:0;padding:0 12px;font-family:inherit;font-size:12.5px}.mode-btn+.mode-btn{border-left:1px solid var(--border-0)}.mode-btn[data-on=true]{color:var(--text-0);background:var(--bg-2)}.mode-btn:hover{color:var(--text-0)}.role-chips{gap:4px;display:inline-flex}.role-chip{border:1px solid var(--border-0);min-height:28px;color:var(--text-3);cursor:pointer;background:0 0;border-radius:99px;align-items:center;gap:6px;padding:0 10px;font-family:inherit;font-size:12.5px;display:inline-flex}.role-chip .dot{background:var(--text-4);border-radius:99px;width:6px;height:6px}.role-chip[data-on=true]{color:var(--text-0);border-color:var(--border-1);background:var(--bg-1)}.role-chip[data-role=user][data-on=true] .dot{background:var(--role-user)}.role-chip[data-role=reasoning][data-on=true] .dot{background:var(--role-reasoning)}.role-chip[data-role=response][data-on=true] .dot{background:var(--role-response)}.role-chip:hover{color:var(--text-0)}.model-filter{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-1);min-height:30px;color:var(--text-3);font-family:var(--font-mono);grid-template-columns:auto minmax(150px,220px);align-items:center;gap:8px;padding:0 8px;font-size:11.5px;display:inline-grid}.model-filter span{text-transform:uppercase;letter-spacing:.06em}.model-filter input{min-width:0;height:26px;color:var(--text-0);font:12.5px var(--font-sans);background:0 0;border:0;outline:0}.model-filter input::placeholder{color:var(--text-4)}.origin-filter{border-radius:var(--r-sm);min-height:30px;color:var(--text-3);font:11px var(--font-mono);background:oklch(74% .16 165/.06);border:1px solid oklch(74% .16 165/.24);grid-template-columns:auto auto;align-items:center;gap:7px;padding:0 8px;display:inline-grid}.origin-filter span{text-transform:uppercase;letter-spacing:.06em}.origin-filter select{height:26px;color:var(--text-0);font:12px var(--font-sans);background:0 0;border:0;outline:0}.date-filter{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-1);min-height:30px;color:var(--text-3);font-family:var(--font-mono);grid-template-columns:auto minmax(118px,142px);align-items:center;gap:8px;padding:0 8px;font-size:11.5px;display:inline-grid}.date-filter span{text-transform:uppercase;letter-spacing:.06em}.date-filter input{min-width:0;height:26px;color:var(--text-0);font:12.5px var(--font-sans);background:0 0;border:0;outline:0}.toolbar-spacer{flex:1}.toolbar-hint{color:var(--text-3);font-size:12px;font-family:var(--font-mono)}.toolbar-hint kbd{font-family:var(--font-mono);font-size:var(--fs-meta);border:1px solid var(--border-0);background:var(--bg-2);color:var(--text-2);border-radius:4px;margin:0 2px;padding:1px 5px}.results-meta-bar{justify-content:space-between;align-items:baseline;gap:10px;margin-top:6px;display:flex}.results-meta-bar .conv-sort{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;color:var(--text-3);align-items:center;gap:6px;font-size:11px;display:inline-flex}.results-meta-bar .conv-sort select{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-1);height:28px;color:var(--text-0);font:12.5px var(--font-sans);text-transform:none;letter-spacing:normal;outline:0;padding:0 6px}.results-meta-bar .conv-sort select:focus{border-color:var(--border-1)}.results-meta-bar .h{min-width:0;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;color:var(--text-3);flex:1;font-size:11px}.results-meta-bar .h b{color:var(--text-1);margin-left:4px;font-weight:500}.results-meta-bar .conv-filter{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-1);width:min(240px,40%);min-width:0;height:28px;color:var(--text-0);font:12.5px var(--font-sans);outline:0;padding:0 10px}.results-meta-bar .conv-filter::placeholder{color:var(--text-4)}.results-meta-bar .conv-filter:focus{border-color:var(--border-1)}.result-list{flex-direction:column;gap:8px;display:flex}.load-more-row{justify-content:center;margin-top:4px;display:flex}.load-more-button{border-radius:var(--r-sm);border:1px solid var(--border-0);background:var(--bg-1);min-height:32px;color:var(--text-1);font:12.5px var(--font-sans);cursor:pointer;padding:0 14px}.load-more-button:hover{border-color:var(--border-2);color:var(--text-0);background:var(--bg-2)}.result{border:1px solid var(--border-0);border-radius:var(--r-md);cursor:pointer;text-align:left;width:100%;color:inherit;background:0 0;grid-template-columns:minmax(0,1fr);gap:6px;padding:15px 18px 13px;font-family:inherit;transition:border-color .12s,background .12s;display:grid;position:relative}.result:hover{border-color:var(--border-1);background:var(--bg-1)}.result:hover .r-snippet{color:var(--text-0)}.result[data-active=true]{border-color:var(--accent-border);background:var(--accent-soft)}.result[data-active=true] .r-snippet{color:var(--text-0)}.result[data-selected=true]{border-color:var(--accent-border);background:var(--accent-soft);box-shadow:inset 2px 0 0 var(--accent)}.result[data-selected=true] .r-snippet{color:var(--text-0)}.open-thread{color:var(--text-2);align-items:center;gap:6px;margin-left:auto;display:inline-flex}.saved-searches{flex-wrap:wrap;align-items:center;gap:6px;margin-top:10px;display:flex}.saved-searches .ss-label{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.07em;color:var(--text-3);align-items:center;gap:5px;margin-right:4px;font-size:11px;display:inline-flex}.saved-searches .ss-chip{border:1px solid var(--border-0);background:var(--bg-1);border-radius:999px;align-items:stretch;display:inline-flex;overflow:hidden}.saved-searches .ss-chip:hover{border-color:var(--border-1)}.saved-searches .ss-run{max-width:320px;color:var(--text-1);font:12px var(--font-sans);cursor:pointer;background:0 0;border:0;align-items:center;gap:6px;padding:3px 4px 3px 10px;display:inline-flex}.saved-searches .ss-run .ss-q{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.saved-searches .ss-run .ss-tag{background:var(--bg-2);font-family:var(--font-mono);font-size:var(--fs-meta);color:var(--text-3);border-radius:999px;flex:none;padding:1px 6px}.saved-searches .ss-del{color:var(--text-4);cursor:pointer;background:0 0;border:0;padding:0 8px 0 4px;font-size:13px}.saved-searches .ss-del:hover{color:var(--danger,#e05555)}.save-search{border:1px solid var(--border-0);background:var(--bg-1);height:28px;color:var(--text-2);font:12px var(--font-sans);cursor:pointer;border-radius:999px;align-items:center;gap:6px;padding:0 10px;display:inline-flex}.save-search:hover{border-color:var(--border-1);color:var(--text-0)}.save-search[data-on=true]{color:var(--accent);border-color:var(--accent-border,var(--border-1))}.pin-toggle{border-radius:var(--r-sm);width:24px;height:24px;color:var(--text-4);cursor:pointer;opacity:0;justify-content:center;align-items:center;margin-left:auto;transition:opacity .12s,color .12s;display:inline-flex}.result:hover .pin-toggle,.result:focus-within .pin-toggle,.pin-toggle[data-on=true]{opacity:1}.pin-toggle:hover,.pin-toggle:focus-visible,.pin-toggle[data-on=true]{color:var(--accent)}.more-like-this{border:1px solid var(--line);color:var(--text-2);cursor:pointer;border-radius:999px;align-items:center;margin-left:auto;padding:2px 8px;transition:color .15s,border-color .15s;display:inline-flex}.more-like-this:hover,.more-like-this:focus-visible{color:var(--accent);border-color:var(--accent)}.more-like-this+.open-thread{margin-left:0}.result-head{align-items:center;gap:10px;min-width:0;display:flex}.r-role{font-size:11px;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;border:1px solid var(--border-0);color:var(--text-1);background:var(--bg-2);border-radius:4px;align-items:center;gap:6px;padding:2px 7px;display:inline-flex}.r-role[data-role=user]{color:var(--role-user);border-color:oklch(78% .1 230/.3)}.r-role[data-role=thinking]{color:var(--role-reasoning);border-color:oklch(80% .13 75/.3)}.r-role[data-role=ai]{color:var(--role-response);border-color:oklch(76% .11 155/.3)}.r-provider{color:var(--text-1);align-items:center;gap:6px;font-size:11.5px;display:inline-flex}.r-provider .pdot{background:var(--border-2);border-radius:99px;width:6px;height:6px}.r-source{min-width:0;color:var(--text-2);flex:260px;align-items:center;gap:6px;display:inline-flex}.r-source svg{flex:none}.r-source .slash{color:var(--text-4)}.r-source-coll{flex:none}.r-source-file{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.r-meta-right{font-family:var(--font-mono);color:var(--text-3);align-items:center;gap:12px;margin-left:auto;font-size:11px;display:inline-flex}.r-score{color:var(--text-2);align-items:center;gap:6px;display:inline-flex}.r-score-bar{background:var(--bg-3);border-radius:99px;width:36px;height:4px;position:relative;overflow:hidden}.r-score-bar i{background:linear-gradient(90deg, var(--accent), oklch(70% .16 280));border-radius:99px;height:100%;display:block}.r-title{letter-spacing:-.012em;color:var(--text-0);overflow-wrap:anywhere;min-width:0;font-size:16px;font-weight:600;line-height:1.35}.result:hover .r-title,.result:focus-visible .r-title{text-decoration:underline;-webkit-text-decoration-color:var(--accent);text-decoration-color:var(--accent);text-underline-offset:3px;text-decoration-thickness:2px}.r-snippet{color:var(--text-1);letter-spacing:-.005em;overflow-wrap:anywhere;-webkit-line-clamp:5;-webkit-box-orient:vertical;font-size:14.5px;line-height:1.58;display:-webkit-box;overflow:hidden}.r-snippet mark,.r-snippet .highlight{background:var(--accent-soft);color:var(--text-0);box-shadow:inset 0 -1px 0 var(--accent-border);border-radius:3px;padding:0 2px}.r-foot{min-width:0;color:var(--text-3);font-size:12.5px;font-family:var(--font-mono);flex-wrap:wrap;align-items:center;gap:14px;display:flex}.r-foot .dot{background:var(--text-4);border-radius:99px;width:3px;height:3px}.r-foot b{color:var(--text-1);font-weight:400}.empty{border:1px dashed var(--border-1);border-radius:var(--r-lg);background:var(--empty-bg);flex-direction:column;gap:14px;margin-top:20px;padding:36px 28px;display:flex}.empty h3{letter-spacing:-.01em;margin:0;font-size:15px;font-weight:500}.empty p{color:var(--text-2);max-width:560px;margin:0;font-size:13px}.empty .examples{flex-wrap:wrap;gap:6px;display:flex}.example-chip{border:1px solid var(--border-0);background:var(--bg-1);height:28px;color:var(--text-1);cursor:pointer;border-radius:99px;align-items:center;gap:7px;padding:0 10px;font-family:inherit;font-size:12.5px;display:inline-flex}.example-chip:hover{border-color:var(--border-2);background:var(--bg-2);color:var(--text-0)}.example-chip svg{width:12px;height:12px;color:var(--text-3)}@keyframes shimmer{0%{background-position:0 0}to{background-position:-200% 0}}.shimmer-card{opacity:.55;background:linear-gradient(90deg, var(--bg-1), var(--bg-2), var(--bg-1));border:1px solid var(--border-0);border-radius:var(--r-md);background-size:200% 100%;min-height:80px;padding:13px 16px 11px;animation:1.4s linear infinite shimmer}.thread{flex-direction:column;flex:1;min-width:0;height:100%;min-height:0;animation:.22s cubic-bezier(.4,0,.2,1) thread-in;display:flex;position:relative;overflow:hidden}.thread:before{content:"";background:linear-gradient(90deg, transparent 0%, var(--provider-color,var(--accent)) 12%, var(--provider-color,var(--accent)) 88%, transparent 100%);z-index:10;opacity:.9;height:2px;position:absolute;top:0;left:0;right:0}@keyframes thread-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.thread-bar{background:var(--thread-bar-bg);-webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);border-bottom:1px solid var(--border-0);z-index:5;flex:none;align-items:center;gap:14px;min-height:56px;padding:0 16px 0 18px;display:flex;position:sticky;top:0}.thread-bar .title-preview{letter-spacing:-.01em;min-width:0;color:var(--text-0);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:14px;font-weight:500;overflow:hidden}.thread-bar .bar-meta{font-family:var(--font-mono);color:var(--text-2);border-right:1px solid var(--border-0);flex:none;align-items:center;gap:7px;height:22px;padding-right:12px;font-size:11px;display:inline-flex}.thread-bar .bar-meta .pdot{background:var(--provider-color,var(--accent));width:6px;height:6px;box-shadow:0 0 0 2px color-mix(in oklch, var(--provider-color,var(--accent)) 25%, transparent);border-radius:99px}.thread-bar .bar-model{color:var(--text-1);white-space:nowrap}.thread-bar .path-crumb{font-family:var(--font-mono);color:var(--text-3);text-overflow:ellipsis;white-space:nowrap;flex:0 auto;max-width:340px;font-size:11px;overflow:hidden}.thread-bar .path-crumb .coll{color:var(--text-2)}.thread-bar .path-crumb .sl{color:var(--text-4);margin:0 5px}.thread-bar kbd{font-family:var(--font-mono);font-size:var(--fs-meta);border:1px solid var(--border-0);background:var(--bg-2);color:var(--text-2);border-radius:4px;padding:2px 5px}.thread-back{background:var(--bg-2);border:1px solid var(--border-1);border-radius:var(--r-sm);height:32px;color:var(--text-0);flex:none;align-items:center;gap:8px;padding:0 12px 0 9px;font-family:inherit;font-size:12.5px;font-weight:500;display:inline-flex}.thread-back:hover{background:var(--bg-3);border-color:var(--border-2)}.thread-back svg{width:14px;height:14px}.thread-inner{background:radial-gradient(900px 380px at 50% 0%, color-mix(in oklch, var(--provider-color,var(--accent)) 14%, transparent), transparent 70%), radial-gradient(800px 400px at 50% 0%, var(--thread-glow-2), transparent 60%);flex-direction:column;flex:auto;align-items:center;min-height:0;display:flex;overflow:auto}.thread-hero{flex-direction:column;gap:16px;width:100%;max-width:960px;padding:clamp(28px,4vw,52px) clamp(24px,4vw,56px) 28px;display:flex}.thread-hero h1{letter-spacing:-.025em;color:var(--text-0);margin:0;font-size:clamp(30px,2.3vw,48px);font-weight:500;line-height:1.18}.thread-hero .meta-row{font-family:var(--font-mono);color:var(--text-2);border-top:1px solid var(--border-0);flex-wrap:wrap;align-items:center;gap:8px 14px;margin-top:6px;padding-top:4px;font-size:11.5px;display:flex}.thread-hero .meta-row .item{align-items:baseline;gap:6px;display:inline-flex}.thread-hero .meta-row .k{color:var(--text-4)}.thread-hero .meta-row .v{color:var(--text-1)}.thread-hero .meta-row .v.match{color:var(--accent)}.thread-hero .meta-row .sep{color:var(--text-4)}.thread-actions-bar{flex-wrap:wrap;align-items:center;gap:8px;width:100%;max-width:960px;padding:0 clamp(24px,4vw,56px) 16px;display:flex}.role-toggles{background:var(--bg-1);border:1px solid var(--border-0);border-radius:var(--r-sm);gap:2px;padding:2px;display:inline-flex}.role-toggle{height:22px;color:var(--text-3);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:4px;align-items:center;gap:6px;padding:0 8px;font-size:11.5px;display:inline-flex;position:relative}.role-toggle input{opacity:0;pointer-events:none;position:absolute}.role-toggle .rt-dot{background:var(--text-4);border-radius:99px;width:6px;height:6px;transition:background .15s}.role-toggle:hover{color:var(--text-1)}.role-toggle[data-on=true]{background:var(--bg-3);color:var(--text-0);box-shadow:inset 0 0 0 1px var(--border-1)}.role-toggle[data-on=true][data-role=user] .rt-dot{background:var(--role-user)}.role-toggle[data-on=true][data-role=thinking] .rt-dot{background:var(--role-reasoning)}.role-toggle[data-on=true][data-role=ai] .rt-dot{background:var(--role-response)}.role-toggle[data-on=true][data-role=threadshelf] .rt-dot{background:oklch(74% .16 165)}.turn-stub{grid-template-columns:44px 1fr;align-items:start}.turn-stub .reasoning-stub{border:1px dashed var(--reasoning-border-strong);height:24px;color:var(--text-3);font-size:11px;font-family:var(--font-mono);cursor:pointer;background:0 0;border-radius:99px;grid-column:2;place-self:start;align-items:center;gap:8px;margin-top:2px;margin-left:0;padding:0 10px 0 4px;display:inline-flex}.turn-stub .reasoning-stub:hover{color:var(--text-1);border-color:var(--reasoning-border-active);background:var(--reasoning-bg)}.turn-stub .reasoning-stub .rs-r{background:var(--reasoning-bg-pill);width:18px;height:18px;color:var(--role-reasoning);font-weight:500;font-size:var(--fs-meta);border:1px solid var(--reasoning-border-strong);border-radius:99px;place-items:center;display:inline-grid}.turn-stub .reasoning-stub .rs-label{text-transform:lowercase;letter-spacing:0}.turn-stub .reasoning-stub .rs-idx{color:var(--text-4)}.turn-stub .reasoning-stub .rs-chevron{color:var(--text-3);text-align:center;width:10px;margin-left:2px;font-size:12px}.turn-stub .reasoning-stub[data-open=true]{background:var(--reasoning-bg);color:var(--text-1);border-style:solid}.turn-stub .reasoning-stub-body{color:var(--text-2);background:var(--reasoning-bg-strong);border:1px solid var(--reasoning-border);border-left-width:2px;border-left-color:var(--reasoning-border-active);border-radius:var(--r-md);white-space:pre-wrap;grid-column:2;margin-top:8px;padding:12px 14px;font-size:13px;font-style:italic;line-height:1.6}.thread-end{font-family:var(--font-mono);font-size:var(--fs-meta);text-transform:uppercase;letter-spacing:.18em;color:var(--text-4);z-index:1;justify-content:center;align-items:center;gap:10px;padding:28px 0 8px;display:flex;position:relative}.thread-end:before,.thread-end:after{content:"";background:linear-gradient(90deg, transparent, var(--border-0), transparent);flex:0 80px;height:1px}.thread-end .dot{background:var(--text-4);border-radius:99px;width:3px;height:3px}.thread-body{flex-direction:column;gap:22px;width:100%;max-width:960px;padding:8px clamp(24px,4vw,56px) 140px;display:flex;position:relative}.thread-body:before{content:"";background:linear-gradient(180deg, transparent, var(--border-0) 8%, var(--border-0) 88%, transparent);width:1px;position:absolute;top:12px;bottom:60px;left:56px}.turn{grid-template-columns:44px 1fr;align-items:start;gap:18px;display:grid;position:relative}.turn[data-standalone=true]{grid-template-columns:minmax(0,1fr);gap:6px;margin:0 0 20px}.turn[data-standalone=true] .turn-content{min-width:0}.turn[data-standalone=true][data-role=user]{justify-items:end}.turn[data-standalone=true][data-role=user] .turn-content{border:1px solid var(--accent-border);background:var(--accent-soft);border-radius:14px 14px 4px;max-width:min(80%,640px);padding:9px 14px}.turn[data-standalone=true][data-role=user] .turn-body{font-size:15.5px}.turn-avatar{background:var(--bg-1);border:1px solid var(--border-0);width:28px;height:28px;color:var(--text-2);z-index:1;font-family:var(--font-mono);border-radius:7px;place-items:center;margin-top:2px;margin-left:8px;font-size:11px;font-weight:500;display:grid;position:relative}.turn[data-role=user] .turn-avatar{color:var(--role-user);border-color:oklch(78% .1 230/.35)}.turn[data-role=thinking] .turn-avatar{color:var(--role-reasoning);border-color:var(--reasoning-border-strong)}.turn[data-role=ai] .turn-avatar{color:var(--role-response);border-color:oklch(76% .11 155/.35)}.turn[data-matched=true] .turn-avatar{background:var(--accent);color:var(--accent-ink);border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft)}.turn[data-origin=threadshelf] .turn-avatar{color:oklch(82% .14 165);background:oklch(74% .16 165/.1);border-color:oklch(74% .16 165/.62);box-shadow:0 0 0 3px oklch(74% .16 165/.08)}.turn[data-origin=threadshelf] .turn-body{border-left:2px solid oklch(74% .16 165/.48);padding-left:12px}.threadshelf-turn-badge{color:oklch(82% .14 165);min-height:18px;font:600 9px var(--font-mono);letter-spacing:.03em;text-transform:none;background:oklch(74% .16 165/.1);border:1px solid oklch(74% .16 165/.38);border-radius:99px;align-items:center;padding:1px 7px;display:inline-flex}.turn-content{min-width:0}.turn-head{font-family:var(--font-mono);font-size:var(--fs-meta);color:var(--text-3);text-transform:uppercase;letter-spacing:.08em;align-items:center;gap:10px;height:24px;margin-bottom:6px;display:flex}.turn-head .role-tag{color:var(--text-1);font-weight:500}.turn-head .turn-idx{color:var(--text-4)}.turn-head .turn-date{color:var(--text-3);text-transform:none;letter-spacing:0;margin-left:2px}.turn-head .match-pill{background:var(--accent-soft);color:var(--accent);border:1px solid var(--accent-border);text-transform:uppercase;letter-spacing:.1em;font-size:var(--fs-micro);border-radius:99px;margin-left:auto;padding:2px 8px;font-weight:600}.turn-head .copy-turn{color:var(--text-2);text-transform:none;letter-spacing:0;font-family:var(--font-mono);font-size:var(--fs-meta);opacity:0;cursor:pointer;background:0 0;border:0;border-radius:4px;margin-left:auto;padding:2px 6px;transition:opacity .12s}.turn-head .copy-turn:hover{background:var(--bg-2);color:var(--text-0)}.turn[data-role=user] .turn-head .role-tag{color:var(--role-user)}.turn[data-role=thinking] .turn-head .role-tag{color:var(--role-reasoning)}.turn[data-role=ai] .turn-head .role-tag{color:var(--role-response)}.turn:hover .turn-head .copy-turn{opacity:1;color:var(--text-1)}.turn-body{color:var(--text-0);white-space:pre-wrap;word-break:break-word;letter-spacing:-.003em;font-size:16.5px;line-height:1.7;position:relative}.turn-body[data-collapsed=true]{max-height:18rem;overflow:hidden}.turn-body[data-collapsed=true]:after{content:"";pointer-events:none;background:linear-gradient(180deg, transparent, var(--bg-0) 84%);height:6rem;position:absolute;inset:auto 0 0}.turn[data-role=user] .turn-body{color:var(--text-1);font-size:16px}.turn[data-role=thinking] .turn-body{color:var(--text-2);background:var(--reasoning-bg-strong);border:1px solid var(--reasoning-border);border-radius:var(--r-md);border-left-width:2px;border-left-color:var(--reasoning-border-active);padding:12px 14px 12px 16px;font-size:15px;font-style:italic}.show-more{border-radius:var(--r-sm);border:1px solid var(--border-0);background:var(--bg-1);height:30px;color:var(--text-1);font:500 12.5px var(--font-sans);margin-top:10px;padding:0 11px}.show-more:hover{background:var(--bg-2);border-color:var(--border-1);color:var(--text-0)}.turn[data-matched=true] .turn-body{background:linear-gradient(180deg, var(--accent-soft), transparent 80%);border:1px solid var(--accent-border);border-radius:var(--r-md);box-shadow:0 12px 40px -24px var(--accent);padding:14px 18px}.turn[data-matched=true] mark{color:var(--text-0);box-shadow:inset 0 -1px 0 var(--accent);background:oklch(100% 0 0/.08);border-radius:3px;padding:0 3px;font-weight:500}.drop-zone{border:1.5px dashed var(--border-1);border-radius:var(--r-lg);background:linear-gradient(180deg, var(--bg-1), transparent);text-align:center;flex-direction:column;align-items:center;gap:12px;padding:28px 24px;transition:border-color .12s,background .12s;display:flex}.drop-zone[data-dragging=true]{border-color:var(--accent);background:var(--accent-soft)}.drop-zone .ico-big{border-radius:var(--r-md);background:var(--bg-2);border:1px solid var(--border-0);width:44px;height:44px;color:var(--text-1);place-items:center;display:grid}.drop-zone h3{margin:0;font-size:15px;font-weight:500}.drop-zone p{color:var(--text-2);max-width:480px;margin:0;font-size:12.5px}.drop-zone .path-input{grid-template-columns:1fr auto;gap:8px;width:100%;max-width:480px;display:grid}.drop-zone input[type=text]{border-radius:var(--r-sm);border:1px solid var(--border-0);background:var(--bg-2);height:32px;font-family:var(--font-mono);outline:none;padding:0 10px;font-size:12px}.drop-zone input[type=text]:focus{border-color:var(--accent-border)}.ingest-options{flex-wrap:wrap;align-items:center;gap:16px;padding:12px 0 0;display:flex}.ingest-options label{color:var(--text-1);cursor:pointer;align-items:center;gap:6px;font-size:12.5px;display:inline-flex}.ingest-options input[type=checkbox]{accent-color:var(--accent)}.ingest-options select{border-radius:var(--r-sm);border:1px solid var(--border-0);background:var(--bg-2);outline:none;height:28px;padding:0 8px;font-size:12px}.progress-panel{border:1px solid var(--border-0);border-radius:var(--r-lg);background:var(--bg-1);overflow:hidden}.progress-head{border-bottom:1px solid var(--border-0);align-items:center;gap:10px;padding:12px 16px;display:flex}.progress-head .step{font-family:var(--font-mono);color:var(--text-2);font-size:11px}.progress-head .step b{color:var(--text-0);font-weight:500}.progress-head .pct{font-family:var(--font-mono);color:var(--accent);margin-left:auto;font-size:13px}.progress-bar-new{background:var(--bg-2);height:4px;overflow:hidden}.progress-bar-new i{background:linear-gradient(90deg, var(--accent), oklch(70% .16 280));height:100%;transition:width .18s ease-out;display:block}.progress-details-new{font-family:var(--font-mono);color:var(--text-2);flex-wrap:wrap;gap:16px;padding:10px 14px;font-size:11.5px;display:flex}.progress-details-new strong{color:var(--text-0);font-weight:500}.progress-file{font-family:var(--font-mono);color:var(--text-3);white-space:nowrap;text-overflow:ellipsis;padding:0 14px 10px;font-size:11px;overflow:hidden}.insights-view{flex-direction:column;gap:14px;display:flex}.insights-head{justify-content:space-between;align-items:flex-end;gap:10px;display:flex}.insights-head h2{color:var(--text-0);margin:0;font-size:18px;font-weight:600}.insights-head .insights-range{font-family:var(--font-mono);color:var(--text-3);margin:2px 0 0;font-size:11.5px}.insights-scope{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;color:var(--text-3);flex:none;align-items:center;gap:6px;font-size:11px;display:inline-flex}.insights-scope select{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-1);height:28px;color:var(--text-0);font:12.5px var(--font-sans);text-transform:none;letter-spacing:normal;outline:0;padding:0 6px}.insights-scope select:focus{border-color:var(--border-1)}.stat-tiles{grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:10px;display:grid}.stat-tile{border:1px solid var(--border-0);border-radius:var(--r-md);background:var(--bg-1);flex-direction:column;gap:4px;padding:12px 14px;display:flex}.stat-tile .stat-label{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.07em;color:var(--text-3);font-size:11px}.stat-tile .stat-value{color:var(--text-0);font-size:24px;font-weight:600}.insight-card{border:1px solid var(--border-0);border-radius:var(--r-md);background:var(--bg-1);min-width:0;padding:14px 16px 16px}.insight-card h3{color:var(--text-1);margin:0;font-size:13.5px;font-weight:600}.insight-card .insight-sub{color:var(--text-3);margin:2px 0 12px;font-size:12px}.insight-grid{grid-template-columns:1fr 1fr;gap:14px;display:grid}@media (width<=860px){.insight-grid{grid-template-columns:1fr}}.chart-empty{color:var(--text-3);margin:8px 0 0;font-size:12.5px}.activity-chart{height:190px;padding-bottom:18px;position:relative}.chart-grid{pointer-events:none;flex-direction:column;justify-content:space-between;display:flex;position:absolute;inset:0 0 18px}.chart-grid .grid-row{align-items:center;gap:6px;height:0;display:flex}.chart-grid .grid-tick{text-align:right;min-width:30px;font-family:var(--font-mono);font-size:var(--fs-meta);color:var(--text-4);flex:none;transform:translateY(-1px)}.chart-grid .grid-line{background:var(--border-0);flex:1;height:1px}.chart-cols{align-items:flex-end;gap:2px;display:flex;position:absolute;inset:0 0 18px 40px}.col-slot{flex:1;justify-content:center;align-items:flex-end;min-width:0;height:100%;display:flex;position:relative}.col-slot .col-bar{background:var(--accent);border-radius:4px 4px 0 0;width:100%;max-width:24px;transition:opacity .1s}.col-slot:hover .col-bar,.col-slot .col-bar[data-hover=true]{opacity:.85}.col-slot .col-peak{font-family:var(--font-mono);font-size:var(--fs-meta);color:var(--text-2);white-space:nowrap;position:absolute;top:-4px;left:50%;transform:translate(-50%,-100%)}.chart-tip{border:1px solid var(--border-1);border-radius:var(--r-sm);background:var(--bg-0);white-space:nowrap;z-index:5;pointer-events:none;flex-direction:column;gap:1px;padding:6px 9px;display:flex;position:absolute;bottom:calc(100% + 6px);left:50%;transform:translate(-50%);box-shadow:0 4px 14px #0000002e}.chart-tip b{color:var(--text-0);font-size:11.5px;font-weight:600}.chart-tip span{font-family:var(--font-mono);color:var(--text-2);font-size:11px}.chart-x{gap:2px;display:flex;position:absolute;inset:auto 0 0 40px}.chart-x .x-slot{text-align:center;min-width:0;font-family:var(--font-mono);font-size:var(--fs-meta);color:var(--text-4);white-space:nowrap;flex:1;overflow:visible}.bar-list{flex-direction:column;gap:8px;display:flex}.bar-row{grid-template-columns:minmax(90px,150px) 1fr auto;align-items:center;gap:10px;min-width:0;display:grid}.bar-row .bar-label{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--text-1);font-size:12px;overflow:hidden}.bar-row .bar-label .mono{font-family:var(--font-mono);font-size:11.5px}.bar-row .provider-label{align-items:center;gap:6px;display:inline-flex}.bar-row .provider-label .pdot{border-radius:99px;flex:none;width:7px;height:7px}.bar-row .bar-track{align-items:center;height:12px;display:flex}.bar-row .bar-fill{background:var(--accent);border-radius:0 4px 4px 0;min-width:2px;height:12px}.bar-row .bar-value{font-family:var(--font-mono);color:var(--text-2);font-variant-numeric:tabular-nums;font-size:11px}.longest-list{flex-direction:column;display:flex}.longest-row{border:0;border-bottom:1px solid var(--border-0);width:100%;color:inherit;text-align:left;cursor:pointer;background:0 0;align-items:center;gap:10px;min-width:0;padding:8px 6px;display:flex}.longest-row:last-child{border-bottom:0}.longest-row:hover{background:var(--bg-2)}.longest-row .rank{font-family:var(--font-mono);color:var(--text-4);text-align:right;flex:0 0 18px;font-size:11px}.longest-row .pdot{border-radius:99px;flex:none;width:7px;height:7px}.longest-row .l-title{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--text-1);flex:1;font-size:13px;overflow:hidden}.longest-row .l-meta{font-family:var(--font-mono);color:var(--text-3);flex:none;font-size:11px}.alpha-badge{background:var(--warning-soft);color:oklch(85% .1 75);width:fit-content;min-height:18px;font:600 9.5px var(--font-mono);letter-spacing:.07em;text-transform:uppercase;border:1px solid oklch(78% .15 75/.38);border-radius:99px;align-items:center;padding:1px 7px;display:inline-flex}.generation-settings{flex-direction:column;gap:14px;display:flex}.generation-panel .generation-form{grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;display:grid}.generation-panel .generation-form>label:not(.check-field){color:var(--text-2);flex-direction:column;gap:6px;font-size:12px;display:flex}.generation-panel .generation-form input:not([type=checkbox]),.generation-panel .generation-form textarea{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-2);width:100%;min-height:34px;color:var(--text-0);font:12px var(--font-mono);resize:vertical;outline:none;padding:7px 10px}.generation-panel .generation-form input:not([type=checkbox]):focus,.generation-panel .generation-form textarea:focus{border-color:var(--accent-border)}.generation-panel .generation-form .setup-note,.generation-panel .generation-form .generation-actions,.generation-panel .generation-form .llama-runtime-config{grid-column:1/-1}.generation-panel .generation-form label:has(textarea){grid-column:1/-1}.generation-panel .generation-form .short-field{max-width:220px}.llama-runtime-config{border:1px solid var(--border-0);border-radius:var(--r-md);background:var(--bg-1);grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:12px;display:grid}.llama-runtime-config label{min-width:0;color:var(--text-2);flex-direction:column;gap:6px;font-size:12px;display:flex}.llama-runtime-config select{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-2);width:100%;min-height:34px;color:var(--text-0);font:12px var(--font-mono);padding:6px 9px}.llama-runtime-config small{color:var(--text-3);font:var(--fs-meta)/1.45 var(--font-mono)}.directory-picker-launch{align-items:center;gap:8px;margin-top:2px;display:flex}.field-error{color:var(--danger);font:var(--fs-meta)/1.4 var(--font-mono)}.directory-picker{border:1px solid var(--accent-border);border-radius:var(--r-md);background:var(--bg-1);flex-direction:column;gap:8px;margin-top:4px;padding:10px;display:flex}.directory-picker-bar{grid-template-columns:auto minmax(0,1fr) auto auto;gap:6px;display:grid}.directory-picker-roots{flex-wrap:wrap;gap:5px;display:flex}.directory-picker-roots button{border:1px solid var(--border-0);background:var(--bg-2);color:var(--text-2);font:var(--fs-meta) var(--font-mono);cursor:pointer;border-radius:99px;padding:3px 7px}.directory-picker-list{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-2);max-height:210px;display:grid;overflow:auto}.directory-picker-list button{border:0;border-bottom:1px solid var(--border-0);color:var(--text-1);text-align:left;font:11px var(--font-mono);cursor:pointer;background:0 0;gap:7px;padding:7px 9px;display:flex}.directory-picker-list button:hover{background:var(--accent-soft)}.directory-picker-list>span{color:var(--text-3);font:11px var(--font-mono);padding:12px}.directory-picker-foot{justify-content:space-between;align-items:center;gap:10px;display:flex}.directory-picker-foot>span{min-width:0;color:var(--text-3);font:var(--fs-meta) var(--font-mono);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.setup-note{color:var(--text-2);font-size:12px;line-height:1.6}.setup-note code{background:var(--code-bg);color:var(--text-1);font:11px var(--font-mono);border-radius:4px;padding:2px 5px}.check-field{color:var(--text-1);align-items:flex-start;gap:8px;font-size:12.5px;line-height:1.45;display:flex}.check-field input{accent-color:var(--accent);margin-top:2px}.openrouter-zdr-option{color:var(--text-2);font:11px var(--font-mono);align-items:center;gap:7px;padding:0 2px;display:flex}.openrouter-zdr-option input{accent-color:var(--accent)}.openrouter-zdr-option span{color:var(--text-4)}.llama-diagnostics{border:1px solid var(--border-0);border-radius:var(--r-md);background:var(--bg-1);margin-top:12px;overflow:hidden}.llama-placement{border-bottom:1px solid var(--border-0);justify-content:space-between;align-items:flex-start;gap:12px;padding:10px 12px;display:flex}.llama-placement>div:first-child{flex-direction:column;gap:3px;min-width:0;display:flex}.llama-placement strong{color:var(--text-1);font:600 11px var(--font-mono)}.llama-placement span{color:var(--text-3);font:var(--fs-meta)/1.45 var(--font-mono)}.chat-create-actions{flex:none;align-items:center;gap:5px;display:flex}.chat-create-actions .btn{height:30px;margin:0}.chat-create-actions .icon-only{width:30px;padding:0}.llama-buffer-split{text-align:right;max-width:46%}.llama-memory-warning{background:var(--warning-soft);color:var(--text-1);border-bottom:1px solid oklch(78% .15 75/.28);padding:9px 12px;font-size:11px;line-height:1.5}.llama-log-details summary{color:var(--text-2);font:var(--fs-meta) var(--font-mono);cursor:pointer;justify-content:space-between;gap:12px;padding:9px 12px;list-style-position:inside;display:flex}.llama-log-details summary span:last-child{color:var(--text-4);text-transform:uppercase;margin-left:auto}.llama-log-details pre{border-top:1px solid var(--border-0);background:var(--code-bg);max-height:360px;color:var(--text-2);font:var(--fs-meta)/1.5 var(--font-mono);white-space:pre-wrap;word-break:break-word;margin:0;padding:12px;overflow:auto}.llama-log-toolbar{border-top:1px solid var(--border-0);color:var(--text-4);font:var(--fs-micro) var(--font-mono);justify-content:space-between;align-items:center;gap:10px;padding:7px 12px;display:flex}.generation-actions{color:var(--text-2);font:11.5px var(--font-mono);flex-wrap:wrap;align-items:center;gap:10px;display:flex}.provider-status{border-left:2px solid var(--danger);padding-left:10px}.provider-status[data-ready=true]{border-left-color:var(--success)}.thread-continuation{display:contents}.turn-model{max-width:min(260px,42vw);color:var(--text-4);font:var(--fs-meta) var(--font-mono);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.generated-reasoning{border:1px solid var(--reasoning-border);border-radius:var(--r-sm);background:var(--reasoning-bg);color:var(--text-2);margin:0 0 10px;padding:8px 10px;font-size:12px}.generated-reasoning summary{cursor:pointer;color:var(--role-reasoning);font-family:var(--font-mono)}.generated-reasoning div{white-space:pre-wrap;margin-top:8px}.stream-fragment{white-space:pre-wrap}.stream-copy-button{border-radius:var(--r-sm);width:max-content;color:var(--text-3);cursor:pointer;font:var(--fs-meta) var(--font-mono);background:0 0;border:0;margin-top:8px;padding:3px 7px}.stream-copy-button:hover,.stream-copy-button:focus-visible{background:var(--bg-2);color:var(--text-1)}.interrupted-generation{border:1px solid color-mix(in oklch, var(--danger) 35%, var(--border-0));border-radius:var(--r-md);background:color-mix(in oklch, var(--danger-soft) 35%, var(--bg-1));margin:4px 0;padding:12px 14px}.interrupted-generation>header{justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:10px;display:flex}.interrupted-generation>header>div:first-child{flex-direction:column;gap:3px;min-width:0;display:flex}.interrupted-generation>header strong{color:var(--danger);font-size:12px}.interrupted-generation>header span{color:var(--text-4);font:var(--fs-micro) var(--font-mono);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.interrupted-generation>footer{max-height:240px;color:var(--danger);font:var(--fs-meta)/1.45 var(--font-mono);overflow-wrap:anywhere;white-space:pre-wrap;margin-top:10px;overflow:auto}.interrupted-generation-actions{flex:none;gap:6px;display:flex}.interrupted-prompt{margin-bottom:10px}.interrupted-prompt span{color:var(--text-4);font:var(--fs-micro) var(--font-mono);text-transform:uppercase}.interrupted-prompt p{color:var(--text-2);white-space:pre-wrap;margin:3px 0 0;font-size:12px}.interrupted-answer{color:var(--text-1);white-space:pre-wrap}.interrupted-answer em{color:var(--text-4);font-size:11px}.continue-card{border:1px solid var(--border-0);border-radius:var(--r-md);background:var(--bg-1);z-index:1;flex-direction:column;gap:12px;margin-top:10px;padding:12px;display:flex;position:relative}.continue-card>.banner.err{overflow-wrap:anywhere;white-space:pre-wrap;max-height:240px;overflow:auto}.continue-card textarea{resize:vertical;border:1px solid var(--border-1);border-radius:var(--r-md);background:var(--bg-0);width:100%;color:var(--text-0);font:14px/1.55 var(--font-sans);outline:none;padding:11px 12px}.continue-card textarea:focus{border-color:var(--accent)}.continue-head{justify-content:space-between;align-items:center;gap:12px;display:flex}.continue-head>div{align-items:center;gap:8px;display:flex}.continue-head strong{font-size:14px;font-weight:500}.continue-head>span{color:var(--text-3);font:var(--fs-meta) var(--font-mono)}.continue-controls{grid-template-columns:132px minmax(180px,1fr) 30px;gap:8px;display:grid}.continue-controls select,.continue-controls input{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-2);min-width:0;height:30px;color:var(--text-1);font:11.5px var(--font-mono);outline:none;padding:0 8px}.continue-controls select:focus,.continue-controls input:focus{border-color:var(--accent-border)}.continue-controls .icon-only{place-items:center;width:30px;padding:0;display:grid}.runtime-details{border:1px solid var(--border-0);border-radius:var(--r-sm);background:color-mix(in oklch, var(--bg-2) 55%, transparent)}.runtime-details[data-state=ready] .runtime-dot,.runtime-details[data-state=external] .runtime-dot{background:var(--success)}.runtime-details[data-state=starting] .runtime-dot,.runtime-details[data-state=loading] .runtime-dot{background:var(--warning);animation:1.2s ease-in-out infinite generation-pulse}.runtime-details[data-state=remote] .runtime-dot{background:var(--accent)}.runtime-details>summary{min-height:34px;color:var(--text-3);cursor:pointer;font:var(--fs-meta) var(--font-mono);grid-template-columns:8px minmax(0,auto) minmax(0,1fr) auto;align-items:center;gap:8px;padding:0 10px;list-style:none;display:grid}.runtime-details>summary::-webkit-details-marker{display:none}.runtime-details>summary strong,.runtime-details>summary span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.runtime-details>summary strong{color:var(--text-1);font-weight:500}.runtime-details>summary em{color:var(--text-4);text-transform:uppercase;font-style:normal}.runtime-details[open]>summary{border-bottom:1px solid var(--border-0)}.runtime-details .model-runtime{border:0;border-bottom:1px solid var(--border-0);background:0 0;border-radius:0;margin:0}.runtime-details .llama-diagnostics{border:0;border-radius:0;margin:0}.turn-generation-metrics{color:var(--text-4);font:var(--fs-micro) var(--font-mono);flex-wrap:wrap;align-items:baseline;gap:7px;margin-top:8px;display:flex}.turn-generation-metrics strong{color:var(--success);font-size:11px}.generation-budget{border-bottom:1px solid var(--border-0);color:var(--text-3);font:var(--fs-meta) var(--font-mono);grid-template-columns:minmax(0,1fr);align-items:center;gap:12px;padding:9px 12px;display:grid}.generation-budget strong{color:var(--text-1);font-weight:500}.generation-budget-field{grid-template-columns:minmax(110px,1fr) 19ch auto;align-items:center;gap:7px;width:100%;display:grid}.generation-budget-field .number-combobox{width:19ch}.generation-context-apply{min-width:52px}.number-combobox{min-width:0;position:relative}.number-combobox>input{border:1px solid var(--border-1);border-radius:var(--r-sm);background:var(--bg-2);width:100%;height:28px;color:var(--text-0);font:11px var(--font-mono);outline:none;padding:0 24px 0 8px}.number-combobox>input:focus{border-color:var(--accent)}.number-combobox>input[aria-invalid=true]{border-color:var(--danger)}.number-combobox-toggle{border-radius:var(--r-sm);width:20px;height:20px;color:var(--text-3);font-size:var(--fs-meta);background:0 0;border:0;place-items:center;padding:0;display:grid;position:absolute;top:50%;right:2px;translate:0 -50%}.number-combobox-toggle:hover{color:var(--text-1)}.number-combobox-popover{z-index:30;scrollbar-gutter:stable;border:1px solid var(--border-1);border-radius:var(--r-sm);background:var(--bg-1);max-height:210px;box-shadow:0 12px 30px -12px var(--bg-0);display:grid;position:absolute;top:calc(100% + 4px);left:0;right:0;overflow:hidden auto}.number-combobox-popover button{color:var(--text-1);text-align:left;font:var(--fs-meta) var(--font-mono);white-space:nowrap;background:0 0;border:0;padding:6px 8px}.number-combobox-popover button[data-active=true]{background:var(--accent-soft)}.number-combobox-popover button[data-selected=true]{color:var(--accent)}.master-prompt{flex:none;position:relative}.master-prompt-chip{border:1px dashed var(--border-1);max-width:130px;height:32px;color:var(--text-3);font:11.5px var(--font-mono);text-overflow:ellipsis;white-space:nowrap;background:0 0;border-radius:99px;padding:0 10px;overflow:hidden}.master-prompt-chip:hover{border-color:var(--accent-border);color:var(--text-1)}.master-prompt-chip[data-active=true]{border-style:solid;border-color:var(--accent-border);background:var(--accent-soft);color:var(--accent)}.master-prompt-popover{z-index:40;width:min(380px,100vw - 24px);max-height:min(520px, var(--master-popover-available-height,520px));overscroll-behavior:contain;scrollbar-gutter:stable;border:1px solid var(--border-1);border-radius:var(--r-md);background:var(--bg-1);box-shadow:0 18px 48px -18px var(--bg-0);transform:translateX(var(--master-popover-shift-x,0));flex-direction:column;gap:8px;padding:10px;display:flex;position:absolute;bottom:calc(100% + 8px);left:0;overflow-y:auto}.master-prompt-popover input,.master-prompt-popover textarea{border:1px solid var(--border-1);border-radius:var(--r-sm);background:var(--bg-2);width:100%;color:var(--text-0);font:11.5px/1.5 var(--font-mono);resize:vertical;outline:none;padding:6px 8px}.master-prompt-popover input:focus,.master-prompt-popover textarea:focus{border-color:var(--accent)}.master-prompt-popover input::placeholder,.master-prompt-popover textarea::placeholder{color:var(--text-4)}.master-prompt[data-popover-placement=down] .master-prompt-popover{top:calc(100% + 8px);bottom:auto}.master-prompt-tabs{flex-wrap:wrap;align-items:center;gap:4px;display:flex}.master-prompt-tabs button{border:1px solid var(--border-0);max-width:120px;color:var(--text-3);font:var(--fs-meta) var(--font-mono);text-overflow:ellipsis;white-space:nowrap;background:0 0;border-radius:99px;padding:3px 8px;overflow:hidden}.master-prompt-tabs button[data-active=true]{border-color:var(--accent-border);background:var(--accent-soft);color:var(--accent)}.master-prompt-foot{color:var(--text-4);font:var(--fs-micro) var(--font-mono);flex-wrap:wrap;align-items:center;gap:8px;display:flex}.master-prompt-foot>span{margin-right:auto}.copyable-runtime-detail{min-width:0;color:var(--text-4);font:var(--fs-meta) var(--font-mono);position:relative}.copyable-runtime-detail>span{text-overflow:ellipsis;white-space:nowrap;cursor:help;max-width:25ch;display:block;overflow:hidden}.copyable-runtime-detail:hover .copyable-runtime-popover,.copyable-runtime-detail:focus-within .copyable-runtime-popover{display:flex}.copyable-runtime-popover{z-index:20;border:1px solid var(--border-1);border-radius:var(--r-sm);background:var(--bg-2);align-items:center;gap:8px;width:min(520px,70vw);padding:8px;display:none;position:absolute;bottom:calc(100% + 7px);left:0;box-shadow:0 10px 30px oklch(0% 0 0/.35)}.copyable-runtime-popover code{overflow-wrap:anywhere;min-width:0;color:var(--text-2);-webkit-user-select:text;user-select:text;flex:1}.model-combobox{min-width:0;position:relative}.model-combobox-input{position:relative}.model-combobox-input input{border:1px solid var(--border-1);border-radius:var(--r-sm);background:var(--bg-2);width:100%;height:32px;color:var(--text-0);font:11.5px var(--font-mono);outline:none;padding:0 28px 0 10px}.model-combobox-input input::placeholder{color:var(--text-4)}.model-combobox-input input:focus{border-color:var(--accent)}.model-combobox-input input:disabled{color:var(--text-3);cursor:not-allowed}.model-combobox-chevron{color:var(--text-3);pointer-events:none;position:absolute;top:50%;right:9px;translate:0 -50%}.model-combobox-popover{z-index:12;border:1px solid var(--accent-border);border-radius:var(--r-md);background:var(--bg-1);max-height:min(420px,58vh);position:absolute;top:calc(100% + 5px);left:0;right:0;overflow:auto;box-shadow:0 16px 45px oklch(0% 0 0/.3)}.model-combobox-summary{z-index:1;border-bottom:1px solid var(--border-0);background:var(--bg-1);color:var(--text-3);font:var(--fs-micro) var(--font-mono);text-transform:uppercase;justify-content:space-between;padding:7px 10px;display:flex;position:sticky;top:0}.model-combobox-empty{color:var(--text-3);text-align:center;font:11px var(--font-mono);padding:18px 12px}.model-option{border-bottom:1px solid var(--border-0);cursor:pointer;grid-template-columns:27px minmax(0,1fr) auto;align-items:center;gap:7px;padding:7px 9px;display:grid}.model-option[data-active=true],.model-option[data-selected=true]{background:var(--accent-soft)}.model-favorite{width:25px;height:25px;color:var(--text-3);cursor:pointer;background:0 0;border:0;place-items:center;padding:0;display:grid}.model-favorite[data-favorite=true]{color:var(--warning)}.model-option-copy{flex-direction:column;gap:2px;min-width:0;display:flex}.model-option-copy strong,.model-option-copy span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.model-option-copy strong{color:var(--text-1);font:11.5px var(--font-mono)}.model-option-copy span{color:var(--text-3);font:var(--fs-micro) var(--font-mono)}.model-option-meta{color:var(--text-3);font:var(--fs-micro) var(--font-mono);white-space:nowrap}.model-catalog-filters{color:var(--text-3);font:var(--fs-meta) var(--font-mono);align-items:center;gap:8px;display:flex}.model-catalog-filters>span{text-transform:uppercase}.model-catalog-filters select{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-2);height:27px;color:var(--text-1);font:var(--fs-meta) var(--font-mono);padding:0 7px}.model-catalog-filters label{align-items:center;gap:5px;display:flex}.model-catalog-filters input{accent-color:var(--accent)}.model-runtime,.generation-progress{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-2);align-items:flex-start;gap:10px;padding:10px 12px;display:flex}.model-runtime>div,.generation-progress>div{flex-direction:column;gap:3px;min-width:0;display:flex}.model-runtime strong,.generation-progress strong{color:var(--text-1);font:600 11.5px var(--font-mono)}.model-runtime span:not(.runtime-dot,.generation-spinner),.generation-progress span:not(.runtime-dot,.generation-spinner){color:var(--text-3);font:var(--fs-meta)/1.4 var(--font-mono);text-overflow:ellipsis;overflow:hidden}.model-runtime>.btn{margin-left:auto}.global-runtime{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-1);grid-template-columns:9px minmax(0,1fr) auto;align-items:center;gap:8px;padding:8px;display:grid}.global-runtime[data-state=ready] .runtime-dot,.global-runtime[data-state=external] .runtime-dot{background:var(--success)}.global-runtime[data-state=starting] .runtime-dot{background:var(--warning);animation:1.2s ease-in-out infinite generation-pulse}.global-runtime button{border:1px solid var(--border-0);color:var(--text-3);font:var(--fs-micro) var(--font-mono);cursor:pointer;background:0 0;border-radius:4px;padding:2px 5px}.global-runtime-copy{flex-direction:column;gap:2px;min-width:0;display:flex}.global-runtime-copy b,.global-runtime-copy span,.global-runtime-copy small{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.global-runtime-copy b{color:var(--text-2);font:600 9.5px var(--font-mono);align-items:center;gap:5px;display:flex}.global-runtime-copy b>span:first-child{min-width:0}.global-runtime-copy b em{border:1px solid var(--border-0);color:var(--text-3);font:8px var(--font-mono);text-transform:uppercase;border-radius:999px;flex:none;padding:1px 4px;font-style:normal}.global-runtime-copy span,.global-runtime-copy small{color:var(--text-4);font:var(--fs-micro) var(--font-mono)}.global-runtime-copy small{white-space:normal;margin-top:2px}.runtime-install-help{border:1px solid var(--border-0);cursor:help;border-radius:50%;flex:0 0 14px;place-items:center;width:14px;height:14px;display:inline-grid;color:var(--text-4)!important;font:8px var(--font-mono)!important}.runtime-install-help:focus-visible{outline:1px solid var(--accent);outline-offset:2px}.runtime-dot{background:var(--text-3);width:8px;height:8px;box-shadow:0 0 0 3px color-mix(in oklch, var(--text-3) 14%, transparent);border-radius:50%;flex:none;margin-top:3px}.model-runtime[data-state=ready] .runtime-dot,.model-runtime[data-state=external] .runtime-dot{background:var(--success);box-shadow:0 0 0 3px color-mix(in oklch, var(--success) 16%, transparent)}.model-runtime[data-state=starting] .runtime-dot,.model-runtime[data-state=loading] .runtime-dot{background:var(--warning);animation:1.2s ease-in-out infinite generation-pulse}.model-runtime[data-state=remote] .runtime-dot{background:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}.generation-progress{border-color:var(--accent-border);background:var(--accent-soft)}.generation-spinner{border:2px solid var(--border-1);border-top-color:var(--accent);border-radius:50%;flex:none;width:14px;height:14px;animation:.8s linear infinite generation-spin}.stream-placeholder{color:var(--text-3);font-style:italic}.stream-cursor{background:var(--accent);width:2px;height:1em;margin-left:3px;animation:.85s step-end infinite generation-pulse;display:inline-block;translate:0 2px}@keyframes generation-spin{to{rotate:360deg}}@keyframes generation-pulse{50%{opacity:.3}}@media (prefers-reduced-motion:reduce){.generation-spinner,.runtime-dot,.stream-cursor{animation:none}}.chat-page{width:100%;min-height:calc(100dvh - 48px);margin:0 auto;position:relative}.chat-workspace{width:100%;min-width:0;min-height:calc(100dvh - 48px);padding:22px clamp(18px,4vw,56px) 48px}.chat-hero{border-bottom:1px solid var(--border-0);flex-direction:column;gap:8px;max-width:760px;margin:0 auto 14px;padding-bottom:12px;display:flex}.chat-hero .chat-title-row,.chat-hero .chat-hero-actions{align-items:center;gap:8px;min-width:0;display:flex}.chat-hero h1{min-width:0;color:var(--text-0);overflow-wrap:anywhere;margin:0;font-size:clamp(19px,2.3vw,24px);font-weight:500;line-height:1.25}.chat-title-row{align-items:flex-start!important}.chat-hero-actions{justify-content:space-between}.chat-storage-status{min-width:0;color:var(--text-4);font:var(--fs-micro) var(--font-mono);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.private-chat-badge{border:1px solid var(--border-1);background:var(--bg-2);color:var(--text-2);font:600 9.5px var(--font-mono);letter-spacing:.02em;border-radius:99px;flex:none;align-items:center;gap:5px;padding:2px 7px;display:inline-flex}.chat-storage-badge{border:1px solid var(--border-1);background:var(--bg-2);color:var(--text-2);font:600 9.5px var(--font-mono);letter-spacing:.02em;border-radius:99px;flex:none;align-items:center;gap:5px;padding:2px 8px;display:inline-flex}.chat-storage-badge.saved{border-color:var(--accent-border);background:var(--accent-soft);color:var(--accent)}.chat-storage-badge svg{flex:none}.saved-chat-actions{flex:none;align-items:center;gap:8px;display:flex}.threadshelf-origin-badge{border:1px solid var(--accent-border);background:var(--accent-soft);color:var(--accent);font:600 9.5px var(--font-mono);letter-spacing:.04em;text-transform:uppercase;border-radius:99px;padding:2px 7px;display:inline-flex}.threadshelf-filter{color:var(--text-2);font:var(--fs-meta) var(--font-mono);align-items:center;gap:7px;display:flex}.threadshelf-filter input{accent-color:oklch(74% .16 165)}.chat-conversation{flex-direction:column;gap:10px;max-width:760px;margin:0 auto;display:flex}.chat-empty{text-align:center;flex-direction:column;justify-content:center;align-items:center;max-width:520px;min-height:58vh;margin:0 auto;display:flex}.chat-empty h1{margin:12px 0 6px;font-size:24px;font-weight:500}.chat-empty p{color:var(--text-3);margin:0 0 18px;line-height:1.6}.chat-empty-icon{border:1px solid var(--accent-border);background:var(--accent-soft);width:42px;height:42px;color:var(--accent);border-radius:50%;place-items:center;display:grid}.chat-empty-alpha{color:var(--text-4);font:var(--fs-meta) var(--font-mono);align-items:center;gap:6px;margin-top:18px;display:inline-flex}.chat-empty-alpha svg{flex:none;width:13px;height:13px}.continue-foot{justify-content:space-between;align-items:center;gap:12px;display:flex}.continue-foot>span{color:var(--text-3);font:var(--fs-meta) var(--font-mono)}@media (width<=760px){.chat-workspace{min-height:calc(100dvh - 52px);padding:14px 12px 32px}.chat-hero{margin-bottom:10px;padding-bottom:10px}.chat-hero .chat-title-row{align-items:flex-start}.chat-hero h1{-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:19px;display:-webkit-box;overflow:hidden}.chat-hero-actions{flex-wrap:wrap;align-items:center}.chat-storage-status{white-space:normal;flex:100%}.saved-chat-actions{margin-left:auto}.generation-panel .generation-form{grid-template-columns:1fr}.generation-panel .generation-form>*{grid-column:1!important}.llama-runtime-config{grid-template-columns:1fr}.directory-picker-bar{grid-template-columns:auto minmax(0,1fr) auto}.directory-picker-bar .btn:last-child{grid-column:1/-1}.continue-controls{grid-template-columns:1fr}.continue-head,.continue-foot{flex-direction:column;align-items:flex-start}}.md-body{white-space:normal}.md-body>:first-child{margin-top:0}.md-body>:last-child{margin-bottom:0}.md-body p{white-space:pre-wrap;margin:0 0 .85em}.md-body h3,.md-body h4,.md-body h5,.md-body h6{color:var(--text-0);margin:1.1em 0 .45em;font-weight:600;line-height:1.3}.md-body h3{font-size:1.12em}.md-body h4{font-size:1.04em}.md-body h5,.md-body h6{color:var(--text-1);font-size:1em}.md-body ul,.md-body ol{margin:0 0 .85em;padding-left:1.5em}.md-body li{margin:.2em 0}.md-body li::marker{color:var(--text-3)}.md-body a{color:var(--accent);text-underline-offset:2px;text-decoration:underline}.md-body strong{color:var(--text-0);font-weight:600}.md-body code{border-radius:var(--r-sm);background:var(--bg-2);font:.88em var(--font-mono);word-break:break-word;padding:.1em .36em}.md-body pre{border:1px solid var(--border-0);border-radius:var(--r-md);background:var(--bg-2);margin:0 0 .85em;padding:12px 14px;overflow-x:auto}.md-body pre code{white-space:pre;background:0 0;padding:0;font-size:.86em;line-height:1.55}.md-body blockquote{border-left:2px solid var(--border-1);color:var(--text-2);margin:0 0 .85em;padding:4px 0 4px 14px}.sb-coll-empty-toggle{border-radius:var(--r-sm);color:var(--text-4);font:var(--fs-meta) var(--font-mono);text-align:left;cursor:pointer;background:0 0;border:0;margin:4px 8px 0;padding:6px 8px}.sb-coll-empty-toggle:hover,.sb-coll-empty-toggle:focus-visible{background:var(--bg-2);color:var(--text-2)}.chat-conversation .continue-card{bottom:max(8px, env(safe-area-inset-bottom));z-index:5;box-shadow:0 -10px 20px -12px var(--bg-0);position:sticky}.composer-bar{justify-content:space-between;align-items:center;gap:10px;display:flex}.model-menu{min-width:0;position:relative}.model-status{border:1px solid var(--border-1);background:var(--bg-2);min-width:0;max-width:100%;height:32px;color:var(--text-1);font:11.5px var(--font-mono);cursor:pointer;border-radius:99px;align-items:center;gap:8px;padding:0 10px;display:inline-flex}.model-status:hover,.model-status[aria-expanded=true]{border-color:var(--accent-border);background:var(--accent-soft)}.model-status .runtime-dot{margin-top:0}.model-status[data-state=ready] .runtime-dot{background:var(--success);box-shadow:0 0 0 3px color-mix(in oklch, var(--success) 16%, transparent)}.model-status[data-state=loading] .runtime-dot{background:var(--warning);animation:1.2s ease-in-out infinite generation-pulse}.model-status[data-state=remote] .runtime-dot{background:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}.model-status-name{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.model-status-chevron{color:var(--text-3)}.off-device-chip{background:var(--accent-soft);color:var(--accent);font-size:var(--fs-micro);letter-spacing:.02em;border-radius:99px;flex:none;padding:1px 6px}.model-popover{z-index:40;width:min(440px,86vw);max-height:min(70dvh, 560px, var(--model-popover-available-height,560px));overscroll-behavior:contain;scrollbar-gutter:stable;border:1px solid var(--border-1);border-radius:var(--r-md);background:var(--bg-1);box-shadow:0 18px 48px -18px var(--bg-0);flex-direction:column;gap:12px;padding:14px 14px 28px;scroll-padding-block:14px 28px;display:flex;position:absolute;bottom:calc(100% + 8px);left:0;overflow-y:auto}.model-menu[data-popover-placement=down] .model-popover{top:calc(100% + 8px);bottom:auto}.model-popover-providers{border-radius:var(--r-sm);background:var(--bg-2);grid-template-columns:1fr 1fr;gap:6px;padding:3px;display:grid}.model-popover-providers button{border-radius:var(--r-sm);height:30px;color:var(--text-3);font:11px var(--font-mono);cursor:pointer;background:0 0;border:0}.model-popover-providers button[data-active=true]{background:var(--bg-0);color:var(--text-0);box-shadow:0 1px 2px var(--bg-0)}.model-popover-pick{grid-template-columns:minmax(0,1fr) auto;gap:8px;display:grid}.model-popover-pick-actions{gap:6px;display:flex}.model-popover-pick-actions .icon-only{place-items:center;width:30px;padding:0;display:grid}.composer-actions{flex:none;align-items:center;gap:10px;display:flex}.composer-hint{color:var(--text-4);font:var(--fs-micro) var(--font-mono)}@media (width<=620px){.generation-budget-field{grid-template-columns:minmax(0,1fr) auto}.generation-budget-field>span:first-child{grid-column:1/-1}.generation-budget-field .number-combobox{width:100%}.composer-hint{display:none}.chat-conversation .continue-card{gap:8px;margin-inline:0;padding:9px}.chat-conversation .continue-card textarea{min-height:62px;max-height:34dvh;padding:9px 10px}.composer-bar,.composer-actions{gap:6px}.model-status{max-width:min(210px,58vw)}}.chat-title-input{border:1px solid var(--accent);border-radius:var(--r-sm);background:var(--bg-0);min-width:0;color:var(--text-0);outline:none;flex:1;padding:4px 8px;font-size:clamp(19px,2.3vw,24px);font-weight:500}.chat-hero h1[title="Double-click to rename"]{cursor:text}.catalog-modal{flex-direction:column;width:min(760px,94vw);max-height:82vh;display:flex}.catalog-head{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.catalog-origin{font-size:var(--fs-micro);border:1px solid var(--warning);color:var(--warning);background:var(--warning-soft);white-space:nowrap;border-radius:999px;flex:none;padding:2px 7px}.catalog-controls{gap:8px;padding:12px 16px 8px;display:flex}.catalog-controls input{border-radius:var(--r-sm);border:1px solid var(--border-0);background:var(--bg-2);outline:0;flex:1;height:32px;padding:0 10px;font-size:12.5px}.catalog-controls input:focus{border-color:var(--accent-border)}.catalog-controls select{border-radius:var(--r-sm);border:1px solid var(--border-0);background:var(--bg-2);height:32px;font-size:12.5px}.catalog-hardware{font-size:var(--fs-meta);color:var(--text-2);flex-wrap:wrap;gap:4px 10px;padding:0 16px 10px;display:flex}.catalog-hardware b{color:var(--text-1);font-weight:500}.catalog-token-hint{color:var(--warning)}.catalog-body{flex-direction:column;gap:6px;padding:0 16px 12px;display:flex;overflow-y:auto}.catalog-empty,.catalog-error{color:var(--text-2);margin:8px 0;font-size:12.5px}.catalog-error{color:var(--danger)}.catalog-item{border:1px solid var(--border-0);border-radius:var(--r-sm);background:var(--bg-2)}.catalog-item[data-open=true]{border-color:var(--accent-border)}.catalog-item-head{text-align:left;cursor:pointer;width:100%;color:inherit;background:0 0;border:0;justify-content:space-between;align-items:center;gap:12px;padding:9px 11px;display:flex}.catalog-item-head:hover{background:var(--bg-3)}.catalog-item-title{flex-direction:column;gap:2px;min-width:0;display:flex}.catalog-item-title b{overflow-wrap:anywhere;font-size:13px;font-weight:500}.catalog-item-title em{font-style:normal;font-size:var(--fs-meta);color:var(--text-2)}.catalog-item-meta{font-size:var(--fs-meta);color:var(--text-2);font-variant-numeric:tabular-nums;flex:none;align-items:center;gap:8px;display:flex}.catalog-badge{font-size:var(--fs-micro);border:1px solid var(--border-1);border-radius:999px;padding:1px 6px}.catalog-badge.trusted{color:var(--success);border-color:var(--success);background:var(--success-soft)}.catalog-badge.gated{color:var(--warning);border-color:var(--warning);background:var(--warning-soft)}.catalog-quants{border-top:1px solid var(--border-0);flex-direction:column;gap:4px;max-height:320px;padding:8px 11px 10px;display:flex;overflow-y:auto}.catalog-gated-note{font-size:var(--fs-meta);color:var(--warning);margin:0 0 6px}.catalog-quant{grid-template-columns:minmax(0,1fr) auto auto auto;align-items:center;gap:10px;padding:4px 0;font-size:12.5px;display:grid}.catalog-quant button{height:26px;font-size:var(--fs-meta);padding:0 10px}.catalog-quant-name{font-family:var(--mono,monospace);overflow-wrap:anywhere;align-items:baseline;gap:6px;display:flex}.catalog-quant-name em,.catalog-quant-name i{font-style:normal;font-size:var(--fs-micro);color:var(--text-2);font-family:inherit}.catalog-quant-name em{color:var(--accent)}.catalog-quant-size{font-variant-numeric:tabular-nums;color:var(--text-2)}.catalog-quant-fit{font-size:var(--fs-micro);white-space:nowrap;border-radius:999px;padding:1px 6px}.catalog-quant-fit[data-fit=fits]{color:var(--success);background:var(--success-soft)}.catalog-quant-fit[data-fit=tight]{color:var(--warning);background:var(--warning-soft)}.catalog-quant-fit[data-fit=too-large]{color:var(--danger);background:var(--danger-soft)}.catalog-progress{font-size:var(--fs-meta);color:var(--text-2);flex-direction:column;gap:4px;margin-top:8px;display:flex}.catalog-progress span{overflow-wrap:anywhere}.catalog-progress-track{background:var(--bg-3);border-radius:999px;height:5px;overflow:hidden}.catalog-progress-fill{background:var(--accent);height:100%;transition:width .2s}.quick-setup{flex-direction:column;gap:10px;display:flex}.quick-setup-variant{align-items:center;gap:8px;font-size:12.5px;display:flex}.quick-setup-variant select{border-radius:var(--r-sm);border:1px solid var(--border-0);background:var(--bg-2);height:30px;font-size:12.5px}.quick-setup-detected{color:var(--text-2);margin:0;font-size:12.5px}.quick-setup-detected b{color:var(--text-1);font-weight:500}.quick-setup-steps{flex-direction:column;gap:8px;margin:0;padding-left:18px;display:flex}.quick-setup-steps li{font-size:12.5px}.quick-setup-steps li[data-action=reuse],.quick-setup-steps li[data-action=none]{color:var(--text-2)}.quick-setup-step-title{overflow-wrap:anywhere;display:block}.quick-setup-step-title em{font-style:normal;font-size:var(--fs-micro);color:var(--text-2);margin-left:6px}.quick-setup-step-meta{font-size:var(--fs-meta);color:var(--text-2);font-family:var(--mono,monospace);overflow-wrap:anywhere;display:block}.quick-setup-destination{font-size:var(--fs-meta);color:var(--text-2);overflow-wrap:anywhere;margin:0}.quick-setup-warning{font-size:var(--fs-meta);color:var(--warning);margin:0}@media (width>=1800px){body{font-size:16px}.app{grid-template-columns:296px 1fr}.view{max-width:1280px}.thread-hero,.thread-actions-bar,.thread-body{max-width:1120px}.turn-body{font-size:18px}.turn[data-role=user] .turn-body{font-size:17px}.r-title{font-size:17.5px}.r-snippet{font-size:15.5px}}@media (width<=1180px){.app,.app[data-reading=true]{grid-template-columns:1fr}.sidebar,.sidebar.rail{z-index:40;width:min(320px,86vw);transition:transform .2s cubic-bezier(.4,0,.2,1);display:flex;position:fixed;inset:0 auto 0 0;transform:translate(-105%);box-shadow:24px 0 60px -32px oklch(0% 0 0/.8)}.app[data-sidebar-open=true] .sidebar{transform:translate(0)}.sidebar-scrim{z-index:35;background:var(--overlay-bg);opacity:0;pointer-events:none;border:0;transition:opacity .2s;display:block;position:fixed;inset:0}.app[data-sidebar-open=true] .sidebar-scrim{opacity:1;pointer-events:auto}.icon-btn.mobile-menu-btn{display:grid}.thread-bar{gap:10px}.thread-bar .bar-meta,.thread-bar kbd{display:none}.thread-bar .path-crumb{max-width:28vw}.view{max-width:none}}@media (width<=640px){body{font-size:15px}.topbar{gap:8px;height:52px;padding:0 12px}.topbar-actions{gap:4px}.topbar-action{padding:0 8px}.topbar-action.primary span{display:none}.view{gap:14px;padding:16px 14px 72px}.search-card{grid-template-columns:38px 1fr;grid-auto-rows:minmax(42px,auto);padding:0 6px 6px 0}.toolbar-hint{display:none}.model-filter{grid-template-columns:auto 1fr;width:100%}.role-chips{grid-template-columns:repeat(3,minmax(0,1fr));width:100%;display:grid}.role-chip{justify-content:center}.result{padding:13px 12px}.result-head{flex-wrap:wrap}.r-source{flex-basis:100%}.results-meta-bar{flex-wrap:wrap}.results-meta-bar .h{flex:100%}.results-meta-bar .conv-filter{flex:150px;width:auto}.r-foot>span:last-child{width:100%;margin-left:0!important}.thread-hero{padding:22px 16px}.thread-body{gap:18px;padding:8px 16px 80px}.thread-body:before{left:30px}.thread-actions-bar{padding:0 16px 12px}.thread-bar{min-height:54px;padding:0 10px}.thread-back span,.thread-bar .path-crumb{display:none}.turn{grid-template-columns:32px 1fr;gap:12px}.turn-avatar{width:26px;height:26px;margin-left:0}.turn-head{flex-wrap:wrap;height:auto;min-height:24px}.turn-body{font-size:15.5px}.turn[data-role=user] .turn-body{font-size:15px}}
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
2
+ <rect width="32" height="32" rx="7" fill="#16242b"/>
3
+ <circle cx="14" cy="14" r="6.5" fill="none" stroke="#4cc9d6" stroke-width="2.4"/>
4
+ <path d="M19 19l5 5" fill="none" stroke="#4cc9d6" stroke-width="2.4" stroke-linecap="round"/>
5
+ <path d="M14 9.5v2M14 16.5v2M9.5 14h2M16.5 14h2" stroke="#9fe8f0" stroke-width="1.5" stroke-linecap="round"/>
6
+ </svg>
@@ -0,0 +1,28 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
7
+ <title>ThreadShelf — local semantic search for AI chats</title>
8
+ <meta
9
+ name="description"
10
+ content="Local-first semantic search and backup tool for AI chat exports (Google AI Studio, OpenRouter, LM Studio, ChatGPT, Claude)."
11
+ />
12
+ <script type="module" crossorigin src="/assets/index-CIm_Idqi.js"></script>
13
+ <link rel="stylesheet" crossorigin href="/assets/index-Dv09K2vS.css">
14
+ </head>
15
+ <body>
16
+ <div id="root"></div>
17
+ <script>
18
+ // Apply persisted theme before first paint to avoid a flash of the wrong theme.
19
+ try {
20
+ var s = JSON.parse(localStorage.getItem('threadshelf:ui') || '{}');
21
+ var t = s && s.state && s.state.theme;
22
+ document.documentElement.dataset.theme = t === 'light' ? 'light' : 'dark';
23
+ } catch (e) {
24
+ document.documentElement.dataset.theme = 'dark';
25
+ }
26
+ </script>
27
+ </body>
28
+ </html>
@@ -0,0 +1,228 @@
1
+ /*
2
+ * OpenRouter BULK export (run in browser DevTools console).
3
+ *
4
+ * Exports EVERY chat in your sidebar — one JSON file per chat — so you can drop the
5
+ * whole download into a folder and index it in one go. For a single chat instead,
6
+ * use scripts/openrouter-export-browser.js.
7
+ *
8
+ * How to use:
9
+ * 1) Open https://openrouter.ai/ signed in, with your chat list (sidebar) visible.
10
+ * 2) Open DevTools Console (F12), paste this whole file, press Enter.
11
+ * 3) Allow "multiple downloads" if the browser asks.
12
+ * 4) Move the downloaded *.json files into a folder and index that folder.
13
+ *
14
+ * Each file is compatible with the ThreadShelf parser (platform: "openrouter").
15
+ * Selectors below match OpenRouter's chat UI as of 2026-06; if the UI changes they
16
+ * may need updating (see test/playwright/openrouter-export.spec.js for the contract).
17
+ */
18
+ (async () => {
19
+ const CONFIG = {
20
+ DOWNLOAD_DELAY_MS: 700,
21
+ NAV_TIMEOUT_MS: 15000,
22
+ SCROLL_PAUSE_MS: 350,
23
+ MAX_SCROLLS: 250,
24
+ };
25
+
26
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
27
+
28
+ function normalizeText(text) {
29
+ return String(text || '')
30
+ .replace(/\u00a0/g, ' ')
31
+ .replace(/\n{3,}/g, '\n\n')
32
+ .trim();
33
+ }
34
+
35
+ function safeName(text) {
36
+ return (
37
+ normalizeText(text)
38
+ .replace(/[\\/:*?"<>|]+/g, '-')
39
+ .replace(/\s+/g, '_')
40
+ .slice(0, 60) || 'chat'
41
+ );
42
+ }
43
+
44
+ // Text of a node with chrome (buttons, icons, avatars) stripped out.
45
+ function cleanText(node) {
46
+ if (!node) return '';
47
+ const clone = node.cloneNode(true);
48
+ clone
49
+ .querySelectorAll('button, svg, picture, img, [role="button"], [aria-hidden="true"]')
50
+ .forEach((n) => n.remove());
51
+ return normalizeText(clone.innerText || clone.textContent || '');
52
+ }
53
+
54
+ // The rendered message text lives in a privacy-masked panel. For assistant
55
+ // messages with reasoning there are two panels (reasoning first, answer last);
56
+ // we keep the last. Falls back to prose elements, then the whole node.
57
+ function messageBody(el) {
58
+ const panels = el.querySelectorAll('[data-dd-privacy="hidden"]');
59
+ if (panels.length) return cleanText(panels[panels.length - 1]);
60
+ const prose = Array.from(el.querySelectorAll('p, li, pre, h1, h2, h3, h4, blockquote'));
61
+ if (prose.length) return normalizeText(prose.map((n) => n.textContent || '').join('\n'));
62
+ return cleanText(el);
63
+ }
64
+
65
+ function getModel(el) {
66
+ const fav = el.querySelector('img[alt^="Favicon for"], img[alt*="Favicon"]');
67
+ if (fav) {
68
+ const m = (fav.getAttribute('alt') || '').replace(/favicon for/i, '').trim();
69
+ if (m) return m;
70
+ }
71
+ return undefined;
72
+ }
73
+
74
+ function extractTurns() {
75
+ const els = Array.from(
76
+ document.querySelectorAll('[data-testid="user-message"], [data-testid="assistant-message"]'),
77
+ );
78
+ const turns = [];
79
+ const seen = new Set();
80
+ for (const el of els) {
81
+ const role = el.getAttribute('data-testid') === 'user-message' ? 'user' : 'assistant';
82
+ const content = messageBody(el);
83
+ if (!content) continue;
84
+ const key = `${role}:${content}`;
85
+ if (seen.has(key)) continue;
86
+ seen.add(key);
87
+ const turn = { role, content };
88
+ if (role === 'assistant') {
89
+ const model = getModel(el);
90
+ if (model) turn.model = model;
91
+ }
92
+ turns.push(turn);
93
+ }
94
+ return turns;
95
+ }
96
+
97
+ // Sidebar chat links look like /chat?room=orc-<id>.
98
+ function findChats() {
99
+ const anchors = Array.from(document.querySelectorAll('a[href*="room="]'));
100
+ const byId = new Map();
101
+ for (const a of anchors) {
102
+ const href = a.getAttribute('href') || '';
103
+ const match = href.match(/[?&]room=([^&#]+)/);
104
+ if (!match) continue;
105
+ const id = match[1];
106
+ if (id && !byId.has(id)) byId.set(id, { id, href, title: normalizeText(a.textContent || '') });
107
+ }
108
+ return [...byId.values()];
109
+ }
110
+
111
+ function findAnchor(id) {
112
+ return Array.from(document.querySelectorAll('a[href*="room="]')).find((a) =>
113
+ (a.getAttribute('href') || '').includes(id),
114
+ );
115
+ }
116
+
117
+ function buildPayload(turns, title) {
118
+ return {
119
+ platform: 'openrouter',
120
+ exportedAt: new Date().toISOString(),
121
+ pageTitle: document.title,
122
+ title: title || document.title,
123
+ sourceUrl: location.href,
124
+ turns,
125
+ };
126
+ }
127
+
128
+ function getScrollContainer() {
129
+ return (
130
+ document.querySelector('[data-testid="message-list-scroll"]') ||
131
+ document.querySelector('[data-testid="message-list-content"]')?.parentElement ||
132
+ document.scrollingElement ||
133
+ document.documentElement
134
+ );
135
+ }
136
+
137
+ async function autoScrollToLoadAll() {
138
+ const container = getScrollContainer();
139
+ let prev = -1;
140
+ let stable = 0;
141
+ for (let i = 0; i < CONFIG.MAX_SCROLLS && stable < 3; i++) {
142
+ const count = document.querySelectorAll(
143
+ '[data-testid="user-message"], [data-testid="assistant-message"]',
144
+ ).length;
145
+ stable = count === prev ? stable + 1 : 0;
146
+ prev = count;
147
+ container.scrollTop = 0;
148
+ await sleep(CONFIG.SCROLL_PAUSE_MS);
149
+ }
150
+ container.scrollTop = container.scrollHeight;
151
+ await sleep(CONFIG.SCROLL_PAUSE_MS);
152
+ }
153
+
154
+ async function waitForChat(id) {
155
+ const start = Date.now();
156
+ while (Date.now() - start < CONFIG.NAV_TIMEOUT_MS) {
157
+ if (location.href.includes(id) && extractTurns().length > 0) return true;
158
+ await sleep(300);
159
+ }
160
+ return false;
161
+ }
162
+
163
+ function download(payload, fileName) {
164
+ const blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/json' });
165
+ const url = URL.createObjectURL(blob);
166
+ const a = document.createElement('a');
167
+ a.href = url;
168
+ a.download = fileName;
169
+ document.body.appendChild(a);
170
+ a.click();
171
+ a.remove();
172
+ URL.revokeObjectURL(url);
173
+ }
174
+
175
+ // Test hook: expose internals and skip side effects when driven by a test.
176
+ if (typeof window !== 'undefined' && window.__OR_TEST__) {
177
+ window.__ORX = { findChats, extractTurns, buildPayload, normalizeText, getModel };
178
+ return;
179
+ }
180
+
181
+ const chats = findChats();
182
+ if (!chats.length) {
183
+ console.error(
184
+ 'No chats found in the sidebar. Open openrouter.ai with your chat list visible, then re-run. ' +
185
+ 'For a single open chat use scripts/openrouter-export-browser.js.',
186
+ );
187
+ return;
188
+ }
189
+
190
+ console.log(`Found ${chats.length} chats. Starting bulk export…`);
191
+ let exported = 0;
192
+ let skipped = 0;
193
+ for (const [i, chat] of chats.entries()) {
194
+ try {
195
+ if (!location.href.includes(chat.id)) {
196
+ const anchor = findAnchor(chat.id);
197
+ if (!anchor) {
198
+ console.warn(`(${i + 1}/${chats.length}) anchor not found, skipping ${chat.id}`);
199
+ skipped++;
200
+ continue;
201
+ }
202
+ anchor.click();
203
+ }
204
+ if (!(await waitForChat(chat.id))) {
205
+ console.warn(`(${i + 1}/${chats.length}) timed out loading ${chat.id}, skipping`);
206
+ skipped++;
207
+ continue;
208
+ }
209
+ await autoScrollToLoadAll();
210
+ const turns = extractTurns();
211
+ if (!turns.length) {
212
+ console.warn(`(${i + 1}/${chats.length}) no messages in ${chat.id}, skipping`);
213
+ skipped++;
214
+ continue;
215
+ }
216
+ const title = chat.title || document.title;
217
+ download(buildPayload(turns, title), `openrouter-${safeName(title)}-${safeName(chat.id)}.json`);
218
+ exported++;
219
+ console.log(`(${i + 1}/${chats.length}) exported "${title}" (${turns.length} messages)`);
220
+ await sleep(CONFIG.DOWNLOAD_DELAY_MS);
221
+ } catch (err) {
222
+ skipped++;
223
+ console.warn(`(${i + 1}/${chats.length}) failed on ${chat.id}:`, err);
224
+ }
225
+ }
226
+
227
+ console.log(`Done. Exported ${exported} chats, skipped ${skipped}. Index the downloaded folder.`);
228
+ })();
@@ -0,0 +1,153 @@
1
+ /*
2
+ * OpenRouter SINGLE-chat export (run in browser DevTools console).
3
+ *
4
+ * Exports the chat that is currently open into one parser-compatible JSON file.
5
+ * To export EVERY chat at once, use scripts/openrouter-export-all.js instead.
6
+ *
7
+ * How to use:
8
+ * 1) Open the chat you want at https://openrouter.ai/chat?room=...
9
+ * 2) Scroll up so the whole conversation is loaded.
10
+ * 3) Open DevTools Console (F12), paste this whole file, press Enter.
11
+ * 4) A JSON file downloads. Move it into a folder and index that folder.
12
+ *
13
+ * Output format is compatible with the ThreadShelf parser (platform: "openrouter").
14
+ * Selectors match OpenRouter's chat UI as of 2026-06 (see
15
+ * test/playwright/openrouter-export.spec.js for the contract).
16
+ */
17
+ (async () => {
18
+ const CONFIG = { SCROLL_PAUSE_MS: 350, MAX_SCROLLS: 250 };
19
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
20
+
21
+ function normalizeText(text) {
22
+ return String(text || '')
23
+ .replace(/\u00a0/g, ' ')
24
+ .replace(/\n{3,}/g, '\n\n')
25
+ .trim();
26
+ }
27
+
28
+ function safeName(text) {
29
+ return (
30
+ normalizeText(text)
31
+ .replace(/[\\/:*?"<>|]+/g, '-')
32
+ .replace(/\s+/g, '_')
33
+ .slice(0, 60) || 'chat'
34
+ );
35
+ }
36
+
37
+ function cleanText(node) {
38
+ if (!node) return '';
39
+ const clone = node.cloneNode(true);
40
+ clone
41
+ .querySelectorAll('button, svg, picture, img, [role="button"], [aria-hidden="true"]')
42
+ .forEach((n) => n.remove());
43
+ return normalizeText(clone.innerText || clone.textContent || '');
44
+ }
45
+
46
+ // Message text is in a privacy-masked panel; for assistant messages with
47
+ // reasoning the answer is the last panel (reasoning is first). Fallbacks: prose,
48
+ // then the node itself.
49
+ function messageBody(el) {
50
+ const panels = el.querySelectorAll('[data-dd-privacy="hidden"]');
51
+ if (panels.length) return cleanText(panels[panels.length - 1]);
52
+ const prose = Array.from(el.querySelectorAll('p, li, pre, h1, h2, h3, h4, blockquote'));
53
+ if (prose.length) return normalizeText(prose.map((n) => n.textContent || '').join('\n'));
54
+ return cleanText(el);
55
+ }
56
+
57
+ function getModel(el) {
58
+ const fav = el.querySelector('img[alt^="Favicon for"], img[alt*="Favicon"]');
59
+ if (fav) {
60
+ const m = (fav.getAttribute('alt') || '').replace(/favicon for/i, '').trim();
61
+ if (m) return m;
62
+ }
63
+ return undefined;
64
+ }
65
+
66
+ function extractTurns() {
67
+ const els = Array.from(
68
+ document.querySelectorAll('[data-testid="user-message"], [data-testid="assistant-message"]'),
69
+ );
70
+ const turns = [];
71
+ const seen = new Set();
72
+ for (const el of els) {
73
+ const role = el.getAttribute('data-testid') === 'user-message' ? 'user' : 'assistant';
74
+ const content = messageBody(el);
75
+ if (!content) continue;
76
+ const key = `${role}:${content}`;
77
+ if (seen.has(key)) continue;
78
+ seen.add(key);
79
+ const turn = { role, content };
80
+ if (role === 'assistant') {
81
+ const model = getModel(el);
82
+ if (model) turn.model = model;
83
+ }
84
+ turns.push(turn);
85
+ }
86
+ return turns;
87
+ }
88
+
89
+ function buildPayload(turns, title) {
90
+ return {
91
+ platform: 'openrouter',
92
+ exportedAt: new Date().toISOString(),
93
+ pageTitle: document.title,
94
+ title: title || document.title,
95
+ sourceUrl: location.href,
96
+ turns,
97
+ };
98
+ }
99
+
100
+ function getScrollContainer() {
101
+ return (
102
+ document.querySelector('[data-testid="message-list-scroll"]') ||
103
+ document.querySelector('[data-testid="message-list-content"]')?.parentElement ||
104
+ document.scrollingElement ||
105
+ document.documentElement
106
+ );
107
+ }
108
+
109
+ async function autoScrollToLoadAll() {
110
+ const container = getScrollContainer();
111
+ let prev = -1;
112
+ let stable = 0;
113
+ for (let i = 0; i < CONFIG.MAX_SCROLLS && stable < 3; i++) {
114
+ const count = document.querySelectorAll(
115
+ '[data-testid="user-message"], [data-testid="assistant-message"]',
116
+ ).length;
117
+ stable = count === prev ? stable + 1 : 0;
118
+ prev = count;
119
+ container.scrollTop = 0;
120
+ await sleep(CONFIG.SCROLL_PAUSE_MS);
121
+ }
122
+ container.scrollTop = container.scrollHeight;
123
+ await sleep(CONFIG.SCROLL_PAUSE_MS);
124
+ }
125
+
126
+ function download(payload, fileName) {
127
+ const blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/json' });
128
+ const url = URL.createObjectURL(blob);
129
+ const a = document.createElement('a');
130
+ a.href = url;
131
+ a.download = fileName;
132
+ document.body.appendChild(a);
133
+ a.click();
134
+ a.remove();
135
+ URL.revokeObjectURL(url);
136
+ }
137
+
138
+ // Test hook: expose internals and skip side effects when driven by a test.
139
+ if (typeof window !== 'undefined' && window.__OR_TEST__) {
140
+ window.__ORX = { extractTurns, buildPayload, normalizeText, getModel };
141
+ return;
142
+ }
143
+
144
+ await autoScrollToLoadAll();
145
+ const turns = extractTurns();
146
+ if (!turns.length) {
147
+ console.error('No messages found. Open a chat, scroll it fully, and run again.');
148
+ return;
149
+ }
150
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-');
151
+ download(buildPayload(turns, document.title), `openrouter-${safeName(document.title)}-${stamp}.json`);
152
+ console.log(`Exported ${turns.length} messages (single chat).`);
153
+ })();