@immediately-run/grove 0.1.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 (92) hide show
  1. package/README.md +122 -0
  2. package/docs/ENGINE_BOUNDARY.md +233 -0
  3. package/llms.txt +115 -0
  4. package/package.json +82 -0
  5. package/src/App.tsx +131 -0
  6. package/src/GroveApp.css +2774 -0
  7. package/src/GroveWiki.tsx +386 -0
  8. package/src/components/AssetImage.tsx +58 -0
  9. package/src/components/Backlinks.tsx +104 -0
  10. package/src/components/Callout.tsx +26 -0
  11. package/src/components/ChildPages.tsx +40 -0
  12. package/src/components/DefaultLayout.tsx +27 -0
  13. package/src/components/Directory.tsx +65 -0
  14. package/src/components/DirectoryList.test.tsx +275 -0
  15. package/src/components/DirectoryList.tsx +189 -0
  16. package/src/components/DirectoryView.tsx +68 -0
  17. package/src/components/DocList.tsx +109 -0
  18. package/src/components/DocsByTag.tsx +13 -0
  19. package/src/components/Drawer.tsx +45 -0
  20. package/src/components/EntryHeader.tsx +51 -0
  21. package/src/components/FamilyTree.tsx +95 -0
  22. package/src/components/GroveAgent.tsx +264 -0
  23. package/src/components/GroveFooter.tsx +20 -0
  24. package/src/components/GroveNav.tsx +102 -0
  25. package/src/components/Icon.tsx +56 -0
  26. package/src/components/Infobox.tsx +19 -0
  27. package/src/components/Kbd.tsx +10 -0
  28. package/src/components/KeyValue.tsx +32 -0
  29. package/src/components/Lede.tsx +6 -0
  30. package/src/components/More.tsx +10 -0
  31. package/src/components/Outlet.tsx +11 -0
  32. package/src/components/PageMeta.tsx +24 -0
  33. package/src/components/PageView.tsx +98 -0
  34. package/src/components/Quote.tsx +36 -0
  35. package/src/components/RecentlyUpdated.tsx +6 -0
  36. package/src/components/SafeEntryBody.tsx +72 -0
  37. package/src/components/SafeLayout.tsx +35 -0
  38. package/src/components/ScrollToFragment.tsx +63 -0
  39. package/src/components/Search.tsx +127 -0
  40. package/src/components/Sidebar.tsx +118 -0
  41. package/src/components/TableOfContents.test.tsx +163 -0
  42. package/src/components/TableOfContents.tsx +101 -0
  43. package/src/components/TagCloud.tsx +46 -0
  44. package/src/components/TagList.tsx +31 -0
  45. package/src/components/Timeline.tsx +55 -0
  46. package/src/components/Toc.tsx +14 -0
  47. package/src/components/WikiLink.tsx +112 -0
  48. package/src/data/themes.ts +14 -0
  49. package/src/devfs.d.ts +4 -0
  50. package/src/hooks/useContentComponents.ts +122 -0
  51. package/src/hooks/useCorpusMetadata.ts +43 -0
  52. package/src/hooks/useDirectoryListing.ts +56 -0
  53. package/src/hooks/useHeadings.ts +96 -0
  54. package/src/hooks/useOpenWikiBoot.ts +95 -0
  55. package/src/index.css +120 -0
  56. package/src/lib/compose.test.ts +92 -0
  57. package/src/lib/compose.ts +99 -0
  58. package/src/lib/content.test.ts +269 -0
  59. package/src/lib/content.ts +267 -0
  60. package/src/lib/contentRoot.ts +61 -0
  61. package/src/lib/corpusComponents.test.ts +101 -0
  62. package/src/lib/corpusComponents.ts +117 -0
  63. package/src/lib/corpusScan.test.ts +157 -0
  64. package/src/lib/corpusScan.ts +105 -0
  65. package/src/lib/directory.test.ts +216 -0
  66. package/src/lib/directory.ts +262 -0
  67. package/src/lib/fragment.test.ts +88 -0
  68. package/src/lib/fragment.ts +55 -0
  69. package/src/lib/frontmatter.ts +26 -0
  70. package/src/lib/layout.ts +84 -0
  71. package/src/lib/openWiki.test.ts +216 -0
  72. package/src/lib/openWiki.ts +84 -0
  73. package/src/lib/queries.test.ts +74 -0
  74. package/src/lib/queries.ts +84 -0
  75. package/src/lib/safeIntrinsics.test.tsx +99 -0
  76. package/src/lib/safeIntrinsics.tsx +77 -0
  77. package/src/lib/safeRender.test.ts +359 -0
  78. package/src/lib/safeSources.ts +25 -0
  79. package/src/lib/shell.ts +71 -0
  80. package/src/lib/sourceCache.test.ts +66 -0
  81. package/src/lib/sourceCache.ts +42 -0
  82. package/src/lib/tocScroll.test.ts +71 -0
  83. package/src/lib/tocScroll.ts +93 -0
  84. package/src/lib/wiki.test.ts +194 -0
  85. package/src/lib/wiki.ts +175 -0
  86. package/src/lib.ts +54 -0
  87. package/src/main.tsx +19 -0
  88. package/src/mdx.d.ts +9 -0
  89. package/src/mdxComponents.ts +89 -0
  90. package/src/test/setup.ts +19 -0
  91. package/viewer-manifest.schema.json +62 -0
  92. package/viewer.manifest.json +267 -0
