secondbrain-py 0.2.1__py3-none-any.whl

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 (273) hide show
  1. brain/__init__.py +0 -0
  2. brain/__main__.py +18 -0
  3. brain/_capture_command.py +445 -0
  4. brain/_compose.py +52 -0
  5. brain/activity.py +206 -0
  6. brain/ask.py +631 -0
  7. brain/audio.py +591 -0
  8. brain/backfill/__init__.py +12 -0
  9. brain/backfill/search_extras.py +141 -0
  10. brain/backfill/source_rows.py +101 -0
  11. brain/bin/__init__.py +1 -0
  12. brain/bin/_launcher.py +107 -0
  13. brain/bin/down.py +8 -0
  14. brain/bin/launchd.py +268 -0
  15. brain/bin/monitor.py +570 -0
  16. brain/bin/rebuild.py +8 -0
  17. brain/bin/status.py +8 -0
  18. brain/bin/up.py +8 -0
  19. brain/brief.py +272 -0
  20. brain/capture.py +49 -0
  21. brain/chat.py +293 -0
  22. brain/cli.py +9760 -0
  23. brain/cli_claude.py +81 -0
  24. brain/cli_connect.py +285 -0
  25. brain/cli_demo.py +266 -0
  26. brain/config.py +1949 -0
  27. brain/connect.py +925 -0
  28. brain/db.py +540 -0
  29. brain/demo/__init__.py +452 -0
  30. brain/demo/corpus/manifest.json +403 -0
  31. brain/demo/embedder.py +74 -0
  32. brain/durations.py +84 -0
  33. brain/edit_session.py +156 -0
  34. brain/editor.py +67 -0
  35. brain/elicit/__init__.py +16 -0
  36. brain/elicit/detectors.py +250 -0
  37. brain/elicit/drafter.py +70 -0
  38. brain/elicit/queue.py +220 -0
  39. brain/elicit/schema.py +48 -0
  40. brain/elicit/session.py +445 -0
  41. brain/embedding_targets.py +54 -0
  42. brain/embeddings.py +424 -0
  43. brain/enrichment.py +808 -0
  44. brain/errors.py +357 -0
  45. brain/eval/__init__.py +129 -0
  46. brain/eval/answer_eval.py +281 -0
  47. brain/eval/baseline.py +265 -0
  48. brain/eval/concept_extraction.py +378 -0
  49. brain/eval/corpus.py +152 -0
  50. brain/eval/errors.py +19 -0
  51. brain/eval/graph_baseline.py +226 -0
  52. brain/eval/graph_retrieval.py +202 -0
  53. brain/eval/graph_runner.py +319 -0
  54. brain/eval/metrics.py +101 -0
  55. brain/eval/runner.py +223 -0
  56. brain/format.py +783 -0
  57. brain/gaps.py +390 -0
  58. brain/graph_rag/__init__.py +94 -0
  59. brain/graph_rag/_retrieval_common.py +113 -0
  60. brain/graph_rag/aggregates.py +303 -0
  61. brain/graph_rag/aliases/__init__.py +583 -0
  62. brain/graph_rag/backends/__init__.py +10 -0
  63. brain/graph_rag/backends/_age_helpers.py +473 -0
  64. brain/graph_rag/backends/age.py +782 -0
  65. brain/graph_rag/backends/base.py +272 -0
  66. brain/graph_rag/build.py +344 -0
  67. brain/graph_rag/communities.py +644 -0
  68. brain/graph_rag/communities_summary.py +437 -0
  69. brain/graph_rag/concepts.py +202 -0
  70. brain/graph_rag/cooccur.py +193 -0
  71. brain/graph_rag/cross_type.py +312 -0
  72. brain/graph_rag/extract.py +885 -0
  73. brain/graph_rag/fuse.py +371 -0
  74. brain/graph_rag/global_.py +412 -0
  75. brain/graph_rag/grouping.py +372 -0
  76. brain/graph_rag/person_resolver.py +167 -0
  77. brain/graph_rag/reconcile.py +792 -0
  78. brain/graph_rag/relational.py +353 -0
  79. brain/graph_rag/retrieve.py +526 -0
  80. brain/graph_rag/router.py +288 -0
  81. brain/graph_rag/schema.py +320 -0
  82. brain/graph_rag/sync.py +237 -0
  83. brain/graph_rag/tenancy.py +43 -0
  84. brain/graph_rag/themes.py +501 -0
  85. brain/graph_rag/weighting.py +202 -0
  86. brain/ingest/__init__.py +1926 -0
  87. brain/ingest/chunker.py +249 -0
  88. brain/ingest/docx.py +40 -0
  89. brain/ingest/gmail.py +621 -0
  90. brain/ingest/markdown.py +37 -0
  91. brain/ingest/pdf.py +61 -0
  92. brain/ingest/stdin.py +22 -0
  93. brain/ingest/sub_tokens.py +91 -0
  94. brain/ingest/text.py +16 -0
  95. brain/interactions.py +205 -0
  96. brain/maintenance.py +355 -0
  97. brain/mcp_server.py +3405 -0
  98. brain/migrations/001_init.sql +43 -0
  99. brain/migrations/002_qwen3_embedding.sql +17 -0
  100. brain/migrations/003_vault_model.sql +41 -0
  101. brain/migrations/004_relax_content_hash_uniqueness.sql +18 -0
  102. brain/migrations/005_derived_links.sql +67 -0
  103. brain/migrations/006_dedup_file_by_source_path.sql +25 -0
  104. brain/migrations/007_email_thread_and_draft.sql +15 -0
  105. brain/migrations/008_gmail_thread_unique.sql +11 -0
  106. brain/migrations/009_chunks_weighted_tsv.sql +28 -0
  107. brain/migrations/010_interactions.sql +30 -0
  108. brain/migrations/011_documents_summary.sql +23 -0
  109. brain/migrations/012_graphrag.sql +171 -0
  110. brain/migrations/013_graphrag_communities.sql +125 -0
  111. brain/migrations/014_graphrag_community_summary_hash.sql +33 -0
  112. brain/migrations/015_interactions_graph_targets.sql +89 -0
  113. brain/migrations/016_index_hygiene.sql +61 -0
  114. brain/migrations/017_elicit.sql +30 -0
  115. brain/migrations/018_review_gap_signal_kinds.sql +40 -0
  116. brain/migrations/019_search_queries.sql +35 -0
  117. brain/migrations/020_link_suggestions.sql +40 -0
  118. brain/migrations/021_timeline_doc_date.sql +34 -0
  119. brain/migrations/022_link_suggestions_undirected.sql +84 -0
  120. brain/migrations/023_search_queries_fts_count.sql +28 -0
  121. brain/quartz_overrides/__init__.py +8 -0
  122. brain/quartz_overrides/quartz/bootstrap-cli.mjs +65 -0
  123. brain/quartz_overrides/quartz/build.ts +568 -0
  124. brain/quartz_overrides/quartz/cli/args.js +152 -0
  125. brain/quartz_overrides/quartz/cli/build_partial_handler.js +544 -0
  126. brain/quartz_overrides/quartz/cli/handlers.js +636 -0
  127. brain/quartz_overrides/quartz/components/CommandPalette.tsx +172 -0
  128. brain/quartz_overrides/quartz/components/Explorer.tsx +198 -0
  129. brain/quartz_overrides/quartz/components/Footer.tsx +27 -0
  130. brain/quartz_overrides/quartz/components/Graph.tsx +468 -0
  131. brain/quartz_overrides/quartz/components/PageTitle.tsx +72 -0
  132. brain/quartz_overrides/quartz/components/RelatedDocs.tsx +38 -0
  133. brain/quartz_overrides/quartz/components/Search.tsx +161 -0
  134. brain/quartz_overrides/quartz/components/SummaryLede.tsx +72 -0
  135. brain/quartz_overrides/quartz/components/index.ts +92 -0
  136. brain/quartz_overrides/quartz/components/pages/TagContent.tsx +272 -0
  137. brain/quartz_overrides/quartz/components/scripts/commandPalette.inline.ts +665 -0
  138. brain/quartz_overrides/quartz/components/scripts/explorer.inline.ts +768 -0
  139. brain/quartz_overrides/quartz/components/scripts/graph.inline.ts +2302 -0
  140. brain/quartz_overrides/quartz/components/scripts/relatedDocs.inline.ts +163 -0
  141. brain/quartz_overrides/quartz/components/scripts/search.inline.ts +1011 -0
  142. brain/quartz_overrides/quartz/plugins/emitters/contentIndex.ts +546 -0
  143. brain/quartz_overrides/quartz/plugins/transformers/codeCopy.ts +94 -0
  144. brain/quartz_overrides/quartz/plugins/transformers/derivedFenceMark.ts +302 -0
  145. brain/quartz_overrides/quartz/plugins/transformers/emailThread.ts +148 -0
  146. brain/quartz_overrides/quartz/plugins/transformers/emptyDoorFilter.ts +213 -0
  147. brain/quartz_overrides/quartz/plugins/transformers/index.ts +114 -0
  148. brain/quartz_overrides/quartz/plugins/transformers/linkKindMark.ts +205 -0
  149. brain/quartz_overrides/quartz/plugins/transformers/linkSourceTag.ts +104 -0
  150. brain/quartz_overrides/quartz/plugins/transformers/relativeDate.ts +100 -0
  151. brain/quartz_overrides/quartz/plugins/transformers/reloadSignal.ts +131 -0
  152. brain/quartz_overrides/quartz/processors/parse.ts +371 -0
  153. brain/quartz_overrides/quartz/processors/parser_cache.ts +78 -0
  154. brain/quartz_overrides/quartz/static/brain-logo-dark.png +0 -0
  155. brain/quartz_overrides/quartz/static/brain-logo-light.png +0 -0
  156. brain/quartz_overrides/quartz/static/codeCopy.js +196 -0
  157. brain/quartz_overrides/quartz/static/emailThread.js +334 -0
  158. brain/quartz_overrides/quartz/static/favicon.ico +0 -0
  159. brain/quartz_overrides/quartz/static/icon.png +0 -0
  160. brain/quartz_overrides/quartz/static/linkSourceTag.js +104 -0
  161. brain/quartz_overrides/quartz/static/relativeDate.js +142 -0
  162. brain/quartz_overrides/quartz/static/reload.js +168 -0
  163. brain/quartz_overrides/quartz/styles/brain/_article.scss +252 -0
  164. brain/quartz_overrides/quartz/styles/brain/_atmosphere.scss +113 -0
  165. brain/quartz_overrides/quartz/styles/brain/_callouts.scss +180 -0
  166. brain/quartz_overrides/quartz/styles/brain/_cmdk.scss +7 -0
  167. brain/quartz_overrides/quartz/styles/brain/_code.scss +208 -0
  168. brain/quartz_overrides/quartz/styles/brain/_command_palette.scss +369 -0
  169. brain/quartz_overrides/quartz/styles/brain/_email_thread.scss +228 -0
  170. brain/quartz_overrides/quartz/styles/brain/_explorer.scss +142 -0
  171. brain/quartz_overrides/quartz/styles/brain/_home.scss +182 -0
  172. brain/quartz_overrides/quartz/styles/brain/_links.scss +322 -0
  173. brain/quartz_overrides/quartz/styles/brain/_marginalia.scss +117 -0
  174. brain/quartz_overrides/quartz/styles/brain/_motion.scss +175 -0
  175. brain/quartz_overrides/quartz/styles/brain/_people_hub.scss +100 -0
  176. brain/quartz_overrides/quartz/styles/brain/_related_docs.scss +137 -0
  177. brain/quartz_overrides/quartz/styles/brain/_search.scss +252 -0
  178. brain/quartz_overrides/quartz/styles/brain/_sidebar.scss +468 -0
  179. brain/quartz_overrides/quartz/styles/brain/_summary_lede.scss +56 -0
  180. brain/quartz_overrides/quartz/styles/brain/_surface.scss +43 -0
  181. brain/quartz_overrides/quartz/styles/brain/_tag_content.scss +118 -0
  182. brain/quartz_overrides/quartz/styles/brain/_tokens.scss +197 -0
  183. brain/quartz_overrides/quartz/styles/brain/_typography.scss +92 -0
  184. brain/quartz_overrides/quartz/styles/custom.scss +89 -0
  185. brain/quartz_overrides/quartz/styles/graph.scss +505 -0
  186. brain/quartz_overrides/quartz/util/ctx.ts +92 -0
  187. brain/quartz_overrides/quartz/util/fastpath_manifest.ts +608 -0
  188. brain/quartz_overrides/quartz/util/path.ts +358 -0
  189. brain/quartz_overrides/quartz/util/sourceIcons.ts +55 -0
  190. brain/quartz_overrides/quartz.config.ts +270 -0
  191. brain/quartz_overrides/quartz.layout.ts +314 -0
  192. brain/queries.py +1188 -0
  193. brain/rank_fusion.py +8 -0
  194. brain/resurface.py +210 -0
  195. brain/review/__init__.py +26 -0
  196. brain/review/emit.py +27 -0
  197. brain/review/queries.py +436 -0
  198. brain/review/render.py +196 -0
  199. brain/review/scans.py +355 -0
  200. brain/review/weekly.py +413 -0
  201. brain/search.py +704 -0
  202. brain/set_similarity.py +15 -0
  203. brain/setup.py +1205 -0
  204. brain/tags.py +56 -0
  205. brain/templates/Caddyfile.j2 +9 -0
  206. brain/templates/__init__.py +1 -0
  207. brain/templates/bin/__init__.py +1 -0
  208. brain/templates/bin/_brain-brief-fg.sh +25 -0
  209. brain/templates/bin/_brain-build-fg.sh +53 -0
  210. brain/templates/bin/_brain-watcher-fg.sh +65 -0
  211. brain/templates/bin/brain-down.sh +89 -0
  212. brain/templates/bin/brain-status.sh +83 -0
  213. brain/templates/bin/brain-up.sh +221 -0
  214. brain/templates/docker/age/Dockerfile +79 -0
  215. brain/templates/docker-compose.stock.yml.j2 +26 -0
  216. brain/templates/docker-compose.yml.j2 +34 -0
  217. brain/templates/env.example +190 -0
  218. brain/templates/launchd/__init__.py +1 -0
  219. brain/templates/launchd/com.brain.brief.plist.j2 +45 -0
  220. brain/templates/launchd/com.brain.build.plist.j2 +46 -0
  221. brain/templates/launchd/com.brain.watcher.plist.j2 +46 -0
  222. brain/templates/skill/SKILL.md +63 -0
  223. brain/templates/skill/__init__.py +1 -0
  224. brain/timeline.py +834 -0
  225. brain/todo.py +124 -0
  226. brain/uninstall.py +185 -0
  227. brain/vault/__init__.py +115 -0
  228. brain/vault/_atomic.py +25 -0
  229. brain/vault/daily_index.py +228 -0
  230. brain/vault/derived_links/__init__.py +50 -0
  231. brain/vault/derived_links/directory.py +683 -0
  232. brain/vault/derived_links/fence.py +408 -0
  233. brain/vault/derived_links/gws.py +64 -0
  234. brain/vault/derived_links/participants.py +143 -0
  235. brain/vault/derived_links/pass_runner.py +362 -0
  236. brain/vault/derived_links/rules.py +137 -0
  237. brain/vault/export.py +683 -0
  238. brain/vault/frontmatter.py +165 -0
  239. brain/vault/graph.py +620 -0
  240. brain/vault/graph_format.py +388 -0
  241. brain/vault/link_rewrite.py +235 -0
  242. brain/vault/links.py +260 -0
  243. brain/vault/note_builder.py +211 -0
  244. brain/vault/paths.py +55 -0
  245. brain/vault/quartz_overlay.py +236 -0
  246. brain/vault/rename.py +591 -0
  247. brain/vault/resolver.py +304 -0
  248. brain/vault/slug.py +127 -0
  249. brain/vault/sync.py +1513 -0
  250. brain/vault/sync_summaries.py +264 -0
  251. brain/vault/templates.py +145 -0
  252. brain/vault/watch.py +1052 -0
  253. brain/wiki/__init__.py +6 -0
  254. brain/wiki/_github_slugger.py +76 -0
  255. brain/wiki/_person_name.py +314 -0
  256. brain/wiki/build_homepage.py +541 -0
  257. brain/wiki/build_partial.py +273 -0
  258. brain/wiki/build_people.py +934 -0
  259. brain/wiki/build_related.py +758 -0
  260. brain/wiki/build_swap.py +585 -0
  261. brain/wiki/build_watcher.py +975 -0
  262. brain/wiki/edit_classifier.py +215 -0
  263. brain/wiki/errors.py +10 -0
  264. brain/wiki/fastpath_manifest.py +475 -0
  265. brain/wiki/fastpath_state.py +174 -0
  266. brain/wiki/install.py +296 -0
  267. brain/wiki/slug.py +111 -0
  268. secondbrain_py-0.2.1.dist-info/METADATA +195 -0
  269. secondbrain_py-0.2.1.dist-info/RECORD +273 -0
  270. secondbrain_py-0.2.1.dist-info/WHEEL +5 -0
  271. secondbrain_py-0.2.1.dist-info/entry_points.txt +11 -0
  272. secondbrain_py-0.2.1.dist-info/licenses/LICENSE +21 -0
  273. secondbrain_py-0.2.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,252 @@
