@vintasoftware/pr-review-canvas 0.1.0

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 (157) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +192 -0
  3. package/bin/pr-review.mjs +5 -0
  4. package/docs/reference.md +340 -0
  5. package/package.json +74 -0
  6. package/pr-review.config.example.yml +68 -0
  7. package/prompts/chat-seed.md +64 -0
  8. package/prompts/generation-format.md +255 -0
  9. package/prompts/generation-strict.md +34 -0
  10. package/prompts/generation-surfacing.md +67 -0
  11. package/prompts/layers-default.md +13 -0
  12. package/prompts/quality-standards.md +32 -0
  13. package/skills/pr-review-canvas/SKILL.md +177 -0
  14. package/src/acpx/acpx.ts +530 -0
  15. package/src/acpx/agents.ts +85 -0
  16. package/src/acpx/events.ts +216 -0
  17. package/src/acpx/ndjson.ts +69 -0
  18. package/src/acpx/preflight.ts +44 -0
  19. package/src/canvas/export.ts +95 -0
  20. package/src/canvas/import.ts +138 -0
  21. package/src/canvas/name.ts +55 -0
  22. package/src/canvas/zip.ts +123 -0
  23. package/src/chat/chat-manager.ts +389 -0
  24. package/src/chat/context.ts +160 -0
  25. package/src/chat/seed.ts +71 -0
  26. package/src/chat/threads.ts +114 -0
  27. package/src/cli.ts +199 -0
  28. package/src/commands.ts +424 -0
  29. package/src/config.ts +142 -0
  30. package/src/contract/api.ts +190 -0
  31. package/src/contract/canvas-manifest.ts +29 -0
  32. package/src/contract/chat.ts +76 -0
  33. package/src/contract/comments.ts +96 -0
  34. package/src/contract/discovery.ts +20 -0
  35. package/src/contract/generation-context.ts +77 -0
  36. package/src/contract/keys.ts +14 -0
  37. package/src/contract/links.ts +5 -0
  38. package/src/contract/mermaid-fences.ts +4 -0
  39. package/src/contract/review-artifact.ts +324 -0
  40. package/src/contract/settings.ts +144 -0
  41. package/src/contract/state.ts +46 -0
  42. package/src/contract/validation.ts +43 -0
  43. package/src/git/diff-collector.ts +151 -0
  44. package/src/git/git.ts +115 -0
  45. package/src/git/lang.ts +1 -0
  46. package/src/git/materialize.ts +79 -0
  47. package/src/git/patch-lines.ts +60 -0
  48. package/src/github/attachments.ts +288 -0
  49. package/src/github/capabilities.ts +112 -0
  50. package/src/github/comments.ts +132 -0
  51. package/src/github/gh.ts +196 -0
  52. package/src/github/post-comment.ts +104 -0
  53. package/src/github/post-review.ts +44 -0
  54. package/src/github/pr.ts +133 -0
  55. package/src/github/review-body.ts +72 -0
  56. package/src/github/threads.ts +63 -0
  57. package/src/paths.ts +10 -0
  58. package/src/project-config.ts +219 -0
  59. package/src/prompt-files.ts +26 -0
  60. package/src/review/diagram-nodes.ts +227 -0
  61. package/src/review/doctor.ts +139 -0
  62. package/src/review/glob.ts +33 -0
  63. package/src/review/install-skill.ts +107 -0
  64. package/src/review/normalize.ts +209 -0
  65. package/src/review/prepare.ts +165 -0
  66. package/src/review/prompt.ts +233 -0
  67. package/src/review/publish.ts +209 -0
  68. package/src/review/skill-command.ts +4 -0
  69. package/src/review/test-paths.ts +32 -0
  70. package/src/review/text-length.ts +15 -0
  71. package/src/review/trim-caps.ts +114 -0
  72. package/src/review/validate-folds.ts +110 -0
  73. package/src/review/validate.ts +520 -0
  74. package/src/server/app.ts +46 -0
  75. package/src/server/bundle.ts +266 -0
  76. package/src/server/capped-body.ts +62 -0
  77. package/src/server/context.ts +174 -0
  78. package/src/server/env.ts +7 -0
  79. package/src/server/errors.ts +65 -0
  80. package/src/server/html.ts +140 -0
  81. package/src/server/node-server.ts +42 -0
  82. package/src/server/routes/api.ts +256 -0
  83. package/src/server/routes/chat-routes.ts +221 -0
  84. package/src/server/routes/pages.ts +64 -0
  85. package/src/server/routes/review-routes.ts +245 -0
  86. package/src/server/routes/static.ts +114 -0
  87. package/src/server/security.ts +104 -0
  88. package/src/server/sse.ts +67 -0
  89. package/src/store/atomic-json.ts +68 -0
  90. package/src/store/canvas-store.ts +120 -0
  91. package/src/store/data-dir.ts +29 -0
  92. package/src/store/derived-store.ts +93 -0
  93. package/src/store/pr-store.ts +69 -0
  94. package/src/store/settings-store.ts +152 -0
  95. package/src/store/state-store.ts +121 -0
  96. package/static/js/anchors.js +141 -0
  97. package/static/js/api.js +542 -0
  98. package/static/js/app.js +418 -0
  99. package/static/js/ask.js +35 -0
  100. package/static/js/chat-context.js +137 -0
  101. package/static/js/chat-scroll.js +114 -0
  102. package/static/js/chat.js +843 -0
  103. package/static/js/code-folds.js +200 -0
  104. package/static/js/commands.js +110 -0
  105. package/static/js/comment-link.js +37 -0
  106. package/static/js/composer.js +241 -0
  107. package/static/js/contract-types.d.ts +59 -0
  108. package/static/js/deep-link.js +160 -0
  109. package/static/js/diagram.js +582 -0
  110. package/static/js/diff-decorations.js +204 -0
  111. package/static/js/diff-renderer.js +860 -0
  112. package/static/js/dom.js +145 -0
  113. package/static/js/download.js +52 -0
  114. package/static/js/empty-state.js +161 -0
  115. package/static/js/errors.js +135 -0
  116. package/static/js/fences.js +90 -0
  117. package/static/js/header.js +134 -0
  118. package/static/js/hunks.js +62 -0
  119. package/static/js/import-zone.js +95 -0
  120. package/static/js/interactions.js +952 -0
  121. package/static/js/keyboard.js +131 -0
  122. package/static/js/keys.js +97 -0
  123. package/static/js/lang.js +54 -0
  124. package/static/js/layers.js +596 -0
  125. package/static/js/links.js +150 -0
  126. package/static/js/markdown.js +232 -0
  127. package/static/js/mermaid-fences.js +55 -0
  128. package/static/js/nav.js +91 -0
  129. package/static/js/overview.js +85 -0
  130. package/static/js/points.js +247 -0
  131. package/static/js/progress.js +49 -0
  132. package/static/js/proposed-comment.js +133 -0
  133. package/static/js/quick-questions.js +216 -0
  134. package/static/js/regenerate.js +69 -0
  135. package/static/js/review-session.js +257 -0
  136. package/static/js/scroll-spy.js +66 -0
  137. package/static/js/selection.js +193 -0
  138. package/static/js/settings.js +206 -0
  139. package/static/js/signoff.js +171 -0
  140. package/static/js/skin.js +56 -0
  141. package/static/js/store.js +35 -0
  142. package/static/js/theme.js +56 -0
  143. package/static/js/threads.js +78 -0
  144. package/static/js/vendor.d.ts +15 -0
  145. package/static/styles/base.css +223 -0
  146. package/static/styles/chat-tools.css +130 -0
  147. package/static/styles/chat.css +140 -0
  148. package/static/styles/commands.css +156 -0
  149. package/static/styles/diff.css +258 -0
  150. package/static/styles/header.css +114 -0
  151. package/static/styles/layout.css +123 -0
  152. package/static/styles/panels.css +152 -0
  153. package/static/styles/responsive.css +80 -0
  154. package/static/styles/review-actions.css +124 -0
  155. package/static/styles/review.css +473 -0
  156. package/static/styles/skin-github.css +356 -0
  157. package/static/styles.css +14 -0