@@ -0,0 +1,2774 @@
1
+ /* ============ app scroll container ============ */
2
+ .device__scroll {
3
+ position: absolute;
4
+ inset: 0;
5
+ overflow-y: auto;
6
+ overflow-x: hidden;
7
+ }
8
+
9
+ /* ============ GROVE THEME TOKENS (the contract) ============ */
10
+ .grove-root {
11
+ --bg: #0a0b11;
12
+ --panel: #13141d;
13
+ --panel-2: #191b26;
14
+ --line: rgba(180, 170, 225, .14);
15
+ --line-2: rgba(180, 170, 225, .22);
16
+ --ink: #ecebf4;
17
+ --ink-2: #9b97b3;
18
+ --ink-3: #6a677f;
19
+ --accent: oklch(0.74 0.17 350);
20
+ --accent-2: oklch(0.66 0.18 295);
21
+ --accent-3: oklch(0.82 0.12 340);
22
+ --grad: linear-gradient(96deg, #f6f1fb 0%, #f49ad4 46%, #b285f2 100%);
23
+ --glow: 0 0 0 1px rgba(150, 110, 240, .5), 0 0 28px rgba(150, 110, 240, .3);
24
+ --accent-pink: #f49ad4;
25
+ --accent-violet: #b285f2;
26
+ --disp: "Gabarito", system-ui, sans-serif;
27
+ --sans: "Public Sans", system-ui, sans-serif;
28
+ --mono: "Space Mono", ui-monospace, monospace;
29
+ --r-xs: 5px;
30
+ --r-sm: 6px;
31
+ --r-md: 12px;
32
+ --r-lg: 16px;
33
+ --r-xl: 18px;
34
+ --r-pill: 30px;
35
+ --shadow-card: 6px 6px 0 var(--accent-2);
36
+ --wash: radial-gradient(60% 50% at 82% -2%, rgba(178, 133, 242, .12), transparent 60%), radial-gradient(48% 38% at 6% 4%, rgba(244, 154, 212, .06), transparent 60%);
37
+ --disp-weight: 800;
38
+ --prose-measure: 70ch;
39
+ --radius-shape: var(--r-lg);
40
+ background: var(--bg);
41
+ color: var(--ink);
42
+ font-family: var(--sans);
43
+ height: 100vh;
44
+ height: 100dvh;
45
+ width: 100%;
46
+ overflow: hidden;
47
+ position: relative;
48
+ background-image: var(--wash);
49
+ -webkit-font-smoothing: antialiased;
50
+ }
51
+ .grove-root[data-theme="light"] {
52
+ --bg: #f6f4fb;
53
+ --panel: #fff;
54
+ --panel-2: #f0ecf8;
55
+ --line: rgba(40, 24, 70, .12);
56
+ --line-2: rgba(40, 24, 70, .2);
57
+ --ink: #1c1726;
58
+ --ink-2: #5d5670;
59
+ --ink-3: #938aa6;
60
+ --accent: oklch(0.58 0.21 1);
61
+ --accent-2: oklch(0.52 0.21 295);
62
+ --accent-3: oklch(0.5 0.2 350);
63
+ --grad: linear-gradient(96deg, #c43d96 0%, #9a45e6 100%);
64
+ --glow: 0 0 0 1px rgba(150, 90, 235, .4), 0 8px 22px rgba(150, 90, 235, .2);
65
+ --accent-pink: #c43d96;
66
+ --accent-violet: #9a45e6;
67
+ }
68
+
69
+ /* —— alternate themes: identical DOM, CSS-only re-skin —— */
70
+ .grove-root[data-grove-theme="pixies"] {
71
+ --bg: #0c0410;
72
+ --panel: #1a0a1e;
73
+ --panel-2: #260f2c;
74
+ --line: rgba(255, 120, 200, .16);
75
+ --line-2: rgba(255, 120, 200, .3);
76
+ --ink: #fce9f6;
77
+ --ink-2: #d79bc9;
78
+ --ink-3: #9c6a8e;
79
+ --accent: #ff2d8e;
80
+ --accent-2: #7b2ff7;
81
+ --accent-3: #ffd23f;
82
+ --grad: linear-gradient(96deg, #ffe14d 0%, #ff2d8e 50%, #9d29ff 100%);
83
+ --glow: 0 0 0 1px rgba(255, 45, 142, .6), 0 0 30px rgba(255, 45, 142, .4);
84
+ --accent-pink: #ff2d8e;
85
+ --accent-violet: #9d29ff;
86
+ --disp-weight: 900;
87
+ --prose-measure: 66ch;
88
+ --radius-shape: 8px;
89
+ --wash: radial-gradient(70% 55% at 85% -5%, rgba(255, 45, 142, .2), transparent 60%), radial-gradient(55% 45% at 4% 2%, rgba(157, 41, 255, .16), transparent 60%);
90
+ }
91
+ .grove-root[data-grove-theme="family"] {
92
+ --bg: #faf6f1;
93
+ --panel: #fffdfa;
94
+ --panel-2: #f4ece2;
95
+ --line: rgba(120, 90, 60, .16);
96
+ --line-2: rgba(120, 90, 60, .28);
97
+ --ink: #3b342c;
98
+ --ink-2: #7c7062;
99
+ --ink-3: #a89c8c;
100
+ --accent: #c8744f;
101
+ --accent-2: #9a8f5e;
102
+ --accent-3: #d9a06a;
103
+ --grad: linear-gradient(96deg, #f3cf9a 0%, #e09a6a 50%, #c8744f 100%);
104
+ --glow: 0 0 0 1px rgba(200, 116, 79, .4), 0 10px 26px rgba(200, 116, 79, .2);
105
+ --accent-pink: #c8744f;
106
+ --accent-violet: #9a8f5e;
107
+ --disp-weight: 700;
108
+ --prose-measure: 64ch;
109
+ --radius-shape: 20px;
110
+ --wash: radial-gradient(60% 50% at 82% -2%, rgba(224, 154, 106, .14), transparent 60%);
111
+ }
112
+ .grove-root[data-grove-theme="lotr"] {
113
+ --bg: #ece2cc;
114
+ --panel: #f4ebd6;
115
+ --panel-2: #e4d8ba;
116
+ --line: rgba(90, 70, 40, .22);
117
+ --line-2: rgba(90, 70, 40, .36);
118
+ --ink: #322712;
119
+ --ink-2: #6a5c40;
120
+ --ink-3: #998a68;
121
+ --accent: #7a5a2a;
122
+ --accent-2: #4a5a38;
123
+ --accent-3: #9a7a3a;
124
+ --grad: linear-gradient(96deg, #b89a56 0%, #8a6a36 50%, #4a5a38 100%);
125
+ --glow: 0 0 0 1px rgba(122, 90, 42, .4), 0 8px 20px rgba(122, 90, 42, .22);
126
+ --accent-pink: #7a5a2a;
127
+ --accent-violet: #4a5a38;
128
+ --disp-weight: 700;
129
+ --prose-measure: 72ch;
130
+ --radius-shape: 4px;
131
+ --wash: radial-gradient(70% 60% at 50% -5%, rgba(122, 90, 42, .1), transparent 65%);
132
+ }
133
+
134
+ /* ============ SHELL ============ */
135
+ .grove-root a {
136
+ color: inherit;
137
+ text-decoration: none;
138
+ cursor: pointer;
139
+ }
140
+ .grove-root button {
141
+ font-family: inherit;
142
+ cursor: pointer;
143
+ }
144
+ .grove-shell {
145
+ display: grid;
146
+ min-height: 100%;
147
+ grid-template-rows: auto 1fr auto;
148
+ }
149
+ .grove-shell[data-nav="side"] {
150
+ grid-template-columns: 248px 1fr;
151
+ grid-template-rows: auto 1fr auto;
152
+ }
153
+ .grove-shell[data-nav="side"] .grove-nav {
154
+ grid-column: 1/3;
155
+ }
156
+ .grove-shell[data-nav="side"] .grove-footer {
157
+ grid-column: 1/3;
158
+ }
159
+ .grove-root[data-vw="mobile"] .grove-shell[data-nav="side"] {
160
+ grid-template-columns: 1fr;
161
+ }
162
+ .grove-root[data-vw="mobile"] .grove-shell[data-nav="side"] .grove-nav,
163
+ .grove-root[data-vw="mobile"] .grove-shell[data-nav="side"] .grove-footer {
164
+ grid-column: 1;
165
+ }
166
+
167
+ /* nav */
168
+ .grove-nav {
169
+ position: sticky;
170
+ top: 0;
171
+ z-index: 20;
172
+ display: flex;
173
+ align-items: center;
174
+ gap: 18px;
175
+ padding: 13px 24px;
176
+ border-bottom: 1px solid var(--line);
177
+ background: color-mix(in srgb, var(--bg) 86%, transparent);
178
+ backdrop-filter: blur(10px);
179
+ }
180
+ .grove-brand {
181
+ display: flex;
182
+ align-items: center;
183
+ gap: 9px;
184
+ font-family: var(--disp);
185
+ font-weight: 800;
186
+ font-size: 18px;
187
+ letter-spacing: -.03em;
188
+ color: var(--ink);
189
+ }
190
+ .grove-brand .tile {
191
+ width: 25px;
192
+ height: 25px;
193
+ border-radius: 24%;
194
+ flex: 0 0 auto;
195
+ box-shadow: 0 2px 9px rgba(150, 110, 240, .25);
196
+ }
197
+ .grove-nav__links {
198
+ display: flex;
199
+ gap: 4px;
200
+ margin-left: 6px;
201
+ }
202
+ .grove-nav__links a {
203
+ font-weight: 600;
204
+ font-size: 13.5px;
205
+ padding: 7px 13px;
206
+ border-radius: var(--r-pill);
207
+ color: var(--ink-2);
208
+ transition: .14s;
209
+ white-space: nowrap;
210
+ }
211
+ .grove-nav__links a:hover {
212
+ background: color-mix(in srgb, var(--ink) 8%, transparent);
213
+ color: var(--ink);
214
+ }
215
+ .grove-nav__links a[data-cur="1"] {
216
+ background: color-mix(in srgb, var(--accent) 16%, transparent);
217
+ color: var(--ink);
218
+ }
219
+ .grove-nav__cluster {
220
+ margin-left: auto;
221
+ display: flex;
222
+ align-items: center;
223
+ gap: 8px;
224
+ }
225
+ .icbtn {
226
+ display: inline-flex;
227
+ align-items: center;
228
+ justify-content: center;
229
+ width: 34px;
230
+ height: 34px;
231
+ border-radius: var(--r-pill);
232
+ background: var(--panel);
233
+ border: 1px solid var(--line);
234
+ color: var(--ink-2);
235
+ transition: .14s;
236
+ }
237
+ .icbtn:hover {
238
+ color: var(--ink);
239
+ border-color: var(--accent-2);
240
+ }
241
+ .icbtn svg {
242
+ width: 17px;
243
+ height: 17px;
244
+ }
245
+ .icbtn--primary {
246
+ background: var(--grad);
247
+ color: #fff;
248
+ border-color: transparent;
249
+ }
250
+ .icbtn--primary:hover {
251
+ box-shadow: var(--glow);
252
+ }
253
+ .grove-nav__more {
254
+ position: relative;
255
+ display: inline-flex;
256
+ }
257
+
258
+ /* theme switcher popover */
259
+ .gtm__scrim {
260
+ position: fixed;
261
+ inset: 0;
262
+ z-index: 50;
263
+ }
264
+ .grove-theme-menu {
265
+ position: absolute;
266
+ top: calc(100% + 8px);
267
+ right: 0;
268
+ z-index: 60;
269
+ width: 236px;
270
+ background: var(--panel);
271
+ border: 1px solid var(--line-2);
272
+ border-radius: var(--r-lg);
273
+ box-shadow: var(--shadow-pop);
274
+ padding: 8px;
275
+ }
276
+ .gtm__h,
277
+ .gtm__sub {
278
+ font-family: var(--mono);
279
+ font-size: 10.5px;
280
+ text-transform: uppercase;
281
+ letter-spacing: .12em;
282
+ color: var(--ink-3);
283
+ padding: 6px 8px 8px;
284
+ }
285
+ .gtm__list {
286
+ display: flex;
287
+ flex-direction: column;
288
+ gap: 2px;
289
+ }
290
+ .gtm__row {
291
+ display: flex;
292
+ align-items: center;
293
+ gap: 10px;
294
+ width: 100%;
295
+ padding: 8px;
296
+ border-radius: var(--r-md);
297
+ border: 1px solid transparent;
298
+ background: none;
299
+ color: var(--ink-2);
300
+ font: 600 13.5px/1 var(--sans);
301
+ text-align: left;
302
+ transition: .14s;
303
+ }
304
+ .gtm__row:hover {
305
+ background: color-mix(in srgb, var(--ink) 7%, transparent);
306
+ color: var(--ink);
307
+ }
308
+ .gtm__row[data-cur="1"] {
309
+ color: var(--ink);
310
+ }
311
+ .gtm__sw {
312
+ width: 22px;
313
+ height: 22px;
314
+ border-radius: 7px;
315
+ flex: 0 0 auto;
316
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .14);
317
+ }
318
+ .gtm__name {
319
+ flex: 1;
320
+ }
321
+ .gtm__ck {
322
+ display: inline-flex;
323
+ color: var(--accent-pink);
324
+ }
325
+ .gtm__ck svg {
326
+ width: 15px;
327
+ height: 15px;
328
+ }
329
+ .gtm__appearance {
330
+ border-top: 1px solid var(--line);
331
+ margin-top: 6px;
332
+ padding-top: 4px;
333
+ }
334
+ .gtm__seg {
335
+ display: flex;
336
+ gap: 6px;
337
+ padding: 0 8px 8px;
338
+ }
339
+ .gtm__seg button {
340
+ flex: 1;
341
+ display: inline-flex;
342
+ align-items: center;
343
+ justify-content: center;
344
+ gap: 6px;
345
+ padding: 8px;
346
+ border-radius: var(--r-md);
347
+ border: 1px solid var(--line);
348
+ background: var(--panel-2);
349
+ color: var(--ink-2);
350
+ font: 600 12.5px/1 var(--sans);
351
+ transition: .14s;
352
+ }
353
+ .gtm__seg button svg {
354
+ width: 15px;
355
+ height: 15px;
356
+ }
357
+ .gtm__seg button[data-on="1"] {
358
+ color: #fff;
359
+ background: var(--grad);
360
+ border-color: transparent;
361
+ }
362
+ .grove-hamburger {
363
+ display: none;
364
+ }
365
+ .grove-root[data-vw="mobile"] .grove-nav__links {
366
+ display: none;
367
+ }
368
+ .grove-root[data-vw="mobile"] .grove-hamburger {
369
+ display: inline-flex;
370
+ }
371
+ .grove-root[data-vw="mobile"] .grove-nav {
372
+ padding: 11px 16px;
373
+ }
374
+
375
+ /* sidebar */
376
+ .grove-sidebar {
377
+ border-right: 1px solid var(--line);
378
+ padding: 20px 14px 40px;
379
+ overflow-y: auto;
380
+ background: color-mix(in srgb, var(--panel) 40%, transparent);
381
+ }
382
+ .grove-root[data-vw="mobile"] .grove-sidebar {
383
+ display: none;
384
+ }
385
+ .grove-shell[data-nav="top"] .grove-sidebar {
386
+ display: none;
387
+ }
388
+ .gs-block {
389
+ margin-bottom: 24px;
390
+ }
391
+ .gs-block__h {
392
+ font-family: var(--mono);
393
+ font-size: 10.5px;
394
+ text-transform: uppercase;
395
+ letter-spacing: .1em;
396
+ color: var(--ink-3);
397
+ padding: 0 8px;
398
+ margin-bottom: 8px;
399
+ display: flex;
400
+ align-items: center;
401
+ justify-content: space-between;
402
+ }
403
+ .gs-tree {
404
+ font-size: 13.5px;
405
+ }
406
+ .gs-tree__row {
407
+ display: flex;
408
+ align-items: center;
409
+ gap: 6px;
410
+ padding: 5px 8px;
411
+ border-radius: var(--r-sm);
412
+ color: var(--ink-2);
413
+ transition: .12s;
414
+ cursor: pointer;
415
+ }
416
+ .gs-tree__row:hover {
417
+ background: var(--panel-2);
418
+ color: var(--ink);
419
+ }
420
+ .gs-tree__row[data-cur="1"] {
421
+ background: color-mix(in srgb, var(--accent) 14%, transparent);
422
+ color: var(--ink);
423
+ font-weight: 600;
424
+ }
425
+ .gs-tree__row svg {
426
+ width: 14px;
427
+ height: 14px;
428
+ flex: 0 0 auto;
429
+ color: var(--ink-3);
430
+ }
431
+ .gs-tree__row .ct {
432
+ margin-left: auto;
433
+ font-family: var(--mono);
434
+ font-size: 10.5px;
435
+ color: var(--ink-3);
436
+ }
437
+ .gs-tree__children {
438
+ margin-left: 14px;
439
+ border-left: 1px solid var(--line);
440
+ padding-left: 4px;
441
+ }
442
+ .gs-folder>svg.chev {
443
+ transition: transform .14s;
444
+ }
445
+ .gs-folder[data-open="0"]>svg.chev {
446
+ transform: rotate(-90deg);
447
+ }
448
+ .gs-section__body {
449
+ font-size: 13px;
450
+ color: var(--ink-2);
451
+ line-height: 1.55;
452
+ padding: 0 8px;
453
+ }
454
+
455
+ /* footer */
456
+ .grove-footer {
457
+ border-top: 1px solid var(--line);
458
+ padding: 22px 24px;
459
+ display: flex;
460
+ flex-wrap: wrap;
461
+ gap: 16px;
462
+ align-items: center;
463
+ justify-content: space-between;
464
+ }
465
+ .grove-footer__links {
466
+ display: flex;
467
+ gap: 16px;
468
+ flex-wrap: wrap;
469
+ }
470
+ .grove-footer__links a {
471
+ font-size: 13px;
472
+ color: var(--ink-2);
473
+ }
474
+ .grove-footer__links a:hover {
475
+ color: var(--accent);
476
+ }
477
+ .grove-footer__meta {
478
+ font-family: var(--mono);
479
+ font-size: 11px;
480
+ color: var(--ink-3);
481
+ }
482
+
483
+ /* ============ READING VIEW ============ */
484
+ .grove-content {
485
+ min-width: 0;
486
+ padding: 34px 0;
487
+ }
488
+ .grove-page {
489
+ margin: 0 auto;
490
+ padding: 0 32px;
491
+ }
492
+ .grove-page[data-layout="doc"] {
493
+ max-width: 1080px;
494
+ display: grid;
495
+ grid-template-columns: 1fr 220px;
496
+ gap: 48px;
497
+ align-items: start;
498
+ }
499
+ .grove-page[data-layout="post"] {
500
+ max-width: 720px;
501
+ }
502
+ .grove-page[data-layout="full"] {
503
+ max-width: 1280px;
504
+ }
505
+ .grove-root[data-vw="mobile"] .grove-page {
506
+ padding: 0 18px;
507
+ display: block;
508
+ max-width: 100%;
509
+ }
510
+ .gp-main {
511
+ min-width: 0;
512
+ }
513
+
514
+ .grove-entry-header {
515
+ margin-bottom: 26px;
516
+ }
517
+ .grove-entry-header .crumb {
518
+ font-family: var(--mono);
519
+ font-size: 11.5px;
520
+ color: var(--ink-3);
521
+ margin-bottom: 12px;
522
+ display: flex;
523
+ align-items: center;
524
+ gap: 6px;
525
+ flex-wrap: wrap;
526
+ }
527
+ .grove-entry-header .crumb a:hover {
528
+ color: var(--accent);
529
+ }
530
+ .grove-entry-header h1 {
531
+ font-family: var(--disp);
532
+ font-weight: var(--disp-weight);
533
+ font-size: clamp(32px, 4.4vw, 52px);
534
+ line-height: .96;
535
+ letter-spacing: -.03em;
536
+ color: var(--ink);
537
+ margin: 0;
538
+ }
539
+ .grove-entry-header h1.grad {
540
+ background: var(--grad);
541
+ -webkit-background-clip: text;
542
+ background-clip: text;
543
+ color: transparent;
544
+ }
545
+ .grove-meta {
546
+ display: flex;
547
+ align-items: center;
548
+ gap: 14px;
549
+ flex-wrap: wrap;
550
+ margin-top: 16px;
551
+ font-family: var(--mono);
552
+ font-size: 12.5px;
553
+ color: var(--ink-2);
554
+ }
555
+ .grove-meta .dot {
556
+ color: var(--ink-3);
557
+ }
558
+ .grove-edit-affordance {
559
+ margin-left: auto;
560
+ display: inline-flex;
561
+ align-items: center;
562
+ gap: 7px;
563
+ font-family: var(--sans);
564
+ font-weight: 600;
565
+ font-size: 12.5px;
566
+ color: var(--ink-2);
567
+ background: var(--panel);
568
+ border: 1px solid var(--line);
569
+ border-radius: var(--r-pill);
570
+ padding: 6px 13px;
571
+ transition: .14s;
572
+ border-style: solid;
573
+ }
574
+ .grove-edit-affordance:hover {
575
+ color: var(--ink);
576
+ border-color: var(--accent-2);
577
+ }
578
+ .grove-edit-affordance svg {
579
+ width: 14px;
580
+ height: 14px;
581
+ }
582
+ .grove-edit-affordance[data-busy="1"] {
583
+ opacity: .6;
584
+ pointer-events: none;
585
+ }
586
+
587
+ .grove-tag {
588
+ display: inline-flex;
589
+ align-items: center;
590
+ font-family: var(--mono);
591
+ font-size: 11.5px;
592
+ color: var(--ink-2);
593
+ background: transparent;
594
+ border: 1px solid var(--line-2);
595
+ border-radius: var(--r-pill);
596
+ padding: 3px 10px;
597
+ transition: .14s;
598
+ cursor: pointer;
599
+ line-height: 1.3;
600
+ }
601
+ .grove-tag:hover {
602
+ background: color-mix(in srgb, var(--accent) 12%, transparent);
603
+ color: var(--ink);
604
+ }
605
+ .grove-tag[data-active="1"] {
606
+ border-color: var(--accent);
607
+ color: var(--ink);
608
+ }
609
+ .grove-meta .grove-tag {
610
+ padding: 2px 9px;
611
+ }
612
+
613
+ /* prose */
614
+ .grove-prose {
615
+ max-width: var(--prose-measure);
616
+ font: var(--body, 400 16px/1.5 var(--sans));
617
+ color: var(--ink);
618
+ font-size: 16.5px;
619
+ line-height: 1.62;
620
+ }
621
+ .grove-prose>*+* {
622
+ margin-top: 1.05em;
623
+ }
624
+ .grove-prose h2 {
625
+ font-family: var(--disp);
626
+ font-weight: var(--disp-weight);
627
+ font-size: 1.75em;
628
+ letter-spacing: -.02em;
629
+ line-height: 1.1;
630
+ margin-top: 1.8em;
631
+ color: var(--ink);
632
+ scroll-margin-top: 70px;
633
+ }
634
+ .grove-prose h3 {
635
+ font-family: var(--disp);
636
+ font-weight: 600;
637
+ font-size: 1.32em;
638
+ letter-spacing: -.01em;
639
+ margin-top: 1.5em;
640
+ color: var(--ink);
641
+ scroll-margin-top: 70px;
642
+ }
643
+ .grove-prose h4 {
644
+ font-family: var(--disp);
645
+ font-weight: 600;
646
+ font-size: 1.08em;
647
+ margin-top: 1.3em;
648
+ color: var(--ink);
649
+ }
650
+ .grove-prose p {
651
+ color: var(--ink);
652
+ opacity: .94;
653
+ }
654
+ .grove-prose ul,
655
+ .grove-prose ol {
656
+ padding-left: 1.3em;
657
+ color: var(--ink);
658
+ opacity: .94;
659
+ }
660
+ .grove-prose li {
661
+ margin: .4em 0;
662
+ }
663
+ .grove-prose li::marker {
664
+ color: var(--accent);
665
+ }
666
+ .grove-prose strong {
667
+ font-weight: 700;
668
+ color: var(--ink);
669
+ opacity: 1;
670
+ }
671
+ .grove-prose blockquote {
672
+ border-left: 3px solid var(--accent-2);
673
+ padding: 2px 0 2px 18px;
674
+ color: var(--ink-2);
675
+ font-style: italic;
676
+ }
677
+ .grove-prose :not(pre)>code {
678
+ font-family: var(--mono);
679
+ font-size: .84em;
680
+ background: var(--panel-2);
681
+ border: 1px solid var(--line);
682
+ border-radius: var(--r-xs);
683
+ padding: 1px 6px;
684
+ color: var(--accent-3);
685
+ }
686
+ .grove-prose a.mdlink {
687
+ color: var(--accent);
688
+ border-bottom: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
689
+ transition: .12s;
690
+ }
691
+ .grove-prose a.mdlink:hover {
692
+ border-bottom-color: var(--accent);
693
+ }
694
+
695
+ /* wiki-links — three states */
696
+ .grove-wikilink {
697
+ cursor: pointer;
698
+ text-decoration: none;
699
+ border-radius: 3px;
700
+ transition: .12s;
701
+ padding: 0 1px;
702
+ }
703
+ .grove-wikilink[data-state="ok"] {
704
+ color: var(--accent-violet);
705
+ border-bottom: 1px solid transparent;
706
+ }
707
+ .grove-wikilink[data-state="ok"]:hover {
708
+ border-bottom-color: var(--accent-violet);
709
+ background: color-mix(in srgb, var(--accent-2) 12%, transparent);
710
+ }
711
+ .grove-wikilink[data-state="ok"]::before {
712
+ content: "";
713
+ display: inline-block;
714
+ width: 5px;
715
+ height: 5px;
716
+ border-radius: 50%;
717
+ background: var(--accent-violet);
718
+ margin: 0 5px 2px 1px;
719
+ vertical-align: middle;
720
+ opacity: .55;
721
+ }
722
+ .grove-wikilink[data-state="broken"] {
723
+ color: var(--ink-3);
724
+ border-bottom: 1px dotted var(--ink-3);
725
+ cursor: help;
726
+ }
727
+ .grove-wikilink[data-state="broken"] svg {
728
+ width: 12px;
729
+ height: 12px;
730
+ display: inline;
731
+ margin: 0 3px -1px 1px;
732
+ color: var(--ink-3);
733
+ }
734
+ .grove-wikilink[data-state="self"] {
735
+ color: var(--ink);
736
+ font-weight: 700;
737
+ cursor: default;
738
+ }
739
+
740
+ /* callouts */
741
+ .grove-callout {
742
+ border: 1px solid var(--line);
743
+ border-left: 3px solid var(--accent);
744
+ border-radius: var(--radius-shape);
745
+ background: var(--panel);
746
+ padding: 14px 16px 14px 15px;
747
+ display: grid;
748
+ grid-template-columns: auto 1fr;
749
+ gap: 12px;
750
+ }
751
+ .grove-callout svg {
752
+ width: 18px;
753
+ height: 18px;
754
+ color: var(--accent);
755
+ margin-top: 2px;
756
+ }
757
+ .grove-callout__t {
758
+ font-family: var(--disp);
759
+ font-weight: 700;
760
+ font-size: .95em;
761
+ color: var(--ink);
762
+ margin-bottom: 3px;
763
+ }
764
+ .grove-callout__b {
765
+ font-size: .94em;
766
+ color: var(--ink-2);
767
+ line-height: 1.55;
768
+ }
769
+ .grove-callout[data-v="note"] {
770
+ border-left-color: var(--ink-2);
771
+ }
772
+ .grove-callout[data-v="note"] svg,
773
+ .grove-callout[data-v="note"] .grove-callout__t {
774
+ color: var(--ink-2);
775
+ }
776
+ .grove-callout[data-v="warning"] {
777
+ border-left-color: var(--accent-3);
778
+ }
779
+ .grove-callout[data-v="warning"] svg {
780
+ color: var(--accent-3);
781
+ }
782
+
783
+ /* pull-quote */
784
+ .grove-quote {
785
+ position: relative;
786
+ margin: 22px 0;
787
+ padding: 22px 24px 20px 28px;
788
+ background: var(--panel);
789
+ border: 1px solid var(--line);
790
+ border-radius: var(--r-lg);
791
+ overflow: hidden;
792
+ }
793
+ .grove-quote::before { /* gradient accent spine */
794
+ content: "";
795
+ position: absolute;
796
+ left: 0;
797
+ top: 0;
798
+ bottom: 0;
799
+ width: 4px;
800
+ background: var(--grad);
801
+ }
802
+ .grove-quote__body {
803
+ font-family: var(--disp);
804
+ font-weight: 500;
805
+ font-size: 1.18rem;
806
+ line-height: 1.5;
807
+ color: var(--ink);
808
+ font-style: normal;
809
+ border: 0;
810
+ margin: 0;
811
+ padding: 0;
812
+ }
813
+ .grove-quote__body::before { /* large gradient opening quote mark */
814
+ content: "\201C";
815
+ font-family: var(--disp);
816
+ font-weight: 900;
817
+ font-size: 3.2rem;
818
+ line-height: 0.1;
819
+ margin-right: 0.06em;
820
+ vertical-align: -0.42em;
821
+ background: var(--grad);
822
+ -webkit-background-clip: text;
823
+ background-clip: text;
824
+ color: transparent;
825
+ }
826
+ .grove-quote__cap {
827
+ display: flex;
828
+ flex-wrap: wrap;
829
+ align-items: baseline;
830
+ gap: 6px 16px;
831
+ margin-top: 14px;
832
+ font-family: var(--mono);
833
+ font-size: 0.8rem;
834
+ }
835
+ .grove-quote__cite {
836
+ color: var(--ink-2);
837
+ }
838
+ .grove-quote__cite::before {
839
+ content: "— ";
840
+ color: var(--ink-3);
841
+ }
842
+ .grove-quote__src {
843
+ color: var(--accent);
844
+ white-space: nowrap;
845
+ border-bottom: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
846
+ transition: 0.12s;
847
+ }
848
+ .grove-quote__src:hover {
849
+ border-bottom-color: var(--accent);
850
+ }
851
+ .grove-quote__cap .grove-wikilink { /* keep broken/self fallback on-scale */
852
+ font-family: var(--mono);
853
+ font-size: 0.8rem;
854
+ }
855
+
856
+ /* code block */
857
+ .grove-codeblock {
858
+ background: var(--panel);
859
+ border: 1px solid var(--line);
860
+ border-radius: var(--radius-shape);
861
+ overflow: hidden;
862
+ font-family: var(--mono);
863
+ }
864
+ .grove-codeblock__bar {
865
+ display: flex;
866
+ align-items: center;
867
+ justify-content: space-between;
868
+ padding: 8px 14px;
869
+ border-bottom: 1px solid var(--line);
870
+ font-size: 11px;
871
+ color: var(--ink-3);
872
+ text-transform: uppercase;
873
+ letter-spacing: .08em;
874
+ }
875
+ .grove-codeblock pre {
876
+ margin: 0;
877
+ padding: 14px 16px;
878
+ overflow-x: auto;
879
+ font-size: 13px;
880
+ line-height: 1.6;
881
+ color: var(--ink);
882
+ }
883
+ .grove-codeblock .k {
884
+ color: #ff6188
885
+ }
886
+ .grove-codeblock .s {
887
+ color: #ffd866
888
+ }
889
+ .grove-codeblock .f {
890
+ color: #a9dc76
891
+ }
892
+ .grove-codeblock .c {
893
+ color: #797687
894
+ }
895
+ .grove-codeblock .n {
896
+ color: #ab9df2
897
+ }
898
+
899
+ /* tables */
900
+ .grove-prose table,
901
+ .grove-table {
902
+ width: 100%;
903
+ border-collapse: collapse;
904
+ font-size: 14px;
905
+ }
906
+ .grove-table-wrap {
907
+ overflow-x: auto;
908
+ border: 1px solid var(--line);
909
+ border-radius: var(--radius-shape);
910
+ }
911
+ .grove-table th {
912
+ text-align: left;
913
+ font-family: var(--mono);
914
+ font-size: 11px;
915
+ text-transform: uppercase;
916
+ letter-spacing: .06em;
917
+ color: var(--ink-3);
918
+ font-weight: 400;
919
+ padding: 11px 14px;
920
+ border-bottom: 1px solid var(--line-2);
921
+ background: var(--panel-2);
922
+ white-space: nowrap;
923
+ }
924
+ .grove-table td {
925
+ padding: 11px 14px;
926
+ border-bottom: 1px solid var(--line);
927
+ color: var(--ink);
928
+ }
929
+ .grove-table tr:last-child td {
930
+ border-bottom: 0;
931
+ }
932
+ .grove-table tr:hover td {
933
+ background: var(--panel);
934
+ }
935
+ .grove-table .mono {
936
+ font-family: var(--mono);
937
+ font-size: 13px;
938
+ color: var(--ink-2);
939
+ }
940
+
941
+ /* image placeholder */
942
+ .grove-img {
943
+ border: 1px solid var(--line);
944
+ border-radius: var(--radius-shape);
945
+ overflow: hidden;
946
+ background: var(--panel);
947
+ }
948
+ .grove-img__box {
949
+ aspect-ratio: 16/9;
950
+ position: relative;
951
+ background-image: radial-gradient(circle at 1px 1px, var(--ink-3) 1px, transparent 0);
952
+ background-size: 22px 22px;
953
+ opacity: 1;
954
+ }
955
+ .grove-img__box::after {
956
+ content: "";
957
+ position: absolute;
958
+ inset: 0;
959
+ background: radial-gradient(60% 60% at 50% 50%, color-mix(in srgb, var(--accent-2) 18%, transparent), transparent 70%);
960
+ }
961
+ .grove-img__el {
962
+ display: block;
963
+ width: 100%;
964
+ height: auto;
965
+ background: var(--panel-2);
966
+ border-radius: var(--radius-shape);
967
+ border: 1px solid var(--line);
968
+ }
969
+
970
+ /* native-MDX additions */
971
+ .grove-lede {
972
+ font-size: 1.22em;
973
+ line-height: 1.5;
974
+ color: var(--ink-2);
975
+ margin-bottom: 8px;
976
+ }
977
+ .grove-more {
978
+ display: flex;
979
+ gap: 8px;
980
+ justify-content: center;
981
+ color: var(--ink-3);
982
+ margin: 22px 0;
983
+ letter-spacing: .3em;
984
+ }
985
+ .grove-infobox__body {
986
+ font-size: 14px;
987
+ color: var(--ink-2);
988
+ }
989
+ .grove-infobox__body ul {
990
+ list-style: none;
991
+ margin: 0;
992
+ padding: 0;
993
+ }
994
+ .grove-infobox__body li {
995
+ padding: 5px 0;
996
+ border-bottom: 1px solid var(--line);
997
+ }
998
+ .grove-doclist-wrap {
999
+ margin: 18px 0;
1000
+ }
1001
+ a.gdl-row {
1002
+ text-decoration: none;
1003
+ color: inherit;
1004
+ }
1005
+ /* in-prose links (the routed wiki/markdown links) */
1006
+ .grove-prose a {
1007
+ color: var(--accent-pink);
1008
+ text-decoration: none;
1009
+ border-bottom: 1px solid color-mix(in srgb, var(--accent-pink) 40%, transparent);
1010
+ transition: border-color .14s, color .14s;
1011
+ }
1012
+ .grove-prose a:hover {
1013
+ border-bottom-color: var(--accent-pink);
1014
+ }
1015
+ .grove-img__cap {
1016
+ font-family: var(--mono);
1017
+ font-size: 11.5px;
1018
+ color: var(--ink-3);
1019
+ padding: 9px 14px;
1020
+ border-top: 1px solid var(--line);
1021
+ }
1022
+
1023
+ /* infobox */
1024
+ .grove-infobox {
1025
+ float: right;
1026
+ width: 280px;
1027
+ margin: 0 0 18px 24px;
1028
+ border: 1px solid var(--line);
1029
+ border-radius: var(--radius-shape);
1030
+ overflow: hidden;
1031
+ background: var(--panel);
1032
+ font-size: 13.5px;
1033
+ }
1034
+ .grove-root[data-vw="mobile"] .grove-infobox {
1035
+ float: none;
1036
+ width: 100%;
1037
+ margin: 0 0 16px;
1038
+ }
1039
+ .grove-infobox__h {
1040
+ background: var(--grad);
1041
+ color: #fff;
1042
+ font-family: var(--disp);
1043
+ font-weight: 800;
1044
+ font-size: 16px;
1045
+ padding: 11px 15px;
1046
+ letter-spacing: -.01em;
1047
+ }
1048
+ .grove-infobox__cover {
1049
+ aspect-ratio: 4/3;
1050
+ background-image: radial-gradient(circle at 1px 1px, rgba(255, 255, 255, .18) 1px, transparent 0);
1051
+ background-size: 18px 18px;
1052
+ background-color: var(--panel-2);
1053
+ }
1054
+ .grove-infobox dl {
1055
+ margin: 0;
1056
+ padding: 6px 15px 12px;
1057
+ }
1058
+ .grove-infobox dt {
1059
+ font-family: var(--mono);
1060
+ font-size: 10.5px;
1061
+ text-transform: uppercase;
1062
+ letter-spacing: .06em;
1063
+ color: var(--ink-3);
1064
+ margin-top: 9px;
1065
+ }
1066
+ .grove-infobox dd {
1067
+ margin: 2px 0 0;
1068
+ color: var(--ink);
1069
+ }
1070
+
1071
+ /* ToC */
1072
+ .grove-toc {
1073
+ position: sticky;
1074
+ top: 78px;
1075
+ font-size: 13px;
1076
+ /* Its OWN scroll container — the whole point of <TableOfContents>. A list taller than
1077
+ the viewport has to scroll somewhere, and if it is not here it is the page, which is
1078
+ how a contents rail ends up showing §1 while the reader is in §12. */
1079
+ max-height: calc(100vh - 110px);
1080
+ overflow-y: auto;
1081
+ overscroll-behavior: contain;
1082
+ /* `offsetTop` is measured from the nearest POSITIONED ancestor; `position: sticky`
1083
+ already makes this one, and the comment is here so nobody "cleans up" the sticky
1084
+ into a plain block and silently moves the scroll arithmetic's origin. */
1085
+ scrollbar-width: thin;
1086
+ }
1087
+ /* A ToC that scrolls needs a visible edge to scroll to, and the default overlay bar is
1088
+ invisible until moved. Keep the gutter reserved so entries don't reflow on hover. */
1089
+ .grove-toc::-webkit-scrollbar {
1090
+ width: 6px;
1091
+ }
1092
+ .grove-toc::-webkit-scrollbar-thumb {
1093
+ background: var(--line-2);
1094
+ border-radius: var(--r-pill);
1095
+ }
1096
+ .grove-root[data-vw="mobile"] .grove-toc {
1097
+ position: static;
1098
+ /* Inside the mobile <details> disclosure the rail is already in a bounded box and the
1099
+ page scrolls; a second nested scroller there traps the touch gesture. */
1100
+ max-height: none;
1101
+ overflow-y: visible;
1102
+ }
1103
+ /* The disclosure's <summary> already says "On this page", so the list's own label is a
1104
+ duplicate there. It always was — but giving it a sticky opaque bar (above) turned a
1105
+ quiet repetition into two stacked headers. The nav keeps its `aria-label`, so nothing
1106
+ is lost for assistive tech. */
1107
+ .grove-toc__disclosure .grove-toc__h {
1108
+ display: none;
1109
+ }
1110
+ .grove-toc__h {
1111
+ font-family: var(--mono);
1112
+ font-size: 10.5px;
1113
+ text-transform: uppercase;
1114
+ letter-spacing: .1em;
1115
+ color: var(--ink-3);
1116
+ margin-bottom: 10px;
1117
+ /* Sticky INSIDE the rail's own scroller: once the list scrolls, the label that says
1118
+ what the list is would otherwise be the first thing to leave. Needs an opaque
1119
+ background or the entries read through it. */
1120
+ position: sticky;
1121
+ top: 0;
1122
+ background: var(--bg);
1123
+ padding-bottom: 6px;
1124
+ z-index: 1;
1125
+ }
1126
+ .grove-toc a {
1127
+ display: block;
1128
+ padding: 4px 0 4px 12px;
1129
+ border-left: 2px solid var(--line);
1130
+ color: var(--ink-2);
1131
+ transition: .12s;
1132
+ line-height: 1.35;
1133
+ }
1134
+ .grove-toc a:hover {
1135
+ color: var(--ink);
1136
+ }
1137
+ .grove-toc a[data-cur="1"] {
1138
+ border-left-color: var(--accent);
1139
+ color: var(--ink);
1140
+ font-weight: 600;
1141
+ }
1142
+ .grove-toc a.lvl3 {
1143
+ padding-left: 22px;
1144
+ font-size: 12.5px;
1145
+ }
1146
+ .grove-toc__disclosure {
1147
+ border: 1px solid var(--line);
1148
+ border-radius: var(--radius-shape);
1149
+ margin-bottom: 20px;
1150
+ background: var(--panel);
1151
+ }
1152
+ .grove-toc__disclosure summary {
1153
+ padding: 11px 15px;
1154
+ font-family: var(--mono);
1155
+ font-size: 12px;
1156
+ color: var(--ink-2);
1157
+ cursor: pointer;
1158
+ list-style: none;
1159
+ /* The native marker is suppressed below, so without a replacement this control has NO
1160
+ affordance at all — on a phone the contents list is the whole navigation, and an
1161
+ unmarked rounded box reads as a caption, not a button. Reported from a real iPhone as
1162
+ "I see no toc": the list was there, collapsed, behind a thing that did not look like
1163
+ it opened. */
1164
+ display: flex;
1165
+ align-items: center;
1166
+ justify-content: space-between;
1167
+ gap: 12px;
1168
+ /* Comfortable thumb target — the text alone is 12px tall. */
1169
+ min-height: 44px;
1170
+ }
1171
+ .grove-toc__disclosure summary::-webkit-details-marker {
1172
+ display: none;
1173
+ }
1174
+ /* A caret drawn in CSS rather than an icon import, so the disclosure stays styling-only
1175
+ and no call site has to change. Points down when closed, up when open. */
1176
+ .grove-toc__disclosure summary::after {
1177
+ content: "";
1178
+ flex: 0 0 auto;
1179
+ width: 7px;
1180
+ height: 7px;
1181
+ margin-right: 2px;
1182
+ border-right: 1.75px solid currentColor;
1183
+ border-bottom: 1.75px solid currentColor;
1184
+ transform: translateY(-2px) rotate(45deg);
1185
+ transition: transform .18s ease;
1186
+ }
1187
+ .grove-toc__disclosure[open] summary::after {
1188
+ transform: translateY(1px) rotate(225deg);
1189
+ }
1190
+ @media (prefers-reduced-motion: reduce) {
1191
+ .grove-toc__disclosure summary::after {
1192
+ transition: none;
1193
+ }
1194
+ }
1195
+ .grove-toc__disclosure summary:hover,
1196
+ .grove-toc__disclosure[open] summary {
1197
+ color: var(--ink);
1198
+ }
1199
+ .grove-toc__disclosure[open] summary {
1200
+ border-bottom: 1px solid var(--line);
1201
+ }
1202
+ .grove-toc__disclosure .grove-toc {
1203
+ position: static;
1204
+ padding: 12px 15px;
1205
+ }
1206
+
1207
+ /* backlinks */
1208
+ .grove-backlinks {
1209
+ margin-top: 54px;
1210
+ border-top: 1px solid var(--line);
1211
+ padding-top: 24px;
1212
+ }
1213
+ .grove-backlinks__h {
1214
+ font-family: var(--disp);
1215
+ font-weight: 700;
1216
+ font-size: 18px;
1217
+ color: var(--ink);
1218
+ margin-bottom: 4px;
1219
+ display: flex;
1220
+ align-items: baseline;
1221
+ gap: 10px;
1222
+ }
1223
+ .grove-backlinks__h .n {
1224
+ font-family: var(--mono);
1225
+ font-weight: 400;
1226
+ font-size: 13px;
1227
+ color: var(--accent-3);
1228
+ background: color-mix(in srgb, var(--accent) 12%, transparent);
1229
+ border: 1px solid var(--line-2);
1230
+ border-radius: var(--r-pill);
1231
+ padding: 3px 10px;
1232
+ }
1233
+ .grove-backlinks__list {
1234
+ margin-top: 16px;
1235
+ display: flex;
1236
+ flex-direction: column;
1237
+ gap: 2px;
1238
+ }
1239
+ .grove-bl {
1240
+ display: block;
1241
+ padding: 13px 15px;
1242
+ border: 1px solid transparent;
1243
+ border-radius: var(--radius-shape);
1244
+ transition: .14s;
1245
+ }
1246
+ .grove-bl:hover {
1247
+ background: var(--panel);
1248
+ border-color: var(--line);
1249
+ transform: translate(-2px, -2px);
1250
+ box-shadow: var(--shadow-card);
1251
+ }
1252
+ .grove-bl__t {
1253
+ display: flex;
1254
+ align-items: baseline;
1255
+ gap: 9px;
1256
+ font-family: var(--disp);
1257
+ font-weight: 700;
1258
+ font-size: 15px;
1259
+ color: var(--ink);
1260
+ }
1261
+ .grove-bl__t .crumb {
1262
+ font-family: var(--mono);
1263
+ font-weight: 400;
1264
+ font-size: 11px;
1265
+ color: var(--ink-3);
1266
+ }
1267
+ .grove-bl__snip {
1268
+ font-size: 13.5px;
1269
+ color: var(--ink-2);
1270
+ margin-top: 5px;
1271
+ line-height: 1.5;
1272
+ }
1273
+ .grove-bl__snip mark {
1274
+ background: color-mix(in srgb, var(--accent) 22%, transparent);
1275
+ color: var(--ink);
1276
+ border-radius: 2px;
1277
+ padding: 0 2px;
1278
+ }
1279
+
1280
+ /* ============ DOCLIST (feed + grid) ============ */
1281
+ .grove-doclist__head {
1282
+ display: flex;
1283
+ align-items: baseline;
1284
+ gap: 12px;
1285
+ margin-bottom: 18px;
1286
+ }
1287
+ .grove-doclist__head h2 {
1288
+ font-family: var(--disp);
1289
+ font-weight: var(--disp-weight);
1290
+ font-size: 26px;
1291
+ letter-spacing: -.02em;
1292
+ color: var(--ink);
1293
+ }
1294
+ .grove-doclist__head .n {
1295
+ font-family: var(--mono);
1296
+ font-size: 12px;
1297
+ color: var(--ink-3);
1298
+ }
1299
+ .grove-doclist[data-shape="feed"] {
1300
+ display: flex;
1301
+ flex-direction: column;
1302
+ }
1303
+ .gdl-row {
1304
+ display: grid;
1305
+ grid-template-columns: 1fr auto;
1306
+ gap: 14px;
1307
+ padding: 18px 4px;
1308
+ border-bottom: 1px solid var(--line);
1309
+ align-items: start;
1310
+ transition: .14s;
1311
+ cursor: pointer;
1312
+ }
1313
+ .gdl-row:hover {
1314
+ background: var(--panel);
1315
+ border-radius: var(--radius-shape);
1316
+ padding-left: 14px;
1317
+ padding-right: 14px;
1318
+ border-bottom-color: transparent;
1319
+ }
1320
+ .gdl-row__t {
1321
+ font-family: var(--disp);
1322
+ font-weight: 700;
1323
+ font-size: 18px;
1324
+ letter-spacing: -.01em;
1325
+ color: var(--ink);
1326
+ }
1327
+ .gdl-row__d {
1328
+ font-size: 14px;
1329
+ color: var(--ink-2);
1330
+ margin-top: 5px;
1331
+ line-height: 1.5;
1332
+ max-width: 62ch;
1333
+ }
1334
+ .gdl-row__tags {
1335
+ display: flex;
1336
+ gap: 6px;
1337
+ margin-top: 10px;
1338
+ flex-wrap: wrap;
1339
+ }
1340
+ .gdl-row__meta {
1341
+ font-family: var(--mono);
1342
+ font-size: 11.5px;
1343
+ color: var(--ink-3);
1344
+ text-align: right;
1345
+ white-space: nowrap;
1346
+ line-height: 1.6;
1347
+ }
1348
+ .grove-doclist[data-shape="grid"] {
1349
+ display: grid;
1350
+ grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
1351
+ gap: 16px;
1352
+ }
1353
+ .grove-root[data-vw="mobile"] .grove-doclist[data-shape="grid"] {
1354
+ grid-template-columns: 1fr;
1355
+ }
1356
+ .gdl-card {
1357
+ border: 1px solid var(--line);
1358
+ border-radius: var(--r-lg);
1359
+ overflow: hidden;
1360
+ background: var(--panel);
1361
+ display: flex;
1362
+ flex-direction: column;
1363
+ transition: .14s;
1364
+ cursor: pointer;
1365
+ }
1366
+ .gdl-card:hover {
1367
+ transform: translate(-3px, -3px);
1368
+ box-shadow: var(--shadow-card);
1369
+ border-color: var(--line-2);
1370
+ }
1371
+ .gdl-card__pic {
1372
+ min-height: 118px;
1373
+ flex: 1;
1374
+ position: relative;
1375
+ background-image: radial-gradient(circle at 1px 1px, var(--ink-3) 1px, transparent 0);
1376
+ background-size: 20px 20px;
1377
+ }
1378
+ .gdl-card__pic::after {
1379
+ content: "";
1380
+ position: absolute;
1381
+ inset: 0;
1382
+ background: radial-gradient(70% 70% at 75% 15%, color-mix(in srgb, var(--accent) 14%, transparent), transparent 70%);
1383
+ }
1384
+ .gdl-card__foot {
1385
+ padding: 14px 15px;
1386
+ border-top: 1px solid var(--line);
1387
+ }
1388
+ .gdl-card__t {
1389
+ font-family: var(--disp);
1390
+ font-weight: 800;
1391
+ font-size: 17px;
1392
+ letter-spacing: -.01em;
1393
+ color: var(--ink);
1394
+ }
1395
+ .gdl-card__d {
1396
+ font-size: 12.5px;
1397
+ color: var(--ink-2);
1398
+ margin-top: 5px;
1399
+ line-height: 1.45;
1400
+ }
1401
+ .gdl-card__tags {
1402
+ display: flex;
1403
+ gap: 6px;
1404
+ margin-top: 11px;
1405
+ flex-wrap: wrap;
1406
+ }
1407
+ .gdl-card.accent {
1408
+ background: linear-gradient(150deg, oklch(0.62 0.18 350), oklch(0.5 0.17 0));
1409
+ border-color: rgba(255, 255, 255, .16);
1410
+ }
1411
+ .gdl-card.accent .gdl-card__t,
1412
+ .gdl-card.accent .gdl-card__d {
1413
+ color: #fff;
1414
+ }
1415
+ .gdl-card.accent .gdl-card__foot {
1416
+ border-color: rgba(255, 255, 255, .25);
1417
+ }
1418
+
1419
+ /* tagcloud */
1420
+ .grove-tagcloud {
1421
+ display: flex;
1422
+ flex-wrap: wrap;
1423
+ gap: 8px;
1424
+ align-items: center;
1425
+ }
1426
+
1427
+ /* ============ skeleton ============ */
1428
+ @keyframes gshimmer {
1429
+ 0% {
1430
+ background-position: -340px 0;
1431
+ }
1432
+ 100% {
1433
+ background-position: 340px 0;
1434
+ }
1435
+ }
1436
+ .sk {
1437
+ background: var(--panel-2);
1438
+ border-radius: 6px;
1439
+ background-image: linear-gradient(90deg, transparent, color-mix(in srgb, var(--ink) 6%, transparent), transparent);
1440
+ background-size: 340px 100%;
1441
+ background-repeat: no-repeat;
1442
+ animation: gshimmer 1.3s infinite linear;
1443
+ }
1444
+ .sk-line {
1445
+ height: 14px;
1446
+ margin: 11px 0;
1447
+ }
1448
+ @media (prefers-reduced-motion: reduce) {
1449
+ .sk {
1450
+ animation: none;
1451
+ }
1452
+ }
1453
+
1454
+ /* empty / error */
1455
+ .grove-state {
1456
+ max-width: 520px;
1457
+ margin: 48px auto;
1458
+ text-align: center;
1459
+ padding: 30px;
1460
+ }
1461
+ .grove-state__art {
1462
+ width: 140px;
1463
+ height: 96px;
1464
+ margin: 0 auto 22px;
1465
+ position: relative;
1466
+ opacity: .8;
1467
+ }
1468
+ .grove-state h2 {
1469
+ font-family: var(--disp);
1470
+ font-weight: var(--disp-weight);
1471
+ font-size: 26px;
1472
+ letter-spacing: -.02em;
1473
+ color: var(--ink);
1474
+ margin-bottom: 8px;
1475
+ }
1476
+ .grove-state p {
1477
+ color: var(--ink-2);
1478
+ font-size: 15px;
1479
+ line-height: 1.55;
1480
+ }
1481
+ .grove-state code {
1482
+ font-family: var(--mono);
1483
+ font-size: .9em;
1484
+ color: var(--accent-3);
1485
+ background: var(--panel-2);
1486
+ border: 1px solid var(--line);
1487
+ border-radius: var(--r-xs);
1488
+ padding: 1px 6px;
1489
+ }
1490
+ .grove-state__actions {
1491
+ margin-top: 22px;
1492
+ display: flex;
1493
+ gap: 10px;
1494
+ justify-content: center;
1495
+ flex-wrap: wrap;
1496
+ }
1497
+ .btn-primary {
1498
+ display: inline-flex;
1499
+ align-items: center;
1500
+ gap: 8px;
1501
+ font-family: var(--sans);
1502
+ font-weight: 600;
1503
+ font-size: 14px;
1504
+ color: #fff;
1505
+ background: var(--grad);
1506
+ border: 0;
1507
+ border-radius: var(--r-pill);
1508
+ padding: 10px 18px;
1509
+ transition: .14s;
1510
+ }
1511
+ .btn-primary:hover {
1512
+ box-shadow: var(--glow);
1513
+ }
1514
+ .btn-ghost {
1515
+ display: inline-flex;
1516
+ align-items: center;
1517
+ gap: 8px;
1518
+ font-family: var(--sans);
1519
+ font-weight: 600;
1520
+ font-size: 14px;
1521
+ color: var(--ink-2);
1522
+ background: var(--panel);
1523
+ border: 1px solid var(--line-2);
1524
+ border-radius: var(--r-pill);
1525
+ padding: 10px 18px;
1526
+ transition: .14s;
1527
+ }
1528
+ .btn-ghost:hover {
1529
+ color: var(--ink);
1530
+ border-color: var(--accent-2);
1531
+ }
1532
+ .btn-ghost svg,
1533
+ .btn-primary svg {
1534
+ width: 15px;
1535
+ height: 15px;
1536
+ }
1537
+
1538
+ /* misc */
1539
+ .gnode {
1540
+ position: absolute;
1541
+ width: 7px;
1542
+ height: 7px;
1543
+ border-radius: 50%;
1544
+ background: var(--accent-violet);
1545
+ opacity: .8;
1546
+ }
1547
+
1548
+ /* ============ SEARCH PALETTE ============ */
1549
+ .grove-search {
1550
+ position: absolute;
1551
+ inset: 0;
1552
+ z-index: 60;
1553
+ display: flex;
1554
+ justify-content: center;
1555
+ align-items: flex-start;
1556
+ padding: 60px 18px;
1557
+ background: color-mix(in srgb, var(--bg) 55%, transparent);
1558
+ backdrop-filter: blur(6px);
1559
+ }
1560
+ .grove-search__box {
1561
+ width: 100%;
1562
+ max-width: 560px;
1563
+ background: var(--panel);
1564
+ border: 1px solid var(--line-2);
1565
+ border-radius: var(--r-xl);
1566
+ box-shadow: 0 24px 70px rgba(0, 0, 0, .5);
1567
+ overflow: hidden;
1568
+ }
1569
+ .grove-search__in {
1570
+ display: flex;
1571
+ align-items: center;
1572
+ gap: 11px;
1573
+ padding: 15px 18px;
1574
+ border-bottom: 1px solid var(--line);
1575
+ }
1576
+ .grove-search__in svg {
1577
+ width: 18px;
1578
+ height: 18px;
1579
+ color: var(--ink-3);
1580
+ flex: 0 0 auto;
1581
+ }
1582
+ .grove-search__in input {
1583
+ flex: 1;
1584
+ background: none;
1585
+ border: 0;
1586
+ outline: none;
1587
+ color: var(--ink);
1588
+ font-family: var(--sans);
1589
+ font-size: 16px;
1590
+ }
1591
+ .grove-search__in input::placeholder {
1592
+ color: var(--ink-3);
1593
+ }
1594
+ .grove-search__in kbd {
1595
+ font-family: var(--mono);
1596
+ font-size: 10px;
1597
+ color: var(--ink-3);
1598
+ border: 1px solid var(--line-2);
1599
+ border-radius: var(--r-xs);
1600
+ padding: 2px 6px;
1601
+ }
1602
+ .grove-search__res {
1603
+ max-height: 330px;
1604
+ overflow-y: auto;
1605
+ padding: 8px;
1606
+ }
1607
+ .grove-search__grp {
1608
+ font-family: var(--mono);
1609
+ font-size: 10px;
1610
+ text-transform: uppercase;
1611
+ letter-spacing: .1em;
1612
+ color: var(--ink-3);
1613
+ padding: 9px 10px 5px;
1614
+ }
1615
+ .grove-search__row {
1616
+ display: flex;
1617
+ align-items: center;
1618
+ gap: 11px;
1619
+ padding: 9px 11px;
1620
+ border-radius: var(--r-md);
1621
+ cursor: pointer;
1622
+ }
1623
+ .grove-search__row:hover,
1624
+ .grove-search__row[data-sel="1"] {
1625
+ background: var(--panel-2);
1626
+ }
1627
+ .grove-search__row svg {
1628
+ width: 15px;
1629
+ height: 15px;
1630
+ color: var(--ink-3);
1631
+ flex: 0 0 auto;
1632
+ }
1633
+ .grove-search__row .t {
1634
+ font-weight: 600;
1635
+ font-size: 14px;
1636
+ color: var(--ink);
1637
+ }
1638
+ .grove-search__row .c {
1639
+ font-family: var(--mono);
1640
+ font-size: 11px;
1641
+ color: var(--ink-3);
1642
+ margin-left: auto;
1643
+ }
1644
+ .grove-search__empty {
1645
+ padding: 26px 16px;
1646
+ text-align: center;
1647
+ color: var(--ink-2);
1648
+ font-size: 14px;
1649
+ }
1650
+
1651
+ /* ============ THE GROVE AGENT ============ */
1652
+ .grove-agent {
1653
+ position: absolute;
1654
+ inset: 0;
1655
+ z-index: 50;
1656
+ pointer-events: none;
1657
+ }
1658
+ .grove-agent>* {
1659
+ pointer-events: auto;
1660
+ }
1661
+ /* resting: thin input line (approach 1) */
1662
+ .ga-line {
1663
+ position: absolute;
1664
+ left: 0;
1665
+ right: 0;
1666
+ bottom: 0;
1667
+ display: flex;
1668
+ align-items: center;
1669
+ gap: 10px;
1670
+ padding: 9px 14px;
1671
+ background: color-mix(in srgb, var(--bg) 88%, transparent);
1672
+ backdrop-filter: blur(12px);
1673
+ border-top: 1px solid var(--line);
1674
+ }
1675
+ .ga-line .mk {
1676
+ width: 22px;
1677
+ height: 22px;
1678
+ border-radius: 24%;
1679
+ background: var(--grad);
1680
+ position: relative;
1681
+ flex: 0 0 auto;
1682
+ }
1683
+ .ga-line input {
1684
+ flex: 1;
1685
+ background: var(--panel);
1686
+ border: 1px solid var(--line-2);
1687
+ border-radius: var(--r-pill);
1688
+ outline: none;
1689
+ color: var(--ink);
1690
+ font-family: var(--sans);
1691
+ font-size: 14px;
1692
+ padding: 9px 15px;
1693
+ transition: .14s;
1694
+ }
1695
+ .ga-line input::placeholder {
1696
+ color: var(--ink-3);
1697
+ }
1698
+ .ga-line input:focus {
1699
+ border-color: var(--accent);
1700
+ box-shadow: var(--glow);
1701
+ }
1702
+ .ga-line .go {
1703
+ width: 34px;
1704
+ height: 34px;
1705
+ border-radius: 50%;
1706
+ background: var(--grad);
1707
+ color: #fff;
1708
+ border: 0;
1709
+ display: flex;
1710
+ align-items: center;
1711
+ justify-content: center;
1712
+ flex: 0 0 auto;
1713
+ }
1714
+ .ga-line .go svg {
1715
+ width: 16px;
1716
+ height: 16px;
1717
+ }
1718
+ /* resting: pull tab (approach 2) */
1719
+ .ga-tab {
1720
+ position: absolute;
1721
+ left: 50%;
1722
+ transform: translateX(-50%);
1723
+ bottom: 0;
1724
+ display: flex;
1725
+ flex-direction: column;
1726
+ align-items: center;
1727
+ gap: 5px;
1728
+ padding: 7px 22px 9px;
1729
+ background: var(--panel);
1730
+ border: 1px solid var(--line-2);
1731
+ border-bottom: 0;
1732
+ border-radius: var(--r-lg) var(--r-lg) 0 0;
1733
+ cursor: pointer;
1734
+ }
1735
+ .ga-tab .grip {
1736
+ width: 34px;
1737
+ height: 4px;
1738
+ border-radius: 3px;
1739
+ background: var(--ink-3);
1740
+ }
1741
+ .ga-tab .lbl {
1742
+ font-family: var(--sans);
1743
+ font-weight: 600;
1744
+ font-size: 12.5px;
1745
+ color: var(--ink-2);
1746
+ display: flex;
1747
+ align-items: center;
1748
+ gap: 6px;
1749
+ }
1750
+ .ga-tab .lbl .mk {
1751
+ width: 15px;
1752
+ height: 15px;
1753
+ border-radius: 24%;
1754
+ background: var(--grad);
1755
+ position: relative;
1756
+ }
1757
+ /* resting: corner icon (approach 3) */
1758
+ .ga-icon {
1759
+ position: absolute;
1760
+ right: 16px;
1761
+ bottom: 16px;
1762
+ width: 50px;
1763
+ height: 50px;
1764
+ border-radius: 50%;
1765
+ background: var(--grad);
1766
+ display: flex;
1767
+ align-items: center;
1768
+ justify-content: center;
1769
+ cursor: pointer;
1770
+ box-shadow: 0 8px 24px rgba(0, 0, 0, .4), var(--glow);
1771
+ }
1772
+ .ga-icon svg {
1773
+ width: 22px;
1774
+ height: 22px;
1775
+ color: #fff;
1776
+ }
1777
+ /* resting: permanent live band (approach 4) */
1778
+ .ga-band {
1779
+ position: absolute;
1780
+ left: 0;
1781
+ right: 0;
1782
+ bottom: 0;
1783
+ background: var(--panel);
1784
+ border-top: 1px solid var(--line-2);
1785
+ padding: 10px 14px 11px;
1786
+ display: flex;
1787
+ flex-direction: column;
1788
+ gap: 8px;
1789
+ }
1790
+ .ga-band__status {
1791
+ display: flex;
1792
+ align-items: center;
1793
+ gap: 8px;
1794
+ font-size: 12.5px;
1795
+ color: var(--ink-2);
1796
+ }
1797
+ .ga-band__status .mk {
1798
+ width: 17px;
1799
+ height: 17px;
1800
+ border-radius: 24%;
1801
+ background: var(--grad);
1802
+ position: relative;
1803
+ flex: 0 0 auto;
1804
+ }
1805
+ .ga-band__status b {
1806
+ color: var(--ink);
1807
+ font-weight: 600;
1808
+ }
1809
+ .ga-band__row {
1810
+ display: flex;
1811
+ align-items: center;
1812
+ gap: 9px;
1813
+ }
1814
+ .ga-band__row input {
1815
+ flex: 1;
1816
+ background: var(--bg);
1817
+ border: 1px solid var(--line-2);
1818
+ border-radius: var(--r-pill);
1819
+ outline: none;
1820
+ color: var(--ink);
1821
+ font-size: 13.5px;
1822
+ padding: 8px 14px;
1823
+ font-family: var(--sans);
1824
+ }
1825
+ .ga-band__row input:focus {
1826
+ border-color: var(--accent);
1827
+ box-shadow: var(--glow);
1828
+ }
1829
+ .ga-band__row .go {
1830
+ width: 32px;
1831
+ height: 32px;
1832
+ border-radius: 50%;
1833
+ background: var(--grad);
1834
+ color: #fff;
1835
+ border: 0;
1836
+ display: flex;
1837
+ align-items: center;
1838
+ justify-content: center;
1839
+ flex: 0 0 auto;
1840
+ }
1841
+ .ga-band__row .go svg {
1842
+ width: 15px;
1843
+ height: 15px;
1844
+ }
1845
+
1846
+ /* expanded panel */
1847
+ .ga-scrim {
1848
+ position: absolute;
1849
+ inset: 0;
1850
+ background: color-mix(in srgb, var(--bg) 30%, transparent);
1851
+ }
1852
+ .ga-panel {
1853
+ position: absolute;
1854
+ display: flex;
1855
+ flex-direction: column;
1856
+ background: var(--panel);
1857
+ border: 1px solid var(--line-2);
1858
+ box-shadow: 0 -10px 50px rgba(0, 0, 0, .4);
1859
+ }
1860
+ /* desktop dock: bottom-anchored, grows up, centered column */
1861
+ .grove-root[data-vw="desktop"] .ga-panel {
1862
+ left: 0;
1863
+ right: 0;
1864
+ bottom: 0;
1865
+ height: 74%;
1866
+ max-height: 600px;
1867
+ border-radius: var(--r-xl) var(--r-xl) 0 0;
1868
+ border-bottom: 0;
1869
+ }
1870
+ .grove-root[data-vw="desktop"] .ga-panel-inner {
1871
+ width: 100%;
1872
+ max-width: 760px;
1873
+ margin: 0 auto;
1874
+ display: flex;
1875
+ flex-direction: column;
1876
+ min-height: 0;
1877
+ flex: 1;
1878
+ }
1879
+ /* mobile sheet */
1880
+ .grove-root[data-vw="mobile"] .ga-panel {
1881
+ left: 0;
1882
+ right: 0;
1883
+ bottom: 0;
1884
+ border-radius: var(--r-xl) var(--r-xl) 0 0;
1885
+ border-bottom: 0;
1886
+ }
1887
+ .grove-root[data-vw="mobile"] .ga-panel[data-detent="half"] {
1888
+ height: 60%;
1889
+ }
1890
+ .grove-root[data-vw="mobile"] .ga-panel[data-detent="full"] {
1891
+ height: 92%;
1892
+ }
1893
+ .grove-root[data-vw="mobile"] .ga-panel-inner {
1894
+ display: flex;
1895
+ flex-direction: column;
1896
+ min-height: 0;
1897
+ flex: 1;
1898
+ }
1899
+
1900
+ .ga-head {
1901
+ display: flex;
1902
+ align-items: center;
1903
+ gap: 11px;
1904
+ padding: 13px 16px;
1905
+ border-bottom: 1px solid var(--line);
1906
+ flex: 0 0 auto;
1907
+ }
1908
+ .ga-head .grip {
1909
+ position: absolute;
1910
+ top: 7px;
1911
+ left: 50%;
1912
+ transform: translateX(-50%);
1913
+ width: 36px;
1914
+ height: 4px;
1915
+ border-radius: 3px;
1916
+ background: var(--ink-3);
1917
+ }
1918
+ .ga-head .mk {
1919
+ width: 26px;
1920
+ height: 26px;
1921
+ border-radius: 24%;
1922
+ background: var(--grad);
1923
+ position: relative;
1924
+ flex: 0 0 auto;
1925
+ }
1926
+ .ga-head .id {
1927
+ font-family: var(--disp);
1928
+ font-weight: 800;
1929
+ font-size: 15px;
1930
+ color: var(--ink);
1931
+ letter-spacing: -.01em;
1932
+ }
1933
+ .ga-head .scope {
1934
+ font-family: var(--mono);
1935
+ font-size: 10px;
1936
+ line-height: 1;
1937
+ color: var(--accent-3);
1938
+ background: color-mix(in srgb, var(--accent) 12%, transparent);
1939
+ border: 1px solid var(--line-2);
1940
+ border-radius: var(--r-pill);
1941
+ padding: 4px 10px;
1942
+ display: inline-flex;
1943
+ align-items: center;
1944
+ gap: 5px;
1945
+ white-space: nowrap;
1946
+ flex: 0 0 auto;
1947
+ }
1948
+ .ga-head .scope svg {
1949
+ width: 11px;
1950
+ height: 11px;
1951
+ flex: 0 0 auto;
1952
+ }
1953
+ .ga-head .grow {
1954
+ margin-left: auto;
1955
+ display: flex;
1956
+ gap: 6px;
1957
+ }
1958
+ .ga-head .ic {
1959
+ width: 30px;
1960
+ height: 30px;
1961
+ border-radius: 50%;
1962
+ background: transparent;
1963
+ border: 1px solid var(--line);
1964
+ color: var(--ink-2);
1965
+ display: flex;
1966
+ align-items: center;
1967
+ justify-content: center;
1968
+ }
1969
+ .ga-head .ic:hover {
1970
+ color: var(--ink);
1971
+ border-color: var(--accent-2);
1972
+ }
1973
+ .ga-head .ic svg {
1974
+ width: 15px;
1975
+ height: 15px;
1976
+ }
1977
+
1978
+ .ga-body {
1979
+ flex: 1;
1980
+ overflow-y: auto;
1981
+ padding: 18px 16px;
1982
+ min-height: 0;
1983
+ display: flex;
1984
+ flex-direction: column;
1985
+ gap: 14px;
1986
+ }
1987
+ .ga-explain {
1988
+ font-size: 13px;
1989
+ color: var(--ink-2);
1990
+ line-height: 1.55;
1991
+ background: var(--panel-2);
1992
+ border: 1px solid var(--line);
1993
+ border-radius: var(--r-md);
1994
+ padding: 12px 14px;
1995
+ }
1996
+ .ga-explain b {
1997
+ color: var(--ink);
1998
+ font-weight: 600;
1999
+ }
2000
+ .ga-chips {
2001
+ display: flex;
2002
+ flex-wrap: wrap;
2003
+ gap: 8px;
2004
+ }
2005
+ .ga-chip {
2006
+ font-family: var(--sans);
2007
+ font-weight: 600;
2008
+ font-size: 12.5px;
2009
+ color: var(--ink-2);
2010
+ background: var(--panel-2);
2011
+ border: 1px solid var(--line-2);
2012
+ border-radius: var(--r-pill);
2013
+ padding: 7px 13px;
2014
+ cursor: pointer;
2015
+ transition: .14s;
2016
+ text-align: left;
2017
+ }
2018
+ .ga-chip:hover {
2019
+ color: var(--ink);
2020
+ border-color: var(--accent);
2021
+ transform: translateY(-1px);
2022
+ }
2023
+
2024
+ .ga-msg {
2025
+ display: flex;
2026
+ gap: 10px;
2027
+ max-width: 100%;
2028
+ }
2029
+ .ga-msg__av {
2030
+ width: 26px;
2031
+ height: 26px;
2032
+ border-radius: 24%;
2033
+ flex: 0 0 auto;
2034
+ position: relative;
2035
+ }
2036
+ .ga-msg__av.grove {
2037
+ background: var(--grad);
2038
+ }
2039
+ .ga-msg__av.user {
2040
+ background: var(--panel-2);
2041
+ border: 1px solid var(--line-2);
2042
+ display: flex;
2043
+ align-items: center;
2044
+ justify-content: center;
2045
+ font-family: var(--mono);
2046
+ font-size: 11px;
2047
+ color: var(--ink-2);
2048
+ }
2049
+ .ga-msg__b {
2050
+ flex: 1;
2051
+ min-width: 0;
2052
+ }
2053
+ .ga-msg__who {
2054
+ font-family: var(--mono);
2055
+ font-size: 10.5px;
2056
+ color: var(--ink-3);
2057
+ margin-bottom: 3px;
2058
+ }
2059
+ .ga-msg__txt {
2060
+ font-size: 14px;
2061
+ line-height: 1.55;
2062
+ color: var(--ink);
2063
+ }
2064
+ .ga-msg.user .ga-msg__txt {
2065
+ color: var(--ink-2);
2066
+ }
2067
+ .ga-msg__txt code {
2068
+ font-family: var(--mono);
2069
+ font-size: .85em;
2070
+ background: var(--panel-2);
2071
+ border: 1px solid var(--line);
2072
+ border-radius: var(--r-xs);
2073
+ padding: 1px 5px;
2074
+ color: var(--accent-3);
2075
+ }
2076
+ .ga-cursor {
2077
+ display: inline-block;
2078
+ width: 7px;
2079
+ height: 15px;
2080
+ background: var(--accent);
2081
+ margin-left: 2px;
2082
+ vertical-align: -2px;
2083
+ animation: gblink 1s steps(2) infinite;
2084
+ }
2085
+ @keyframes gblink {
2086
+ 50% {
2087
+ opacity: 0;
2088
+ }
2089
+ }
2090
+
2091
+ /* proposed-change preview */
2092
+ .ga-preview {
2093
+ border: 1px solid var(--line-2);
2094
+ border-radius: var(--r-md);
2095
+ overflow: hidden;
2096
+ background: var(--bg);
2097
+ margin-top: 4px;
2098
+ }
2099
+ .ga-preview__h {
2100
+ display: flex;
2101
+ align-items: center;
2102
+ gap: 9px;
2103
+ padding: 10px 13px;
2104
+ border-bottom: 1px solid var(--line);
2105
+ font-size: 12.5px;
2106
+ color: var(--ink);
2107
+ }
2108
+ .ga-preview__h .badge {
2109
+ font-family: var(--mono);
2110
+ font-size: 10px;
2111
+ color: var(--accent-3);
2112
+ background: color-mix(in srgb, var(--accent) 12%, transparent);
2113
+ border: 1px solid var(--line-2);
2114
+ border-radius: var(--r-pill);
2115
+ padding: 2px 8px;
2116
+ }
2117
+ .ga-preview__files {
2118
+ padding: 9px 13px;
2119
+ display: flex;
2120
+ flex-direction: column;
2121
+ gap: 5px;
2122
+ border-bottom: 1px solid var(--line);
2123
+ }
2124
+ .ga-pf {
2125
+ display: flex;
2126
+ align-items: center;
2127
+ gap: 8px;
2128
+ font-family: var(--mono);
2129
+ font-size: 11.5px;
2130
+ color: var(--ink-2);
2131
+ }
2132
+ .ga-pf .op {
2133
+ width: 16px;
2134
+ text-align: center;
2135
+ font-weight: 700;
2136
+ }
2137
+ .ga-pf .op.add {
2138
+ color: #7bd88f
2139
+ }
2140
+ .ga-pf .op.edit {
2141
+ color: var(--accent-3);
2142
+ }
2143
+ .ga-diff {
2144
+ font-family: var(--mono);
2145
+ font-size: 11.5px;
2146
+ line-height: 1.55;
2147
+ padding: 10px 13px;
2148
+ overflow-x: auto;
2149
+ max-height: 180px;
2150
+ overflow-y: auto;
2151
+ }
2152
+ .ga-diff .ln {
2153
+ white-space: pre;
2154
+ display: block;
2155
+ }
2156
+ .ga-diff .add {
2157
+ color: #7bd88f;
2158
+ background: color-mix(in srgb, #7bd88f 10%, transparent);
2159
+ }
2160
+ .ga-diff .del {
2161
+ color: #ff6188;
2162
+ background: color-mix(in srgb, #ff6188 9%, transparent);
2163
+ }
2164
+ .ga-diff .ctx {
2165
+ color: var(--ink-3);
2166
+ }
2167
+ .ga-preview__act {
2168
+ display: flex;
2169
+ gap: 9px;
2170
+ padding: 11px 13px;
2171
+ border-top: 1px solid var(--line);
2172
+ }
2173
+ .ga-preview__act .ap {
2174
+ flex: 1;
2175
+ justify-content: center;
2176
+ }
2177
+ .ga-note {
2178
+ display: flex;
2179
+ align-items: center;
2180
+ gap: 8px;
2181
+ font-size: 12px;
2182
+ color: var(--ink-2);
2183
+ background: color-mix(in srgb, var(--accent) 8%, transparent);
2184
+ border: 1px solid var(--line);
2185
+ border-radius: var(--r-md);
2186
+ padding: 9px 12px;
2187
+ margin-top: 6px;
2188
+ }
2189
+ .ga-note svg {
2190
+ width: 14px;
2191
+ height: 14px;
2192
+ color: var(--accent);
2193
+ flex: 0 0 auto;
2194
+ }
2195
+ .ga-note code {
2196
+ font-family: var(--mono);
2197
+ font-size: .9em;
2198
+ color: var(--accent-3);
2199
+ }
2200
+ .ga-applied {
2201
+ display: flex;
2202
+ gap: 9px;
2203
+ align-items: flex-start;
2204
+ font-size: 13px;
2205
+ color: var(--ink);
2206
+ background: var(--panel-2);
2207
+ border: 1px solid var(--line-2);
2208
+ border-radius: var(--r-md);
2209
+ padding: 11px 13px;
2210
+ }
2211
+ .ga-applied svg {
2212
+ width: 16px;
2213
+ height: 16px;
2214
+ color: #7bd88f;
2215
+ flex: 0 0 auto;
2216
+ margin-top: 1px;
2217
+ }
2218
+ .ga-applied a {
2219
+ color: var(--accent);
2220
+ border-bottom: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
2221
+ }
2222
+ .ga-applied .undo {
2223
+ margin-left: auto;
2224
+ font-family: var(--sans);
2225
+ font-weight: 600;
2226
+ font-size: 12px;
2227
+ color: var(--ink-2);
2228
+ display: inline-flex;
2229
+ align-items: center;
2230
+ gap: 5px;
2231
+ white-space: nowrap;
2232
+ }
2233
+ .ga-applied .undo svg {
2234
+ width: 13px;
2235
+ height: 13px;
2236
+ color: var(--ink-2);
2237
+ }
2238
+
2239
+ .ga-foot {
2240
+ flex: 0 0 auto;
2241
+ border-top: 1px solid var(--line);
2242
+ padding: 11px 14px;
2243
+ display: flex;
2244
+ flex-direction: column;
2245
+ gap: 9px;
2246
+ }
2247
+ .ga-foot__row {
2248
+ display: flex;
2249
+ align-items: center;
2250
+ gap: 9px;
2251
+ }
2252
+ .ga-foot input {
2253
+ flex: 1;
2254
+ background: var(--bg);
2255
+ border: 1px solid var(--line-2);
2256
+ border-radius: var(--r-pill);
2257
+ outline: none;
2258
+ color: var(--ink);
2259
+ font-size: 14px;
2260
+ padding: 10px 16px;
2261
+ font-family: var(--sans);
2262
+ }
2263
+ .ga-foot input:focus {
2264
+ border-color: var(--accent);
2265
+ box-shadow: var(--glow);
2266
+ }
2267
+ .ga-foot input:disabled {
2268
+ opacity: .5;
2269
+ }
2270
+ .ga-foot .go {
2271
+ width: 38px;
2272
+ height: 38px;
2273
+ border-radius: 50%;
2274
+ background: var(--grad);
2275
+ color: #fff;
2276
+ border: 0;
2277
+ display: flex;
2278
+ align-items: center;
2279
+ justify-content: center;
2280
+ flex: 0 0 auto;
2281
+ }
2282
+ .ga-foot .go:disabled {
2283
+ opacity: .4;
2284
+ filter: grayscale(.5);
2285
+ }
2286
+ .ga-foot .go svg {
2287
+ width: 17px;
2288
+ height: 17px;
2289
+ }
2290
+ .ga-foot__hand {
2291
+ display: flex;
2292
+ align-items: center;
2293
+ justify-content: space-between;
2294
+ font-size: 11.5px;
2295
+ color: var(--ink-3);
2296
+ }
2297
+ .ga-foot__hand a {
2298
+ display: inline-flex;
2299
+ align-items: center;
2300
+ gap: 5px;
2301
+ color: var(--ink-2);
2302
+ }
2303
+ .ga-foot__hand a:hover {
2304
+ color: var(--accent);
2305
+ }
2306
+ .ga-foot__hand a svg {
2307
+ width: 12px;
2308
+ height: 12px;
2309
+ }
2310
+
2311
+ /* agent banner states (no-key / forbidden / read-only) */
2312
+ .ga-banner {
2313
+ margin: 0;
2314
+ border-radius: 0;
2315
+ border: 0;
2316
+ border-bottom: 1px solid var(--line);
2317
+ background: var(--panel-2);
2318
+ padding: 14px 16px;
2319
+ display: flex;
2320
+ gap: 11px;
2321
+ align-items: flex-start;
2322
+ }
2323
+ .ga-banner svg {
2324
+ width: 18px;
2325
+ height: 18px;
2326
+ color: var(--accent-3);
2327
+ flex: 0 0 auto;
2328
+ margin-top: 1px;
2329
+ }
2330
+ .ga-banner__t {
2331
+ font-weight: 600;
2332
+ font-size: 13.5px;
2333
+ color: var(--ink);
2334
+ margin-bottom: 3px;
2335
+ }
2336
+ .ga-banner__d {
2337
+ font-size: 12.5px;
2338
+ color: var(--ink-2);
2339
+ line-height: 1.5;
2340
+ }
2341
+ .ga-banner__d a {
2342
+ color: var(--accent);
2343
+ border-bottom: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
2344
+ }
2345
+
2346
+ /* ============ EXTENSIBILITY VIEWS ============ */
2347
+ @keyframes gtlin {
2348
+ from {
2349
+ opacity: 0;
2350
+ transform: translateY(8px);
2351
+ }
2352
+ to {
2353
+ opacity: 1;
2354
+ transform: none;
2355
+ }
2356
+ }
2357
+ .grove-timeline {
2358
+ position: relative;
2359
+ max-width: 760px;
2360
+ margin: 8px auto 0;
2361
+ padding-left: 8px;
2362
+ }
2363
+ .gtl-row {
2364
+ display: grid;
2365
+ grid-template-columns: 96px 28px 1fr;
2366
+ align-items: start;
2367
+ gap: 0;
2368
+ cursor: pointer;
2369
+ animation: gtlin .4s both;
2370
+ }
2371
+ @media (prefers-reduced-motion: reduce) {
2372
+ .gtl-row {
2373
+ animation: none;
2374
+ }
2375
+ }
2376
+ .grove-root[data-vw="mobile"] .gtl-row {
2377
+ grid-template-columns: 70px 24px 1fr;
2378
+ }
2379
+ .gtl-date {
2380
+ font-family: var(--mono);
2381
+ font-size: 11.5px;
2382
+ color: var(--ink-3);
2383
+ padding-top: 18px;
2384
+ text-align: right;
2385
+ padding-right: 12px;
2386
+ }
2387
+ .gtl-node {
2388
+ position: relative;
2389
+ display: flex;
2390
+ justify-content: center;
2391
+ padding-top: 20px;
2392
+ }
2393
+ .gtl-node::before {
2394
+ content: "";
2395
+ position: absolute;
2396
+ top: 0;
2397
+ bottom: -100%;
2398
+ width: 1px;
2399
+ background: var(--line-2);
2400
+ }
2401
+ .gtl-row:last-child .gtl-node::before {
2402
+ bottom: auto;
2403
+ height: 24px;
2404
+ }
2405
+ .gtl-node::after {
2406
+ content: "";
2407
+ position: relative;
2408
+ width: 11px;
2409
+ height: 11px;
2410
+ border-radius: 50%;
2411
+ background: var(--accent);
2412
+ border: 2px solid var(--bg);
2413
+ z-index: 1;
2414
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
2415
+ }
2416
+ .gtl-card {
2417
+ margin: 8px 0 18px;
2418
+ border: 1px solid var(--line);
2419
+ border-radius: var(--radius-shape);
2420
+ background: var(--panel);
2421
+ padding: 13px 16px;
2422
+ transition: .14s;
2423
+ }
2424
+ .gtl-row:hover .gtl-card {
2425
+ transform: translate(-2px, -2px);
2426
+ box-shadow: var(--shadow-card);
2427
+ border-color: var(--line-2);
2428
+ }
2429
+ .gtl-title {
2430
+ font-family: var(--disp);
2431
+ font-weight: 700;
2432
+ font-size: 16px;
2433
+ letter-spacing: -.01em;
2434
+ color: var(--ink);
2435
+ }
2436
+ .gtl-desc {
2437
+ font-size: 13px;
2438
+ color: var(--ink-2);
2439
+ margin-top: 4px;
2440
+ line-height: 1.45;
2441
+ }
2442
+ .gtl-tags {
2443
+ display: flex;
2444
+ gap: 6px;
2445
+ margin-top: 9px;
2446
+ }
2447
+ .gtl-tags .grove-tag {
2448
+ cursor: default;
2449
+ }
2450
+ .grove-graph {
2451
+ display: flex;
2452
+ justify-content: center;
2453
+ padding: 20px 0 10px;
2454
+ border: 1px solid var(--line);
2455
+ border-radius: var(--radius-shape);
2456
+ background: var(--panel);
2457
+ margin-top: 8px;
2458
+ }
2459
+ .grove-graph svg text {
2460
+ font-weight: 500;
2461
+ }
2462
+
2463
+ /* ============ MOBILE DRAWER ============ */
2464
+ .grove-drawer {
2465
+ position: absolute;
2466
+ inset: 0;
2467
+ z-index: 55;
2468
+ background: color-mix(in srgb, var(--bg) 50%, transparent);
2469
+ backdrop-filter: blur(5px);
2470
+ }
2471
+ .grove-drawer__panel {
2472
+ position: absolute;
2473
+ top: 0;
2474
+ left: 0;
2475
+ bottom: 0;
2476
+ width: 82%;
2477
+ max-width: 310px;
2478
+ background: var(--panel);
2479
+ border-right: 1px solid var(--line-2);
2480
+ box-shadow: var(--shadow-pop);
2481
+ overflow-y: auto;
2482
+ }
2483
+ .grove-drawer__h {
2484
+ display: flex;
2485
+ align-items: center;
2486
+ gap: 9px;
2487
+ padding: 15px 16px;
2488
+ border-bottom: 1px solid var(--line);
2489
+ }
2490
+ .grove-drawer__h .mk {
2491
+ width: 24px;
2492
+ height: 24px;
2493
+ border-radius: 24%;
2494
+ background: var(--grad);
2495
+ position: relative;
2496
+ flex: 0 0 auto;
2497
+ }
2498
+ .grove-drawer__h .t {
2499
+ font-family: var(--disp);
2500
+ font-weight: 800;
2501
+ font-size: 15px;
2502
+ color: var(--ink);
2503
+ }
2504
+ .grove-drawer__h .x {
2505
+ margin-left: auto;
2506
+ width: 30px;
2507
+ height: 30px;
2508
+ border-radius: 50%;
2509
+ border: 1px solid var(--line);
2510
+ color: var(--ink-2);
2511
+ background: transparent;
2512
+ display: flex;
2513
+ align-items: center;
2514
+ justify-content: center;
2515
+ }
2516
+ .grove-drawer__h .x svg {
2517
+ width: 15px;
2518
+ height: 15px;
2519
+ }
2520
+ .grove-drawer__nav {
2521
+ padding: 12px 12px 4px;
2522
+ display: flex;
2523
+ flex-direction: column;
2524
+ gap: 2px;
2525
+ border-bottom: 1px solid var(--line);
2526
+ }
2527
+ .grove-drawer__nav a {
2528
+ padding: 9px 12px;
2529
+ border-radius: var(--r-sm);
2530
+ font-weight: 600;
2531
+ font-size: 14.5px;
2532
+ color: var(--ink-2);
2533
+ }
2534
+ .grove-drawer__nav a[data-cur="1"] {
2535
+ background: color-mix(in srgb, var(--accent) 14%, transparent);
2536
+ color: var(--ink);
2537
+ }
2538
+ .grove-drawer .grove-sidebar {
2539
+ display: block;
2540
+ border-right: 0;
2541
+ background: transparent;
2542
+ }
2543
+
2544
+ /* Section layouts — chrome shared by a folder of entries via `_layout.mdx`
2545
+ (see src/lib/layout.ts). The section wrapper aligns its hero and "more" rail
2546
+ to the reading column while the page (<Outlet/>) keeps its own layout. */
2547
+ .grove-section {
2548
+ max-width: 1080px;
2549
+ margin: 0 auto;
2550
+ padding: 0 32px;
2551
+ }
2552
+ .grove-section > .grove-page {
2553
+ padding: 0;
2554
+ margin: 0;
2555
+ max-width: 100%;
2556
+ }
2557
+ .grove-section__hero {
2558
+ margin-bottom: 30px;
2559
+ padding-bottom: 22px;
2560
+ border-bottom: 1px solid var(--line);
2561
+ }
2562
+ .grove-section__eyebrow {
2563
+ font-family: var(--mono);
2564
+ font-size: 11px;
2565
+ text-transform: uppercase;
2566
+ letter-spacing: .12em;
2567
+ color: var(--ink-3);
2568
+ margin: 0 0 8px;
2569
+ }
2570
+ .grove-section__hero h2 {
2571
+ margin: 0;
2572
+ font-size: 30px;
2573
+ line-height: 1.1;
2574
+ }
2575
+ .grove-section__lede {
2576
+ margin: 10px 0 0;
2577
+ max-width: 60ch;
2578
+ color: var(--ink-2);
2579
+ }
2580
+ .grove-section__more {
2581
+ margin-top: 40px;
2582
+ padding-top: 22px;
2583
+ border-top: 1px solid var(--line);
2584
+ }
2585
+ .grove-section__more-h {
2586
+ font-family: var(--mono);
2587
+ font-size: 10.5px;
2588
+ text-transform: uppercase;
2589
+ letter-spacing: .1em;
2590
+ color: var(--ink-3);
2591
+ margin: 0 0 12px;
2592
+ }
2593
+ .grove-root[data-vw="mobile"] .grove-section {
2594
+ padding: 0 18px;
2595
+ }
2596
+
2597
+ /* Boot gate (R3-169) — shown only while a dispatched viewer resolves its delegated
2598
+ corpus, or when that delegation never arrived. Deliberately plain: at this point the
2599
+ corpus is not readable, so none of its theming applies. */
2600
+ .grove-boot {
2601
+ display: grid;
2602
+ place-items: center;
2603
+ min-height: 60vh;
2604
+ padding: 2rem;
2605
+ }
2606
+
2607
+ .grove-boot__msg {
2608
+ color: var(--muted, #8b8f98);
2609
+ font-family: var(--mono, ui-monospace, monospace);
2610
+ font-size: 0.9rem;
2611
+ text-align: center;
2612
+ max-width: 32rem;
2613
+ }
2614
+
2615
+ /* ============ DIRECTORY LISTING ============ */
2616
+ /* <DirectoryList/> — a folder's files as a table. Reuses the .grove-table shell so a
2617
+ listing sits in prose like any other table; the additions here are the name cell
2618
+ (icon + label + on-disk filename) and the folder-vs-file weighting. */
2619
+ .grove-dirlist {
2620
+ margin: 22px 0;
2621
+ }
2622
+ .grove-dirlist[data-state="checking"] {
2623
+ min-height: 44px;
2624
+ }
2625
+ .grove-dirlist__table {
2626
+ table-layout: auto;
2627
+ }
2628
+ .grove-dirlist__table td {
2629
+ vertical-align: top;
2630
+ }
2631
+ .gdir__namebox {
2632
+ display: flex;
2633
+ align-items: flex-start;
2634
+ gap: 10px;
2635
+ min-width: 0;
2636
+ }
2637
+ .gdir__icon {
2638
+ flex: 0 0 auto;
2639
+ display: inline-flex;
2640
+ width: 16px;
2641
+ height: 16px;
2642
+ margin-top: 2px;
2643
+ color: var(--ink-3);
2644
+ }
2645
+ .gdir__icon svg {
2646
+ width: 16px;
2647
+ height: 16px;
2648
+ }
2649
+ tr[data-kind="dir"] .gdir__icon {
2650
+ color: var(--accent);
2651
+ }
2652
+ .gdir__labels {
2653
+ display: flex;
2654
+ flex-direction: column;
2655
+ gap: 2px;
2656
+ min-width: 0;
2657
+ }
2658
+ a.gdir__link {
2659
+ font-weight: 600;
2660
+ color: var(--ink);
2661
+ text-decoration: none;
2662
+ border-bottom: 1px solid transparent;
2663
+ transition: .14s;
2664
+ }
2665
+ a.gdir__link:hover {
2666
+ color: var(--accent);
2667
+ border-bottom-color: color-mix(in srgb, var(--accent) 60%, transparent);
2668
+ }
2669
+ tr[data-kind="dir"] a.gdir__link::after {
2670
+ content: "/";
2671
+ color: var(--ink-3);
2672
+ }
2673
+ /* An asset row is listed but not navigable — muted so the absence of a link reads as
2674
+ deliberate rather than as a broken one. */
2675
+ .gdir__plain {
2676
+ color: var(--ink-2);
2677
+ }
2678
+ .gdir__file {
2679
+ font-family: var(--mono);
2680
+ font-size: 11px;
2681
+ color: var(--ink-3);
2682
+ overflow-wrap: anywhere;
2683
+ }
2684
+ .gdir__desc {
2685
+ color: var(--ink-2);
2686
+ max-width: 52ch;
2687
+ }
2688
+ .gdir__tagbox {
2689
+ display: flex;
2690
+ gap: 6px;
2691
+ flex-wrap: wrap;
2692
+ }
2693
+ .gdir__tagbox .grove-tag {
2694
+ padding: 2px 8px;
2695
+ font-size: 11px;
2696
+ }
2697
+ .gdir__updated,
2698
+ .gdir__status {
2699
+ white-space: nowrap;
2700
+ color: var(--ink-2);
2701
+ }
2702
+ .gdir__title-icon {
2703
+ display: inline-flex;
2704
+ width: .78em;
2705
+ height: .78em;
2706
+ margin-right: .28em;
2707
+ color: var(--accent);
2708
+ vertical-align: baseline;
2709
+ }
2710
+ .gdir__title-icon svg {
2711
+ width: 100%;
2712
+ height: 100%;
2713
+ }
2714
+ /* Mobile: the description is the first thing to go — the name, tags and date still
2715
+ answer "what is in this folder", and a four-column table on a phone answers nothing. */
2716
+ .grove-root[data-vw="mobile"] .gdir__desc,
2717
+ .grove-root[data-vw="mobile"] .gdir__th--description {
2718
+ display: none;
2719
+ }
2720
+ /* …and the on-disk filename with it: in a phone-width name column it wraps mid-word
2721
+ ("onboarding.md / x"), and the title above it already answers what the row is. An
2722
+ asset row is unaffected — there the filename IS the label. */
2723
+ .grove-root[data-vw="mobile"] .gdir__file {
2724
+ display: none;
2725
+ }
2726
+ .grove-dirlist__empty {
2727
+ display: flex;
2728
+ flex-direction: column;
2729
+ align-items: center;
2730
+ gap: 4px;
2731
+ padding: 40px 20px;
2732
+ border: 1px dashed var(--line-2);
2733
+ border-radius: var(--radius-shape);
2734
+ text-align: center;
2735
+ }
2736
+ .grove-dirlist__empty .gdir__icon {
2737
+ width: 26px;
2738
+ height: 26px;
2739
+ margin: 0 0 8px;
2740
+ color: var(--ink-3);
2741
+ }
2742
+ .grove-dirlist__empty .gdir__icon svg {
2743
+ width: 26px;
2744
+ height: 26px;
2745
+ }
2746
+ .grove-dirlist__empty-t {
2747
+ font-family: var(--disp);
2748
+ font-weight: 700;
2749
+ font-size: 17px;
2750
+ letter-spacing: -.01em;
2751
+ color: var(--ink);
2752
+ }
2753
+ .grove-dirlist__empty-d {
2754
+ font-family: var(--mono);
2755
+ font-size: 11.5px;
2756
+ color: var(--ink-3);
2757
+ }
2758
+
2759
+ /* Corpus component declarations that could not be loaded (R3-174). A visible, dismissible-
2760
+ free notice rather than a console line: the author of the corpus is the person who needs
2761
+ to see it, and they are reading the page, not the devtools. */
2762
+ .grove-decl-error {
2763
+ margin: 0.75rem 1rem;
2764
+ padding: 0.75rem 1rem;
2765
+ border: 1px solid color-mix(in srgb, currentColor 25%, transparent);
2766
+ border-left-width: 3px;
2767
+ border-radius: 6px;
2768
+ font-size: 0.9rem;
2769
+ opacity: 0.9;
2770
+ }
2771
+ .grove-decl-error ul {
2772
+ margin: 0.4rem 0 0;
2773
+ padding-left: 1.2rem;
2774
+ }