1
+ // Brain search popover — Phase 3.2 styling for the custom Search.tsx.
2
+ //
3
+ // This file is installed at
4
+ // `<vault>/.quartz/quartz/styles/brain/_search.scss` by `brain vault
5
+ // render --overlay` and pulled into the global SCSS via `custom.scss`'s
6
+ // `@use "./brain/search"` line. It is loaded after `_sidebar.scss` so
7
+ // the chip rail can layer on top of the sidebar's sticky header
8
+ // without the sticky band's `border-bottom` rule painting over the
9
+ // chip pills.
10
+ //
11
+ // Scope of this file:
12
+ //
13
+ // * Result row layout — `{icon} {title} {date}` on one line, with
14
+ // the snippet wrapped to a single line below. Replaces the stock
15
+ // Quartz `<h3>title</h3><p>snippet</p>` stack.
16
+ // * Source-filter chip rail above the input — pill buttons with an
17
+ // active/inactive state keyed off `[data-active="true"]` so the
18
+ // inline script can flip state without touching layout-class names.
19
+ // * Preview pane refinements — same surface tier as the rest of the
20
+ // popover; `<mark>` highlights inherit the brain accent.
21
+ //
22
+ // Tokens consumed (from `_tokens.scss`):
23
+ //
24
+ // * `--accent-soft` — chip background + mark fill
25
+ // * `--accent` — active chip border + mark color
26
+ // * `--rule` — preview-pane separator + chip border
27
+ // * `--ink-1` / `--ink-2` — title / metadata text
28
+ // * `--surface-1` — chip rail background
29
+ // * `--codeFont` — date column monospace fallback
30
+ //
31
+ // Chrome scope: every selector here is rooted under
32
+ // `.search > .search-container` so the rules can't bleed onto
33
+ // non-search markup that happens to share class names.
34
+
35
+ .search > .search-container {
36
+ position: fixed;
37
+ contain: layout;
38
+ z-index: 999;
39
+ left: 0;
40
+ top: 0;
41
+ width: 100vw;
42
+ height: 100vh;
43
+ overflow-y: auto;
44
+ display: none;
45
+ backdrop-filter: blur(4px);
46
+ }
47
+
48
+ .search > .search-container.active {
49
+ display: block;
50
+ }
51
+
52
+ .search > .search-container .brain-search-chips {
53
+ display: flex;
54
+ flex-wrap: wrap;
55
+ gap: 0.25rem;
56
+ padding: 0.5rem 0.75rem;
57
+ background: var(--surface-1, var(--light));
58
+ border-bottom: 1px solid var(--rule, var(--lightgray));
59
+ // brain: the search-space wraps every direct child (chips, input,
60
+ // results) in the upstream stylesheet's `border-radius` rule. We
61
+ // keep the chip rail visually attached to the input below by
62
+ // squaring its bottom corners.
63
+ border-bottom-left-radius: 0;
64
+ border-bottom-right-radius: 0;
65
+ margin-bottom: 0;
66
+
67
+ .brain-search-chip {
68
+ display: inline-flex;
69
+ align-items: center;
70
+ gap: 0.3rem;
71
+ padding: 0.15rem 0.6rem;
72
+ border-radius: 999px;
73
+ border: 1px solid var(--rule, var(--lightgray));
74
+ background: transparent;
75
+ color: var(--ink-2, var(--gray));
76
+ font: inherit;
77
+ font-size: 0.8rem;
78
+ line-height: 1.4;
79
+ cursor: pointer;
80
+ transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
81
+
82
+ &:hover {
83
+ background: var(--accent-soft, var(--highlight));
84
+ color: var(--ink-1, var(--darkgray));
85
+ }
86
+
87
+ &[data-active="true"] {
88
+ // brain: active chip flips fg/bg per spec. `--accent` (terracotta
89
+ // in light, peach in dark) is the same accent the snippet `<mark>`
90
+ // uses below — keeping the two in lock-step makes the rail read
91
+ // as part of the same filter affordance.
92
+ background: var(--accent, var(--secondary));
93
+ color: var(--light, white);
94
+ border-color: var(--accent, var(--secondary));
95
+ }
96
+
97
+ .brain-search-chip-icon {
98
+ font-size: 0.85rem;
99
+ line-height: 1;
100
+ }
101
+
102
+ .brain-search-chip-label {
103
+ font-variant-caps: all-small-caps;
104
+ letter-spacing: 0.04em;
105
+ }
106
+ }
107
+
108
+ .brain-search-chip-all {
109
+ font-weight: 600;
110
+ }
111
+ }
112
+
113
+ // brain: explicit `.search-bar` layout. The brain `Search.tsx` override
114
+ // drops upstream's `Search.css = style` binding, so the stock
115
+ // `& > .search-space > input { box-sizing: border-box; width: 100%;
116
+ // padding: 0.5em 1em; ... }` rule from
117
+ // `quartz/components/styles/search.scss` never loads. Without
118
+ // `width: 100%`, the input collapses to the UA-default ~177px and
119
+ // shows a visible gap on the right edge versus the chip rail and
120
+ // result rows below — and without an explicit background it reads as
121
+ // transparent against the darkened popover scrim. `_sidebar.scss`
122
+ // already paints `background: var(--surface-1); border: 1px solid
123
+ // var(--rule)` on `.search-space > input` for theme parity; this rule
124
+ // supplies the missing layout primitives plus a defense-in-depth
125
+ // background restate so a future `_sidebar.scss` refactor cannot
126
+ // reintroduce the regression silently. Top corners squared so the
127
+ // input sits flush with the chip rail above (which squares its bottom
128
+ // corners via `border-bottom-{left,right}-radius: 0`).
129
+ .search > .search-container > .search-space > .search-bar {
130
+ box-sizing: border-box;
131
+ width: 100%;
132
+ padding: 0.6rem 0.9rem;
133
+ font-family: var(--bodyFont);
134
+ font-size: 1rem;
135
+ color: var(--ink-0, var(--dark));
136
+ background: var(--surface-1, var(--light));
137
+ border-top-left-radius: 0;
138
+ border-top-right-radius: 0;
139
+
140
+ &:focus {
141
+ outline: none;
142
+ }
143
+ }
144
+
145
+ // brain: result row — flex layout with the icon and date pinned and
146
+ // the title taking the remaining width. The snippet wraps below via
147
+ // the explicit grid-column override; we keep `display: flex` for the
148
+ // header strip and reserve the snippet line as a flex item that takes
149
+ // 100% width.
150
+ .search > .search-container .results-container .result-card.brain-search-row {
151
+ display: flex;
152
+ flex-wrap: wrap;
153
+ align-items: baseline;
154
+ gap: 0.5rem;
155
+ padding: 0.65rem 0.9rem;
156
+
157
+ .brain-search-icon {
158
+ flex: 0 0 auto;
159
+ width: 1.25rem;
160
+ font-size: 1rem;
161
+ line-height: 1.2;
162
+ text-align: center;
163
+ }
164
+
165
+ .brain-search-title {
166
+ flex: 1 1 auto;
167
+ min-width: 0;
168
+ font-weight: 600;
169
+ color: var(--ink-1, var(--dark));
170
+ white-space: nowrap;
171
+ overflow: hidden;
172
+ text-overflow: ellipsis;
173
+ }
174
+
175
+ .brain-search-date {
176
+ flex: 0 0 auto;
177
+ font-family: var(--codeFont, ui-monospace, SFMono-Regular, Menlo, monospace);
178
+ font-size: 0.75rem;
179
+ opacity: 0.7;
180
+ color: var(--ink-2, var(--gray));
181
+ }
182
+
183
+ .brain-search-snippet {
184
+ flex: 0 0 100%;
185
+ width: 100%;
186
+ margin: 0;
187
+ margin-top: 0.15rem;
188
+ font-size: 0.85rem;
189
+ line-height: 1.4;
190
+ opacity: 0.85;
191
+ color: var(--ink-2, var(--gray));
192
+ // brain: clamp to a single line — the snippet is already a 240-
193
+ // char preview from the slim contentIndex, so a one-line clamp
194
+ // keeps every row visually scannable. Falls back to `overflow:
195
+ // hidden` on engines that don't honor `-webkit-line-clamp`.
196
+ display: -webkit-box;
197
+ -webkit-line-clamp: 1;
198
+ -webkit-box-orient: vertical;
199
+ overflow: hidden;
200
+ text-overflow: ellipsis;
201
+ max-height: 1.4em;
202
+
203
+ mark {
204
+ background: var(--accent-soft, var(--highlight));
205
+ color: var(--accent, var(--secondary));
206
+ border-radius: 3px;
207
+ padding: 0 0.15rem;
208
+ }
209
+ }
210
+
211
+ .brain-search-tags {
212
+ flex: 0 0 100%;
213
+ margin-top: 0.25rem;
214
+ margin-bottom: 0;
215
+ padding-left: 0;
216
+ list-style: none;
217
+ }
218
+ }
219
+
220
+ // brain: preview pane refinements. The upstream class
221
+ // `.preview-container` already has its own padding + scroll; we layer
222
+ // the brain-specific surface treatment on the brain class so the two
223
+ // stylesheets coexist.
224
+ .search > .search-container .preview-container.brain-search-preview {
225
+ border-left: 1px solid var(--rule, var(--lightgray));
226
+ padding: 1rem 1.5rem;
227
+ overflow-y: auto;
228
+
229
+ .brain-search-preview-body,
230
+ .brain-search-preview-fallback {
231
+ font-size: 0.95rem;
232
+ line-height: 1.5;
233
+ color: var(--ink-1, var(--dark));
234
+ white-space: pre-wrap;
235
+ word-break: break-word;
236
+ }
237
+
238
+ .brain-search-preview-fallback {
239
+ // brain: dimmed slightly so the user can tell the preview is the
240
+ // 240-char snippet fallback rather than the full body. Matches
241
+ // the snippet column treatment so the two reads consistently.
242
+ opacity: 0.85;
243
+ }
244
+
245
+ mark,
246
+ .highlight {
247
+ background: var(--accent-soft, var(--highlight));
248
+ color: var(--accent, var(--secondary));
249
+ border-radius: 3px;
250
+ padding: 0 0.15rem;
251
+ }
252
+ }