nlm-memory 0.4.2 → 0.5.1

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 (285) hide show
  1. package/README.md +72 -34
  2. package/dist/cli/nlm.js +223 -33
  3. package/dist/cli/nlm.js.map +1 -1
  4. package/dist/core/adapters/cursor.d.ts +45 -0
  5. package/dist/core/adapters/cursor.js +397 -0
  6. package/dist/core/adapters/cursor.js.map +1 -0
  7. package/dist/core/adapters/from-source.js +10 -0
  8. package/dist/core/adapters/from-source.js.map +1 -1
  9. package/dist/core/adapters/windsurf.d.ts +44 -0
  10. package/dist/core/adapters/windsurf.js +299 -0
  11. package/dist/core/adapters/windsurf.js.map +1 -0
  12. package/dist/core/hook/claude-settings.d.ts +12 -5
  13. package/dist/core/hook/claude-settings.js +21 -6
  14. package/dist/core/hook/claude-settings.js.map +1 -1
  15. package/dist/core/sources/source-registry.d.ts +1 -1
  16. package/dist/core/sources/source-registry.js +18 -0
  17. package/dist/core/sources/source-registry.js.map +1 -1
  18. package/dist/core/storage/sqlite-session-store.d.ts +2 -0
  19. package/dist/core/storage/sqlite-session-store.js +38 -2
  20. package/dist/core/storage/sqlite-session-store.js.map +1 -1
  21. package/dist/hook/hook-auth.d.ts +13 -0
  22. package/dist/hook/hook-auth.js +19 -0
  23. package/dist/hook/hook-auth.js.map +1 -0
  24. package/dist/hook/prompt-recall-hook.js +7 -1
  25. package/dist/hook/prompt-recall-hook.js.map +1 -1
  26. package/dist/hook/session-start-hook.js +4 -1
  27. package/dist/hook/session-start-hook.js.map +1 -1
  28. package/dist/hook/stop-hook.js +4 -1
  29. package/dist/hook/stop-hook.js.map +1 -1
  30. package/dist/http/app.d.ts +2 -0
  31. package/dist/http/app.js +76 -1
  32. package/dist/http/app.js.map +1 -1
  33. package/dist/install/claude-code.js +1 -1
  34. package/dist/install/claude-code.js.map +1 -1
  35. package/dist/install/cursor.d.ts +25 -0
  36. package/dist/install/cursor.js +43 -0
  37. package/dist/install/cursor.js.map +1 -0
  38. package/dist/install/nlm-dir-perms.d.ts +19 -0
  39. package/dist/install/nlm-dir-perms.js +43 -0
  40. package/dist/install/nlm-dir-perms.js.map +1 -0
  41. package/dist/install/ollama.d.ts +18 -1
  42. package/dist/install/ollama.js +62 -7
  43. package/dist/install/ollama.js.map +1 -1
  44. package/dist/install/setup.d.ts +4 -0
  45. package/dist/install/setup.js +141 -18
  46. package/dist/install/setup.js.map +1 -1
  47. package/dist/install/windsurf.d.ts +25 -0
  48. package/dist/install/windsurf.js +43 -0
  49. package/dist/install/windsurf.js.map +1 -0
  50. package/dist/mcp/server.js +20 -1
  51. package/dist/mcp/server.js.map +1 -1
  52. package/dist/shared/types.d.ts +4 -0
  53. package/dist/ui/assets/{index-BA6IpU8g.css → index-Beo8psd-.css} +1 -1
  54. package/dist/ui/assets/index-CSPTTeeM.js +69 -0
  55. package/dist/ui/index.html +2 -2
  56. package/package.json +26 -1
  57. package/plugin/scripts/prompt-recall-hook.mjs +55 -4
  58. package/plugin/scripts/stop-hook.mjs +57 -6
  59. package/.agents/plugins/marketplace.json +0 -20
  60. package/.github/workflows/ci.yml +0 -30
  61. package/dist/ui/assets/index-B_qIVV0k.js +0 -69
  62. package/docs/methodology/re-derivation-rate.md +0 -112
  63. package/docs/methodology/useful-hit-rate.md +0 -79
  64. package/docs/plans/2026-05-20-fts5-lexical-recall.md +0 -1088
  65. package/docs/plans/2026-05-20-recall-daemon-wedge-fix.md +0 -662
  66. package/docs/plans/2026-05-20-recall-hook-design.md +0 -131
  67. package/docs/plans/2026-05-20-recall-hook-implementation.md +0 -1222
  68. package/docs/plans/desktop-product.md +0 -69
  69. package/docs/plans/factstore-design.md +0 -236
  70. package/logs/CHANGELOG/CHANGELOG-2026.md +0 -1389
  71. package/logs/CHANGELOG/CHANGELOG.md +0 -337
  72. package/migrations/000_initial_schema.sql +0 -174
  73. package/migrations/001_entity_type_rename.sql +0 -17
  74. package/migrations/002_adapter_state_extend.sql +0 -12
  75. package/migrations/003_session_embeddings.sql +0 -11
  76. package/migrations/004_facts.sql +0 -46
  77. package/migrations/005_sources.sql +0 -31
  78. package/migrations/006_providers.sql +0 -33
  79. package/migrations/007_source_tokens.sql +0 -17
  80. package/migrations/008_fts_rebuild.sql +0 -9
  81. package/migrations/009_session_embedding_chunks.sql +0 -46
  82. package/migrations/010_sources_opencode.sql +0 -30
  83. package/migrations/011_sources_hermes_agent.sql +0 -30
  84. package/migrations/012_sources_aider.sql +0 -30
  85. package/migrations/013_adapter_state_failure_count.sql +0 -12
  86. package/plugin-hermes-agent/README.md +0 -49
  87. package/plugin-hermes-agent/__init__.py +0 -75
  88. package/plugin-hermes-agent/plugin.yaml +0 -15
  89. package/scripts/backfill-citations.mjs +0 -0
  90. package/scripts/build-codex-plugin.mjs +0 -61
  91. package/scripts/deepseek-probe.mjs +0 -67
  92. package/scripts/extract-triples.mjs +0 -207
  93. package/scripts/longmemeval/embedding-cache.ts +0 -77
  94. package/scripts/longmemeval/fetch-dataset.sh +0 -25
  95. package/scripts/longmemeval/run-harness.ts +0 -315
  96. package/scripts/longmemeval/scorer.ts +0 -99
  97. package/scripts/longmemeval/tsconfig.json +0 -9
  98. package/scripts/longmemeval/types.ts +0 -35
  99. package/scripts/nlm-daily-digest.py +0 -239
  100. package/scripts/nlm-daily-digest.sh +0 -28
  101. package/src/cli/classify-parity.ts +0 -257
  102. package/src/cli/launchctl-helpers.ts +0 -49
  103. package/src/cli/nlm.ts +0 -885
  104. package/src/core/actions/actions-log.ts +0 -118
  105. package/src/core/actions/overlay.ts +0 -117
  106. package/src/core/adapters/aider.ts +0 -205
  107. package/src/core/adapters/claude-code.ts +0 -293
  108. package/src/core/adapters/common.ts +0 -54
  109. package/src/core/adapters/from-source.ts +0 -57
  110. package/src/core/adapters/hermes-agent.ts +0 -240
  111. package/src/core/adapters/hermes.ts +0 -277
  112. package/src/core/adapters/jsonl-generic.ts +0 -208
  113. package/src/core/adapters/opencode.ts +0 -281
  114. package/src/core/adapters/pi.ts +0 -264
  115. package/src/core/classifier/prompt.ts +0 -200
  116. package/src/core/dataset/build-dataset.ts +0 -463
  117. package/src/core/embedding/chunk-body.ts +0 -76
  118. package/src/core/embedding/embed-backfill.ts +0 -210
  119. package/src/core/embedding/embed-normalize.ts +0 -135
  120. package/src/core/facts/backfill-facts.ts +0 -254
  121. package/src/core/facts/extract-facts.ts +0 -50
  122. package/src/core/hook/citation-detect.ts +0 -124
  123. package/src/core/hook/cite-memo.ts +0 -68
  124. package/src/core/hook/claude-settings.ts +0 -166
  125. package/src/core/hook/gate.ts +0 -25
  126. package/src/core/hook/hook-log.ts +0 -41
  127. package/src/core/hook/memo-sweep.ts +0 -164
  128. package/src/core/hook/memo.ts +0 -67
  129. package/src/core/hook/pointer-block.ts +0 -26
  130. package/src/core/hook/select.ts +0 -32
  131. package/src/core/hook/transcript.ts +0 -121
  132. package/src/core/ingest/ingest-session.ts +0 -111
  133. package/src/core/providers/provider-models.ts +0 -100
  134. package/src/core/providers/provider-registry.ts +0 -196
  135. package/src/core/recall/citation-log.ts +0 -108
  136. package/src/core/recall/filter.ts +0 -27
  137. package/src/core/recall/index.ts +0 -6
  138. package/src/core/recall/match-fields.ts +0 -40
  139. package/src/core/recall/query-log.ts +0 -149
  140. package/src/core/recall/query-shape.ts +0 -66
  141. package/src/core/recall/recall-service.ts +0 -320
  142. package/src/core/recall/recent-log.ts +0 -59
  143. package/src/core/recall/tokenize.ts +0 -18
  144. package/src/core/recall/useful-scan.ts +0 -336
  145. package/src/core/recall-facts/fact-query-log.ts +0 -150
  146. package/src/core/recall-facts/fact-recall-service.ts +0 -327
  147. package/src/core/scheduler/scan-once.ts +0 -142
  148. package/src/core/scheduler/scheduler.ts +0 -225
  149. package/src/core/sources/source-registry.ts +0 -260
  150. package/src/core/storage/db-restore.ts +0 -133
  151. package/src/core/storage/live-status.ts +0 -45
  152. package/src/core/storage/migrate.ts +0 -72
  153. package/src/core/storage/sqlite-fact-store.ts +0 -304
  154. package/src/core/storage/sqlite-session-store.ts +0 -765
  155. package/src/hook/prompt-recall-hook.ts +0 -174
  156. package/src/hook/session-end-hook.ts +0 -81
  157. package/src/hook/session-start-hook.ts +0 -165
  158. package/src/hook/stop-hook.ts +0 -236
  159. package/src/http/app.ts +0 -1137
  160. package/src/install/claude-code.ts +0 -128
  161. package/src/install/codex.ts +0 -367
  162. package/src/install/hermes-agent.ts +0 -76
  163. package/src/install/hermes.ts +0 -78
  164. package/src/install/ollama.ts +0 -211
  165. package/src/install/setup.ts +0 -368
  166. package/src/llm/classifier-box.ts +0 -64
  167. package/src/llm/deepseek-client.ts +0 -150
  168. package/src/llm/env-autoload.ts +0 -55
  169. package/src/llm/ollama-client.ts +0 -189
  170. package/src/mcp/server.ts +0 -534
  171. package/src/ports/fact-store.ts +0 -102
  172. package/src/ports/llm-client.ts +0 -52
  173. package/src/ports/logger.ts +0 -16
  174. package/src/ports/session-store.ts +0 -45
  175. package/src/ports/transcript-adapter.ts +0 -55
  176. package/src/shared/types.ts +0 -145
  177. package/src/ui/App.tsx +0 -58
  178. package/src/ui/components/PromoteOpenButton.tsx +0 -65
  179. package/src/ui/components/SessionDrawer.tsx +0 -136
  180. package/src/ui/components/SideNav.tsx +0 -162
  181. package/src/ui/components/Skeleton.tsx +0 -107
  182. package/src/ui/index.html +0 -13
  183. package/src/ui/lib/actions.ts +0 -30
  184. package/src/ui/lib/api.ts +0 -92
  185. package/src/ui/lib/dataset.ts +0 -141
  186. package/src/ui/lib/registries.ts +0 -155
  187. package/src/ui/lib/view-settings.ts +0 -41
  188. package/src/ui/main.tsx +0 -15
  189. package/src/ui/pages/Live.tsx +0 -229
  190. package/src/ui/pages/Pulse.tsx +0 -415
  191. package/src/ui/pages/Recall.tsx +0 -190
  192. package/src/ui/pages/River.tsx +0 -308
  193. package/src/ui/pages/Search.tsx +0 -93
  194. package/src/ui/pages/Stub.tsx +0 -9
  195. package/src/ui/pages/Thread.tsx +0 -262
  196. package/src/ui/pages/settings/Classifier.tsx +0 -227
  197. package/src/ui/pages/settings/Data.tsx +0 -190
  198. package/src/ui/pages/settings/Index.tsx +0 -65
  199. package/src/ui/pages/settings/Labels.tsx +0 -224
  200. package/src/ui/pages/settings/Providers.tsx +0 -305
  201. package/src/ui/pages/settings/SettingsSubnav.tsx +0 -28
  202. package/src/ui/pages/settings/Sources.tsx +0 -326
  203. package/src/ui/pages/settings/Views.tsx +0 -96
  204. package/src/ui/styles.css +0 -1766
  205. package/src/ui/tsconfig.json +0 -21
  206. package/src/ui/vite.config.ts +0 -19
  207. package/tests/fixtures/claude_code/short_session.jsonl +0 -2
  208. package/tests/fixtures/claude_code/standard_iso.jsonl +0 -4
  209. package/tests/fixtures/claude_code/tool_heavy.jsonl +0 -8
  210. package/tests/fixtures/claude_code/with_subagent.jsonl +0 -7
  211. package/tests/fixtures/facts.ts +0 -17
  212. package/tests/fixtures/golden-corpus.ts +0 -85
  213. package/tests/fixtures/hermes/paired_request_dump.json +0 -24
  214. package/tests/fixtures/hermes/paired_session.json +0 -23
  215. package/tests/fixtures/hermes/request_dump.json +0 -28
  216. package/tests/fixtures/hermes/session_iso.json +0 -38
  217. package/tests/fixtures/hermes/session_unix.json +0 -38
  218. package/tests/fixtures/hermes/system_only.json +0 -18
  219. package/tests/fixtures/pi/error-connection-abort.jsonl +0 -8
  220. package/tests/fixtures/pi/short-successful.jsonl +0 -5
  221. package/tests/fixtures/pi/with-custom-message.jsonl +0 -6
  222. package/tests/fixtures/sessions.ts +0 -22
  223. package/tests/integration/backfill-facts.test.ts +0 -362
  224. package/tests/integration/citation-explicit.test.ts +0 -111
  225. package/tests/integration/cite-event.test.ts +0 -169
  226. package/tests/integration/cite-memo.test.ts +0 -87
  227. package/tests/integration/db-restore.test.ts +0 -153
  228. package/tests/integration/embed-backfill.test.ts +0 -176
  229. package/tests/integration/fact-supersedence.test.ts +0 -313
  230. package/tests/integration/fts-index.test.ts +0 -60
  231. package/tests/integration/getbyids-sqlite.test.ts +0 -60
  232. package/tests/integration/hermes-agent-hooks.test.ts +0 -248
  233. package/tests/integration/hook-claude-settings.test.ts +0 -205
  234. package/tests/integration/hook-log.test.ts +0 -54
  235. package/tests/integration/hook-memo.test.ts +0 -68
  236. package/tests/integration/hook-pre-compact.test.ts +0 -105
  237. package/tests/integration/hook-subagent-start.test.ts +0 -102
  238. package/tests/integration/http.test.ts +0 -401
  239. package/tests/integration/keyword-search-fts.test.ts +0 -66
  240. package/tests/integration/mcp-recall-logging.test.ts +0 -88
  241. package/tests/integration/mcp.test.ts +0 -248
  242. package/tests/integration/memo-sweep.test.ts +0 -91
  243. package/tests/integration/prompt-recall-hook.test.ts +0 -88
  244. package/tests/integration/provider-registry.test.ts +0 -107
  245. package/tests/integration/recall-golden.test.ts +0 -59
  246. package/tests/integration/recall-sqlite.test.ts +0 -169
  247. package/tests/integration/scheduler.test.ts +0 -391
  248. package/tests/integration/session-end-hook.test.ts +0 -48
  249. package/tests/integration/session-start-hook.test.ts +0 -126
  250. package/tests/integration/source-registry.test.ts +0 -120
  251. package/tests/integration/sqlite-fact-store.test.ts +0 -346
  252. package/tests/integration/stop-hook.test.ts +0 -560
  253. package/tests/integration/wal-checkpoint.test.ts +0 -49
  254. package/tests/unit/cli/launchctl-helpers.test.ts +0 -60
  255. package/tests/unit/core/adapters/aider.test.ts +0 -230
  256. package/tests/unit/core/adapters/claude-code.test.ts +0 -118
  257. package/tests/unit/core/adapters/hermes-agent.test.ts +0 -329
  258. package/tests/unit/core/adapters/hermes.test.ts +0 -81
  259. package/tests/unit/core/adapters/jsonl-generic.test.ts +0 -142
  260. package/tests/unit/core/adapters/opencode.test.ts +0 -354
  261. package/tests/unit/core/adapters/pi.test.ts +0 -110
  262. package/tests/unit/core/classifier/prompt.test.ts +0 -126
  263. package/tests/unit/core/embedding/chunk-body.test.ts +0 -100
  264. package/tests/unit/core/facts/extract-facts.test.ts +0 -117
  265. package/tests/unit/core/filter.test.ts +0 -40
  266. package/tests/unit/core/hook/citation-detect-cite-session.test.ts +0 -96
  267. package/tests/unit/core/hook/citation-detect.test.ts +0 -124
  268. package/tests/unit/core/hook/gate.test.ts +0 -29
  269. package/tests/unit/core/hook/pointer-block.test.ts +0 -22
  270. package/tests/unit/core/hook/select.test.ts +0 -66
  271. package/tests/unit/core/match-fields.test.ts +0 -39
  272. package/tests/unit/core/mcp-cite-session.test.ts +0 -51
  273. package/tests/unit/core/providers/provider-models.test.ts +0 -101
  274. package/tests/unit/core/query-shape.test.ts +0 -92
  275. package/tests/unit/core/recall-facts/fact-recall-service.test.ts +0 -258
  276. package/tests/unit/core/recall-service.test.ts +0 -200
  277. package/tests/unit/core/storage/live-status.test.ts +0 -54
  278. package/tests/unit/core/tokenize.test.ts +0 -32
  279. package/tests/unit/core/useful-scan.test.ts +0 -537
  280. package/tests/unit/llm/embed.test.ts +0 -93
  281. package/tests/unit/llm/ollama-client.test.ts +0 -124
  282. package/tests/unit/scripts/longmemeval-scorer.test.ts +0 -114
  283. package/tsconfig.json +0 -31
  284. package/tsconfig.test.json +0 -11
  285. package/vitest.config.ts +0 -22
