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,468 @@
1
+ // Brain sidebar polish — Lane C of the 2026 commonplace-book redesign.
2
+ //
3
+ // This file is installed at
4
+ // `<vault>/.quartz/quartz/styles/brain/_sidebar.scss` by `brain vault
5
+ // render --overlay` and pulled into the global SCSS via `custom.scss`'s
6
+ // `@use "./brain/sidebar"` line.
7
+ //
8
+ // Scope of this file:
9
+ //
10
+ // * Compact icon row in the LEFT sidebar — `Search`, `Darkmode`,
11
+ // `ReaderMode` rendered side-by-side as 32px square buttons with a
12
+ // consistent stroke / hover treatment. Stock Quartz draws each
13
+ // button with its own component CSS (different sizes, different
14
+ // hover behavior); this file levels them out without rewriting
15
+ // the components.
16
+ // * Sticky search header — `position: sticky; top: 0;` on the Flex
17
+ // row that holds the icon trio, so the search affordance stays in
18
+ // view as the explorer scrolls. Background `--surface-1` so the
19
+ // sticky header reads as a chrome band rather than running text.
20
+ // * Explorer tree indent guides — `border-left: 1px solid var(--rule)`
21
+ // on nested `<ul>` so the folder hierarchy reads at a glance,
22
+ // plus a smoother rotation transition on the fold caret.
23
+ // * RIGHT sidebar elevation — matching `--surface-1` background +
24
+ // `8px` border-radius on the ToC and Backlinks panels so they
25
+ // read as a pair with the graph component (which already styles
26
+ // itself in `graph.scss`). Padding follows the `0.6rem` plan spec.
27
+ //
28
+ // Scope NOT covered here:
29
+ //
30
+ // * Surface tier baseline — `_surface.scss` (Lane A) already paints
31
+ // `.sidebar { background: var(--surface-1); }`. This file only
32
+ // refines the children.
33
+ // * Graph component visuals — owned by `graph.scss` and `Graph.tsx`.
34
+ // We don't restyle the graph itself; we only add card chrome to
35
+ // its sibling panels (ToC + Backlinks).
36
+ // * Cmd-K palette — owned by `_cmdk.scss` (Lane C, separate file)
37
+ // because its visual language (modal + backdrop) is large enough
38
+ // to warrant its own partial.
39
+ //
40
+ // Tokens consumed (all from `_tokens.scss`):
41
+ //
42
+ // * `--surface-1` — sticky header band + ToC/Backlinks card bg
43
+ // * `--rule` — explorer indent guides + sticky header bottom rule
44
+ // * `--ink-0`/`--ink-2` — icon stroke + label colors
45
+ // * `--accent-soft` — icon hover background
46
+ // * `--motion-fast`/`--motion-easing` — transitions
47
+
48
+ // ---------------------------------------------------------------------------
49
+ // 1. Compact icon row + sticky search header (LEFT sidebar)
50
+ // ---------------------------------------------------------------------------
51
+ //
52
+ // Stock Quartz gives both sidebars a large top/bottom gutter via
53
+ // `.page > #quartz-body .sidebar { padding: 6rem 2rem 2rem; }`.
54
+ // Brain's denser wiki chrome needs the sidebar to start closer to the
55
+ // viewport edge, while keeping the same horizontal rhythm.
56
+ .page > #quartz-body .sidebar {
57
+ padding: 2rem;
58
+ }
59
+
60
+ // Stock Quartz renders the Search/Darkmode/ReaderMode trio inside a
61
+ // `<div class="flex-component">` (rendered by `Component.Flex`). Each
62
+ // child wraps a single button. We flatten visual sizing across the
63
+ // three so they read as a single icon strip.
64
+ //
65
+ // The Flex container itself becomes the sticky band. `.sidebar.left`
66
+ // already has `position: sticky` from base.scss; we layer this on top.
67
+
68
+ .sidebar.left {
69
+ // brain: the Flex row that holds Search/Darkmode/ReaderMode is the
70
+ // first non-title flex-component child of the left sidebar. Pin it
71
+ // to the top so search remains reachable as the explorer scrolls.
72
+ // `top: 0` works because `.sidebar.left` is itself sticky to the
73
+ // viewport top — both elements share the same scrolling context.
74
+ > .flex-component {
75
+ position: sticky;
76
+ top: 0;
77
+ z-index: 5;
78
+ background: var(--surface-1);
79
+ // Subtle bottom hairline so the sticky band reads as a header rule
80
+ // rather than melting into the explorer below.
81
+ border-bottom: 1px solid var(--rule);
82
+ padding-bottom: 0.5rem;
83
+ margin-bottom: 0.4rem;
84
+ }
85
+ }
86
+
87
+ // Icon trio normalization. Quartz emits each control as a `<button>`
88
+ // with a class that names the control (`.search-button`, `.darkmode`,
89
+ // `.readermode`). We unify their box, hover, and focus treatment so
90
+ // the row reads as a single component instead of three loose buttons.
91
+ .sidebar.left {
92
+ // Search button — looks like an inline search input so the affordance
93
+ // is obvious (Linear variant feedback: icon-only button hid the
94
+ // search functionality from sight). Grows to fill its flex slot;
95
+ // the darkmode + readermode buttons stay icon-squares to its right.
96
+ .search-button {
97
+ box-sizing: border-box;
98
+ width: 100%;
99
+ height: 32px;
100
+ padding: 0 0.6rem;
101
+ display: inline-flex;
102
+ align-items: center;
103
+ justify-content: flex-start;
104
+ gap: 0.5rem;
105
+ background: var(--surface-2);
106
+ border: 1px solid var(--rule);
107
+ border-radius: 6px;
108
+ color: var(--ink-2);
109
+ cursor: pointer;
110
+ font-family: var(--bodyFont);
111
+ font-size: 0.875rem;
112
+ transition:
113
+ background var(--motion-fast) var(--motion-easing),
114
+ border-color var(--motion-fast) var(--motion-easing),
115
+ color var(--motion-fast) var(--motion-easing);
116
+
117
+ > svg {
118
+ width: 14px;
119
+ height: 14px;
120
+ stroke-width: 2;
121
+ flex-shrink: 0;
122
+ // Stock CSS sets `margin: 0 0.5rem` on the svg — kill it so the
123
+ // 0.5rem gap on the parent flex is the only spacing between
124
+ // icon and text (otherwise we get 0.5rem + 0.5rem stacked and
125
+ // the text gets pushed off the right edge of narrow sidebars).
126
+ margin: 0;
127
+ }
128
+
129
+ // Stock emits `<p>Search</p>` next to the magnifier. Stock CSS
130
+ // sets `display: inline; color: var(--gray); text-wrap: unset` on
131
+ // it; that's fine until we wrap the row in a flex container with a
132
+ // `gap`. In flex context, `display: inline` is treated as block,
133
+ // and an unconstrained text node CAN squeeze to its content width.
134
+ // Force the `<p>` visible by:
135
+ // * explicit `display: block` so flex-layout treats it predictably,
136
+ // * `flex: 1 1 auto` so it fills the remaining space after the icon,
137
+ // * `min-width: 0` so it can shrink without overflowing,
138
+ // * `text-wrap: unset` (preserve stock) so "Search" stays one line.
139
+ > p {
140
+ display: block;
141
+ flex: 1 1 auto;
142
+ min-width: 0;
143
+ margin: 0;
144
+ color: var(--ink-2);
145
+ font-weight: 400;
146
+ font-size: 0.875rem;
147
+ line-height: 1;
148
+ text-wrap: unset;
149
+ }
150
+
151
+ &:hover {
152
+ border-color: var(--ink-2);
153
+ color: var(--ink-1);
154
+
155
+ > p {
156
+ color: var(--ink-1);
157
+ }
158
+ }
159
+
160
+ &:focus-visible {
161
+ outline: 2px solid var(--accent-strong);
162
+ outline-offset: 2px;
163
+ }
164
+ }
165
+
166
+ // Darkmode + readermode stay as 32px icon squares — they're toggles,
167
+ // not search affordances, so the icon-only treatment is correct.
168
+ button.darkmode,
169
+ button.readermode {
170
+ box-sizing: border-box;
171
+ width: 32px;
172
+ height: 32px;
173
+ padding: 0;
174
+ display: inline-flex;
175
+ align-items: center;
176
+ justify-content: center;
177
+ background: transparent;
178
+ border: 1px solid transparent;
179
+ border-radius: 6px;
180
+ color: var(--ink-1);
181
+ cursor: pointer;
182
+ transition:
183
+ background var(--motion-fast) var(--motion-easing),
184
+ border-color var(--motion-fast) var(--motion-easing),
185
+ color var(--motion-fast) var(--motion-easing);
186
+
187
+ > svg {
188
+ width: 18px;
189
+ height: 18px;
190
+ stroke-width: 2;
191
+ }
192
+
193
+ &:hover {
194
+ background: var(--accent-soft);
195
+ border-color: var(--rule);
196
+ color: var(--ink-0);
197
+ }
198
+
199
+ // Keyboard-only focus ring (mouse focus reads as click).
200
+ &:focus-visible {
201
+ outline: 2px solid var(--accent-strong);
202
+ outline-offset: 1px;
203
+ }
204
+ }
205
+ }
206
+
207
+ // Stock Quartz's search panel positioning recipe (`width: 65%` +
208
+ // `margin-left/right: auto` inside an `inline-block` parent + the
209
+ // container's own `position: fixed`) is unreliable in our cascade —
210
+ // previous attempts via `display: flex; justify-content: center` and
211
+ // then `position: absolute; left: 50%` both failed to center the panel
212
+ // in practice. The robust path is to bypass stock's positioning
213
+ // entirely on BOTH the wrapper and the inner space, and use explicit
214
+ // fixed-position values.
215
+ //
216
+ // brain (Linear-variant feedback round 3):
217
+ // 1. `display: block` on `.search-container.active` kills stock's
218
+ // `display: inline-block` (which can collapse the container to
219
+ // content-width despite its `width: 100vw` declaration).
220
+ // 2. `.search-space` becomes its own `position: fixed` element
221
+ // anchored directly to the viewport via `left: 50%` + a
222
+ // `translateX(-50%)` offset — no parent cascade involvement.
223
+ // Width capped at 800px or 90vw so it reads as a focused modal
224
+ // on wide viewports, not a stretched bar.
225
+ .search > .search-container.active {
226
+ display: block;
227
+ }
228
+
229
+ .search > .search-container > .search-space {
230
+ position: fixed;
231
+ left: 50%;
232
+ top: 12vh;
233
+ transform: translateX(-50%);
234
+ // brain (Linear-variant feedback round 4): bumped from min(800px, 90vw)
235
+ // to min(1100px, 90vw). On a 1440 viewport the previous 800px modal
236
+ // had 320px margin on each side — exactly matching the left sidebar
237
+ // width — which made the modal read as left-anchored against the
238
+ // sidebar even though it was geometrically centered on the viewport.
239
+ // 1100px wide × 1440 viewport leaves 170px margin per side, which
240
+ // visually presents as a properly-centered focused modal.
241
+ width: min(1100px, 90vw);
242
+ margin: 0;
243
+ }
244
+
245
+ // Linear-variant retint of the search panel inner card. Stock paints
246
+ // `.search-space > *` with `var(--light)` (page bg) + a warm shadow
247
+ // recipe; against our charcoal `--surface-0` the panel reads as a
248
+ // flat extension of the page. Lift to `--surface-1` and trade the
249
+ // shadow for an outline-style hairline so the panel actually looks
250
+ // like an elevated modal in dark mode.
251
+ .search > .search-container > .search-space > * {
252
+ background: var(--surface-1);
253
+ box-shadow: var(--shadow-md);
254
+ border: 1px solid var(--rule);
255
+ }
256
+
257
+ .search > .search-container > .search-space > input {
258
+ background: var(--surface-1);
259
+ color: var(--ink-0);
260
+ border: 1px solid var(--rule);
261
+ }
262
+
263
+ // ---------------------------------------------------------------------------
264
+ // 2. Explorer tree polish — indent guides + smoother fold transition
265
+ // ---------------------------------------------------------------------------
266
+ //
267
+ // Stock Quartz already paints a `border-left: 1px solid var(--lightgray)`
268
+ // on `.folder-outer > ul` (see upstream `explorer.scss`). We re-pin
269
+ // the rule color to `--rule` so it tracks the redesign tokens, lift
270
+ // the indent slightly so deep trees read clearly, and smooth the
271
+ // fold-icon rotation.
272
+
273
+ .explorer-content {
274
+ .folder-outer > ul {
275
+ border-left: 1px solid var(--rule);
276
+ margin-left: 8px;
277
+ padding-left: 0.8rem;
278
+ }
279
+ }
280
+
281
+ .folder-icon {
282
+ // brain: stock sets a 0.3s linear-ease transition; bump easing to
283
+ // the shared smooth-out-quint so the rotation feels paper-like
284
+ // rather than mechanical.
285
+ transition: transform var(--motion-mid) var(--motion-easing);
286
+ }
287
+
288
+ // brain: folder file-count badge — appended after `.folder-title` by
289
+ // `quartz_overrides/quartz/components/scripts/explorer.inline.ts`. Reads
290
+ // as a dim subscript next to the folder name (e.g. "company-id 5"), so it
291
+ // recedes against the title until you scan for it. Recursive count of
292
+ // leaf descendants — what's actually visible under the folder, not the
293
+ // raw contentIndex.
294
+ .folder-count {
295
+ margin-left: 0.4em;
296
+ font-size: 0.8em;
297
+ font-variant-numeric: tabular-nums;
298
+ color: var(--ink-2);
299
+ // The badge sits inside `.folder-container > div`, alongside the
300
+ // title button/anchor. `vertical-align: baseline` is the default but
301
+ // explicit-align here so the count stays aligned even if a parent
302
+ // sets a different vertical-align rule.
303
+ vertical-align: baseline;
304
+ }
305
+
306
+ // Active note highlight — stock Quartz colors `.explorer-content li > a.active`
307
+ // with `--tertiary`. Repaint to `--accent-strong` so the active
308
+ // affordance tracks the link palette.
309
+ .explorer-content ul li > a.active {
310
+ color: var(--accent-strong);
311
+ }
312
+
313
+ // brain: hover treatment parity for file links. Upstream paints
314
+ // `.folder-container div > a:hover` and `.folder-icon:hover` with
315
+ // `--tertiary`, but file `<li><a>` rows get no hover affordance — the
316
+ // only way to tell what you're about to click is to follow the cursor.
317
+ // Match the folder hover (repainted to `--accent-strong` for token
318
+ // consistency) so every clickable thing in the explorer reacts the
319
+ // same way to a hover.
320
+ .explorer-content ul li > a {
321
+ transition: color var(--motion-fast) var(--motion-easing);
322
+
323
+ &:hover {
324
+ color: var(--accent-strong);
325
+ opacity: 1;
326
+ }
327
+ }
328
+
329
+ // Repaint the upstream `--tertiary` folder-link + folder-icon hovers
330
+ // to `--accent-strong` so every explorer hover reads the same.
331
+ .folder-container div > a:hover,
332
+ .folder-icon:hover {
333
+ color: var(--accent-strong);
334
+ }
335
+
336
+ // ---------------------------------------------------------------------------
337
+ // 3. RIGHT sidebar — card chrome + scroll + flex-shrink contract
338
+ // ---------------------------------------------------------------------------
339
+ //
340
+ // The graph component already styles itself with the matching surface
341
+ // + radius via `graph.scss`. ToC and Backlinks need the same
342
+ // treatment so the right sidebar reads as a stack of four coordinated
343
+ // panels rather than two flat rivers around a card.
344
+ //
345
+ // Stock markup: `<div class="toc">…</div>` + `<div class="backlinks">…</div>`,
346
+ // plus the brain-overlay `<div class="brain-related-docs">…</div>` (Phase 5.2)
347
+ // sandwiched between them. We paint each as a `--surface-1` card with
348
+ // `8px` radius and `0.6rem` padding (per the plan spec). The shadow is
349
+ // subtle (`--shadow-sm`) so panels don't compete with the article column.
350
+ //
351
+ // brain (2026-05-08): three coordinated additions to the right-sidebar
352
+ // section close the long-standing "TOC swallows the whole sidebar" bug
353
+ // reported on `/company-id/ai-adoption-complete-playbook` (22 ToC entries):
354
+ //
355
+ // 1. `.sidebar.right { overflow-y: auto; }` — upstream `base.scss`
356
+ // paints `.sidebar { height: 100vh; position: sticky; display: flex }`
357
+ // with NO `overflow-y` declared, so the fixed viewport-tall box
358
+ // silently CLIPS anything past the bottom edge. The TOC's own
359
+ // `<ul.toc-content.overflow>` only self-scrolls inside the TOC's
360
+ // flex slice — never the whole right-sidebar column. Declaring
361
+ // `overflow-y: auto` here gives the entire panel column a single,
362
+ // themed scrollbar that reaches every child (graph, ToC, related,
363
+ // backlinks). `overscroll-behavior: contain` keeps the page
364
+ // underneath from scrolling when the user rubber-bands inside the
365
+ // sidebar; `scrollbar-width: thin` + `--lightgray` thumb keeps the
366
+ // scrollbar reading as part of the sidebar chrome rather than the
367
+ // OS default.
368
+ //
369
+ // 2. `.sidebar.right > {graph,toc,brain-related-docs,backlinks} { flex: 0 0 auto }`
370
+ // — stops the flex-shrink fight. Stock `.toc { flex: 0 0.5 auto }`
371
+ // shrinks 0.5x; default `flex: 0 1 auto` on siblings shrinks 1x;
372
+ // `.brain-related-docs` deliberately takes `min-height: 0` so a
373
+ // packed related list can shrink inside its OWN section box —
374
+ // which, combined with the upstream sticky `.sidebar { height:
375
+ // 100vh }` ceiling, made `.brain-related-docs` collapse all the
376
+ // way down to ~19px (DevTools-confirmed: `256 × 19px` rendering,
377
+ // header-only). Pinning all four direct children to `flex: 0 0
378
+ // auto` removes the fight: each child holds its natural size, and
379
+ // overflow lives on the sidebar itself (rule 1 above) instead of
380
+ // stealing height from siblings.
381
+ //
382
+ // 3. `.sidebar.right > .toc { max-height: 40vh }` — caps the TOC at
383
+ // ~40% viewport height so a 22-entry table of contents can't fill
384
+ // the sidebar even before the sidebar scroll kicks in. The
385
+ // upstream `.toc { overflow-y: hidden }` already clips, and the
386
+ // inner `<ul.toc-content.overflow>` already has `max-height:
387
+ // calc(100% - 2rem)` self-scrolling — bounded by our 40vh cap,
388
+ // that just works: an over-tall TOC scrolls inside the cap, not
389
+ // by stealing space from RelatedDocs / Backlinks. Pairs with the
390
+ // 32vh cap on `.brain-related-docs-list` so on a typical viewport
391
+ // the entire right-sidebar stack fits at a glance.
392
+
393
+ .sidebar.right {
394
+ // brain: rule 1 — make the sidebar scroll. Without this declaration
395
+ // the upstream `.sidebar { height: 100vh; position: sticky }` silently
396
+ // clips anything past the viewport edge, and TOC self-scroll only
397
+ // covers the TOC's own slice.
398
+ overflow-y: auto;
399
+ overscroll-behavior: contain;
400
+ scrollbar-width: thin;
401
+ scrollbar-color: var(--lightgray) transparent;
402
+
403
+ &::-webkit-scrollbar {
404
+ width: 4px;
405
+ }
406
+
407
+ &::-webkit-scrollbar-thumb {
408
+ background: var(--lightgray);
409
+ border-radius: 2px;
410
+ }
411
+
412
+ .toc,
413
+ .backlinks {
414
+ background: var(--surface-1);
415
+ border-radius: 8px;
416
+ padding: 0.6rem 0.8rem;
417
+ box-shadow: var(--shadow-sm);
418
+ box-sizing: border-box;
419
+
420
+ // Section heading inside each card — Quartz emits `<h3>` for both
421
+ // ToC and Backlinks. Tighten the top margin so the heading sits
422
+ // close to the card edge rather than floating mid-air.
423
+ > h3 {
424
+ margin-top: 0;
425
+ margin-bottom: 0.4rem;
426
+ // brain (Linear): uppercase + tracking instead of small-caps.
427
+ // Cleaner tech feel; reads as a section label without the
428
+ // editorial small-caps voice.
429
+ font-weight: 600;
430
+ font-size: 0.7rem;
431
+ letter-spacing: 0.06em;
432
+ text-transform: uppercase;
433
+ color: var(--ink-1);
434
+ }
435
+ }
436
+
437
+ // Backlinks list items — tighten leading so multiple backlinks
438
+ // stack as a compact reference list rather than running prose.
439
+ .backlinks ul li {
440
+ line-height: 1.4;
441
+ margin: 0.2rem 0;
442
+ }
443
+ }
444
+
445
+ // brain: rule 2 — stop the flex-shrink fight. The child-combinator `>`
446
+ // is intentional so we only target direct children of the right
447
+ // sidebar (avoids accidentally hitting nested ToC widgets if any).
448
+ // Pinning all four to `flex: 0 0 auto` keeps each at its natural
449
+ // height; the sidebar's `overflow-y: auto` above handles overflow.
450
+ .sidebar.right > .graph,
451
+ .sidebar.right > .toc,
452
+ .sidebar.right > .brain-related-docs,
453
+ .sidebar.right > .backlinks {
454
+ flex: 0 0 auto;
455
+ }
456
+
457
+ // brain: rule 3 — cap the TOC at 40vh. Note: the existing
458
+ // `.sidebar.right { .toc, .backlinks { ... } }` block above already
459
+ // paints the card chrome (background, border-radius, padding,
460
+ // box-shadow) on `.sidebar.right .toc`. This rule is additive — keep
461
+ // both. The child-combinator `>` scopes the cap to only the top-level
462
+ // TOC inside the right sidebar.
463
+ .sidebar.right > .toc {
464
+ // The upstream `.toc { overflow-y: hidden }` clips at this max-height,
465
+ // and the inner `<ul.toc-content.overflow>` (`max-height:
466
+ // calc(100% - 2rem)`) provides the user-facing scroll inside the cap.
467
+ max-height: 40vh;
468
+ }
@@ -0,0 +1,56 @@
1
+ // Brain summary-lede styles — wave Q2-SUMMARY-WIKI.
2
+ //
3
+ // This file is installed at `<vault>/.quartz/quartz/styles/brain/_summary_lede.scss`
4
+ // by `brain vault render --overlay` and loaded globally via
5
+ // `custom.scss`'s `@use "./brain/summary_lede"` line.
6
+ //
7
+ // Renders the `<aside class="brain-summary-lede">` block (emitted by
8
+ // `SummaryLede.tsx` when `frontmatter.summary` is a non-empty string)
9
+ // as a soft TL;DR card above the article body. Visual weight stays
10
+ // LOW so the lede doesn't compete with the page title for first
11
+ // fixation — the eyebrow ("AI summary") uses the ink-2 muted tier,
12
+ // and the body copy reads at the regular body type scale.
13
+ //
14
+ // The selector is anchored on the dedicated class so the rules only
15
+ // fire on pages where `SummaryLede.tsx` renders. No `[data-*]` hooks
16
+ // are needed — the component returns `null` when no summary is
17
+ // present, so we never paint an empty aside.
18
+
19
+ .brain-summary-lede {
20
+ // Surface card matching the related-docs panel — soft accent tint
21
+ // pulled from the design tokens, so a dark-mode swap inherits the
22
+ // right contrast for free.
23
+ background: var(--surface-1);
24
+ border-left: 3px solid var(--accent-strong);
25
+ border-radius: 6px;
26
+ padding: 0.65rem 0.9rem 0.75rem;
27
+ margin: 1rem 0 1.5rem;
28
+ // Same shadow tier as the related-docs section so the two cards
29
+ // read as siblings.
30
+ box-shadow: var(--shadow-sm);
31
+
32
+ // The eyebrow is a low-emphasis label — small caps + ink-2 muted
33
+ // tier so the title of the lede doesn't shout louder than the
34
+ // body. Display-block so it sits on its own line above the
35
+ // summary paragraph.
36
+ .brain-summary-lede-eyebrow {
37
+ display: block;
38
+ font-family: var(--displayFont);
39
+ font-weight: 600;
40
+ font-size: var(--fs-xs);
41
+ letter-spacing: 0.08em;
42
+ text-transform: uppercase;
43
+ color: var(--ink-2);
44
+ margin-bottom: 0.3rem;
45
+ }
46
+
47
+ // Body copy at the regular body type scale (no italic, no smaller-
48
+ // than-body shrinkage — the lede is a first-class read, not an
49
+ // afterthought).
50
+ .brain-summary-lede-body {
51
+ margin: 0;
52
+ color: var(--ink-1);
53
+ font-size: var(--fs-sm);
54
+ line-height: 1.55;
55
+ }
56
+ }
@@ -0,0 +1,43 @@
1
+ // Brain surface system — applies the three-tier surface scale defined
2
+ // in `_tokens.scss` to the page chrome.
3
+ //
4
+ // Tier semantics:
5
+ // --surface-0 → page bg (matches Quartz `--light`)
6
+ // --surface-1 → cards, sidebars (one notch warmer)
7
+ // --surface-2 → inline code, popovers (one more notch warmer)
8
+ //
9
+ // Quartz's stock `body { background-color: var(--light); }` already
10
+ // covers `--surface-0`. We re-pin it explicitly so the tier name
11
+ // reads in any future audit and so swapping `--surface-0` in dark
12
+ // mode propagates without relying on `--light` alignment.
13
+
14
+ body {
15
+ background-color: var(--surface-0);
16
+ }
17
+
18
+ // Sidebars (left + right) sit on `--surface-1` so the article column
19
+ // reads as the focal "page" against a slightly warmer chrome. The
20
+ // shadow elevates the card without aggressive contrast.
21
+ //
22
+ // Quartz's stock markup is `<div class="sidebar left">` /
23
+ // `<div class="sidebar right">` — selecting on `.sidebar` covers both.
24
+ // Lane C (`sidebar.scss`) refines layout / spacing; this file owns
25
+ // only the surface tier + elevation.
26
+ .sidebar {
27
+ background-color: var(--surface-1);
28
+ }
29
+
30
+ // Inline code pops against the page bg with a one-step-warmer surface.
31
+ // `code:not(pre code)` excludes code inside `<pre>` blocks (those get
32
+ // their own surface treatment in Lane C `code.scss`).
33
+ code:not(pre code) {
34
+ background-color: var(--surface-2);
35
+ }
36
+
37
+ // Popover bodies (footnotes, link previews) ride the same `--surface-2`
38
+ // so the depth scale stays consistent across hover surfaces.
39
+ // Quartz emits `.popover .popover-inner` for hover previews.
40
+ .popover .popover-inner {
41
+ background-color: var(--surface-2);
42
+ box-shadow: var(--shadow-md);
43
+ }
@@ -0,0 +1,118 @@
1
+ // Brain tag-content styles — Phase 3.3 of the Wiki UX Overhaul.
2
+ //
3
+ // Layout for the per-tag listing rows produced by
4
+ // `quartz_overrides/quartz/components/pages/TagContent.tsx`. The
5
+ // component renders an `<ul class="brain-tag-results">` of
6
+ // `<li class="brain-tag-row">` items, each containing:
7
+ // * an icon glyph,
8
+ // * a title,
9
+ // * a date column,
10
+ // * a 1-line snippet around the tag occurrence,
11
+ // * a `tagged: #...` footer.
12
+ //
13
+ // The grid below lays the icon / title / date in a single row across
14
+ // the page width with the snippet wrapping on its own row underneath
15
+ // (where a `&-snippet` slot is allocated). The footer floats a tiny
16
+ // label + chip strip beneath each row.
17
+ //
18
+ // All class hooks are documented in the component file. Keep the two
19
+ // in lock-step — a class rename here that's not mirrored there
20
+ // silently degrades to unstyled markup.
21
+
22
+ .brain-tag-results {
23
+ list-style: none;
24
+ margin: 0;
25
+ padding: 0;
26
+ }
27
+
28
+ .brain-tag-row {
29
+ margin: 0 0 1.1rem 0;
30
+ padding: 0;
31
+ border-bottom: 1px dashed var(--lightgray);
32
+ padding-bottom: 0.6rem;
33
+
34
+ &:last-child {
35
+ border-bottom: 0;
36
+ }
37
+ }
38
+
39
+ .brain-tag-row-link {
40
+ display: grid;
41
+ // brain: icon · title (flex) · date (auto) on the first row, snippet
42
+ // spans the full width on a second row. `auto-flow: row dense` lets
43
+ // the snippet drop cleanly underneath the title column without
44
+ // needing an explicit grid-area name.
45
+ grid-template-columns: auto 1fr auto;
46
+ column-gap: 0.6rem;
47
+ row-gap: 0.25rem;
48
+ align-items: baseline;
49
+ text-decoration: none;
50
+ color: inherit;
51
+
52
+ &:hover .brain-tag-title {
53
+ text-decoration: underline;
54
+ }
55
+ }
56
+
57
+ .brain-tag-icon {
58
+ font-size: 1.05rem;
59
+ line-height: 1;
60
+ // brain: nudge down a hair so the emoji baseline aligns with the
61
+ // title's text baseline (emoji glyphs sit slightly higher than Latin).
62
+ transform: translateY(0.05em);
63
+ }
64
+
65
+ .brain-tag-title {
66
+ font-weight: 600;
67
+ // brain: clamp the title to a single line — long thread titles
68
+ // ("Re: Re: Re: VP of Engineering — eve…") would otherwise wrap and
69
+ // shove the date column down.
70
+ overflow: hidden;
71
+ text-overflow: ellipsis;
72
+ white-space: nowrap;
73
+ }
74
+
75
+ .brain-tag-date {
76
+ font-family: var(--codeFont, monospace);
77
+ font-size: 0.78rem;
78
+ color: var(--gray);
79
+ white-space: nowrap;
80
+ }
81
+
82
+ .brain-tag-snippet {
83
+ grid-column: 1 / -1;
84
+ font-size: 0.85rem;
85
+ color: var(--darkgray);
86
+ // brain: 1-line clamp — the snippet is meant to be a glance-sized
87
+ // peek, not a full description. The component already chunks the
88
+ // window down to ~200 chars, but on narrow viewports that can still
89
+ // overflow, so the clamp is the belt-and-suspenders guard.
90
+ display: -webkit-box;
91
+ -webkit-line-clamp: 1;
92
+ line-clamp: 1;
93
+ -webkit-box-orient: vertical;
94
+ overflow: hidden;
95
+ }
96
+
97
+ .brain-tag-footer {
98
+ margin: 0.3rem 0 0 0;
99
+ font-size: 0.78rem;
100
+ color: var(--gray);
101
+ }
102
+
103
+ .brain-tag-footer-label {
104
+ font-style: italic;
105
+ margin-right: 0.25rem;
106
+ }
107
+
108
+ .brain-tag-footer-link {
109
+ // brain: chip-style tag link — softens the underline `_links.scss`
110
+ // applies to internal anchors so the "tagged: #a #b #c" line reads
111
+ // as a meta strip rather than three competing CTAs.
112
+ text-decoration: none;
113
+ margin-right: 0.4rem;
114
+
115
+ &:hover {
116
+ text-decoration: underline;
117
+ }
118
+ }