@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,258 @@
1
+ /* ---- Diff table ---- */
2
+ .diff-wrap {
3
+ overflow-x: auto;
4
+ max-width: 100%;
5
+ }
6
+ .diff {
7
+ border-collapse: collapse;
8
+ width: 100%;
9
+ font-family: var(--mono);
10
+ font-size: 12px;
11
+ line-height: 20px;
12
+ tab-size: 4;
13
+ }
14
+ .diff td,
15
+ .diff th {
16
+ padding: 0 10px;
17
+ vertical-align: top;
18
+ white-space: pre;
19
+ text-align: left;
20
+ }
21
+ .diff th {
22
+ font-family: var(--sans);
23
+ font-size: 10px;
24
+ font-weight: 600;
25
+ text-transform: uppercase;
26
+ letter-spacing: 0.06em;
27
+ color: var(--fg-muted);
28
+ border-bottom: 1px solid var(--line);
29
+ background: var(--panel-2);
30
+ padding: 3px 10px;
31
+ }
32
+ .diff .ln {
33
+ width: 1%;
34
+ min-width: 3.4em;
35
+ text-align: right;
36
+ color: var(--fg-dim);
37
+ border-right: 1px solid var(--line);
38
+ user-select: none;
39
+ }
40
+ .diff .gut {
41
+ width: 1%;
42
+ padding: 0 2px;
43
+ }
44
+ .diff .code {
45
+ width: 100%;
46
+ }
47
+ .diff + .diff {
48
+ border-top: 1px solid var(--ink);
49
+ }
50
+ .plus {
51
+ width: 18px;
52
+ height: 18px;
53
+ border: 1px solid var(--ink);
54
+ background: var(--accent);
55
+ color: var(--panel);
56
+ font: 700 13px/16px var(--sans);
57
+ padding: 0;
58
+ opacity: 0;
59
+ cursor: pointer;
60
+ vertical-align: middle;
61
+ box-shadow: 1px 1px 0 var(--shadow);
62
+ }
63
+ tr:hover .plus,
64
+ .plus:focus-visible {
65
+ opacity: 1;
66
+ }
67
+ .plus:disabled {
68
+ cursor: not-allowed;
69
+ }
70
+ tr.add td {
71
+ background: var(--add-bg);
72
+ }
73
+ tr.del td {
74
+ background: var(--del-bg);
75
+ }
76
+ .wa {
77
+ background: var(--add-w);
78
+ }
79
+ .wd {
80
+ background: var(--del-w);
81
+ }
82
+ tr.hunk td {
83
+ background: var(--hunk-bg);
84
+ color: var(--accent);
85
+ padding-top: 2px;
86
+ padding-bottom: 2px;
87
+ }
88
+ tr.hunk .ln {
89
+ border-right-color: transparent;
90
+ }
91
+ tr.ann td.ln:first-child {
92
+ box-shadow: inset 4px 0 0 var(--purple);
93
+ }
94
+ tr.is-target td {
95
+ box-shadow: inset 0 0 0 1px var(--accent);
96
+ }
97
+ .diff .x {
98
+ white-space: normal;
99
+ font-family: var(--sans);
100
+ font-size: var(--fs);
101
+ padding: 10px 14px;
102
+ border-top: 1px solid var(--ink);
103
+ border-bottom: 1px solid var(--ink);
104
+ line-height: var(--lh);
105
+ }
106
+ tr.annot .x {
107
+ background: var(--annot-bg);
108
+ box-shadow: inset 4px 0 0 var(--purple);
109
+ }
110
+ tr.ifind .x {
111
+ background: var(--panel);
112
+ box-shadow: inset 4px 0 0 var(--sev-major);
113
+ }
114
+ tr.ifind.decide .x {
115
+ box-shadow: inset 4px 0 0 var(--sev-blocker);
116
+ }
117
+ tr.ifind.fyi .x {
118
+ box-shadow: inset 4px 0 0 var(--sev-minor);
119
+ }
120
+ tr.thread .x {
121
+ background: var(--panel-2);
122
+ }
123
+ tr.thread.resolved .x,
124
+ tr.thread.hidden-thread .x {
125
+ padding: 6px 14px;
126
+ color: var(--fg-muted);
127
+ font-size: 12px;
128
+ }
129
+ tr.is-approx .x::before {
130
+ content: "near line ";
131
+ color: var(--fg-muted);
132
+ font-size: 11px;
133
+ }
134
+ .x .lbl {
135
+ margin-bottom: 3px;
136
+ }
137
+ .x p {
138
+ margin: 0 0 6px;
139
+ max-width: 100ch;
140
+ }
141
+ .x .sq {
142
+ margin-right: 8px;
143
+ }
144
+ .x .f-title {
145
+ font-size: 14px;
146
+ }
147
+ tr.more td {
148
+ font-family: var(--sans);
149
+ white-space: normal;
150
+ color: var(--fg-muted);
151
+ padding: 6px 14px;
152
+ background: var(--panel-2);
153
+ border-top: 1px solid var(--line);
154
+ }
155
+ tr.folded {
156
+ display: none;
157
+ }
158
+ tr.folded.shown,
159
+ tr.folded[data-code-fold] {
160
+ display: table-row;
161
+ }
162
+ /* The summary of a moved block: the one place a move is painted, so neither end reads as new code. */
163
+ tr.more.fold.move td {
164
+ background: var(--mv-bg);
165
+ box-shadow: inset 4px 0 0 var(--purple);
166
+ }
167
+ tr.move-from .ln,
168
+ tr.move-to .ln {
169
+ color: var(--purple);
170
+ }
171
+ .cmt {
172
+ display: grid;
173
+ grid-template-columns: 24px minmax(0, 1fr);
174
+ gap: 0 10px;
175
+ padding-bottom: 8px;
176
+ margin-bottom: 8px;
177
+ border-bottom: 1px solid var(--line);
178
+ }
179
+ .cmt:last-of-type {
180
+ border-bottom: 0;
181
+ margin-bottom: 0;
182
+ padding-bottom: 0;
183
+ }
184
+ .av {
185
+ width: 24px;
186
+ height: 24px;
187
+ border: 1px solid var(--ink);
188
+ font-size: 10px;
189
+ font-weight: 700;
190
+ display: grid;
191
+ place-items: center;
192
+ grid-row: span 2;
193
+ background: var(--panel);
194
+ box-shadow: 1px 1px 0 var(--shadow);
195
+ text-transform: uppercase;
196
+ }
197
+ .who {
198
+ font-size: 0.92em;
199
+ }
200
+ .cmt .prose {
201
+ font-size: 13px;
202
+ }
203
+
204
+ /* highlight.js tokens, one palette for added, deleted, and context rows */
205
+ .diff .hljs-comment,
206
+ .diff .hljs-quote {
207
+ color: var(--syn-comment);
208
+ font-style: italic;
209
+ }
210
+ .diff .hljs-keyword,
211
+ .diff .hljs-selector-tag,
212
+ .diff .hljs-literal,
213
+ .diff .hljs-doctag {
214
+ color: var(--syn-keyword);
215
+ }
216
+ .diff .hljs-string,
217
+ .diff .hljs-regexp,
218
+ .diff .hljs-addition {
219
+ color: var(--syn-string);
220
+ }
221
+ .diff .hljs-number,
222
+ .diff .hljs-built_in,
223
+ .diff .hljs-symbol {
224
+ color: var(--syn-number);
225
+ }
226
+ .diff .hljs-title,
227
+ .diff .hljs-title.function_,
228
+ .diff .hljs-section {
229
+ color: var(--syn-title);
230
+ }
231
+ .diff .hljs-title.class_,
232
+ .diff .hljs-type,
233
+ .diff .hljs-class {
234
+ color: var(--syn-type);
235
+ }
236
+ .diff .hljs-attr,
237
+ .diff .hljs-attribute,
238
+ .diff .hljs-property,
239
+ .diff .hljs-selector-class,
240
+ .diff .hljs-selector-id {
241
+ color: var(--syn-attr);
242
+ }
243
+ .diff .hljs-tag,
244
+ .diff .hljs-name,
245
+ .diff .hljs-deletion {
246
+ color: var(--syn-tag);
247
+ }
248
+ .diff .hljs-meta,
249
+ .diff .hljs-link,
250
+ .diff .hljs-bullet {
251
+ color: var(--syn-meta);
252
+ }
253
+ .diff .hljs-emphasis {
254
+ font-style: italic;
255
+ }
256
+ .diff .hljs-strong {
257
+ font-weight: 600;
258
+ }
@@ -0,0 +1,114 @@
1
+ /* ---- Header ---- */
2
+ .hdr {
3
+ background: var(--bg);
4
+ }
5
+ .hdr-bar {
6
+ min-height: 44px;
7
+ display: flex;
8
+ flex-wrap: wrap;
9
+ gap: 8px 16px;
10
+ align-items: center;
11
+ justify-content: space-between;
12
+ padding: 10px 20px;
13
+ }
14
+ .brand {
15
+ display: flex;
16
+ gap: 10px;
17
+ align-items: baseline;
18
+ font-weight: 700;
19
+ letter-spacing: 0.08em;
20
+ text-transform: uppercase;
21
+ font-size: 12px;
22
+ }
23
+ .brand .box {
24
+ border: 2px solid var(--ink);
25
+ padding: 2px 8px;
26
+ box-shadow: 3px 3px 0 var(--shadow);
27
+ color: var(--fg);
28
+ }
29
+ .hdr-actions {
30
+ display: flex;
31
+ flex-wrap: wrap;
32
+ gap: 4px 16px;
33
+ align-items: baseline;
34
+ }
35
+ .stripe {
36
+ height: 6px;
37
+ background: var(--stripe-y);
38
+ }
39
+ .hdr-title {
40
+ padding: 16px 20px 18px;
41
+ border-bottom: 1px solid var(--ink);
42
+ }
43
+ .title {
44
+ display: flex;
45
+ flex-wrap: wrap;
46
+ gap: 2px 10px;
47
+ align-items: baseline;
48
+ }
49
+ h1 .num {
50
+ font-weight: 400;
51
+ color: var(--fg-muted);
52
+ margin-right: 4px;
53
+ }
54
+ .title .cmd {
55
+ font-size: 13px;
56
+ }
57
+ .meta {
58
+ color: var(--fg-muted);
59
+ margin: 8px 0 0;
60
+ display: flex;
61
+ flex-wrap: wrap;
62
+ gap: 4px 12px;
63
+ align-items: center;
64
+ }
65
+ .meta a {
66
+ color: var(--accent);
67
+ font-weight: 600;
68
+ text-decoration: none;
69
+ }
70
+ .meta a:hover {
71
+ text-decoration: underline;
72
+ }
73
+ .meta .diffstat {
74
+ font-family: var(--mono);
75
+ font-weight: 600;
76
+ }
77
+ .touches {
78
+ margin: 8px 0 0;
79
+ display: flex;
80
+ flex-wrap: wrap;
81
+ gap: 4px 8px;
82
+ align-items: center;
83
+ font-size: 12px;
84
+ color: var(--fg-muted);
85
+ }
86
+ .progress {
87
+ display: flex;
88
+ align-items: center;
89
+ gap: 12px;
90
+ margin-top: 14px;
91
+ max-width: 640px;
92
+ }
93
+ .pline {
94
+ flex: 1;
95
+ height: 6px;
96
+ background: linear-gradient(var(--line), var(--line)) 0 50% / 100% 1px no-repeat;
97
+ }
98
+ .pline span {
99
+ display: block;
100
+ height: 100%;
101
+ background: var(--progress);
102
+ }
103
+ .ptext {
104
+ font-size: 12px;
105
+ color: var(--fg-muted);
106
+ white-space: nowrap;
107
+ }
108
+ .signoff {
109
+ display: flex;
110
+ flex-wrap: wrap;
111
+ gap: 10px 16px;
112
+ align-items: center;
113
+ margin-top: 12px;
114
+ }
@@ -0,0 +1,123 @@
1
+ /* ---- Layout: rail | main | AI chat, column lines painted once ---- */
2
+ .layout {
3
+ display: grid;
4
+ grid-template-columns: var(--rail-w) minmax(0, 1fr) var(--chat-w);
5
+ flex: 1;
6
+ align-items: start;
7
+ background:
8
+ linear-gradient(var(--ink), var(--ink)) calc(var(--rail-w) - 1px) 0 / 1px 100% no-repeat,
9
+ linear-gradient(var(--ink), var(--ink)) calc(100% - var(--chat-w)) 0 / 1px 100% no-repeat,
10
+ linear-gradient(var(--ink), var(--ink)) 100% 0 / 1px 100% no-repeat;
11
+ }
12
+ .layout.no-chat {
13
+ grid-template-columns: var(--rail-w) minmax(0, 1fr);
14
+ background: linear-gradient(var(--ink), var(--ink)) calc(var(--rail-w) - 1px) 0 / 1px 100% no-repeat;
15
+ }
16
+ .rail,
17
+ .chat {
18
+ position: sticky;
19
+ top: 0;
20
+ }
21
+ /* Sticky positioning also anchors the pane's resize handle. */
22
+ .rail {
23
+ max-height: 100vh;
24
+ overflow: auto;
25
+ padding: 14px 1px 16px 0;
26
+ }
27
+ .grp-lbl {
28
+ padding: 14px 14px 6px;
29
+ }
30
+ .tree a {
31
+ display: grid;
32
+ grid-template-columns: auto auto minmax(0, 1fr);
33
+ grid-template-areas:
34
+ "d n t"
35
+ "d n m";
36
+ column-gap: 8px;
37
+ padding: 6px 14px 6px 12px;
38
+ color: var(--fg);
39
+ text-decoration: none;
40
+ align-items: start;
41
+ font-size: 13px;
42
+ line-height: 1.35;
43
+ }
44
+ .tree a:not(:has(.dot)) {
45
+ grid-template-columns: minmax(0, 1fr);
46
+ grid-template-areas:
47
+ "t"
48
+ "m";
49
+ }
50
+ .tree a:hover {
51
+ background: var(--panel-2);
52
+ }
53
+ .tree a[aria-current] {
54
+ background: var(--panel-2);
55
+ box-shadow: inset 3px 0 0 var(--ink);
56
+ }
57
+ .tree a[aria-current] .t {
58
+ font-weight: 600;
59
+ }
60
+ .tree .n {
61
+ grid-area: n;
62
+ font-size: 11px;
63
+ color: var(--fg-muted);
64
+ padding-top: 1px;
65
+ }
66
+ .tree .t {
67
+ grid-area: t;
68
+ font-weight: 500;
69
+ }
70
+ .tree .m {
71
+ grid-area: m;
72
+ font-size: 11px;
73
+ color: var(--fg-muted);
74
+ }
75
+ .tree .dot {
76
+ grid-area: d;
77
+ width: 10px;
78
+ height: 10px;
79
+ border-radius: 50%;
80
+ border: 2px solid var(--dc, var(--fg-dim));
81
+ margin-top: 4px;
82
+ }
83
+ .tree .dot.on {
84
+ background: var(--dc);
85
+ }
86
+ .tree .dot.half {
87
+ background: radial-gradient(circle, var(--dc) 0 1.5px, transparent 2px);
88
+ }
89
+ .tree .layers a {
90
+ padding-left: 24px;
91
+ }
92
+ .tree .other a {
93
+ color: var(--fg-muted);
94
+ }
95
+ main {
96
+ min-width: 0;
97
+ padding: var(--main-pad);
98
+ }
99
+ main > * {
100
+ max-width: 1100px;
101
+ margin-left: auto;
102
+ margin-right: auto;
103
+ }
104
+ #overview {
105
+ max-width: none;
106
+ }
107
+ main.home {
108
+ padding: var(--main-pad);
109
+ max-width: 100%;
110
+ }
111
+ main.home > * {
112
+ max-width: 720px;
113
+ }
114
+ .home-form {
115
+ display: flex;
116
+ gap: 12px;
117
+ align-items: end;
118
+ flex-wrap: wrap;
119
+ }
120
+ .home-form label {
121
+ display: grid;
122
+ gap: 4px;
123
+ }
@@ -0,0 +1,152 @@
1
+ /* ---- Empty state, callouts, dialogs, footer ---- */
2
+ .lbl.divider {
3
+ padding: 24px 0 10px;
4
+ max-width: 1100px;
5
+ margin: 0 auto;
6
+ }
7
+ .center {
8
+ text-align: center;
9
+ padding: 36px 16px;
10
+ max-width: 600px;
11
+ margin: 0 auto;
12
+ }
13
+ .hint {
14
+ color: var(--fg-muted);
15
+ font-size: 0.92em;
16
+ margin: 0 0 28px;
17
+ }
18
+ .cmdbox {
19
+ display: flex;
20
+ gap: 12px;
21
+ align-items: center;
22
+ justify-content: center;
23
+ flex-wrap: wrap;
24
+ margin: 0 0 12px;
25
+ }
26
+ .cmdbox code {
27
+ font-size: 14px;
28
+ padding: 8px 12px;
29
+ border: 1px solid var(--ink);
30
+ background: var(--panel-2);
31
+ }
32
+ .drop {
33
+ display: block;
34
+ border: 2px dashed var(--ink);
35
+ background: var(--panel);
36
+ color: var(--fg);
37
+ padding: 26px;
38
+ cursor: pointer;
39
+ transition:
40
+ transform 0.08s ease-out,
41
+ box-shadow 0.08s ease-out;
42
+ }
43
+ .drop:hover {
44
+ transform: translate(-2px, -2px);
45
+ box-shadow: 4px 4px 0 var(--shadow);
46
+ }
47
+ .drop:focus-within {
48
+ outline: 3px solid var(--focus);
49
+ }
50
+ .drop .link {
51
+ color: var(--accent);
52
+ text-decoration: underline;
53
+ }
54
+ .callout {
55
+ text-align: left;
56
+ margin-top: 16px;
57
+ padding: 10px 12px;
58
+ border: 1px solid var(--ink);
59
+ background: var(--accent-bg);
60
+ box-shadow: 2px 2px 0 var(--shadow);
61
+ overflow-wrap: anywhere;
62
+ }
63
+ .callout.warn {
64
+ background: var(--warn-bg);
65
+ }
66
+ .callout .cmd {
67
+ margin-left: 4px;
68
+ }
69
+ .drop.over {
70
+ transform: translate(-2px, -2px);
71
+ box-shadow: 4px 4px 0 var(--shadow);
72
+ background: var(--accent-bg);
73
+ }
74
+ .drop-status {
75
+ min-height: 1.4em;
76
+ margin: 8px 0 0;
77
+ font-size: 13px;
78
+ color: var(--fg-muted);
79
+ }
80
+ .stale-bar {
81
+ position: sticky;
82
+ top: 0;
83
+ z-index: 3;
84
+ margin: 0 0 16px;
85
+ padding: 8px 12px;
86
+ border: 1px solid var(--ink);
87
+ background: var(--warn-bg);
88
+ box-shadow: 2px 2px 0 var(--shadow);
89
+ font-size: 13px;
90
+ }
91
+ .notice {
92
+ margin: 10px 0 0;
93
+ padding: 6px 10px;
94
+ border: 1px solid var(--ink);
95
+ background: var(--warn-bg);
96
+ font-size: 13px;
97
+ width: fit-content;
98
+ }
99
+ .banner {
100
+ padding: 8px 20px;
101
+ background: var(--warn-bg);
102
+ border-bottom: 1px solid var(--ink);
103
+ font-size: 13px;
104
+ }
105
+ .error-card .body p {
106
+ overflow-wrap: anywhere;
107
+ }
108
+ dialog {
109
+ background: var(--panel);
110
+ color: var(--fg);
111
+ border: 2px solid var(--ink);
112
+ box-shadow: 6px 6px 0 var(--shadow);
113
+ padding: 0;
114
+ max-width: 480px;
115
+ width: calc(100% - 32px);
116
+ }
117
+ dialog::backdrop {
118
+ background: rgba(30, 31, 43, 0.6);
119
+ }
120
+ dialog form {
121
+ padding: 20px;
122
+ display: grid;
123
+ gap: 16px;
124
+ }
125
+ dialog h2 {
126
+ font-size: 18px;
127
+ }
128
+ dialog .hint {
129
+ margin: 0;
130
+ }
131
+ dialog .cmdbox {
132
+ justify-content: flex-start;
133
+ margin: 0;
134
+ }
135
+ dialog .cmdbox code {
136
+ overflow-wrap: anywhere;
137
+ }
138
+ .dialog-actions {
139
+ display: flex;
140
+ justify-content: flex-end;
141
+ gap: 12px;
142
+ }
143
+ footer {
144
+ border-top: 1px solid var(--ink);
145
+ padding: 12px 20px;
146
+ color: var(--fg-muted);
147
+ font-size: 11px;
148
+ display: flex;
149
+ flex-wrap: wrap;
150
+ gap: 6px 20px;
151
+ background: var(--bg);
152
+ }
@@ -0,0 +1,80 @@
1
+ /* ---- Responsive ---- */
2
+ @media (max-width: 1360px) {
3
+ .layout {
4
+ grid-template-columns: var(--rail-w) minmax(0, 1fr);
5
+ background: linear-gradient(var(--ink), var(--ink)) calc(var(--rail-w) - 1px) 0 / 1px 100% no-repeat;
6
+ }
7
+ .chat {
8
+ grid-column: 2;
9
+ position: static;
10
+ align-self: auto;
11
+ height: auto;
12
+ border-top: 2px solid var(--ink);
13
+ padding: 0;
14
+ }
15
+ .transcript {
16
+ max-height: 50vh;
17
+ }
18
+ .handle {
19
+ display: none;
20
+ }
21
+ }
22
+ @media (max-width: 1000px) {
23
+ .chat {
24
+ grid-column: 1 / -1;
25
+ }
26
+ .layout,
27
+ .layout.no-chat {
28
+ grid-template-columns: minmax(0, 1fr);
29
+ background: none;
30
+ }
31
+ .rail {
32
+ position: static;
33
+ max-height: none;
34
+ border-bottom: 1px solid var(--ink);
35
+ padding: 8px 0 6px;
36
+ }
37
+ .tree {
38
+ display: flex;
39
+ overflow-x: auto;
40
+ gap: 4px;
41
+ padding: 0 8px;
42
+ }
43
+ .tree .grp,
44
+ .tree .layers {
45
+ display: contents;
46
+ }
47
+ .tree li {
48
+ flex: 0 0 auto;
49
+ }
50
+ .tree .m,
51
+ .grp-lbl {
52
+ display: none;
53
+ }
54
+ .tree a,
55
+ .tree a:not(:has(.dot)) {
56
+ grid-template-areas: "d n t";
57
+ grid-template-columns: auto auto minmax(0, 1fr);
58
+ align-items: center;
59
+ border: 1px solid var(--ink);
60
+ padding: 5px 10px;
61
+ box-shadow: 1px 1px 0 var(--shadow);
62
+ }
63
+ .tree .layers a {
64
+ padding-left: 10px;
65
+ }
66
+ .tree .dot {
67
+ margin-top: 0;
68
+ }
69
+ .tree a[aria-current] {
70
+ box-shadow: inset 0 -3px 0 var(--ink);
71
+ }
72
+ main {
73
+ padding: 12px 12px 32px;
74
+ }
75
+ .hdr-bar,
76
+ .hdr-title {
77
+ padding-left: 12px;
78
+ padding-right: 12px;
79
+ }
80
+ }