package/src/ui/styles.css DELETED
@@ -1,1766 +0,0 @@
1
- /* NLM — Design system v2
2
- Single source of truth for all tokens, surfaces, and shared components.
3
- All pages import this via BaseLayout. No :global() needed — .css is always global. */
4
-
5
- /* ── Tokens ──────────────────────────────────────────────────────────────── */
6
- :root {
7
- /* Surface scale — 4 clean steps (dark-gray, not near-black) */
8
- --surface-0: #161616; /* page background */
9
- --surface-1: #1d1d1d; /* card / tile */
10
- --surface-2: #242424; /* card hover / raised input */
11
- --surface-float: #2c2c2c; /* floating panel (dropdowns, modals) */
12
-
13
- /* Border scale — 4 levels (bumped to stay visible on lighter surfaces) */
14
- --border-1: #262626; /* hairline / divider */
15
- --border-2: #303030; /* card border */
16
- --border-3: #3d3d3d; /* hover / active border */
17
- --border-4: #525252; /* focused / bright */
18
-
19
- /* Text scale — 4 semantic levels */
20
- --text-1: #e8e8e8; /* primary — body, values */
21
- --text-2: #b0b0b0; /* secondary — labels, subtitles */
22
- --text-3: #686868; /* muted — timestamps, section headers */
23
- --text-4: #383838; /* disabled / placeholder */
24
-
25
- /* Legacy text aliases — TODO: migrate .astro call sites to --text-1/2/3/4 */
26
- --text-primary: #e8e8e8;
27
- --text-dim: #b8b8b8; /* TODO: migrate */
28
- --text-muted: #888; /* TODO: migrate */
29
- --text-faint: #777; /* TODO: migrate */
30
- --text-ghost: #666; /* TODO: migrate */
31
- --text-dead: #555; /* TODO: migrate */
32
- --text-void: #444; /* TODO: migrate */
33
-
34
- /* Signal colors */
35
- --accent: #e8ff6e;
36
- --accent-dim: rgba(232, 255, 110, 0.12);
37
- --accent-glow: rgba(232, 255, 110, 0.06);
38
- --warn: #ff9933;
39
- --warn-dim: rgba(255, 153, 51, 0.12);
40
- --danger: #ff6b35;
41
- --danger-dim: rgba(255, 107, 53, 0.07);
42
- --danger-glow: rgba(255, 107, 53, 0.12);
43
-
44
- /* Typography — type scale */
45
- --font-mono: 'IBM Plex Mono', 'Fira Code', ui-monospace, monospace;
46
-
47
- --text-xs: 10px;
48
- --text-sm: 11px;
49
- --text-base: 13px;
50
- --text-md: 15px;
51
- --text-lg: 18px;
52
- --text-xl: 22px;
53
- --text-stat: 36px;
54
-
55
- --lh-tight: 1.3;
56
- --lh-base: 1.5;
57
- --lh-loose: 1.7;
58
-
59
- /* Spacing */
60
- --page-x: 28px;
61
- --section-gap: 24px;
62
-
63
- /* Shape */
64
- --r-sm: 3px;
65
- --r-md: 5px;
66
- --r-lg: 7px;
67
-
68
- /* Motion */
69
- --ease: 0.15s ease;
70
- --ease-fast: 0.1s ease;
71
- }
72
-
73
- /* ── Reset ───────────────────────────────────────────────────────────────── */
74
- *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
75
-
76
- html {
77
- background-color: var(--surface-0);
78
- }
79
-
80
- body {
81
- /* Subtle accent radial at top — the one atmospheric element.
82
- Reads as a ceiling light above a dark instrument panel. */
83
- background-image: radial-gradient(
84
- ellipse 100% 40% at 50% -8%,
85
- rgba(232, 255, 110, 0.032) 0%,
86
- transparent 100%
87
- );
88
- background-attachment: fixed;
89
- color: var(--text-1);
90
- font-family: var(--font-mono);
91
- min-height: 100vh;
92
- -webkit-font-smoothing: antialiased;
93
- -moz-osx-font-smoothing: grayscale;
94
- }
95
-
96
- /* ── Scrollbar ───────────────────────────────────────────────────────────── */
97
- ::-webkit-scrollbar { width: 4px; height: 4px; }
98
- ::-webkit-scrollbar-track { background: var(--surface-1); }
99
- ::-webkit-scrollbar-thumb { background: var(--border-3); border-radius: 2px; }
100
-
101
- /* ── Animation ───────────────────────────────────────────────────────────── */
102
- @keyframes fadeSlideIn {
103
- from { opacity: 0; transform: translateY(6px); }
104
- to { opacity: 1; transform: translateY(0); }
105
- }
106
-
107
- @media (prefers-reduced-motion: reduce) {
108
- *, *::before, *::after {
109
- animation-duration: 0.01ms !important;
110
- animation-delay: 0ms !important;
111
- transition-duration: 0.01ms !important;
112
- }
113
- }
114
-
115
- /* ── Skeleton ────────────────────────────────────────────────────────────── */
116
- .skeleton {
117
- display: inline-block;
118
- background: linear-gradient(
119
- 90deg,
120
- var(--surface-1) 0%,
121
- var(--surface-2) 50%,
122
- var(--surface-1) 100%
123
- );
124
- background-size: 200% 100%;
125
- animation: skeleton-shimmer 1.2s ease-in-out infinite;
126
- vertical-align: middle;
127
- }
128
- @keyframes skeleton-shimmer {
129
- 0% { background-position: 200% 0; }
130
- 100% { background-position: -200% 0; }
131
- }
132
- @media (prefers-reduced-motion: reduce) {
133
- .skeleton { animation: none; background: var(--surface-2); }
134
- }
135
-
136
- /* ── Card ────────────────────────────────────────────────────────────────── */
137
- /* Base surface. Combine with .card-lift for interactive tiles. */
138
- .card {
139
- background: var(--surface-1);
140
- border: 1px solid var(--border-2);
141
- border-radius: var(--r-md);
142
- }
143
- .card-lift {
144
- transition: border-color var(--ease), background var(--ease);
145
- }
146
- .card-lift:hover {
147
- background: var(--surface-2);
148
- border-color: var(--border-3);
149
- }
150
-
151
- /* ── Button ──────────────────────────────────────────────────────────────── */
152
- /* Canonical button. All interactive controls should use this or a variant. */
153
- .btn {
154
- display: inline-flex;
155
- align-items: center;
156
- gap: 5px;
157
- font-family: var(--font-mono);
158
- font-size: var(--text-sm);
159
- letter-spacing: 0.06em;
160
- text-transform: uppercase;
161
- padding: 5px 12px;
162
- border-radius: var(--r-sm);
163
- border: 1px solid var(--border-3);
164
- background: transparent;
165
- color: var(--text-2);
166
- cursor: pointer;
167
- white-space: nowrap;
168
- text-decoration: none;
169
- user-select: none;
170
- transition: border-color var(--ease), color var(--ease), background var(--ease);
171
- }
172
- .btn:hover { border-color: var(--border-4); color: var(--text-1); }
173
- .btn:active { background: var(--surface-2); }
174
- .btn.active { background: var(--surface-2); border-color: var(--border-3); color: var(--text-1); }
175
- .btn-primary { background: var(--accent); border-color: var(--accent); color: #080808; font-weight: 600; }
176
- .btn-primary:hover { background: #d4eb5e; border-color: #d4eb5e; color: #080808; }
177
- .btn-accent { color: var(--accent); border-color: rgba(232,255,110,0.25); }
178
- .btn-accent:hover { background: var(--accent-glow); border-color: rgba(232,255,110,0.4); }
179
-
180
- .form-row {
181
- display: flex;
182
- align-items: center;
183
- gap: 12px;
184
- flex-wrap: wrap;
185
- margin: 12px 0;
186
- }
187
- .form-row .form-label { color: var(--text-3); font-size: var(--text-xs); }
188
- .btn-danger:hover { border-color: var(--danger); color: var(--danger); }
189
-
190
- /* File input — restyle the native picker button to match .btn; the
191
- filename text stays native but tuned to the app's muted mono. */
192
- input[type="file"].file-input {
193
- font-family: var(--font-mono);
194
- font-size: var(--text-xs);
195
- color: var(--text-3);
196
- max-width: 24rem;
197
- }
198
- input[type="file"].file-input::file-selector-button {
199
- display: inline-flex;
200
- align-items: center;
201
- font-family: var(--font-mono);
202
- font-size: var(--text-sm);
203
- letter-spacing: 0.06em;
204
- text-transform: uppercase;
205
- padding: 5px 12px;
206
- margin-right: 10px;
207
- border-radius: var(--r-sm);
208
- border: 1px solid var(--border-3);
209
- background: transparent;
210
- color: var(--text-2);
211
- cursor: pointer;
212
- transition: border-color var(--ease), color var(--ease), background var(--ease);
213
- }
214
- input[type="file"].file-input::file-selector-button:hover {
215
- border-color: var(--border-4);
216
- color: var(--text-1);
217
- }
218
- input[type="file"].file-input:disabled {
219
- cursor: not-allowed;
220
- }
221
- input[type="file"].file-input:disabled::file-selector-button {
222
- opacity: 0.5;
223
- cursor: not-allowed;
224
- }
225
-
226
- /* ── Chip ────────────────────────────────────────────────────────────────── */
227
- /* Filter / state toggles. Lowercase, smaller presence than .btn. */
228
- .chip {
229
- display: inline-flex;
230
- align-items: center;
231
- gap: 4px;
232
- font-family: var(--font-mono);
233
- font-size: var(--text-sm);
234
- letter-spacing: 0.06em;
235
- text-transform: lowercase;
236
- padding: 3px 9px;
237
- border-radius: var(--r-sm);
238
- border: 1px solid var(--border-1);
239
- background: transparent;
240
- color: var(--text-3);
241
- cursor: pointer;
242
- user-select: none;
243
- white-space: nowrap;
244
- transition: border-color var(--ease), color var(--ease), background var(--ease);
245
- }
246
- .chip:hover { border-color: var(--border-3); color: var(--text-2); }
247
- .chip.active { border-color: var(--border-3); color: var(--text-1); background: var(--surface-2); }
248
-
249
- /* Semantic chip tints — opt-in via data attributes */
250
- .chip[data-severity="critical"].active { border-color: rgba(255,107,53,0.4); color: var(--danger); background: var(--danger-dim); }
251
- .chip[data-severity="high"].active { border-color: rgba(204,68,34,0.35); color: #cc4422; background: rgba(204,68,34,0.06); }
252
- .chip[data-severity="medium"].active { border-color: rgba(255,153,51,0.35); color: var(--warn); background: var(--warn-dim); }
253
- .chip[data-severity="low"].active { border-color: var(--border-3); color: var(--text-2); background: var(--surface-2); }
254
- .chip[data-status="active"].active { color: var(--accent); border-color: rgba(232,255,110,0.3); background: var(--accent-glow); }
255
- .chip[data-status="idle"].active { color: #ffcc80; }
256
- .chip[data-length].active { color: var(--text-1); }
257
- .chip[data-marker].active { color: var(--accent); border-color: rgba(232,255,110,0.3); background: var(--accent-glow); }
258
-
259
- /* ── Floating panel ──────────────────────────────────────────────────────── */
260
- /* Glass treatment — ONLY for elements that genuinely overlay scrolled content
261
- (dropdowns, session preview, sticky bulk toolbar, KB legend). */
262
- .panel-float {
263
- background: rgba(16, 16, 16, 0.96);
264
- backdrop-filter: blur(18px);
265
- -webkit-backdrop-filter: blur(18px);
266
- border: 1px solid var(--border-3);
267
- border-radius: var(--r-md);
268
- box-shadow: 0 12px 40px rgba(0,0,0,0.65), 0 0 0 1px rgba(255,255,255,0.03);
269
- }
270
-
271
- /* ── Navigation pills ────────────────────────────────────────────────────── */
272
- .nav-link {
273
- display: inline-flex;
274
- align-items: center;
275
- background: transparent;
276
- border: 1px solid transparent;
277
- color: var(--text-3);
278
- border-radius: var(--r-sm);
279
- padding: 4px 10px;
280
- font-size: var(--text-sm);
281
- font-family: var(--font-mono);
282
- letter-spacing: 0.06em;
283
- text-transform: uppercase;
284
- text-decoration: none;
285
- transition: color var(--ease), border-color var(--ease), background var(--ease);
286
- }
287
- .nav-link:hover { color: var(--text-2); border-color: var(--border-3); }
288
- .nav-link.active {
289
- background: var(--surface-2);
290
- border-color: var(--border-3);
291
- color: var(--text-1);
292
- }
293
-
294
- /* ── Inputs ──────────────────────────────────────────────────────────────── */
295
- .search-input {
296
- background: var(--surface-1);
297
- border: 1px solid var(--border-2);
298
- color: var(--text-1);
299
- font-family: var(--font-mono);
300
- font-size: var(--text-xs);
301
- padding: 5px 10px;
302
- border-radius: var(--r-sm);
303
- letter-spacing: 0.04em;
304
- outline: none;
305
- transition: border-color var(--ease);
306
- }
307
- .search-input:focus { border-color: var(--border-3); }
308
- .search-input::placeholder { color: var(--text-4); letter-spacing: 0.06em; }
309
-
310
- /* ── Control buttons (River toolbar: zoom, axis, entity pickers) ─────────── */
311
- .ctrl-btn {
312
- background: var(--surface-1);
313
- border: 1px solid var(--border-2);
314
- color: var(--text-2);
315
- font-family: var(--font-mono);
316
- font-size: var(--text-sm);
317
- letter-spacing: 0.06em;
318
- text-transform: uppercase;
319
- padding: 4px 10px;
320
- border-radius: var(--r-sm);
321
- cursor: pointer;
322
- white-space: nowrap;
323
- transition: border-color var(--ease), color var(--ease), background var(--ease);
324
- }
325
- .ctrl-btn:hover { border-color: var(--border-3); color: var(--text-1); }
326
- .ctrl-btn.active { background: var(--surface-2); border-color: var(--border-3); color: var(--accent); }
327
- .ctrl-btn[data-active="1"] { color: var(--accent); border-color: rgba(232,255,110,0.25); }
328
-
329
- .ctrl-label {
330
- font-size: var(--text-sm);
331
- color: var(--text-3);
332
- letter-spacing: 0.06em;
333
- text-transform: uppercase;
334
- flex-shrink: 0;
335
- }
336
-
337
- /* ── Settings subnav ─────────────────────────────────────────────────────── */
338
- .subnav {
339
- padding: 0 28px;
340
- border-bottom: 1px solid var(--border-1);
341
- display: flex;
342
- gap: 0;
343
- }
344
- .subnav-link {
345
- font-size: var(--text-sm);
346
- font-family: var(--font-mono);
347
- letter-spacing: 0.06em;
348
- text-transform: uppercase;
349
- color: var(--text-3);
350
- text-decoration: none;
351
- padding: 10px 14px;
352
- border-bottom: 2px solid transparent;
353
- margin-bottom: -1px;
354
- transition: color var(--ease), border-color var(--ease);
355
- }
356
- .subnav-link:hover { color: var(--text-2); }
357
- .subnav-link.active { color: var(--accent); border-bottom-color: var(--accent); }
358
-
359
- /* ── App shell ────────────────────────────────────────────────────────────
360
- Ported from BaseLayout.astro. Side-nav is sticky inside the flex row,
361
- so the main panel doesn't need a margin offset. */
362
- .page-shell {
363
- display: flex;
364
- min-height: 100vh;
365
- background: var(--surface-0);
366
- }
367
-
368
- .page-main {
369
- flex: 1;
370
- min-width: 0;
371
- display: flex;
372
- flex-direction: column;
373
- }
374
-
375
- /* ── AppHeader (slim top bar) ─────────────────────────────────────────── */
376
- .app-header {
377
- position: sticky;
378
- top: 0;
379
- z-index: 50;
380
- height: 52px;
381
- padding: 0 var(--page-x);
382
- display: flex;
383
- align-items: center;
384
- gap: 20px;
385
- background: rgba(22, 22, 22, 0.9);
386
- backdrop-filter: blur(12px);
387
- -webkit-backdrop-filter: blur(12px);
388
- border-bottom: 1px solid var(--border-1);
389
- }
390
-
391
- .app-header .wordmark-page {
392
- font-size: var(--text-sm);
393
- color: var(--text-3);
394
- letter-spacing: 0.04em;
395
- text-transform: lowercase;
396
- }
397
-
398
- .app-header .header-spacer { flex: 1; }
399
-
400
- .app-header .status-dot {
401
- width: 7px;
402
- height: 7px;
403
- border-radius: 50%;
404
- background: var(--accent);
405
- box-shadow: 0 0 6px var(--accent-dim);
406
- animation: pulse-dot 2s ease-in-out infinite;
407
- }
408
-
409
- @keyframes pulse-dot {
410
- 0%, 100% { opacity: 1; }
411
- 50% { opacity: 0.4; }
412
- }
413
-
414
- .app-header .header-info {
415
- font-size: var(--text-xs);
416
- color: var(--text-3);
417
- letter-spacing: 0.04em;
418
- }
419
-
420
- /* ── SideNav (ported from SideNav.astro <style> block) ─────────────────── */
421
- .sidenav {
422
- width: 180px;
423
- flex-shrink: 0;
424
- display: flex;
425
- flex-direction: column;
426
- background: var(--surface-1);
427
- border-right: 1px solid var(--border-1);
428
- position: sticky;
429
- top: 0;
430
- height: 100vh;
431
- overflow: hidden;
432
- transition: width 150ms ease;
433
- z-index: 100;
434
- }
435
-
436
- .sidenav.collapsed { width: 52px; }
437
-
438
- .sidenav-header {
439
- padding: 0 8px 0 16px;
440
- height: 52px;
441
- display: flex;
442
- align-items: center;
443
- justify-content: space-between;
444
- border-bottom: 1px solid var(--border-1);
445
- flex-shrink: 0;
446
- }
447
-
448
- .sidenav-wordmark {
449
- font-size: 11px;
450
- font-family: var(--font-mono);
451
- letter-spacing: 0.2em;
452
- text-transform: uppercase;
453
- color: var(--accent);
454
- user-select: none;
455
- white-space: nowrap;
456
- overflow: hidden;
457
- transition: opacity 100ms ease, width 100ms ease;
458
- }
459
-
460
- .sidenav.collapsed .sidenav-wordmark { opacity: 0; width: 0; padding: 0; }
461
-
462
- .sidenav-toggle {
463
- background: none;
464
- border: none;
465
- color: var(--text-3);
466
- cursor: pointer;
467
- padding: 5px;
468
- border-radius: var(--r-sm);
469
- display: flex;
470
- align-items: center;
471
- justify-content: center;
472
- flex-shrink: 0;
473
- transition: color var(--ease), background var(--ease);
474
- }
475
-
476
- .sidenav-toggle:hover { color: var(--text-1); background: var(--surface-2); }
477
-
478
- .sidenav.collapsed .sidenav-header { justify-content: center; padding: 0 8px; }
479
-
480
- .sidenav-items {
481
- flex: 1;
482
- padding: 10px 8px;
483
- display: flex;
484
- flex-direction: column;
485
- gap: 2px;
486
- overflow: hidden;
487
- }
488
-
489
- .sidenav-item {
490
- display: flex;
491
- align-items: center;
492
- gap: 9px;
493
- padding: 8px 10px;
494
- border-radius: var(--r-sm);
495
- font-size: 11px;
496
- font-family: var(--font-mono);
497
- letter-spacing: 0.06em;
498
- text-transform: uppercase;
499
- color: var(--text-3);
500
- text-decoration: none;
501
- border-left: 3px solid transparent;
502
- transition: color var(--ease), background var(--ease), border-color var(--ease);
503
- user-select: none;
504
- white-space: nowrap;
505
- overflow: hidden;
506
- position: relative;
507
- }
508
-
509
- .sidenav-item:hover { color: var(--text-1); background: var(--surface-2); }
510
- .sidenav-item.active {
511
- color: var(--text-1);
512
- border-left-color: var(--accent);
513
- background: var(--accent-glow);
514
- }
515
-
516
- .item-icon { flex-shrink: 0; display: flex; align-items: center; opacity: 0.7; }
517
- .sidenav-item.active .item-icon { opacity: 1; }
518
- .item-label { transition: opacity 100ms ease; }
519
-
520
- .sidenav.collapsed .item-label { display: none; }
521
- .sidenav.collapsed .sidenav-item {
522
- gap: 0;
523
- padding: 8px;
524
- justify-content: center;
525
- border-left: 3px solid transparent;
526
- }
527
- .sidenav.collapsed .sidenav-item.active { border-left-color: var(--accent); }
528
-
529
- .sidenav.collapsed .sidenav-item::after {
530
- content: attr(data-label);
531
- position: absolute;
532
- left: calc(100% + 8px);
533
- top: 50%;
534
- transform: translateY(-50%);
535
- background: var(--surface-float);
536
- color: var(--text-1);
537
- font-size: 10px;
538
- font-family: var(--font-mono);
539
- letter-spacing: 0.06em;
540
- text-transform: uppercase;
541
- padding: 4px 8px;
542
- border-radius: var(--r-sm);
543
- border: 1px solid var(--border-2);
544
- white-space: nowrap;
545
- pointer-events: none;
546
- opacity: 0;
547
- transition: opacity 100ms ease;
548
- z-index: 200;
549
- }
550
-
551
- .sidenav.collapsed .sidenav-item:hover::after { opacity: 1; }
552
-
553
- .sidenav-footer {
554
- padding: 8px;
555
- border-top: 1px solid var(--border-1);
556
- flex-shrink: 0;
557
- }
558
-
559
- .sidenav-data { font-size: 10px; }
560
-
561
- /* ── Live page — three-column board ───────────────────────────────────── */
562
- .live-page {
563
- display: flex;
564
- flex-direction: column;
565
- flex: 1;
566
- min-height: 0;
567
- }
568
-
569
- .live-status {
570
- display: flex;
571
- align-items: center;
572
- gap: 8px;
573
- padding: 12px var(--page-x) 4px;
574
- }
575
-
576
- .live-status-dot {
577
- width: 7px;
578
- height: 7px;
579
- border-radius: 50%;
580
- flex-shrink: 0;
581
- }
582
- .live-status-live {
583
- background: var(--accent);
584
- box-shadow: 0 0 6px var(--accent);
585
- }
586
- .live-status-connecting { background: var(--text-3); }
587
- .live-status-reconnecting {
588
- background: var(--warn);
589
- animation: pulse-dot 1.2s ease-in-out infinite;
590
- }
591
-
592
- .live-status-label {
593
- font-family: var(--font-mono);
594
- font-size: var(--text-sm);
595
- letter-spacing: 0.06em;
596
- text-transform: uppercase;
597
- color: var(--text-2);
598
- }
599
-
600
- .live-board {
601
- padding: 4px var(--page-x) 0;
602
- display: grid;
603
- grid-template-columns: repeat(3, 1fr);
604
- gap: 16px;
605
- flex: 1;
606
- min-height: 0;
607
- }
608
-
609
- .live-col {
610
- background: var(--surface-1);
611
- border: 1px solid var(--border-2);
612
- border-radius: var(--r-md);
613
- display: flex;
614
- flex-direction: column;
615
- overflow: hidden;
616
- min-height: 0;
617
- }
618
-
619
- .live-col-head {
620
- padding: 10px 14px;
621
- border-bottom: 1px solid var(--border-1);
622
- display: flex;
623
- align-items: baseline;
624
- justify-content: space-between;
625
- }
626
-
627
- .live-col-title {
628
- font-size: var(--text-sm);
629
- font-family: var(--font-mono);
630
- letter-spacing: 0.06em;
631
- text-transform: uppercase;
632
- color: var(--text-2);
633
- }
634
-
635
- .live-col-count {
636
- font-size: var(--text-xs);
637
- color: var(--text-3);
638
- font-family: var(--font-mono);
639
- }
640
-
641
- .live-col-body { overflow-y: auto; flex: 1; }
642
-
643
- .live-row {
644
- padding: 8px 14px;
645
- border-bottom: 1px solid var(--border-1);
646
- animation: fadeSlideIn 200ms ease-out;
647
- }
648
-
649
- .live-row:last-child { border-bottom: none; }
650
-
651
- .live-row.clickable {
652
- cursor: pointer;
653
- transition: background var(--ease);
654
- }
655
- .live-row.clickable:hover { background: var(--surface-2); }
656
- .live-row.clickable:focus-visible {
657
- outline: 1px solid rgba(255, 255, 255, 0.5);
658
- outline-offset: -1px;
659
- }
660
-
661
- /* Newly arrived rows flash once so the feed reads as live. */
662
- .live-row.is-new { animation: fadeSlideIn 200ms ease-out, liveFlash 1200ms ease-out; }
663
-
664
- @keyframes liveFlash {
665
- 0% { background: var(--accent-glow); }
666
- 100% { background: transparent; }
667
- }
668
-
669
- .live-row .label { color: var(--text-1); font-size: var(--text-base); line-height: var(--lh-tight); }
670
- .live-row .body { color: var(--text-3); font-size: var(--text-sm); margin-top: 3px; line-height: var(--lh-tight); }
671
- .live-row .meta { color: var(--text-3); font-size: var(--text-xs); margin-top: 4px; letter-spacing: 0.04em; }
672
-
673
- .live-tag {
674
- display: inline-block;
675
- font-size: var(--text-xs);
676
- font-family: var(--font-mono);
677
- letter-spacing: 0.06em;
678
- text-transform: uppercase;
679
- padding: 1px 6px;
680
- margin-right: 6px;
681
- border-radius: var(--r-sm);
682
- background: var(--surface-2);
683
- color: var(--text-2);
684
- border: 1px solid var(--border-2);
685
- }
686
-
687
- .live-tag[data-kind="decision"] {
688
- background: var(--accent-glow);
689
- border-color: rgba(232,255,110,0.25);
690
- color: var(--accent);
691
- }
692
-
693
- .live-tag[data-kind="open"] {
694
- background: var(--warn-dim);
695
- border-color: rgba(255,153,51,0.25);
696
- color: var(--warn);
697
- }
698
-
699
- .live-empty {
700
- padding: 32px 16px;
701
- text-align: center;
702
- color: var(--text-3);
703
- font-size: var(--text-xs);
704
- letter-spacing: 0.06em;
705
- text-transform: uppercase;
706
- }
707
-
708
- /* ── Stub page (placeholder for unported routes) ───────────────────────── */
709
- .stub-shell {
710
- padding: 80px var(--page-x);
711
- text-align: center;
712
- color: var(--text-3);
713
- font-size: var(--text-base);
714
- line-height: var(--lh-loose);
715
- }
716
- .stub-shell .stub-name {
717
- color: var(--accent);
718
- font-size: var(--text-md);
719
- text-transform: lowercase;
720
- letter-spacing: 0.04em;
721
- display: block;
722
- margin-bottom: 12px;
723
- }
724
- .stub-shell .stub-hint { color: var(--text-4); font-size: var(--text-sm); }
725
-
726
- /* ── Page chrome shared across all routes ───────────────────────────────── */
727
- .page-pad {
728
- padding: 20px var(--page-x) 60px;
729
- flex: 1;
730
- min-width: 0;
731
- }
732
-
733
- .page-title {
734
- font-size: var(--text-lg);
735
- font-family: var(--font-mono);
736
- font-weight: 500;
737
- color: var(--text-1);
738
- margin-bottom: 16px;
739
- }
740
-
741
- .page-header {
742
- display: flex;
743
- align-items: center;
744
- gap: 24px;
745
- margin-bottom: 24px;
746
- padding-top: 8px;
747
- }
748
-
749
- .subnav + .page-header,
750
- .subnav + .page-title {
751
- gap: 28px;
752
- margin-top: 28px;
753
- margin-bottom: 28px;
754
- padding-top: 0;
755
- }
756
-
757
- .page-header .page-title { margin-bottom: 0; }
758
- .page-header .header-spacer,
759
- .thread-header .header-spacer,
760
- .river-toolbar .header-spacer { flex: 1; }
761
-
762
- .section-title {
763
- font-size: var(--text-sm);
764
- text-transform: uppercase;
765
- letter-spacing: 0.06em;
766
- color: var(--text-3);
767
- margin: 24px 0 8px;
768
- font-weight: 500;
769
- }
770
-
771
- .muted { color: var(--text-3); }
772
- .muted.small { font-size: var(--text-xs); letter-spacing: 0.04em; }
773
- .muted.error { color: var(--danger); }
774
- .right { text-align: right; }
775
- .mono { font-family: var(--font-mono); }
776
- .small { font-size: var(--text-xs); }
777
-
778
- code, .code-block {
779
- font-family: var(--font-mono);
780
- font-size: var(--text-sm);
781
- background: var(--surface-2);
782
- border: 1px solid var(--border-2);
783
- padding: 2px 6px;
784
- border-radius: var(--r-sm);
785
- color: var(--text-1);
786
- }
787
- .code-block { display: block; padding: 10px 14px; margin: 8px 0; }
788
-
789
- /* ── Settings ───────────────────────────────────────────────────────────── */
790
- .settings-grid {
791
- display: grid;
792
- grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
793
- gap: 12px;
794
- margin-top: 16px;
795
- }
796
-
797
- .settings-card {
798
- padding: 14px;
799
- text-decoration: none;
800
- display: flex;
801
- flex-direction: column;
802
- gap: 6px;
803
- color: var(--text-1);
804
- }
805
-
806
- .settings-card-title {
807
- font-size: var(--text-sm);
808
- letter-spacing: 0.06em;
809
- text-transform: uppercase;
810
- color: var(--accent);
811
- font-weight: 500;
812
- }
813
-
814
- .settings-card-body { color: var(--text-2); font-size: var(--text-sm); }
815
-
816
- .kv-list {
817
- display: grid;
818
- grid-template-columns: max-content 1fr;
819
- gap: 6px 16px;
820
- margin-top: 12px;
821
- }
822
-
823
- .kv-label {
824
- color: var(--text-3);
825
- font-size: var(--text-sm);
826
- letter-spacing: 0.04em;
827
- }
828
-
829
- .kv-value { color: var(--text-1); font-size: var(--text-sm); }
830
- .kv-value.mono { font-family: var(--font-mono); word-break: break-all; }
831
-
832
- .form-grid {
833
- display: grid;
834
- gap: 12px;
835
- margin-top: 12px;
836
- max-width: 420px;
837
- }
838
-
839
- .form-field {
840
- display: flex;
841
- flex-direction: column;
842
- gap: 4px;
843
- }
844
-
845
- .form-label {
846
- font-size: var(--text-xs);
847
- color: var(--text-3);
848
- letter-spacing: 0.06em;
849
- text-transform: uppercase;
850
- }
851
-
852
- .form-input {
853
- background: var(--surface-1);
854
- border: 1px solid var(--border-2);
855
- color: var(--text-1);
856
- padding: 6px 10px;
857
- font-family: var(--font-mono);
858
- font-size: var(--text-sm);
859
- border-radius: var(--r-sm);
860
- }
861
- .form-input:focus { border-color: var(--border-4); outline: none; }
862
-
863
- /* ── Data table (labels page) ───────────────────────────────────────────── */
864
- .data-table {
865
- width: 100%;
866
- border-collapse: collapse;
867
- margin-top: 12px;
868
- font-size: var(--text-sm);
869
- }
870
-
871
- .data-table th {
872
- text-align: left;
873
- font-weight: 500;
874
- font-size: var(--text-xs);
875
- letter-spacing: 0.06em;
876
- text-transform: uppercase;
877
- color: var(--text-3);
878
- padding: 8px 10px;
879
- border-bottom: 1px solid var(--border-2);
880
- }
881
-
882
- .data-table th.right { text-align: right; }
883
-
884
- .data-table td {
885
- padding: 7px 10px;
886
- border-bottom: 1px solid var(--border-1);
887
- color: var(--text-1);
888
- vertical-align: middle;
889
- }
890
-
891
- .data-table tr:hover td { background: var(--surface-1); }
892
-
893
- .canonical .dot { margin-right: 8px; vertical-align: middle; }
894
-
895
- .dot {
896
- display: inline-block;
897
- width: 8px;
898
- height: 8px;
899
- border-radius: 50%;
900
- flex-shrink: 0;
901
- }
902
- .dot.lg { width: 14px; height: 14px; }
903
-
904
- .chip-inline {
905
- display: inline-flex;
906
- align-items: center;
907
- gap: 4px;
908
- padding: 2px 8px;
909
- border-radius: var(--r-sm);
910
- border: 1px solid var(--border-2);
911
- background: var(--surface-2);
912
- color: var(--text-2);
913
- font-family: var(--font-mono);
914
- font-size: var(--text-xs);
915
- letter-spacing: 0.04em;
916
- text-transform: lowercase;
917
- }
918
-
919
- .chip-inline.status-active { color: var(--accent); border-color: rgba(232,255,110,0.25); background: var(--accent-glow); }
920
- .chip-inline.status-idle { color: #ffcc80; border-color: rgba(255,204,128,0.25); }
921
- .chip-inline.status-closed { color: var(--text-2); }
922
- .chip-inline.status-superseded { color: var(--text-3); text-decoration: line-through; }
923
- .chip-inline.status-retired { color: var(--danger); border-color: rgba(255,107,53,0.25); background: var(--danger-dim); }
924
- .chip-inline.status-stale { color: var(--warn); border-color: rgba(255,153,51,0.25); background: var(--warn-dim); }
925
- .chip-inline.severity-high { color: var(--danger); border-color: rgba(255,107,53,0.35); background: var(--danger-dim); }
926
- .chip-inline.severity-medium { color: var(--warn); border-color: rgba(255,153,51,0.35); background: var(--warn-dim); }
927
-
928
- .chip-x {
929
- background: none;
930
- border: none;
931
- color: inherit;
932
- cursor: pointer;
933
- font-size: 12px;
934
- padding: 0 0 0 4px;
935
- line-height: 1;
936
- }
937
-
938
- /* ── Pulse ──────────────────────────────────────────────────────────────── */
939
- .kpi-row {
940
- display: grid;
941
- grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
942
- gap: 12px;
943
- margin-bottom: 18px;
944
- }
945
-
946
- .kpi {
947
- background: var(--surface-1);
948
- border: 1px solid var(--border-2);
949
- border-radius: var(--r-md);
950
- padding: 14px 16px;
951
- display: flex;
952
- flex-direction: column;
953
- gap: 4px;
954
- }
955
-
956
- .kpi-label {
957
- font-size: var(--text-xs);
958
- letter-spacing: 0.06em;
959
- text-transform: uppercase;
960
- color: var(--text-3);
961
- }
962
-
963
- .kpi-value {
964
- font-size: var(--text-stat);
965
- font-family: var(--font-mono);
966
- color: var(--text-1);
967
- line-height: 1;
968
- }
969
-
970
- .kpi-hint { font-size: var(--text-xs); color: var(--text-3); }
971
-
972
- .kpi-sparkline { gap: 8px; }
973
-
974
- .sparkline {
975
- display: flex;
976
- align-items: flex-end;
977
- gap: 4px;
978
- height: 40px;
979
- }
980
-
981
- .spark-bar {
982
- flex: 1;
983
- background: var(--accent);
984
- opacity: 0.7;
985
- border-radius: 1px;
986
- min-height: 2px;
987
- }
988
-
989
- .pulse-grid {
990
- display: grid;
991
- grid-template-columns: 1fr 1fr 1fr;
992
- grid-template-rows: 1fr 1fr;
993
- grid-template-areas:
994
- "coherence recent stale"
995
- "runtimes recent stale";
996
- gap: 12px;
997
- margin-top: 6px;
998
- /* Bound the grid to viewport-minus-chrome so cards have a real bounding box
999
- and their bodies scroll instead of stretching the page. */
1000
- height: calc(100vh - 280px);
1001
- min-height: 360px;
1002
- }
1003
-
1004
- .pulse-area-coherence { grid-area: coherence; }
1005
- .pulse-area-runtimes { grid-area: runtimes; }
1006
- .pulse-area-recent { grid-area: recent; }
1007
- .pulse-area-stale { grid-area: stale; }
1008
-
1009
- /* Scroll containers (Stale alerts, Recent sessions). Card lays out as a
1010
- flex column with header fixed and body filling the remainder. */
1011
- .pulse-scroll-card {
1012
- display: flex;
1013
- flex-direction: column;
1014
- min-height: 0;
1015
- overflow: hidden;
1016
- }
1017
-
1018
- .pulse-scroll-card .card-head { flex-shrink: 0; }
1019
-
1020
- /* Hover affordance for the major blocks on the Pulse view — KPI tiles
1021
- and the three pulse-grid cards get a clean white outline so it's
1022
- obvious they're interactive zones. */
1023
- .kpi,
1024
- .pulse-grid > .card {
1025
- transition: outline-color var(--ease), border-color var(--ease);
1026
- outline: 1px solid transparent;
1027
- outline-offset: -1px;
1028
- }
1029
-
1030
- .kpi:hover,
1031
- .pulse-grid > .card:hover {
1032
- outline-color: rgba(255, 255, 255, 0.55);
1033
- }
1034
-
1035
- .pulse-scroll-body {
1036
- flex: 1;
1037
- min-height: 0;
1038
- overflow-y: auto;
1039
- }
1040
-
1041
- .card-head {
1042
- display: flex;
1043
- align-items: baseline;
1044
- justify-content: space-between;
1045
- padding: 10px 14px;
1046
- border-bottom: 1px solid var(--border-1);
1047
- }
1048
-
1049
- .card-head h3 {
1050
- font-size: var(--text-sm);
1051
- letter-spacing: 0.06em;
1052
- text-transform: uppercase;
1053
- color: var(--text-2);
1054
- font-weight: 500;
1055
- }
1056
-
1057
- .bar-stack { padding: 14px; display: flex; flex-direction: column; gap: 10px; }
1058
- .bar-item { display: grid; grid-template-columns: 80px 1fr auto; gap: 10px; align-items: center; }
1059
- .bar-label { font-size: var(--text-sm); color: var(--text-2); }
1060
- .bar-track { height: 8px; background: var(--surface-2); border-radius: 4px; overflow: hidden; }
1061
- .bar-fill { height: 100%; transition: width 0.3s ease; }
1062
- .bar-fill.tone-active { background: var(--accent); }
1063
- .bar-fill.tone-warn { background: var(--warn); }
1064
- .bar-fill.tone-danger { background: var(--danger); }
1065
- .bar-value { font-size: var(--text-sm); color: var(--text-1); min-width: 96px; text-align: right; white-space: nowrap; }
1066
- .bar-pct { margin-left: 2px; }
1067
-
1068
- /* Recall — adoption + coverage telemetry */
1069
- .recall-head {
1070
- display: flex;
1071
- justify-content: space-between;
1072
- align-items: flex-start;
1073
- gap: 24px;
1074
- margin-bottom: 20px;
1075
- }
1076
- .recall-note { max-width: 60ch; margin: 0; line-height: 1.5; }
1077
- .recall-block { margin-bottom: 28px; }
1078
- .recall-block-head { margin-bottom: 14px; }
1079
- .recall-block-head .page-title { margin-bottom: 2px; }
1080
- .recall-block-head p { margin: 0; max-width: 70ch; }
1081
- .recall-empty { padding: 18px; font-size: var(--text-sm); }
1082
- .recall-cards {
1083
- display: grid;
1084
- grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
1085
- gap: 14px;
1086
- margin-top: 14px;
1087
- }
1088
- .recall-bars .bar-item { grid-template-columns: 140px 1fr auto; }
1089
- .recall-bar-label {
1090
- overflow: hidden;
1091
- text-overflow: ellipsis;
1092
- white-space: nowrap;
1093
- }
1094
- .recall-bars .bar-value { min-width: 0; }
1095
- .recall-bars-empty { padding: 4px 0; }
1096
-
1097
- @media (max-width: 720px) {
1098
- .recall-head { flex-direction: column; gap: 12px; }
1099
- }
1100
-
1101
- /* Runtimes panel (Pulse) */
1102
- .runtime-list { list-style: none; padding: 4px 0; margin: 0; }
1103
- .runtime-row {
1104
- display: grid;
1105
- grid-template-columns: 12px 1fr auto auto;
1106
- align-items: center;
1107
- gap: 10px;
1108
- padding: 8px 12px;
1109
- border-bottom: 1px solid var(--border-1);
1110
- }
1111
- .runtime-row:last-child { border-bottom: none; }
1112
- .runtime-dot {
1113
- width: 8px; height: 8px; border-radius: 50%;
1114
- background: var(--text-3);
1115
- box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.04);
1116
- }
1117
- .runtime-dot.runtime-active { background: var(--accent); box-shadow: 0 0 6px rgba(232,255,110,0.6); }
1118
- .runtime-dot.runtime-idle { background: var(--warn); }
1119
- .runtime-dot.runtime-dormant { background: var(--text-3); opacity: 0.5; }
1120
- .runtime-name { color: var(--text-1); font-size: var(--text-sm); }
1121
- .runtime-counts { white-space: nowrap; }
1122
- .runtime-counts-sep { margin: 0 6px; opacity: 0.5; }
1123
- .runtime-counts-prev { opacity: 0.7; }
1124
- .runtime-age { min-width: 60px; text-align: right; }
1125
-
1126
- .alert-list { list-style: none; padding: 4px 0; }
1127
- .alert-row-empty { padding: 16px 14px; }
1128
-
1129
- .alert-row {
1130
- display: grid;
1131
- grid-template-columns: auto auto 1fr;
1132
- gap: 10px;
1133
- align-items: center;
1134
- padding: 7px 14px;
1135
- border-bottom: 1px solid var(--border-1);
1136
- }
1137
-
1138
- .alert-entity { color: var(--text-1); font-size: var(--text-sm); }
1139
-
1140
- .alert-summary {
1141
- display: -webkit-box;
1142
- -webkit-line-clamp: 1;
1143
- -webkit-box-orient: vertical;
1144
- overflow: hidden;
1145
- text-overflow: ellipsis;
1146
- color: var(--text-3);
1147
- font-size: var(--text-xs);
1148
- letter-spacing: 0.04em;
1149
- min-width: 0;
1150
- line-height: var(--lh-base);
1151
- }
1152
-
1153
- .alert-row.clickable { cursor: pointer; transition: background var(--ease); }
1154
- .alert-row.clickable:hover { background: var(--surface-2); }
1155
- .alert-row.clickable:focus-visible { outline: 1px solid var(--border-4); outline-offset: -2px; }
1156
- .alert-row.clickable:hover .alert-entity { color: var(--accent); }
1157
-
1158
- .drawer-actions {
1159
- display: flex;
1160
- flex-wrap: wrap;
1161
- gap: 6px;
1162
- margin: 14px 0 6px;
1163
- }
1164
-
1165
- .session-list { list-style: none; }
1166
- .session-list.compact .session-row { padding: 6px 0; border-bottom: 1px solid var(--border-1); }
1167
-
1168
- .session-row {
1169
- display: grid;
1170
- grid-template-columns: auto 1fr auto;
1171
- gap: 10px;
1172
- align-items: center;
1173
- padding: 8px 14px;
1174
- border-bottom: 1px solid var(--border-1);
1175
- }
1176
-
1177
- .session-row-detail {
1178
- grid-template-columns: auto 1fr auto;
1179
- }
1180
-
1181
- .session-row-main {
1182
- display: flex;
1183
- flex-direction: column;
1184
- gap: 2px;
1185
- min-width: 0;
1186
- }
1187
-
1188
- .session-label {
1189
- color: var(--text-1);
1190
- font-size: var(--text-sm);
1191
- text-decoration: none;
1192
- white-space: nowrap;
1193
- overflow: hidden;
1194
- text-overflow: ellipsis;
1195
- }
1196
- a.session-label:hover { color: var(--accent); }
1197
-
1198
- .session-meta {
1199
- color: var(--text-3);
1200
- font-size: var(--text-xs);
1201
- letter-spacing: 0.04em;
1202
- }
1203
-
1204
- @media (max-width: 1100px) {
1205
- .pulse-grid {
1206
- grid-template-columns: 1fr 1fr;
1207
- grid-template-rows: auto;
1208
- grid-template-areas:
1209
- "coherence runtimes"
1210
- "recent recent"
1211
- "stale stale";
1212
- height: auto;
1213
- min-height: 0;
1214
- }
1215
- .pulse-scroll-body { max-height: 360px; }
1216
- }
1217
-
1218
- @media (max-width: 700px) {
1219
- .pulse-grid {
1220
- grid-template-columns: 1fr;
1221
- grid-template-areas:
1222
- "coherence"
1223
- "runtimes"
1224
- "recent"
1225
- "stale";
1226
- }
1227
- }
1228
-
1229
- /* ── Search ─────────────────────────────────────────────────────────────── */
1230
- .search-bar {
1231
- display: flex;
1232
- gap: 10px;
1233
- align-items: center;
1234
- margin-bottom: 12px;
1235
- }
1236
-
1237
- .search-input.search-big {
1238
- flex: 1;
1239
- padding: 10px 14px;
1240
- font-size: var(--text-md);
1241
- }
1242
-
1243
- .search-meta { margin: 8px 0; }
1244
-
1245
- /* ── Thread ─────────────────────────────────────────────────────────────── */
1246
- .thread-header {
1247
- display: flex;
1248
- align-items: center;
1249
- gap: 14px;
1250
- margin-bottom: 16px;
1251
- }
1252
-
1253
- .thread-header .page-title { margin-bottom: 0; }
1254
-
1255
- .thread-grid {
1256
- display: grid;
1257
- grid-template-columns: 1fr 1fr;
1258
- gap: 12px;
1259
- margin-bottom: 18px;
1260
- }
1261
-
1262
- .marker-list { list-style: none; max-height: 360px; overflow-y: auto; }
1263
- .marker-row {
1264
- display: grid;
1265
- grid-template-columns: auto 1fr auto;
1266
- gap: 10px;
1267
- padding: 7px 14px;
1268
- border-bottom: 1px solid var(--border-1);
1269
- align-items: baseline;
1270
- }
1271
-
1272
- .marker-text { color: var(--text-1); font-size: var(--text-sm); }
1273
-
1274
- .entity-grid {
1275
- list-style: none;
1276
- display: grid;
1277
- grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
1278
- gap: 10px;
1279
- margin-top: 16px;
1280
- }
1281
-
1282
- .entity-card {
1283
- padding: 10px 12px;
1284
- text-decoration: none;
1285
- color: var(--text-1);
1286
- display: flex;
1287
- align-items: center;
1288
- gap: 8px;
1289
- }
1290
-
1291
- .entity-name {
1292
- flex: 1;
1293
- font-size: var(--text-sm);
1294
- overflow: hidden;
1295
- text-overflow: ellipsis;
1296
- white-space: nowrap;
1297
- }
1298
-
1299
- @media (max-width: 800px) {
1300
- .thread-grid { grid-template-columns: 1fr; }
1301
- }
1302
-
1303
- /* ── River ──────────────────────────────────────────────────────────────── */
1304
- .river-toolbar {
1305
- display: flex;
1306
- align-items: center;
1307
- gap: 12px;
1308
- margin-bottom: 16px;
1309
- }
1310
-
1311
- .river-toolbar .page-title { margin-bottom: 0; font-size: var(--text-lg); }
1312
-
1313
- .river-grid {
1314
- --river-label-w: 200px;
1315
- --river-row-gap: 3px;
1316
- --river-cell-gap: 2px;
1317
- --river-cell-h: 16px;
1318
- padding: 12px;
1319
- width: 100%;
1320
- display: flex;
1321
- flex-direction: column;
1322
- gap: var(--river-row-gap);
1323
- }
1324
-
1325
- /* Density tiers — Settings → Views. Comfortable matches the base values
1326
- above; compact and spacious retune row gap, cell gap, and cell height. */
1327
- .river-grid.river-density-compact {
1328
- --river-row-gap: 1px;
1329
- --river-cell-gap: 1px;
1330
- --river-cell-h: 10px;
1331
- }
1332
- .river-grid.river-density-spacious {
1333
- --river-row-gap: 6px;
1334
- --river-cell-gap: 4px;
1335
- --river-cell-h: 24px;
1336
- }
1337
-
1338
- .river-row {
1339
- display: grid;
1340
- grid-template-columns: var(--river-label-w) 1fr;
1341
- gap: 6px;
1342
- align-items: center;
1343
- width: 100%;
1344
- min-width: 0;
1345
- }
1346
-
1347
- .river-row-dates {
1348
- margin-bottom: 2px;
1349
- }
1350
-
1351
- .river-lane-label {
1352
- display: flex;
1353
- align-items: center;
1354
- gap: 6px;
1355
- padding: 2px 6px;
1356
- border-radius: var(--r-sm);
1357
- text-decoration: none;
1358
- color: var(--text-2);
1359
- font-size: var(--text-sm);
1360
- white-space: nowrap;
1361
- overflow: hidden;
1362
- width: 100%;
1363
- min-width: 0;
1364
- }
1365
- .river-lane-label:hover { background: var(--surface-2); color: var(--text-1); }
1366
-
1367
- .river-lane-label--header {
1368
- padding: 0;
1369
- background: none;
1370
- }
1371
-
1372
- .river-lane-name { flex: 1; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
1373
-
1374
- .river-cells {
1375
- display: grid;
1376
- grid-template-columns: repeat(var(--cells, 1), minmax(0, 1fr));
1377
- gap: var(--river-cell-gap);
1378
- width: 100%;
1379
- min-width: 0;
1380
- }
1381
-
1382
- .river-date-cell {
1383
- font-size: var(--text-xs);
1384
- color: var(--text-2);
1385
- letter-spacing: 0.04em;
1386
- text-align: center;
1387
- overflow: hidden;
1388
- text-overflow: ellipsis;
1389
- white-space: nowrap;
1390
- }
1391
-
1392
- .river-cell {
1393
- height: var(--river-cell-h);
1394
- border-radius: 2px;
1395
- background: var(--surface-2);
1396
- min-width: 0;
1397
- }
1398
-
1399
- .river-cell.tier-1 { background: rgba(232,255,110,0.20); }
1400
- .river-cell.tier-2 { background: rgba(232,255,110,0.40); }
1401
- .river-cell.tier-3 { background: rgba(232,255,110,0.65); }
1402
- .river-cell.tier-4 { background: var(--accent); }
1403
-
1404
- /* ── Inline action buttons (Pulse alerts, Labels rows) ─────────────────── */
1405
- .alert-row {
1406
- grid-template-columns: auto auto 1fr auto;
1407
- }
1408
-
1409
- .alert-actions {
1410
- display: flex;
1411
- gap: 6px;
1412
- align-items: center;
1413
- }
1414
-
1415
- .alert-actions .chip {
1416
- font-size: var(--text-xs);
1417
- padding: 2px 8px;
1418
- }
1419
-
1420
- .row-actions {
1421
- display: flex;
1422
- gap: 6px;
1423
- }
1424
-
1425
- .row-actions .chip {
1426
- font-size: var(--text-xs);
1427
- padding: 2px 8px;
1428
- }
1429
-
1430
- .row-busy { opacity: 0.5; pointer-events: none; transition: opacity 0.15s ease; }
1431
-
1432
- .form-input-inline {
1433
- padding: 3px 8px;
1434
- font-size: var(--text-xs);
1435
- letter-spacing: 0.04em;
1436
- }
1437
-
1438
- /* ── River interactivity ───────────────────────────────────────────────── */
1439
- .river-grid {
1440
- position: relative;
1441
- user-select: none;
1442
- }
1443
-
1444
- .river-drag-rect {
1445
- position: absolute;
1446
- top: 0;
1447
- bottom: 0;
1448
- background: var(--accent-glow);
1449
- border-left: 1px dashed var(--accent);
1450
- border-right: 1px dashed var(--accent);
1451
- pointer-events: none;
1452
- z-index: 1;
1453
- }
1454
-
1455
- .river-lane-label {
1456
- background: none;
1457
- border: none;
1458
- text-align: left;
1459
- cursor: pointer;
1460
- font-family: var(--font-mono);
1461
- }
1462
-
1463
- .river-cell {
1464
- transition: transform 0.08s ease, outline-color var(--ease);
1465
- outline: 1px solid transparent;
1466
- outline-offset: 1px;
1467
- position: relative;
1468
- z-index: 0;
1469
- }
1470
-
1471
- .river-cell:hover {
1472
- transform: scale(1.3);
1473
- outline-color: rgba(255, 255, 255, 0.7);
1474
- z-index: 1;
1475
- }
1476
-
1477
- .river-hover {
1478
- position: fixed;
1479
- display: flex;
1480
- align-items: center;
1481
- gap: 8px;
1482
- background: var(--surface-float);
1483
- border: 1px solid var(--border-3);
1484
- border-radius: var(--r-sm);
1485
- padding: 6px 10px;
1486
- font-size: var(--text-xs);
1487
- pointer-events: none;
1488
- z-index: 200;
1489
- box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
1490
- }
1491
-
1492
- .river-hover-name {
1493
- color: var(--text-1);
1494
- font-size: var(--text-sm);
1495
- }
1496
-
1497
- /* ── Thread drawer ─────────────────────────────────────────────────────── */
1498
- .session-row.clickable { cursor: pointer; }
1499
- .session-row.clickable:hover { background: var(--surface-1); }
1500
-
1501
- .link-button {
1502
- background: none;
1503
- border: none;
1504
- color: var(--text-3);
1505
- font-family: var(--font-mono);
1506
- font-size: var(--text-xs);
1507
- cursor: pointer;
1508
- padding: 0;
1509
- letter-spacing: 0.04em;
1510
- }
1511
- .link-button:hover { color: var(--accent); }
1512
-
1513
- .drawer-backdrop {
1514
- position: fixed;
1515
- inset: 0;
1516
- background: rgba(0, 0, 0, 0.55);
1517
- z-index: 199;
1518
- animation: fadeIn 0.15s ease;
1519
- }
1520
-
1521
- @keyframes fadeIn {
1522
- from { opacity: 0; }
1523
- to { opacity: 1; }
1524
- }
1525
-
1526
- .session-drawer {
1527
- position: fixed;
1528
- top: 0;
1529
- right: 0;
1530
- bottom: 0;
1531
- width: min(560px, 100vw);
1532
- background: var(--surface-1);
1533
- border-left: 1px solid var(--border-3);
1534
- box-shadow: -16px 0 40px rgba(0, 0, 0, 0.55);
1535
- z-index: 200;
1536
- display: flex;
1537
- flex-direction: column;
1538
- animation: slideInRight 0.18s ease;
1539
- }
1540
-
1541
- @keyframes slideInRight {
1542
- from { transform: translateX(20px); opacity: 0; }
1543
- to { transform: translateX(0); opacity: 1; }
1544
- }
1545
-
1546
- .drawer-head {
1547
- display: flex;
1548
- align-items: center;
1549
- gap: 10px;
1550
- padding: 14px 18px;
1551
- border-bottom: 1px solid var(--border-1);
1552
- }
1553
-
1554
- .drawer-title {
1555
- flex: 1;
1556
- font-size: var(--text-md);
1557
- font-family: var(--font-mono);
1558
- font-weight: 500;
1559
- color: var(--text-1);
1560
- min-width: 0;
1561
- overflow: hidden;
1562
- text-overflow: ellipsis;
1563
- white-space: nowrap;
1564
- }
1565
-
1566
- .drawer-close {
1567
- background: none;
1568
- border: none;
1569
- color: var(--text-3);
1570
- font-size: 24px;
1571
- line-height: 1;
1572
- cursor: pointer;
1573
- padding: 0 6px;
1574
- }
1575
- .drawer-close:hover { color: var(--text-1); }
1576
-
1577
- .drawer-body {
1578
- overflow-y: auto;
1579
- padding: 16px 18px 80px;
1580
- flex: 1;
1581
- }
1582
-
1583
- .drawer-section {
1584
- font-size: var(--text-xs);
1585
- letter-spacing: 0.06em;
1586
- text-transform: uppercase;
1587
- color: var(--text-3);
1588
- margin: 18px 0 8px;
1589
- font-weight: 500;
1590
- }
1591
-
1592
- .drawer-list {
1593
- list-style: none;
1594
- display: flex;
1595
- flex-direction: column;
1596
- gap: 8px;
1597
- font-size: var(--text-sm);
1598
- color: var(--text-1);
1599
- }
1600
-
1601
- .drawer-list li { display: flex; gap: 8px; align-items: baseline; }
1602
-
1603
- .drawer-paragraph {
1604
- font-size: var(--text-sm);
1605
- color: var(--text-1);
1606
- line-height: var(--lh-loose);
1607
- }
1608
-
1609
- .drawer-body-text {
1610
- background: var(--surface-0);
1611
- border: 1px solid var(--border-1);
1612
- border-radius: var(--r-sm);
1613
- padding: 10px 12px;
1614
- font-size: var(--text-xs);
1615
- color: var(--text-2);
1616
- white-space: pre-wrap;
1617
- word-break: break-word;
1618
- max-height: 360px;
1619
- overflow-y: auto;
1620
- line-height: var(--lh-base);
1621
- }
1622
-
1623
- .entity-chips {
1624
- display: flex;
1625
- flex-wrap: wrap;
1626
- gap: 6px;
1627
- }
1628
-
1629
- /* ── Card head with stacked filters ──────────────────────────────────── */
1630
- .card-head.card-head-stack {
1631
- flex-direction: column;
1632
- align-items: stretch;
1633
- gap: 8px;
1634
- padding: 10px 14px 12px;
1635
- }
1636
-
1637
- .card-head-row {
1638
- display: flex;
1639
- align-items: baseline;
1640
- justify-content: space-between;
1641
- }
1642
-
1643
- .card-filters {
1644
- display: flex;
1645
- gap: 12px;
1646
- flex-wrap: wrap;
1647
- }
1648
-
1649
- .filter-group {
1650
- display: flex;
1651
- gap: 4px;
1652
- }
1653
-
1654
- .filter-group .chip {
1655
- font-size: var(--text-xs);
1656
- padding: 2px 8px;
1657
- }
1658
-
1659
- /* ── Thread sessions: search + filters + pagination ──────────────────── */
1660
- .thread-sessions-head {
1661
- display: flex;
1662
- align-items: center;
1663
- gap: 12px;
1664
- margin: 24px 0 8px;
1665
- }
1666
-
1667
- .thread-sessions-title { margin: 0; flex-shrink: 0; }
1668
-
1669
- .thread-sessions-head .search-input { flex: 1; }
1670
-
1671
- .thread-filters {
1672
- display: flex;
1673
- align-items: center;
1674
- gap: 12px;
1675
- flex-wrap: wrap;
1676
- margin-bottom: 8px;
1677
- }
1678
-
1679
- .thread-filters .filter-group { flex-wrap: wrap; }
1680
-
1681
- .empty-row { padding: 16px 14px; }
1682
-
1683
- .pagination {
1684
- display: flex;
1685
- align-items: center;
1686
- gap: 16px;
1687
- flex-wrap: wrap;
1688
- padding: 14px 0 4px;
1689
- border-top: 1px solid var(--border-1);
1690
- margin-top: 4px;
1691
- }
1692
-
1693
- .page-size {
1694
- display: flex;
1695
- align-items: center;
1696
- gap: 8px;
1697
- }
1698
-
1699
- .page-nav {
1700
- display: flex;
1701
- align-items: center;
1702
- gap: 4px;
1703
- }
1704
-
1705
- .page-nav .chip:disabled {
1706
- opacity: 0.4;
1707
- cursor: not-allowed;
1708
- }
1709
-
1710
- .page-indicator {
1711
- font-size: var(--text-sm);
1712
- color: var(--text-2);
1713
- padding: 0 8px;
1714
- min-width: 60px;
1715
- text-align: center;
1716
- }
1717
-
1718
- /* ── Promote-open inline control ───────────────────────────────────────── */
1719
- .marker-row-promotable {
1720
- display: grid;
1721
- grid-template-columns: auto 1fr auto auto;
1722
- gap: 10px;
1723
- align-items: baseline;
1724
- }
1725
-
1726
- .marker-row-promotable .marker-actions {
1727
- display: flex;
1728
- gap: 6px;
1729
- align-items: baseline;
1730
- }
1731
-
1732
- .promote-chip {
1733
- font-size: var(--text-xs);
1734
- padding: 2px 8px;
1735
- color: var(--accent);
1736
- border-color: rgba(232,255,110,0.3);
1737
- background: var(--accent-glow);
1738
- }
1739
- .promote-chip:hover {
1740
- border-color: rgba(232,255,110,0.55);
1741
- color: var(--accent);
1742
- background: var(--accent-dim);
1743
- }
1744
-
1745
- .promote-editor {
1746
- display: flex;
1747
- gap: 6px;
1748
- align-items: center;
1749
- min-width: 280px;
1750
- }
1751
-
1752
- .promote-input {
1753
- flex: 1;
1754
- min-width: 200px;
1755
- }
1756
-
1757
- /* Compact pagination — used inside drawers / narrow panels */
1758
- .pagination.pagination-compact {
1759
- gap: 10px;
1760
- padding: 10px 0 4px;
1761
- font-size: var(--text-xs);
1762
- flex-wrap: wrap;
1763
- }
1764
- .pagination.pagination-compact .page-indicator { min-width: 40px; padding: 0 4px; font-size: var(--text-xs); }
1765
- .pagination.pagination-compact .chip { padding: 1px 6px; font-size: var(--text-xs); }
1766
- .pagination.pagination-compact .form-label { font-size: 9px; }