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.
- brain/__init__.py +0 -0
- brain/__main__.py +18 -0
- brain/_capture_command.py +445 -0
- brain/_compose.py +52 -0
- brain/activity.py +206 -0
- brain/ask.py +631 -0
- brain/audio.py +591 -0
- brain/backfill/__init__.py +12 -0
- brain/backfill/search_extras.py +141 -0
- brain/backfill/source_rows.py +101 -0
- brain/bin/__init__.py +1 -0
- brain/bin/_launcher.py +107 -0
- brain/bin/down.py +8 -0
- brain/bin/launchd.py +268 -0
- brain/bin/monitor.py +570 -0
- brain/bin/rebuild.py +8 -0
- brain/bin/status.py +8 -0
- brain/bin/up.py +8 -0
- brain/brief.py +272 -0
- brain/capture.py +49 -0
- brain/chat.py +293 -0
- brain/cli.py +9760 -0
- brain/cli_claude.py +81 -0
- brain/cli_connect.py +285 -0
- brain/cli_demo.py +266 -0
- brain/config.py +1949 -0
- brain/connect.py +925 -0
- brain/db.py +540 -0
- brain/demo/__init__.py +452 -0
- brain/demo/corpus/manifest.json +403 -0
- brain/demo/embedder.py +74 -0
- brain/durations.py +84 -0
- brain/edit_session.py +156 -0
- brain/editor.py +67 -0
- brain/elicit/__init__.py +16 -0
- brain/elicit/detectors.py +250 -0
- brain/elicit/drafter.py +70 -0
- brain/elicit/queue.py +220 -0
- brain/elicit/schema.py +48 -0
- brain/elicit/session.py +445 -0
- brain/embedding_targets.py +54 -0
- brain/embeddings.py +424 -0
- brain/enrichment.py +808 -0
- brain/errors.py +357 -0
- brain/eval/__init__.py +129 -0
- brain/eval/answer_eval.py +281 -0
- brain/eval/baseline.py +265 -0
- brain/eval/concept_extraction.py +378 -0
- brain/eval/corpus.py +152 -0
- brain/eval/errors.py +19 -0
- brain/eval/graph_baseline.py +226 -0
- brain/eval/graph_retrieval.py +202 -0
- brain/eval/graph_runner.py +319 -0
- brain/eval/metrics.py +101 -0
- brain/eval/runner.py +223 -0
- brain/format.py +783 -0
- brain/gaps.py +390 -0
- brain/graph_rag/__init__.py +94 -0
- brain/graph_rag/_retrieval_common.py +113 -0
- brain/graph_rag/aggregates.py +303 -0
- brain/graph_rag/aliases/__init__.py +583 -0
- brain/graph_rag/backends/__init__.py +10 -0
- brain/graph_rag/backends/_age_helpers.py +473 -0
- brain/graph_rag/backends/age.py +782 -0
- brain/graph_rag/backends/base.py +272 -0
- brain/graph_rag/build.py +344 -0
- brain/graph_rag/communities.py +644 -0
- brain/graph_rag/communities_summary.py +437 -0
- brain/graph_rag/concepts.py +202 -0
- brain/graph_rag/cooccur.py +193 -0
- brain/graph_rag/cross_type.py +312 -0
- brain/graph_rag/extract.py +885 -0
- brain/graph_rag/fuse.py +371 -0
- brain/graph_rag/global_.py +412 -0
- brain/graph_rag/grouping.py +372 -0
- brain/graph_rag/person_resolver.py +167 -0
- brain/graph_rag/reconcile.py +792 -0
- brain/graph_rag/relational.py +353 -0
- brain/graph_rag/retrieve.py +526 -0
- brain/graph_rag/router.py +288 -0
- brain/graph_rag/schema.py +320 -0
- brain/graph_rag/sync.py +237 -0
- brain/graph_rag/tenancy.py +43 -0
- brain/graph_rag/themes.py +501 -0
- brain/graph_rag/weighting.py +202 -0
- brain/ingest/__init__.py +1926 -0
- brain/ingest/chunker.py +249 -0
- brain/ingest/docx.py +40 -0
- brain/ingest/gmail.py +621 -0
- brain/ingest/markdown.py +37 -0
- brain/ingest/pdf.py +61 -0
- brain/ingest/stdin.py +22 -0
- brain/ingest/sub_tokens.py +91 -0
- brain/ingest/text.py +16 -0
- brain/interactions.py +205 -0
- brain/maintenance.py +355 -0
- brain/mcp_server.py +3405 -0
- brain/migrations/001_init.sql +43 -0
- brain/migrations/002_qwen3_embedding.sql +17 -0
- brain/migrations/003_vault_model.sql +41 -0
- brain/migrations/004_relax_content_hash_uniqueness.sql +18 -0
- brain/migrations/005_derived_links.sql +67 -0
- brain/migrations/006_dedup_file_by_source_path.sql +25 -0
- brain/migrations/007_email_thread_and_draft.sql +15 -0
- brain/migrations/008_gmail_thread_unique.sql +11 -0
- brain/migrations/009_chunks_weighted_tsv.sql +28 -0
- brain/migrations/010_interactions.sql +30 -0
- brain/migrations/011_documents_summary.sql +23 -0
- brain/migrations/012_graphrag.sql +171 -0
- brain/migrations/013_graphrag_communities.sql +125 -0
- brain/migrations/014_graphrag_community_summary_hash.sql +33 -0
- brain/migrations/015_interactions_graph_targets.sql +89 -0
- brain/migrations/016_index_hygiene.sql +61 -0
- brain/migrations/017_elicit.sql +30 -0
- brain/migrations/018_review_gap_signal_kinds.sql +40 -0
- brain/migrations/019_search_queries.sql +35 -0
- brain/migrations/020_link_suggestions.sql +40 -0
- brain/migrations/021_timeline_doc_date.sql +34 -0
- brain/migrations/022_link_suggestions_undirected.sql +84 -0
- brain/migrations/023_search_queries_fts_count.sql +28 -0
- brain/quartz_overrides/__init__.py +8 -0
- brain/quartz_overrides/quartz/bootstrap-cli.mjs +65 -0
- brain/quartz_overrides/quartz/build.ts +568 -0
- brain/quartz_overrides/quartz/cli/args.js +152 -0
- brain/quartz_overrides/quartz/cli/build_partial_handler.js +544 -0
- brain/quartz_overrides/quartz/cli/handlers.js +636 -0
- brain/quartz_overrides/quartz/components/CommandPalette.tsx +172 -0
- brain/quartz_overrides/quartz/components/Explorer.tsx +198 -0
- brain/quartz_overrides/quartz/components/Footer.tsx +27 -0
- brain/quartz_overrides/quartz/components/Graph.tsx +468 -0
- brain/quartz_overrides/quartz/components/PageTitle.tsx +72 -0
- brain/quartz_overrides/quartz/components/RelatedDocs.tsx +38 -0
- brain/quartz_overrides/quartz/components/Search.tsx +161 -0
- brain/quartz_overrides/quartz/components/SummaryLede.tsx +72 -0
- brain/quartz_overrides/quartz/components/index.ts +92 -0
- brain/quartz_overrides/quartz/components/pages/TagContent.tsx +272 -0
- brain/quartz_overrides/quartz/components/scripts/commandPalette.inline.ts +665 -0
- brain/quartz_overrides/quartz/components/scripts/explorer.inline.ts +768 -0
- brain/quartz_overrides/quartz/components/scripts/graph.inline.ts +2302 -0
- brain/quartz_overrides/quartz/components/scripts/relatedDocs.inline.ts +163 -0
- brain/quartz_overrides/quartz/components/scripts/search.inline.ts +1011 -0
- brain/quartz_overrides/quartz/plugins/emitters/contentIndex.ts +546 -0
- brain/quartz_overrides/quartz/plugins/transformers/codeCopy.ts +94 -0
- brain/quartz_overrides/quartz/plugins/transformers/derivedFenceMark.ts +302 -0
- brain/quartz_overrides/quartz/plugins/transformers/emailThread.ts +148 -0
- brain/quartz_overrides/quartz/plugins/transformers/emptyDoorFilter.ts +213 -0
- brain/quartz_overrides/quartz/plugins/transformers/index.ts +114 -0
- brain/quartz_overrides/quartz/plugins/transformers/linkKindMark.ts +205 -0
- brain/quartz_overrides/quartz/plugins/transformers/linkSourceTag.ts +104 -0
- brain/quartz_overrides/quartz/plugins/transformers/relativeDate.ts +100 -0
- brain/quartz_overrides/quartz/plugins/transformers/reloadSignal.ts +131 -0
- brain/quartz_overrides/quartz/processors/parse.ts +371 -0
- brain/quartz_overrides/quartz/processors/parser_cache.ts +78 -0
- brain/quartz_overrides/quartz/static/brain-logo-dark.png +0 -0
- brain/quartz_overrides/quartz/static/brain-logo-light.png +0 -0
- brain/quartz_overrides/quartz/static/codeCopy.js +196 -0
- brain/quartz_overrides/quartz/static/emailThread.js +334 -0
- brain/quartz_overrides/quartz/static/favicon.ico +0 -0
- brain/quartz_overrides/quartz/static/icon.png +0 -0
- brain/quartz_overrides/quartz/static/linkSourceTag.js +104 -0
- brain/quartz_overrides/quartz/static/relativeDate.js +142 -0
- brain/quartz_overrides/quartz/static/reload.js +168 -0
- brain/quartz_overrides/quartz/styles/brain/_article.scss +252 -0
- brain/quartz_overrides/quartz/styles/brain/_atmosphere.scss +113 -0
- brain/quartz_overrides/quartz/styles/brain/_callouts.scss +180 -0
- brain/quartz_overrides/quartz/styles/brain/_cmdk.scss +7 -0
- brain/quartz_overrides/quartz/styles/brain/_code.scss +208 -0
- brain/quartz_overrides/quartz/styles/brain/_command_palette.scss +369 -0
- brain/quartz_overrides/quartz/styles/brain/_email_thread.scss +228 -0
- brain/quartz_overrides/quartz/styles/brain/_explorer.scss +142 -0
- brain/quartz_overrides/quartz/styles/brain/_home.scss +182 -0
- brain/quartz_overrides/quartz/styles/brain/_links.scss +322 -0
- brain/quartz_overrides/quartz/styles/brain/_marginalia.scss +117 -0
- brain/quartz_overrides/quartz/styles/brain/_motion.scss +175 -0
- brain/quartz_overrides/quartz/styles/brain/_people_hub.scss +100 -0
- brain/quartz_overrides/quartz/styles/brain/_related_docs.scss +137 -0
- brain/quartz_overrides/quartz/styles/brain/_search.scss +252 -0
- brain/quartz_overrides/quartz/styles/brain/_sidebar.scss +468 -0
- brain/quartz_overrides/quartz/styles/brain/_summary_lede.scss +56 -0
- brain/quartz_overrides/quartz/styles/brain/_surface.scss +43 -0
- brain/quartz_overrides/quartz/styles/brain/_tag_content.scss +118 -0
- brain/quartz_overrides/quartz/styles/brain/_tokens.scss +197 -0
- brain/quartz_overrides/quartz/styles/brain/_typography.scss +92 -0
- brain/quartz_overrides/quartz/styles/custom.scss +89 -0
- brain/quartz_overrides/quartz/styles/graph.scss +505 -0
- brain/quartz_overrides/quartz/util/ctx.ts +92 -0
- brain/quartz_overrides/quartz/util/fastpath_manifest.ts +608 -0
- brain/quartz_overrides/quartz/util/path.ts +358 -0
- brain/quartz_overrides/quartz/util/sourceIcons.ts +55 -0
- brain/quartz_overrides/quartz.config.ts +270 -0
- brain/quartz_overrides/quartz.layout.ts +314 -0
- brain/queries.py +1188 -0
- brain/rank_fusion.py +8 -0
- brain/resurface.py +210 -0
- brain/review/__init__.py +26 -0
- brain/review/emit.py +27 -0
- brain/review/queries.py +436 -0
- brain/review/render.py +196 -0
- brain/review/scans.py +355 -0
- brain/review/weekly.py +413 -0
- brain/search.py +704 -0
- brain/set_similarity.py +15 -0
- brain/setup.py +1205 -0
- brain/tags.py +56 -0
- brain/templates/Caddyfile.j2 +9 -0
- brain/templates/__init__.py +1 -0
- brain/templates/bin/__init__.py +1 -0
- brain/templates/bin/_brain-brief-fg.sh +25 -0
- brain/templates/bin/_brain-build-fg.sh +53 -0
- brain/templates/bin/_brain-watcher-fg.sh +65 -0
- brain/templates/bin/brain-down.sh +89 -0
- brain/templates/bin/brain-status.sh +83 -0
- brain/templates/bin/brain-up.sh +221 -0
- brain/templates/docker/age/Dockerfile +79 -0
- brain/templates/docker-compose.stock.yml.j2 +26 -0
- brain/templates/docker-compose.yml.j2 +34 -0
- brain/templates/env.example +190 -0
- brain/templates/launchd/__init__.py +1 -0
- brain/templates/launchd/com.brain.brief.plist.j2 +45 -0
- brain/templates/launchd/com.brain.build.plist.j2 +46 -0
- brain/templates/launchd/com.brain.watcher.plist.j2 +46 -0
- brain/templates/skill/SKILL.md +63 -0
- brain/templates/skill/__init__.py +1 -0
- brain/timeline.py +834 -0
- brain/todo.py +124 -0
- brain/uninstall.py +185 -0
- brain/vault/__init__.py +115 -0
- brain/vault/_atomic.py +25 -0
- brain/vault/daily_index.py +228 -0
- brain/vault/derived_links/__init__.py +50 -0
- brain/vault/derived_links/directory.py +683 -0
- brain/vault/derived_links/fence.py +408 -0
- brain/vault/derived_links/gws.py +64 -0
- brain/vault/derived_links/participants.py +143 -0
- brain/vault/derived_links/pass_runner.py +362 -0
- brain/vault/derived_links/rules.py +137 -0
- brain/vault/export.py +683 -0
- brain/vault/frontmatter.py +165 -0
- brain/vault/graph.py +620 -0
- brain/vault/graph_format.py +388 -0
- brain/vault/link_rewrite.py +235 -0
- brain/vault/links.py +260 -0
- brain/vault/note_builder.py +211 -0
- brain/vault/paths.py +55 -0
- brain/vault/quartz_overlay.py +236 -0
- brain/vault/rename.py +591 -0
- brain/vault/resolver.py +304 -0
- brain/vault/slug.py +127 -0
- brain/vault/sync.py +1513 -0
- brain/vault/sync_summaries.py +264 -0
- brain/vault/templates.py +145 -0
- brain/vault/watch.py +1052 -0
- brain/wiki/__init__.py +6 -0
- brain/wiki/_github_slugger.py +76 -0
- brain/wiki/_person_name.py +314 -0
- brain/wiki/build_homepage.py +541 -0
- brain/wiki/build_partial.py +273 -0
- brain/wiki/build_people.py +934 -0
- brain/wiki/build_related.py +758 -0
- brain/wiki/build_swap.py +585 -0
- brain/wiki/build_watcher.py +975 -0
- brain/wiki/edit_classifier.py +215 -0
- brain/wiki/errors.py +10 -0
- brain/wiki/fastpath_manifest.py +475 -0
- brain/wiki/fastpath_state.py +174 -0
- brain/wiki/install.py +296 -0
- brain/wiki/slug.py +111 -0
- secondbrain_py-0.2.1.dist-info/METADATA +195 -0
- secondbrain_py-0.2.1.dist-info/RECORD +273 -0
- secondbrain_py-0.2.1.dist-info/WHEEL +5 -0
- secondbrain_py-0.2.1.dist-info/entry_points.txt +11 -0
- secondbrain_py-0.2.1.dist-info/licenses/LICENSE +21 -0
- secondbrain_py-0.2.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// Brain marginalia — Lane D of the 2026 commonplace-book redesign.
|
|
2
|
+
//
|
|
3
|
+
// This file is installed at
|
|
4
|
+
// `<vault>/.quartz/quartz/styles/brain/_marginalia.scss` by `brain
|
|
5
|
+
// vault render --overlay` and pulled into the global SCSS via
|
|
6
|
+
// `custom.scss`'s `@use "./brain/marginalia"` line (between
|
|
7
|
+
// `article` and `callouts`).
|
|
8
|
+
//
|
|
9
|
+
// What this file owns: at desktop+ viewports (≥1280px), the right
|
|
10
|
+
// sidebar's `<div class="backlinks">` block reads as figure-margin
|
|
11
|
+
// side-notes — narrow column width, italic Newsreader, dimmed ink,
|
|
12
|
+
// tight per-link spacing — so backlinks register as "the
|
|
13
|
+
// commonplace book's marginal annotations" rather than "another
|
|
14
|
+
// chrome panel."
|
|
15
|
+
//
|
|
16
|
+
// brain (Lane D — fallback path taken):
|
|
17
|
+
//
|
|
18
|
+
// The original Lane D plan considered moving `.backlinks` out of
|
|
19
|
+
// `.right.sidebar` and rendering it as a true sibling of `.center`
|
|
20
|
+
// in the article column's right gutter — the "real Tufte
|
|
21
|
+
// side-note" approach. We did NOT take that path. Reasons:
|
|
22
|
+
//
|
|
23
|
+
// 1. Quartz's three-column grid is defined in `base.scss` via
|
|
24
|
+
// `templateAreas` (`grid-sidebar-left grid-center
|
|
25
|
+
// grid-sidebar-right`). Extracting `.backlinks` into a fourth
|
|
26
|
+
// grid area requires modifying the template at the source —
|
|
27
|
+
// either by editing `base.scss` (which the overlay tries hard
|
|
28
|
+
// to leave untouched, since stock Quartz's `joinStyles()` and
|
|
29
|
+
// grid map machinery in `variables.scss` are tightly coupled),
|
|
30
|
+
// or by duplicating the grid declaration here, which then
|
|
31
|
+
// becomes a fragile fork.
|
|
32
|
+
//
|
|
33
|
+
// 2. The backlinks component itself is rendered by Quartz's layout
|
|
34
|
+
// engine into the `right` slot (see `quartz.layout.ts` line
|
|
35
|
+
// 144). To make `.backlinks` a sibling of `.center` in the DOM
|
|
36
|
+
// we'd need to either move the component declaration out of
|
|
37
|
+
// `right: [...]` (and lose its sticky-sidebar positioning for
|
|
38
|
+
// everything else in that column), or split the component
|
|
39
|
+
// tree, neither of which is a single-file SCSS concern.
|
|
40
|
+
//
|
|
41
|
+
// 3. The team-lead's brief explicitly endorses this fallback:
|
|
42
|
+
// "If marginalia turns out architecturally infeasible without
|
|
43
|
+
// layout surgery, document why and fall back to a 'softer'
|
|
44
|
+
// treatment: the right-sidebar Backlinks block gets the same
|
|
45
|
+
// italic / smaller / dimmed treatment it would have in
|
|
46
|
+
// marginalia, but stays in its current position. This is
|
|
47
|
+
// acceptable — design intent is preserved, layout architecture
|
|
48
|
+
// isn't violated."
|
|
49
|
+
//
|
|
50
|
+
// The fallback preserves ~95% of the visual intent: backlinks read
|
|
51
|
+
// as marginalia (narrow, italic, dimmed, compact), they just live
|
|
52
|
+
// in the right sidebar instead of the article's right gutter. A
|
|
53
|
+
// future redesign that's willing to fork `base.scss` can take the
|
|
54
|
+
// architectural path; this file is the current best-effort
|
|
55
|
+
// styling contract.
|
|
56
|
+
//
|
|
57
|
+
// Below the desktop breakpoint (1280px and narrower) this file makes
|
|
58
|
+
// NO changes — the right sidebar falls back to its Lane C card
|
|
59
|
+
// styling from `_sidebar.scss`. That's deliberate: at 1200px or
|
|
60
|
+
// 1024px the backlinks panel needs the full sidebar width to read,
|
|
61
|
+
// and squeezing it into a 18ch column would force every backlink
|
|
62
|
+
// title to truncate.
|
|
63
|
+
//
|
|
64
|
+
// Tokens consumed (all from `_tokens.scss`):
|
|
65
|
+
// * `--ink-2` — dimmed marginalia ink color
|
|
66
|
+
// * `--fs-sm` / `--fs-xs` — smaller-than-body type
|
|
67
|
+
// * `--rule` — vertical rule on the marginalia column edge
|
|
68
|
+
// * `--bodyFont` — Newsreader italic for the side-note voice
|
|
69
|
+
// (printed marginalia is always body type one
|
|
70
|
+
// notch smaller than running prose, not display
|
|
71
|
+
// type — even though Lane A's project-wide
|
|
72
|
+
// italic convention reaches for Fraunces, that
|
|
73
|
+
// rule applies to inline emphasis, not to a
|
|
74
|
+
// whole-block side-note voice)
|
|
75
|
+
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// 1. Marginalia treatment at desktop+ viewports
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
//
|
|
80
|
+
// 1280px is one notch above Quartz's `$desktop` breakpoint (1200px).
|
|
81
|
+
// At 1200-1279px the right sidebar is already cramped (the local
|
|
82
|
+
// graph eats most of the vertical space); marginalia would compete
|
|
83
|
+
// with the graph and ToC for too little room. At 1280px+ there's
|
|
84
|
+
// enough vertical breathing room to make the backlinks panel feel
|
|
85
|
+
// like figure-margin annotations rather than another stacked card.
|
|
86
|
+
//
|
|
87
|
+
// Why scope to `.right.sidebar > .backlinks` (not just `.backlinks`)?
|
|
88
|
+
// Quartz emits `<div class="backlinks">` from `Component.Backlinks`
|
|
89
|
+
// (see `quartz/components/Backlinks.tsx` line 32). The same component
|
|
90
|
+
// could in theory appear elsewhere (e.g. `.center` slot for a
|
|
91
|
+
// custom layout); we only want the marginalia treatment when the
|
|
92
|
+
// component is sitting in the right sidebar position. The descendant
|
|
93
|
+
// selector enforces that scope.
|
|
94
|
+
//
|
|
95
|
+
// brain: this rule wins over Lane C's `.sidebar.right .backlinks`
|
|
96
|
+
// card chrome (background, border-radius, shadow, padding) because
|
|
97
|
+
// it's both later in the cascade AND uses overrides where they
|
|
98
|
+
// matter (background → transparent, padding → 0). Where Lane C
|
|
99
|
+
// rules don't conflict (e.g. nothing about font-style) we inherit
|
|
100
|
+
// Lane C's defaults silently — which is fine.
|
|
101
|
+
|
|
102
|
+
// brain (2026-05-06): the marginalia treatment was REMOVED per user
|
|
103
|
+
// feedback that Backlinks read as visually inconsistent with the
|
|
104
|
+
// Related and Table of Contents cards above it (190px column vs ~256px
|
|
105
|
+
// full-width cards). Backlinks now inherits Lane C's full-width card
|
|
106
|
+
// chrome from `_sidebar.scss` (`background: var(--surface-1)`,
|
|
107
|
+
// `border-radius: 8px`, `box-shadow: var(--shadow-sm)`,
|
|
108
|
+
// `padding: 0.6rem 0.8rem`), matching the ToC and Related panels above
|
|
109
|
+
// it. The italic / dimmed / narrow side-note voice is dropped — sidebar
|
|
110
|
+
// reads as a stack of three coordinated panels instead.
|
|
111
|
+
//
|
|
112
|
+
// If a future redesign wants the Tufte side-note treatment back, the
|
|
113
|
+
// architectural path is to extract `.backlinks` into a fourth grid
|
|
114
|
+
// area in `base.scss`'s template (see the original analysis in this
|
|
115
|
+
// file's git history at commit 2eaf550) — re-applying the SCSS without
|
|
116
|
+
// also moving the DOM out of `.right.sidebar` reproduces the exact
|
|
117
|
+
// width-mismatch bug this removal addresses.
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// Brain motion — Lane D of the 2026 commonplace-book redesign.
|
|
2
|
+
//
|
|
3
|
+
// This file is installed at
|
|
4
|
+
// `<vault>/.quartz/quartz/styles/brain/_motion.scss` by `brain vault
|
|
5
|
+
// render --overlay` and pulled into the global SCSS via
|
|
6
|
+
// `custom.scss`'s `@use "./brain/motion"` line (between
|
|
7
|
+
// `atmosphere` and `links`).
|
|
8
|
+
//
|
|
9
|
+
// What this file owns:
|
|
10
|
+
//
|
|
11
|
+
// 1. Page-load reveal animation — staggered slide/fade for the
|
|
12
|
+
// three-column shell on first paint. Sidebar-left slides in
|
|
13
|
+
// from the left, center fades up, sidebar-right slides in from
|
|
14
|
+
// the right; offsets ramped 50ms / 150ms / 250ms so the eye
|
|
15
|
+
// reads them in sequence rather than as a single twitch.
|
|
16
|
+
// 2. `prefers-reduced-motion` accessibility gate — the entire
|
|
17
|
+
// animation block sits inside a `(prefers-reduced-motion:
|
|
18
|
+
// no-preference)` media query so a user with the OS-level
|
|
19
|
+
// reduce-motion setting never sees the slide-in. Without the
|
|
20
|
+
// gate the WCAG 2.2 SC 2.3.3 (Animation from Interactions)
|
|
21
|
+
// regression risk is real for vestibular-disorder users.
|
|
22
|
+
// 3. Documentation pointer to the canonical motion-token knobs.
|
|
23
|
+
// Lane A's `_tokens.scss` defines `--motion-fast`, `--motion-mid`,
|
|
24
|
+
// `--motion-slow`, and `--motion-easing` — every other partial
|
|
25
|
+
// consumes those tokens for hover / focus / transition timings.
|
|
26
|
+
// This file does NOT redefine them; it just notes where they
|
|
27
|
+
// live so a future maintainer knows the single source of truth.
|
|
28
|
+
//
|
|
29
|
+
// Tokens consumed (all from `_tokens.scss`):
|
|
30
|
+
// * `--motion-easing` — smooth-out-quint cubic-bezier for the
|
|
31
|
+
// reveal animations.
|
|
32
|
+
//
|
|
33
|
+
// Tokens NOT redefined here (deliberate — see above):
|
|
34
|
+
// * `--motion-fast` (150ms) — hover transitions, link underline
|
|
35
|
+
// reveals (Lane B `_links.scss`), code-copy button (Lane C).
|
|
36
|
+
// * `--motion-mid` (250ms) — Cmd-K modal entrance, ToC card hovers,
|
|
37
|
+
// callout chrome.
|
|
38
|
+
// * `--motion-slow` (400ms) — page-load reveal duration; the
|
|
39
|
+
// stagger offsets below cap at 250ms so the cumulative reveal
|
|
40
|
+
// finishes around 650ms (slow + last-stagger), short enough to
|
|
41
|
+
// not feel laggy but long enough to register as "the page
|
|
42
|
+
// composed itself" rather than "the page snapped in."
|
|
43
|
+
//
|
|
44
|
+
// brain (Lane D): hover micro-interactions are already wired in
|
|
45
|
+
// Lanes B (link underlines) and C (sidebar icon trio, code-copy
|
|
46
|
+
// button, callout chrome). This file deliberately does NOT
|
|
47
|
+
// re-declare those — the `--motion-fast/mid/slow` + `--motion-easing`
|
|
48
|
+
// tokens declared in `_tokens.scss` are the canonical knobs, and
|
|
49
|
+
// the consuming partials read them directly. If a future change
|
|
50
|
+
// wants to retune motion globally, change the tokens once in
|
|
51
|
+
// `_tokens.scss` and every consumer updates.
|
|
52
|
+
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// 1. Page-load reveal — staggered three-column entrance
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
//
|
|
57
|
+
// The animation block is wrapped in
|
|
58
|
+
// `(prefers-reduced-motion: no-preference)` — the negative form
|
|
59
|
+
// matches when the OS-level reduce-motion setting is OFF. Users
|
|
60
|
+
// with reduce-motion ON see the page paint statically, no slide,
|
|
61
|
+
// no fade.
|
|
62
|
+
//
|
|
63
|
+
// Stagger order:
|
|
64
|
+
// * `.left.sidebar` — 50ms delay, slides 12px from the left
|
|
65
|
+
// * `.center` — 150ms delay, fades up 8px
|
|
66
|
+
// * `.right.sidebar` — 250ms delay, slides 12px from the right
|
|
67
|
+
//
|
|
68
|
+
// Why this order: the eye reads the page from outside-in. The
|
|
69
|
+
// left-sidebar (search + explorer) and right-sidebar (graph + ToC +
|
|
70
|
+
// backlinks) are reference scaffolding; the center is the article
|
|
71
|
+
// itself. By staggering the chrome before the content, we cue the
|
|
72
|
+
// reader's eye toward the center column on arrival — the page
|
|
73
|
+
// "composes itself" around the article rather than dumping
|
|
74
|
+
// everything in at once.
|
|
75
|
+
//
|
|
76
|
+
// `animation-fill-mode: both` (the `both` keyword in the shorthand)
|
|
77
|
+
// applies the `from` keyframe state during the delay window. Without
|
|
78
|
+
// it, the elements would paint at their final state during the 50/
|
|
79
|
+
// 150/250ms delay, then snap back to `from` and run the animation —
|
|
80
|
+
// the dreaded "FOUC of motion." `both` makes the delay window the
|
|
81
|
+
// `from` state.
|
|
82
|
+
//
|
|
83
|
+
// SPA navigation (Quartz's `enableSPA` + micromorph) patches DOM in
|
|
84
|
+
// place rather than replacing it, so `.left.sidebar` / `.center` /
|
|
85
|
+
// `.right.sidebar` are typically NOT re-mounted between routes. The
|
|
86
|
+
// animation fires once per hard load, which is the desired behavior
|
|
87
|
+
// — the cinematic entrance shouldn't replay on every internal click.
|
|
88
|
+
|
|
89
|
+
// brain (Lane D audit fix 2026-05-02): the original commit hardcoded
|
|
90
|
+
// the stagger delays as `0.05s`, `0.15s`, `0.25s`. Project rule is
|
|
91
|
+
// tokens-only — the literals were swapped for `--motion-stagger-1/2/3`
|
|
92
|
+
// declared in `_tokens.scss` (next to the existing `--motion-fast/
|
|
93
|
+
// mid/slow` block). The duration `var(--motion-slow)` was already a
|
|
94
|
+
// token; no change needed there.
|
|
95
|
+
|
|
96
|
+
// brain (Linear-variant feedback round 4): `animation-fill-mode` is
|
|
97
|
+
// `backwards`, NOT `both`. With `both`, the final keyframe's
|
|
98
|
+
// `transform: none` was getting interpolated into
|
|
99
|
+
// `matrix(1, 0, 0, 1, 0, 0)` (the identity) and stuck on the element
|
|
100
|
+
// permanently. A non-`none` transform on `.right.sidebar` creates a
|
|
101
|
+
// containing block for `position: fixed` descendants, which broke the
|
|
102
|
+
// global-graph modal — it anchored to the sidebar instead of the
|
|
103
|
+
// viewport, rendering as a narrow strip on the right edge.
|
|
104
|
+
//
|
|
105
|
+
// `backwards` applies the `from` keyframe BEFORE animation starts (so
|
|
106
|
+
// the entrance animation has its hidden-and-shifted starting state
|
|
107
|
+
// during the delay window) and lets the element fall back to its
|
|
108
|
+
// natural style (transform: none, opacity: 1) after the animation
|
|
109
|
+
// completes. No leftover identity-transform → no leftover containing
|
|
110
|
+
// block → fixed-position modals anchor to viewport correctly.
|
|
111
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
112
|
+
.left.sidebar {
|
|
113
|
+
animation: brain-slide-in-left var(--motion-slow) var(--motion-easing) var(--motion-stagger-1) backwards;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.center {
|
|
117
|
+
animation: brain-fade-up var(--motion-slow) var(--motion-easing) var(--motion-stagger-2) backwards;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.right.sidebar {
|
|
121
|
+
animation: brain-slide-in-right var(--motion-slow) var(--motion-easing) var(--motion-stagger-3) backwards;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Keyframes live OUTSIDE the media query — declaring them inside
|
|
126
|
+
// would scope them to that query in a way some renderers handle
|
|
127
|
+
// inconsistently. The `@keyframes` themselves are inert until
|
|
128
|
+
// referenced by an `animation` property; defining them globally is
|
|
129
|
+
// the conventional shape.
|
|
130
|
+
|
|
131
|
+
// brain (Linear-variant feedback round 4): the `to` keyframes MUST end
|
|
132
|
+
// with `transform: none`, NOT `transform: translateX(0)` /
|
|
133
|
+
// `translateY(0)`. Reason: a non-`none` transform value on any
|
|
134
|
+
// ancestor creates a containing block for `position: fixed` descendants
|
|
135
|
+
// (per CSS spec). With `animation-fill-mode: both` (set on the
|
|
136
|
+
// `.left.sidebar / .center / .right.sidebar` rules above), the final
|
|
137
|
+
// keyframe's transform value sticks AFTER the animation finishes —
|
|
138
|
+
// leaving `matrix(1,0,0,1,0,0)` on the sidebars permanently. That CB
|
|
139
|
+
// caused the global-graph modal (which is `position: fixed; left: 0;
|
|
140
|
+
// width: 100vw` inside `.right.sidebar`) to anchor to the sidebar
|
|
141
|
+
// instead of the viewport, rendering as a narrow strip on the right
|
|
142
|
+
// edge of the page. `transform: none` in the `to` keyframe restores
|
|
143
|
+
// the default and the modal anchors back to the viewport.
|
|
144
|
+
@keyframes brain-slide-in-left {
|
|
145
|
+
from {
|
|
146
|
+
opacity: 0;
|
|
147
|
+
transform: translateX(-12px);
|
|
148
|
+
}
|
|
149
|
+
to {
|
|
150
|
+
opacity: 1;
|
|
151
|
+
transform: none;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@keyframes brain-fade-up {
|
|
156
|
+
from {
|
|
157
|
+
opacity: 0;
|
|
158
|
+
transform: translateY(8px);
|
|
159
|
+
}
|
|
160
|
+
to {
|
|
161
|
+
opacity: 1;
|
|
162
|
+
transform: none;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@keyframes brain-slide-in-right {
|
|
167
|
+
from {
|
|
168
|
+
opacity: 0;
|
|
169
|
+
transform: translateX(12px);
|
|
170
|
+
}
|
|
171
|
+
to {
|
|
172
|
+
opacity: 1;
|
|
173
|
+
transform: none;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Brain People Hub — Phase C of the 2026-05-07 People Hub plan.
|
|
2
|
+
//
|
|
3
|
+
// This file is installed at
|
|
4
|
+
// `<vault>/.quartz/quartz/styles/brain/_people_hub.scss` by `brain
|
|
5
|
+
// vault render --overlay` and pulled into the global SCSS via
|
|
6
|
+
// `custom.scss`'s `@use "./brain/people_hub"` line.
|
|
7
|
+
//
|
|
8
|
+
// Scope of this file:
|
|
9
|
+
//
|
|
10
|
+
// * Distinct heading + frontmatter treatment for `kind: people`
|
|
11
|
+
// pages so the user can tell at a glance they're on a hub page
|
|
12
|
+
// (a person's roster) vs. a regular doc.
|
|
13
|
+
// * Index page (`/people/index`) gets a slightly heavier treatment
|
|
14
|
+
// to read as a directory landing page.
|
|
15
|
+
//
|
|
16
|
+
// Targeting strategy:
|
|
17
|
+
//
|
|
18
|
+
// Quartz exposes `body[data-slug=...]` (set in `renderPage.tsx`)
|
|
19
|
+
// but does NOT expose a `data-kind` attribute for arbitrary
|
|
20
|
+
// frontmatter fields. We key off the slug prefix instead — every
|
|
21
|
+
// people-hub page lives under `people/...` (per the
|
|
22
|
+
// `<vault>/people/<slug>.md` emit contract in
|
|
23
|
+
// `src/brain/wiki/build_people.py`), so `body[data-slug^="people/"]`
|
|
24
|
+
// selects the entire hub. The index page gets an additional rule
|
|
25
|
+
// keyed off `body[data-slug="people/index"]` for landing-page treatment.
|
|
26
|
+
//
|
|
27
|
+
// Tokens consumed (all from `_tokens.scss`):
|
|
28
|
+
//
|
|
29
|
+
// * `--accent-strong` — page-kind accent rail
|
|
30
|
+
// * `--surface-1` — H1 underline backdrop
|
|
31
|
+
// * `--rule` — primary-email block hairline
|
|
32
|
+
// * `--ink-0` / `--ink-2` — text colors
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// 1. Per-person pages — `body[data-slug^="people/"]` minus the index.
|
|
36
|
+
//
|
|
37
|
+
// We rely on a sibling rule below to refine the index landing page.
|
|
38
|
+
// The :not() selector keeps individual roster pages tighter (a
|
|
39
|
+
// distinct accent rail under the H1) and lets the index claim the
|
|
40
|
+
// fuller card treatment.
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
body[data-slug^="people/"]:not([data-slug="people/index"]) {
|
|
44
|
+
// Page-kind accent: a colored vertical rail to the left of the H1
|
|
45
|
+
// so the person's name reads as a heading-of-headings, not just
|
|
46
|
+
// another doc title. Uses padding (not margin) so the rail aligns
|
|
47
|
+
// with the article column rather than the page edge.
|
|
48
|
+
article > h1:first-of-type {
|
|
49
|
+
border-left: 4px solid var(--accent-strong, var(--secondary));
|
|
50
|
+
padding-left: 0.6rem;
|
|
51
|
+
// Subtle background so the rail reads as an enclosed badge rather
|
|
52
|
+
// than a stray vertical line. Falls back to `--gray` if the surface
|
|
53
|
+
// token isn't defined (older theme setups).
|
|
54
|
+
background: linear-gradient(
|
|
55
|
+
to right,
|
|
56
|
+
var(--surface-1, transparent) 0%,
|
|
57
|
+
transparent 60%
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Primary-email line: bold the label, faintly indent the value, give
|
|
62
|
+
// it a hairline underline so it reads as a header field rather than
|
|
63
|
+
// body prose. Targets the first `<p>` inside the article (the
|
|
64
|
+
// emitter writes "**Primary email:** [...]" as the very first
|
|
65
|
+
// paragraph).
|
|
66
|
+
article > p:first-of-type {
|
|
67
|
+
border-bottom: 1px solid var(--rule, var(--lightgray));
|
|
68
|
+
padding-bottom: 0.4rem;
|
|
69
|
+
margin-bottom: 1.2rem;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// 2. Index page — `body[data-slug="people/index"]`.
|
|
75
|
+
//
|
|
76
|
+
// The index lists every person; we want it to read as a "directory
|
|
77
|
+
// landing" page — heavier H1 treatment, a touch more breathing room
|
|
78
|
+
// between roster rows. Ordering matters: this block must come AFTER
|
|
79
|
+
// the per-person block above so its more specific selector wins
|
|
80
|
+
// (the per-person rule's `:not([data-slug="people/index"])` already
|
|
81
|
+
// excludes the index, but defense in depth).
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
body[data-slug="people/index"] {
|
|
85
|
+
article > h1:first-of-type {
|
|
86
|
+
// Heavier weight than the per-person H1; this is a landing page
|
|
87
|
+
// for the whole hub.
|
|
88
|
+
font-weight: 700;
|
|
89
|
+
border-bottom: 2px solid var(--accent-strong, var(--secondary));
|
|
90
|
+
padding-bottom: 0.4rem;
|
|
91
|
+
margin-bottom: 1.4rem;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Roster rows — one per person — get a touch more vertical
|
|
95
|
+
// breathing room so the curated badge + name + doc count reads
|
|
96
|
+
// as a glanceable directory rather than a dense bullet list.
|
|
97
|
+
article ul > li {
|
|
98
|
+
padding: 0.2rem 0;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// Brain related-docs sidebar — Phase 5.2 of the Wiki UX Overhaul.
|
|
2
|
+
//
|
|
3
|
+
// Loaded globally via `custom.scss`. The component only renders in the
|
|
4
|
+
// right sidebar for content pages; the runtime hides the whole panel
|
|
5
|
+
// until `/static/related/<slug>.json` returns valid rows.
|
|
6
|
+
|
|
7
|
+
.sidebar.right {
|
|
8
|
+
.brain-related-docs {
|
|
9
|
+
background: var(--surface-1);
|
|
10
|
+
border-radius: 8px;
|
|
11
|
+
padding: 0.6rem 0.8rem;
|
|
12
|
+
box-shadow: var(--shadow-sm);
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
// brain: allow the panel to shrink in the right-sidebar flex column
|
|
15
|
+
// so a tall related list never pushes ToC / Backlinks off the
|
|
16
|
+
// viewport. Without `min-height: 0` flex children refuse to shrink
|
|
17
|
+
// below their content size, which is what produced the original
|
|
18
|
+
// "can't scroll to the ToC" bug on hub pages.
|
|
19
|
+
min-height: 0;
|
|
20
|
+
// brain: become a flex column ourselves so the inner <ol> can be
|
|
21
|
+
// flex-shrunk to whatever height the parent sidebar grants this
|
|
22
|
+
// section. Without this, the section flex-shrinks but the inner
|
|
23
|
+
// list keeps its hardcoded `max-height: 32vh` and renders past the
|
|
24
|
+
// section's box (overflow: visible) — visually spilling onto the
|
|
25
|
+
// Backlinks panel below it. Pairs with `min-height: 0` on the list.
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
|
|
29
|
+
&[hidden] {
|
|
30
|
+
display: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
> h3 {
|
|
34
|
+
margin-top: 0;
|
|
35
|
+
margin-bottom: 0.4rem;
|
|
36
|
+
font-weight: 600;
|
|
37
|
+
font-size: 0.7rem;
|
|
38
|
+
letter-spacing: 0.06em;
|
|
39
|
+
text-transform: uppercase;
|
|
40
|
+
color: var(--ink-1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// brain: cap the related-docs list at ~one third of the viewport with
|
|
45
|
+
// its own internal scroll. The panel chrome (background, h3, padding)
|
|
46
|
+
// stays put; only the rows scroll. Combined with reordering the ToC
|
|
47
|
+
// above this panel in `quartz.layout.ts`, this guarantees the ToC and
|
|
48
|
+
// Backlinks panels remain reachable on hub pages with many related
|
|
49
|
+
// notes (COMPANY_REDACTED, COMPANY_REDACTED, etc. routinely pull 12+).
|
|
50
|
+
.brain-related-docs-list {
|
|
51
|
+
list-style: none;
|
|
52
|
+
margin: 0;
|
|
53
|
+
padding: 0;
|
|
54
|
+
display: grid;
|
|
55
|
+
gap: 0.35rem;
|
|
56
|
+
// brain: cap natural height at 32vh so a packed related set still
|
|
57
|
+
// leaves room for Backlinks below. `min-height: 0` plus the section
|
|
58
|
+
// being a flex column above lets the right sidebar's flex layout
|
|
59
|
+
// shrink the list (with its own internal scroll) when the column is
|
|
60
|
+
// squeezed — keeps the list inside the section's box instead of
|
|
61
|
+
// spilling onto the Backlinks panel below.
|
|
62
|
+
max-height: 32vh;
|
|
63
|
+
min-height: 0;
|
|
64
|
+
overflow-y: auto;
|
|
65
|
+
overscroll-behavior: contain;
|
|
66
|
+
scrollbar-width: thin;
|
|
67
|
+
scrollbar-color: var(--lightgray) transparent;
|
|
68
|
+
|
|
69
|
+
&::-webkit-scrollbar {
|
|
70
|
+
width: 4px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
&::-webkit-scrollbar-thumb {
|
|
74
|
+
background: var(--lightgray);
|
|
75
|
+
border-radius: 2px;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.brain-related-docs-item {
|
|
80
|
+
margin: 0;
|
|
81
|
+
|
|
82
|
+
> a {
|
|
83
|
+
display: grid;
|
|
84
|
+
grid-template-columns: 1.25rem minmax(0, 1fr);
|
|
85
|
+
gap: 0.45rem;
|
|
86
|
+
align-items: start;
|
|
87
|
+
padding: 0.35rem 0;
|
|
88
|
+
color: var(--ink-1);
|
|
89
|
+
text-decoration: none;
|
|
90
|
+
border-radius: 6px;
|
|
91
|
+
transition:
|
|
92
|
+
background var(--motion-fast) var(--motion-easing),
|
|
93
|
+
color var(--motion-fast) var(--motion-easing);
|
|
94
|
+
|
|
95
|
+
&:hover {
|
|
96
|
+
background: var(--accent-soft);
|
|
97
|
+
color: var(--ink-0);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.brain-related-docs-source {
|
|
103
|
+
width: 1.25rem;
|
|
104
|
+
line-height: 1.25;
|
|
105
|
+
text-align: center;
|
|
106
|
+
font-size: var(--fs-sm);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.brain-related-docs-body {
|
|
110
|
+
min-width: 0;
|
|
111
|
+
display: grid;
|
|
112
|
+
gap: 0.12rem;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.brain-related-docs-title {
|
|
116
|
+
color: var(--ink-0);
|
|
117
|
+
font-weight: 600;
|
|
118
|
+
font-size: var(--fs-sm);
|
|
119
|
+
line-height: 1.25;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.brain-related-docs-snippet {
|
|
123
|
+
display: -webkit-box;
|
|
124
|
+
color: var(--ink-2);
|
|
125
|
+
font-size: var(--fs-xs);
|
|
126
|
+
line-height: 1.35;
|
|
127
|
+
-webkit-line-clamp: 2;
|
|
128
|
+
-webkit-box-orient: vertical;
|
|
129
|
+
overflow: hidden;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.brain-related-docs-empty {
|
|
133
|
+
margin: 0;
|
|
134
|
+
color: var(--ink-2);
|
|
135
|
+
font-size: var(--fs-xs);
|
|
136
|
+
}
|
|
137
|
+
}
|