@@ -0,0 +1,124 @@
1
+ /* Selection, comments, sign-off, dismissed points, and notifications. */
2
+ tr.is-selected td {
3
+ background: var(--accent-bg);
4
+ }
5
+ tr.is-selected .ln {
6
+ box-shadow: inset 2px 0 0 var(--accent);
7
+ }
8
+ tr.sel-bar .x {
9
+ background: var(--panel-2);
10
+ display: flex;
11
+ align-items: center;
12
+ justify-content: space-between;
13
+ gap: 12px;
14
+ }
15
+ tr.sel-bar .lbl {
16
+ margin: 0;
17
+ }
18
+ .composer-box {
19
+ display: grid;
20
+ gap: 8px;
21
+ margin: 8px 0;
22
+ }
23
+ .composer-box textarea {
24
+ width: 100%;
25
+ font-family: var(--sans);
26
+ font-size: var(--fs);
27
+ line-height: var(--lh);
28
+ color: var(--fg);
29
+ background: var(--bg);
30
+ border: 1px solid var(--ink);
31
+ padding: 8px 10px;
32
+ resize: vertical;
33
+ }
34
+ .composer-box textarea:focus-visible {
35
+ outline: 2px solid var(--focus);
36
+ outline-offset: 1px;
37
+ }
38
+ .composer-actions {
39
+ display: flex;
40
+ gap: 12px;
41
+ align-items: center;
42
+ }
43
+ tr.composer .x {
44
+ background: var(--panel-2);
45
+ }
46
+ .cmt.pending {
47
+ opacity: 0.6;
48
+ }
49
+ .dismissed-list {
50
+ padding: 0 20px 16px;
51
+ }
52
+ .dismissed-line {
53
+ margin: 0;
54
+ font-size: 12px;
55
+ }
56
+ .findings.dismissed li {
57
+ opacity: 0.75;
58
+ }
59
+ .is-focused {
60
+ outline: 2px solid var(--focus);
61
+ outline-offset: 2px;
62
+ }
63
+ .toast {
64
+ position: fixed;
65
+ right: 16px;
66
+ bottom: 16px;
67
+ z-index: 30;
68
+ background: var(--panel);
69
+ border: 1px solid var(--ink);
70
+ box-shadow: 2px 2px 0 var(--shadow);
71
+ padding: 8px 12px;
72
+ font-size: 12px;
73
+ max-width: 340px;
74
+ }
75
+ .toast:empty {
76
+ display: none;
77
+ }
78
+ dialog.signoff-dialog[open] {
79
+ display: grid;
80
+ gap: 12px;
81
+ }
82
+ dialog.signoff-dialog {
83
+ max-width: 720px;
84
+ padding: 20px;
85
+ }
86
+ dialog.signoff-dialog textarea {
87
+ width: 100%;
88
+ font-family: var(--mono);
89
+ font-size: 12px;
90
+ line-height: 1.6;
91
+ color: var(--fg);
92
+ background: var(--bg);
93
+ border: 1px solid var(--ink);
94
+ padding: 10px 12px;
95
+ resize: vertical;
96
+ }
97
+ dialog.signoff-dialog .signoff-result:empty {
98
+ display: none;
99
+ }
100
+ dialog.help {
101
+ max-width: 520px;
102
+ }
103
+ table.keys {
104
+ border-collapse: collapse;
105
+ width: 100%;
106
+ font-size: 13px;
107
+ }
108
+ table.keys td {
109
+ padding: 4px 8px;
110
+ border-bottom: 1px solid var(--line);
111
+ }
112
+ table.keys td:first-child {
113
+ width: 96px;
114
+ color: var(--accent);
115
+ }
116
+
117
+ @media (prefers-reduced-motion: reduce) {
118
+ *,
119
+ *::before,
120
+ *::after {
121
+ animation: none !important;
122
+ transition: none !important;
123
+ }
124
+ }
@@ -0,0 +1,473 @@
1
+ /* ---- Panels, layers, cards ---- */
2
+ .panel,
3
+ .layer {
4
+ border: 1px solid var(--ink);
5
+ background: var(--panel);
6
+ box-shadow: 2px 2px 0 var(--shadow);
7
+ margin-bottom: var(--gap);
8
+ border-radius: var(--r);
9
+ }
10
+ .panel-h,
11
+ .layer-h {
12
+ display: flex;
13
+ flex-wrap: wrap;
14
+ gap: 6px 12px;
15
+ align-items: center;
16
+ justify-content: space-between;
17
+ padding: 10px 16px;
18
+ border-bottom: 1px solid var(--ink);
19
+ background: var(--panel-2);
20
+ }
21
+ .layer-h h2 {
22
+ font-size: 18px;
23
+ margin-right: auto;
24
+ }
25
+ .layer-h h2 .lbl {
26
+ margin-bottom: 4px;
27
+ }
28
+ .layer-h .risks {
29
+ display: inline-flex;
30
+ gap: 6px;
31
+ margin-left: 10px;
32
+ vertical-align: middle;
33
+ }
34
+ .layer-ctl {
35
+ display: flex;
36
+ flex-wrap: wrap;
37
+ gap: 6px 14px;
38
+ align-items: center;
39
+ }
40
+ /* The `>` chevron before a layer or file title is its collapse toggle. It points right when the card
41
+ is closed and turns down while it is open; the reduced-motion rule below removes the turn. */
42
+ .chev {
43
+ flex: 0 0 auto;
44
+ background: none;
45
+ border: 0;
46
+ padding: 0 2px;
47
+ margin: 0;
48
+ color: var(--ink);
49
+ font: inherit;
50
+ font-weight: 700;
51
+ line-height: 1;
52
+ cursor: pointer;
53
+ transition: transform 0.12s ease-out;
54
+ }
55
+ .chev[aria-expanded="true"] {
56
+ transform: rotate(90deg);
57
+ }
58
+ .body {
59
+ padding: 14px 16px;
60
+ }
61
+ .lbl.sub {
62
+ padding: 12px 16px 8px;
63
+ border-top: 1px solid var(--ink);
64
+ background: var(--panel-2);
65
+ border-bottom: 1px solid var(--line);
66
+ color: var(--fg);
67
+ }
68
+ .summary,
69
+ .rationale,
70
+ .prose {
71
+ max-width: 100ch;
72
+ }
73
+ .summary {
74
+ font-size: 15px;
75
+ line-height: 1.55;
76
+ }
77
+ /* A diagram sits in its own card under a header that closes it. */
78
+ .diagram {
79
+ margin-top: 14px;
80
+ border: 1px solid var(--ink);
81
+ background: var(--panel);
82
+ box-shadow: 2px 2px 0 var(--shadow);
83
+ border-radius: var(--r);
84
+ }
85
+ .diagram-h {
86
+ display: flex;
87
+ align-items: center;
88
+ gap: 6px;
89
+ padding: 6px 10px;
90
+ border-bottom: 1px solid var(--line);
91
+ }
92
+ .diagram-h .lbl {
93
+ flex: 1 1 auto;
94
+ }
95
+ /* A wide drawing scrolls sideways inside the card instead of shrinking. */
96
+ .diagram-body {
97
+ padding: 12px;
98
+ overflow-x: auto;
99
+ }
100
+ .diagram-body svg {
101
+ display: block;
102
+ max-width: none;
103
+ height: auto;
104
+ }
105
+ /* A node the model linked: clicking it jumps to the code it stands for. */
106
+ .diagram-body [data-link] {
107
+ cursor: pointer;
108
+ }
109
+ .diagram-body [data-link]:hover {
110
+ filter: brightness(1.15);
111
+ }
112
+ .diagram-body [data-link]:focus-visible {
113
+ outline: 3px solid var(--focus);
114
+ outline-offset: 2px;
115
+ }
116
+ .diagram-src {
117
+ margin: 0 0 6px;
118
+ padding: 8px 10px;
119
+ border: 1px solid var(--line);
120
+ background: var(--panel-2);
121
+ overflow-x: auto;
122
+ font-family: var(--mono);
123
+ font-size: 12px;
124
+ }
125
+ .diagram-body p.muted {
126
+ margin: 0;
127
+ }
128
+ .judgment {
129
+ margin-top: 14px;
130
+ }
131
+ .judgment .lbl {
132
+ font-size: 11px;
133
+ font-weight: 700;
134
+ letter-spacing: 0.06em;
135
+ text-transform: uppercase;
136
+ margin-bottom: 4px;
137
+ }
138
+ .prose h3,
139
+ .prose h4,
140
+ .prose h5,
141
+ .prose h6 {
142
+ margin: 14px 0 6px;
143
+ }
144
+ .prose h3:first-child {
145
+ margin-top: 0;
146
+ }
147
+ .prose h3 {
148
+ font-size: 15px;
149
+ }
150
+ .prose h4,
151
+ .prose h5,
152
+ .prose h6 {
153
+ font-size: 14px;
154
+ }
155
+ .prose ul,
156
+ .prose ol {
157
+ padding-left: 22px;
158
+ margin: 0 0 0.6em;
159
+ }
160
+ .prose ul {
161
+ list-style: square;
162
+ }
163
+ .prose ol {
164
+ list-style: decimal;
165
+ }
166
+ .prose li {
167
+ margin: 2px 0;
168
+ }
169
+ .prose blockquote {
170
+ margin: 0 0 0.6em;
171
+ padding: 2px 12px;
172
+ border-left: 3px solid var(--line-strong);
173
+ color: var(--fg-muted);
174
+ }
175
+ .prose table {
176
+ border-collapse: collapse;
177
+ margin: 0 0 0.6em;
178
+ }
179
+ .prose th,
180
+ .prose td {
181
+ border: 1px solid var(--line);
182
+ padding: 2px 8px;
183
+ text-align: left;
184
+ }
185
+ .prose hr {
186
+ border: 0;
187
+ border-top: 1px solid var(--line);
188
+ }
189
+ .prose pre {
190
+ margin: 0 0 0.6em;
191
+ border: 1px solid var(--line);
192
+ background: var(--panel-2);
193
+ }
194
+ .prose pre code {
195
+ background: none;
196
+ border: 0;
197
+ }
198
+ .prose a.loc {
199
+ font-family: var(--mono);
200
+ font-size: 0.92em;
201
+ }
202
+ .summary h3 {
203
+ font-size: 13px;
204
+ font-weight: 700;
205
+ text-transform: uppercase;
206
+ letter-spacing: 0.06em;
207
+ color: var(--fg-muted);
208
+ margin: 18px 0 6px;
209
+ }
210
+ .summary h3:first-child {
211
+ margin-top: 0;
212
+ }
213
+
214
+ .sevsum {
215
+ position: relative;
216
+ display: inline-flex;
217
+ gap: 14px;
218
+ align-items: center;
219
+ font-weight: 600;
220
+ font-size: 13px;
221
+ padding: 2px 4px;
222
+ }
223
+ .sevsum > span,
224
+ .sevsum > a {
225
+ display: inline-flex;
226
+ align-items: center;
227
+ gap: 6px;
228
+ }
229
+ .sevsum > a {
230
+ color: inherit;
231
+ text-decoration: none;
232
+ }
233
+ .sevsum > a:hover {
234
+ text-decoration: underline;
235
+ }
236
+ .sq {
237
+ display: inline-block;
238
+ width: 12px;
239
+ height: 12px;
240
+ flex: 0 0 12px;
241
+ box-sizing: border-box;
242
+ border: 1px solid var(--ink);
243
+ background: var(--sc);
244
+ vertical-align: -1px;
245
+ }
246
+ .sq.blocker,
247
+ .sq.decide {
248
+ --sc: var(--sev-blocker);
249
+ }
250
+ .sq.major,
251
+ .sq.check {
252
+ --sc: var(--sev-major);
253
+ background: radial-gradient(circle, var(--sq-mark) 0 2px, var(--sc) 2.5px);
254
+ }
255
+ .sq.minor,
256
+ .sq.fyi {
257
+ --sc: var(--sev-minor);
258
+ background: transparent;
259
+ }
260
+ .sevsum > .legend {
261
+ position: absolute;
262
+ right: 0;
263
+ top: calc(100% + 8px);
264
+ display: none;
265
+ z-index: 4;
266
+ background: var(--panel);
267
+ border: 1px solid var(--ink);
268
+ box-shadow: 2px 2px 0 var(--shadow);
269
+ padding: 6px 10px;
270
+ font-size: 12px;
271
+ font-weight: 400;
272
+ white-space: nowrap;
273
+ color: var(--fg);
274
+ }
275
+ .legend span {
276
+ display: inline-flex;
277
+ align-items: center;
278
+ gap: 6px;
279
+ margin-right: 12px;
280
+ }
281
+ .legend span:last-child {
282
+ margin-right: 0;
283
+ }
284
+ .sevsum:hover > .legend,
285
+ .sevsum:focus > .legend,
286
+ .sevsum:focus-within > .legend {
287
+ display: block;
288
+ }
289
+
290
+ .findings li {
291
+ display: grid;
292
+ grid-template-columns: auto minmax(0, 1fr);
293
+ gap: 4px 12px;
294
+ padding: 12px 16px;
295
+ border-top: 1px solid var(--line);
296
+ align-items: start;
297
+ }
298
+ .findings li:first-child {
299
+ border-top: 0;
300
+ }
301
+ .findings > li > .sq {
302
+ margin-top: 5px;
303
+ }
304
+ .findings p {
305
+ max-width: 100ch;
306
+ }
307
+ .f-title {
308
+ font-size: 15px;
309
+ font-weight: 600;
310
+ margin-bottom: 2px;
311
+ display: flex;
312
+ flex-wrap: wrap;
313
+ gap: 4px 10px;
314
+ align-items: baseline;
315
+ }
316
+ .f-title .loc {
317
+ font-weight: 400;
318
+ overflow-wrap: anywhere;
319
+ }
320
+ .findings .tbtns {
321
+ margin-top: 6px;
322
+ }
323
+ .pr-desc {
324
+ border-top: 1px solid var(--ink);
325
+ }
326
+ /* A <details> summary reads like a card header: the chevron before the title is its toggle. The row
327
+ itself keeps the default cursor and no hover background; the native <details> handles the click. */
328
+ summary {
329
+ list-style: none;
330
+ padding: 10px 16px;
331
+ font-weight: 600;
332
+ display: flex;
333
+ align-items: center;
334
+ gap: 8px;
335
+ cursor: default;
336
+ }
337
+ summary::-webkit-details-marker {
338
+ display: none;
339
+ }
340
+ summary h2 {
341
+ display: inline;
342
+ }
343
+ details[open] > summary .chev {
344
+ transform: rotate(90deg);
345
+ }
346
+ .plain li {
347
+ padding: 4px 0;
348
+ display: flex;
349
+ flex-wrap: wrap;
350
+ gap: 6px;
351
+ align-items: center;
352
+ overflow-wrap: anywhere;
353
+ }
354
+
355
+ /* test map */
356
+ .testmap {
357
+ width: 100%;
358
+ border-collapse: collapse;
359
+ font-size: 13px;
360
+ }
361
+ .testmap th {
362
+ text-align: left;
363
+ font-size: 11px;
364
+ font-weight: 600;
365
+ color: var(--fg-muted);
366
+ padding: 4px 16px;
367
+ border-bottom: 1px solid var(--line);
368
+ background: var(--panel-2);
369
+ }
370
+ .testmap td {
371
+ padding: 5px 16px;
372
+ border-bottom: 1px solid var(--line);
373
+ vertical-align: top;
374
+ }
375
+ .testmap tr:last-child td {
376
+ border-bottom: 0;
377
+ }
378
+ .testmap .st {
379
+ white-space: nowrap;
380
+ font-weight: 600;
381
+ }
382
+ .testmap .st.covered {
383
+ color: var(--ok);
384
+ }
385
+ .testmap .st.missing {
386
+ color: var(--bad);
387
+ }
388
+ .testmap .st.not-needed {
389
+ color: var(--fg-muted);
390
+ }
391
+ .layer-end {
392
+ padding: 4px 16px 16px;
393
+ }
394
+
395
+ /* file cards sit flush left under the layer's "Files" sub-header: a hairline between files and the
396
+ chevron before each path show the nesting; only the layer section carries the panel border and shadow */
397
+ .file {
398
+ background: var(--panel);
399
+ min-width: 0;
400
+ }
401
+ .file + .file {
402
+ border-top: 1px solid var(--line);
403
+ }
404
+ .files {
405
+ padding-bottom: 8px;
406
+ }
407
+ .file-h {
408
+ position: sticky;
409
+ top: 0;
410
+ z-index: 2;
411
+ display: flex;
412
+ flex-wrap: wrap;
413
+ gap: 6px 12px;
414
+ align-items: center;
415
+ padding: 8px 14px;
416
+ background: var(--panel-2);
417
+ border-bottom: 1px solid var(--line);
418
+ }
419
+ .file-h .path {
420
+ font-size: 12px;
421
+ font-weight: 700;
422
+ flex: 1 1 220px;
423
+ min-width: 0;
424
+ overflow-wrap: anywhere;
425
+ margin: 0;
426
+ }
427
+ .file-h .path .old {
428
+ color: var(--fg-muted);
429
+ font-weight: 400;
430
+ }
431
+ .file-h .status {
432
+ font-size: 11px;
433
+ color: var(--fg-muted);
434
+ }
435
+ .file-h .tbtns {
436
+ margin-left: auto;
437
+ }
438
+ .note {
439
+ display: grid;
440
+ grid-template-columns: auto minmax(0, 1fr);
441
+ gap: 12px;
442
+ padding: 10px 14px;
443
+ border-bottom: 1px solid var(--line);
444
+ background: var(--panel);
445
+ align-items: baseline;
446
+ }
447
+ .note p {
448
+ max-width: 100ch;
449
+ }
450
+ .more-hunks {
451
+ padding: 8px 14px;
452
+ font-size: 12px;
453
+ color: var(--fg-muted);
454
+ border-top: 1px solid var(--line);
455
+ }
456
+ .unavailable {
457
+ padding: 12px 14px;
458
+ color: var(--fg-muted);
459
+ font-size: 13px;
460
+ }
461
+ .deferred {
462
+ display: flex;
463
+ flex-wrap: wrap;
464
+ gap: 8px 14px;
465
+ align-items: baseline;
466
+ padding: 12px 14px;
467
+ }
468
+ .deferred .hint {
469
+ margin: 0;
470
+ }
471
+
472
+ .prose img { max-width: 100%; height: auto; }
473
+ img.av { object-fit: cover; border-radius: 50%; }