bottleship 0.1.0-prototype.0 → 0.1.0-prototype.2

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 (167) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +118 -113
  3. package/dist/src/boxes.d.ts +41 -39
  4. package/dist/src/boxes.js +181 -179
  5. package/dist/src/cli.js +298 -83
  6. package/dist/src/config.d.ts +3 -6
  7. package/dist/src/config.js +19 -85
  8. package/dist/src/init.d.ts +3 -4
  9. package/dist/src/init.js +120 -205
  10. package/dist/src/local.d.ts +8 -0
  11. package/dist/src/local.js +24 -0
  12. package/dist/src/onboard.d.ts +5 -0
  13. package/dist/src/onboard.js +25 -0
  14. package/dist/src/paths.d.ts +0 -1
  15. package/dist/src/paths.js +0 -1
  16. package/dist/src/provider.d.ts +16 -0
  17. package/dist/src/provider.js +81 -0
  18. package/dist/src/repo.d.ts +21 -0
  19. package/dist/src/repo.js +75 -0
  20. package/dist/src/review/comments.d.ts +66 -0
  21. package/dist/src/review/comments.js +344 -0
  22. package/dist/src/review/contract.d.ts +82 -0
  23. package/dist/src/review/contract.js +189 -0
  24. package/dist/src/review/github.d.ts +120 -0
  25. package/dist/src/review/github.js +160 -0
  26. package/dist/src/review/local.d.ts +14 -0
  27. package/dist/src/review/local.js +70 -0
  28. package/dist/src/review/loop.d.ts +12 -0
  29. package/dist/src/review/loop.js +119 -0
  30. package/dist/src/review/pr.d.ts +14 -0
  31. package/dist/src/review/pr.js +68 -0
  32. package/dist/src/review/prompt.d.ts +15 -0
  33. package/dist/src/review/prompt.js +48 -0
  34. package/dist/src/review/serve.d.ts +1 -0
  35. package/dist/src/review/serve.js +8 -0
  36. package/dist/src/review/server.d.ts +14 -0
  37. package/dist/src/review/server.js +484 -0
  38. package/dist/src/review/setting-up.d.ts +4 -0
  39. package/dist/src/review/setting-up.js +74 -0
  40. package/dist/src/review/start.d.ts +32 -0
  41. package/dist/src/review/start.js +140 -0
  42. package/dist/src/review/target.d.ts +20 -0
  43. package/dist/src/review/target.js +66 -0
  44. package/dist/src/review/template.d.ts +3 -0
  45. package/dist/src/review/template.js +13 -0
  46. package/dist/src/review/terminal.d.ts +4 -0
  47. package/dist/src/review/terminal.js +91 -0
  48. package/dist/src/secrets.d.ts +1 -0
  49. package/dist/src/secrets.js +11 -1
  50. package/dist/src/types.d.ts +1 -71
  51. package/dist/src/ui.d.ts +6 -1
  52. package/dist/src/ui.js +22 -23
  53. package/dist/src/util.d.ts +11 -0
  54. package/dist/src/util.js +40 -0
  55. package/package.json +7 -14
  56. package/presets/agents/claude.json +1 -5
  57. package/presets/agents/codex.json +1 -10
  58. package/presets/agents/cursor.json +1 -9
  59. package/presets/agents/opencode.json +1 -14
  60. package/presets/providers/docker/create +12 -0
  61. package/presets/providers/docker/destroy +2 -0
  62. package/presets/providers/docker/exec +2 -0
  63. package/presets/providers/docker/list +4 -0
  64. package/presets/providers/docker/status +2 -0
  65. package/presets/providers/docker/url +4 -0
  66. package/review-app/KIT.md +106 -0
  67. package/review-app/WRITING.md +93 -0
  68. package/review-app/examples/rply-16.tsx +98 -0
  69. package/review-app/index.html +15 -0
  70. package/review-app/package-lock.json +2539 -0
  71. package/review-app/package.json +24 -0
  72. package/review-app/playground/fixtures/excalidraw-12602/data/box.json +1 -0
  73. package/review-app/playground/fixtures/excalidraw-12602/data/pr.diff +91 -0
  74. package/review-app/playground/fixtures/excalidraw-12602/data/pr.json +62 -0
  75. package/review-app/playground/fixtures/excalidraw-12602/data/review-comments.json +44 -0
  76. package/review-app/playground/fixtures/excalidraw-12602/events.json +1 -0
  77. package/review-app/playground/fixtures/excalidraw-12602/files/shots/base-ar-zoom.png +0 -0
  78. package/review-app/playground/fixtures/excalidraw-12602/files/shots/base-en-US-zoom.png +0 -0
  79. package/review-app/playground/fixtures/excalidraw-12602/files/shots/base-he-IL-zoom.png +0 -0
  80. package/review-app/playground/fixtures/excalidraw-12602/files/shots/base-he-dark.png +0 -0
  81. package/review-app/playground/fixtures/excalidraw-12602/files/shots/base-he-hover.png +0 -0
  82. package/review-app/playground/fixtures/excalidraw-12602/files/shots/base-he-page.png +0 -0
  83. package/review-app/playground/fixtures/excalidraw-12602/files/shots/base-he-tip.png +0 -0
  84. package/review-app/playground/fixtures/excalidraw-12602/files/shots/base-he-zen.png +0 -0
  85. package/review-app/playground/fixtures/excalidraw-12602/files/shots/head-ar-zoom.png +0 -0
  86. package/review-app/playground/fixtures/excalidraw-12602/files/shots/head-en-US-zoom.png +0 -0
  87. package/review-app/playground/fixtures/excalidraw-12602/files/shots/head-he-IL-zoom.png +0 -0
  88. package/review-app/playground/fixtures/excalidraw-12602/files/shots/head-he-dark.png +0 -0
  89. package/review-app/playground/fixtures/excalidraw-12602/files/shots/head-he-hover.png +0 -0
  90. package/review-app/playground/fixtures/excalidraw-12602/files/shots/head-he-page.png +0 -0
  91. package/review-app/playground/fixtures/excalidraw-12602/files/shots/head-he-tip.png +0 -0
  92. package/review-app/playground/fixtures/excalidraw-12602/files/shots/head-he-zen.png +0 -0
  93. package/review-app/playground/fixtures/excalidraw-12602/instances.json +1 -0
  94. package/review-app/playground/fixtures/excalidraw-12602/review.tsx +103 -0
  95. package/review-app/playground/fixtures/rply-16/data/box.json +1 -0
  96. package/review-app/playground/fixtures/rply-16/data/hooks.diff +28 -0
  97. package/review-app/playground/fixtures/rply-16/data/pr.diff +114 -0
  98. package/review-app/playground/fixtures/rply-16/data/pr.json +68 -0
  99. package/review-app/playground/fixtures/rply-16/data/review-comments.json +1 -0
  100. package/review-app/playground/fixtures/rply-16/events.json +156 -0
  101. package/review-app/playground/fixtures/rply-16/instances.json +1 -0
  102. package/review-app/playground/fixtures/rply-16/review.tsx +98 -0
  103. package/review-app/playground/gallery.tsx +127 -0
  104. package/review-app/playground/index.html +15 -0
  105. package/review-app/playground/main.tsx +26 -0
  106. package/review-app/playground/mock.ts +215 -0
  107. package/review-app/playground/playground.css +18 -0
  108. package/review-app/playground/vite.config.ts +32 -0
  109. package/review-app/scripts/check.cjs +47 -0
  110. package/review-app/scripts/clip.cjs +104 -0
  111. package/review-app/scripts/shot.cjs +66 -0
  112. package/review-app/src/App.tsx +132 -0
  113. package/review-app/src/data/box.json +1 -0
  114. package/review-app/src/data/hooks.diff +28 -0
  115. package/review-app/src/data/pr.diff +114 -0
  116. package/review-app/src/data/pr.json +68 -0
  117. package/review-app/src/data/review-comments.json +1 -0
  118. package/review-app/src/kit/agent.tsx +287 -0
  119. package/review-app/src/kit/chapter.tsx +178 -0
  120. package/review-app/src/kit/code.tsx +217 -0
  121. package/review-app/src/kit/comments.tsx +377 -0
  122. package/review-app/src/kit/finish.tsx +274 -0
  123. package/review-app/src/kit/flow.tsx +184 -0
  124. package/review-app/src/kit/index.ts +10 -0
  125. package/review-app/src/kit/kit.css +696 -0
  126. package/review-app/src/kit/live.ts +91 -0
  127. package/review-app/src/kit/media.tsx +348 -0
  128. package/review-app/src/kit/overview.tsx +161 -0
  129. package/review-app/src/kit/pr.ts +100 -0
  130. package/review-app/src/kit/pullrequest.tsx +298 -0
  131. package/review-app/src/kit/review.ts +74 -0
  132. package/review-app/src/kit/theme.ts +30 -0
  133. package/review-app/src/kit/ui.tsx +127 -0
  134. package/review-app/src/main.tsx +6 -0
  135. package/review-app/src/review.tsx +22 -0
  136. package/review-app/tsconfig.json +17 -0
  137. package/review-app/vite.config.ts +12 -0
  138. package/dist/presets/providers/command.d.ts +0 -3
  139. package/dist/presets/providers/command.js +0 -39
  140. package/dist/presets/providers/daytona.d.ts +0 -3
  141. package/dist/presets/providers/daytona.js +0 -173
  142. package/dist/presets/providers/docker.d.ts +0 -3
  143. package/dist/presets/providers/docker.js +0 -31
  144. package/dist/presets/providers/e2b.d.ts +0 -3
  145. package/dist/presets/providers/e2b.js +0 -124
  146. package/dist/presets/providers/exe.d.ts +0 -3
  147. package/dist/presets/providers/exe.js +0 -28
  148. package/dist/presets/providers/http.example.d.ts +0 -3
  149. package/dist/presets/providers/http.example.js +0 -47
  150. package/dist/presets/providers/local.d.ts +0 -3
  151. package/dist/presets/providers/local.js +0 -52
  152. package/dist/presets/providers/modal.d.ts +0 -3
  153. package/dist/presets/providers/modal.js +0 -117
  154. package/dist/presets/providers/ssh.d.ts +0 -3
  155. package/dist/presets/providers/ssh.js +0 -49
  156. package/dist/presets/providers/util.d.ts +0 -13
  157. package/dist/presets/providers/util.js +0 -102
  158. package/presets/providers/command.ts +0 -43
  159. package/presets/providers/daytona.ts +0 -181
  160. package/presets/providers/docker.ts +0 -38
  161. package/presets/providers/e2b.ts +0 -130
  162. package/presets/providers/exe.ts +0 -35
  163. package/presets/providers/http.example.ts +0 -64
  164. package/presets/providers/local.ts +0 -56
  165. package/presets/providers/modal.ts +0 -121
  166. package/presets/providers/ssh.ts +0 -54
  167. package/presets/providers/util.ts +0 -112
@@ -0,0 +1,696 @@
1
+ /* The review's look: neutral surfaces, hairlines, color only for status. Light or dark per data-theme (theme.ts). */
2
+ :root {
3
+ --bg: #f4f4f5; --panel: #fafafa; --card: #ffffff; --raised: #efeff1; --hover: rgba(0,0,0,.035); --press: rgba(0,0,0,.06);
4
+ --line: rgba(0,0,0,.075); --line-2: rgba(0,0,0,.12);
5
+ --text: #1b1b1f; --text-2: #67676f; --text-3: #a1a1a9;
6
+ --green: #2f9e64; --red: #d14343; --amber: #b7791f;
7
+ --green-bg: rgba(47,158,100,.085); --red-bg: rgba(209,67,67,.075); --amber-bg: rgba(183,121,31,.09);
8
+ --add: rgba(47,158,100,.09); --del: rgba(209,67,67,.08); --sel: rgba(0,0,0,.05);
9
+ --btn: #1b1b1f; --btn-text: #ffffff;
10
+ --shadow: 0 1px 2px rgba(0,0,0,.04), 0 8px 24px rgba(0,0,0,.05);
11
+ --shadow-float: 0 1px 2px rgba(0,0,0,.06), 0 12px 32px rgba(0,0,0,.12);
12
+ --kw: #8b5cf6; --str: #16803c; --num: #c2410c; --fn: #2563eb; --com: #a1a1a9; --ty: #0e7490;
13
+ --sans: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
14
+ --mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;
15
+ --r-sm: 6px; --r: 8px; --r-lg: 12px;
16
+ /* type: six sizes, two weights, three line heights; add one only when a page needs it */
17
+ --fs-xl: 24px; --fs-lg: 16px; --fs: 14px; --fs-sm: 13px; --fs-mono: 12px; --fs-xs: 10px;
18
+ --lh-tight: 1.25; --lh: 1.5; --lh-text: 1.6; --lh-code: 1.7;
19
+ --ls: -0.006em; --ls-lg: -0.012em; --ls-xl: -0.02em;
20
+ --ease: cubic-bezier(0.23, 1, 0.32, 1);
21
+ color-scheme: light;
22
+ }
23
+ :root[data-theme="dark"] {
24
+ --bg: #0c0c0d; --panel: #101012; --card: #141416; --raised: #19191c; --hover: rgba(255,255,255,.035); --press: rgba(255,255,255,.06);
25
+ --line: rgba(255,255,255,.065); --line-2: rgba(255,255,255,.1);
26
+ --text: #e8e8eb; --text-2: #96969d; --text-3: #5f5f66;
27
+ --green: #4cb782; --red: #eb5d5d; --amber: #d9a441;
28
+ --green-bg: rgba(76,183,130,.1); --red-bg: rgba(235,93,93,.1); --amber-bg: rgba(217,164,65,.1);
29
+ --add: rgba(76,183,130,.085); --del: rgba(235,93,93,.085); --sel: rgba(255,255,255,.06);
30
+ --btn: #e8e8eb; --btn-text: #101012;
31
+ --shadow: 0 0 0 1px rgba(255,255,255,.03), 0 12px 32px rgba(0,0,0,.4);
32
+ --shadow-float: 0 0 0 1px rgba(255,255,255,.04), 0 16px 40px rgba(0,0,0,.55);
33
+ --kw: #c4a7e7; --str: #a6d189; --num: #ef9f76; --fn: #8caaee; --com: #5f5f66; --ty: #81c8be;
34
+ color-scheme: dark;
35
+ }
36
+
37
+ /* base */
38
+ * { box-sizing: border-box; }
39
+ [hidden] { display: none !important; }
40
+ html, body { margin: 0; height: 100%; }
41
+ body { background: var(--bg); color: var(--text); font: 400 var(--fs)/var(--lh) var(--sans); font-feature-settings: "cv11", "ss01", "ss03"; letter-spacing: var(--ls); -webkit-font-smoothing: antialiased; display: grid; grid-template-columns: 248px minmax(0, 1fr); overflow: hidden; }
42
+ #root { display: contents; }
43
+ main { height: 100vh; min-width: 0; display: flex; flex-direction: column; }
44
+ main > .main-row { flex: 1; min-height: 0; display: flex; }
45
+ main .content { flex: 1; min-width: 0; overflow: auto; }
46
+ /* the agent's panel, when docked */
47
+ .dock { flex: none; display: flex; width: 380px; border-left: 1px solid var(--line); background: var(--card); }
48
+ .dock:empty { display: none; }
49
+ button { font: inherit; color: inherit; }
50
+ a { color: inherit; }
51
+ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 1ms !important; transition-duration: 1ms !important; } }
52
+ @keyframes rise { from { opacity: 0; transform: translateY(6px); } }
53
+ @keyframes fade { from { opacity: 0; } }
54
+ @keyframes pulse { from { opacity: .35; } }
55
+ @keyframes pop { from { opacity: 0; transform: scale(.97) translateY(-2px); } }
56
+ svg.i { width: 14px; height: 14px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
57
+ .view { animation: rise 260ms var(--ease); }
58
+ .plus { color: var(--green); } .minus { color: var(--red); }
59
+ .empty { color: var(--text-3); padding: 40px; }
60
+
61
+ /* type */
62
+ .title { font-size: var(--fs-xl); line-height: var(--lh-tight); font-weight: 500; letter-spacing: var(--ls-xl); margin: 0; text-wrap: balance; }
63
+ .meta { display: flex; align-items: center; gap: 6px 20px; color: var(--text-2); font-size: var(--fs-sm); margin-top: 12px; flex-wrap: wrap; }
64
+ .meta .who { display: inline-flex; align-items: center; gap: 7px; }
65
+ .refs { display: inline-flex; align-items: center; gap: 7px; font: var(--fs-mono) var(--mono); letter-spacing: 0; color: var(--text-3); min-width: 0; }
66
+ .refs > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
67
+ .refs-arrow { width: 14px; height: 8px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; }
68
+ .avatar { width: 18px; height: 18px; border-radius: 50%; background: var(--raised); border: 1px solid var(--line-2); display: inline-flex; align-items: center; justify-content: center; font-size: var(--fs-xs); font-weight: 500; color: var(--text-2); }
69
+ .lead { font-size: var(--fs-lg); line-height: var(--lh-text); color: var(--text); margin: 0; letter-spacing: var(--ls-lg); text-wrap: pretty; }
70
+ .prose { font-size: var(--fs); line-height: var(--lh-text); color: var(--text-2); margin: 0; text-wrap: pretty; }
71
+ .prose p { margin: 0 0 10px; } .prose p:last-child { margin: 0; }
72
+ .prose code, .lead code, .row code, .ba code, .ot code, figcaption code, .fig-title code { font-family: var(--mono); font-size: .9em; letter-spacing: 0; padding: 1px 4px; border-radius: 4px; background: var(--raised); }
73
+ .label { font-size: var(--fs-sm); font-weight: 500; color: var(--text-2); margin: 0 0 12px; display: flex; align-items: baseline; gap: 8px; }
74
+ .label .c { color: var(--text-3); font-weight: 400; }
75
+ .label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
76
+
77
+ /* a key that does the same as the control next to it */
78
+ kbd { flex: none; display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 4px; border-radius: 4px; background: var(--raised); font: 500 var(--fs-xs) var(--mono); color: var(--text-3); }
79
+
80
+ /* controls */
81
+ .btn { display: inline-flex; align-items: center; gap: 7px; height: 32px; padding: 0 12px; border-radius: var(--r); border: 1px solid var(--line-2); background: var(--card); cursor: pointer; font-size: var(--fs-sm); font-weight: 500; white-space: nowrap; transition: background-color 140ms ease-out, border-color 140ms ease-out; }
82
+ .btn:hover { background: var(--raised); }
83
+ .btn:active { transform: scale(.98); }
84
+ .btn.primary { background: var(--btn); border-color: transparent; color: var(--btn-text); }
85
+ .btn.primary:hover { background: color-mix(in srgb, var(--btn) 86%, var(--bg)); }
86
+ .btn.ghost { border-color: transparent; background: transparent; color: var(--text-2); }
87
+ .btn.ghost:hover { color: var(--text); background: var(--hover); }
88
+ .btn.sm { height: 28px; padding: 0 9px; }
89
+ .btn:disabled { opacity: .5; cursor: default; transform: none; }
90
+ .btn:focus-visible, .row:focus-visible, .media:focus-visible, .rail button:focus-visible { outline: 2px solid var(--text-3); outline-offset: 2px; }
91
+ .modes { position: relative; display: inline-flex; gap: 2px; flex: none; padding: 3px; border-radius: var(--r); background: var(--raised); }
92
+ .modes .pill { position: absolute; top: 3px; left: 0; height: calc(100% - 6px); border-radius: calc(var(--r) - 3px); background: var(--card); box-shadow: 0 1px 2px rgba(0,0,0,.08); pointer-events: none; }
93
+ .modes .pill.moved { transition: transform 260ms var(--ease), width 260ms var(--ease); }
94
+ .modes button { all: unset; position: relative; box-sizing: border-box; height: 24px; padding: 0 9px; display: inline-flex; align-items: center; border-radius: calc(var(--r) - 3px); font-size: var(--fs-sm); font-weight: 500; color: var(--text-3); cursor: pointer; white-space: nowrap; transition: color 200ms ease-out; }
95
+ .modes button:hover { color: var(--text-2); }
96
+ .modes button[aria-pressed="true"] { color: var(--text); }
97
+ .modes button:focus-visible { outline: 2px solid var(--text-3); outline-offset: 1px; }
98
+ .lamp { width: 7px; height: 7px; border-radius: 50%; background: var(--text-3); flex: none; transition: background-color 240ms ease-out; }
99
+
100
+ /* a quiet text link: where an item leads, e.g. its chapter */
101
+ .link { all: unset; flex: none; cursor: pointer; font-size: var(--fs-sm); color: var(--text-2); white-space: nowrap; text-decoration: underline; text-decoration-color: currentColor; text-decoration-thickness: 1px; text-underline-offset: 3px; transition: color 140ms ease-out; }
102
+ .link:hover { color: var(--text); }
103
+ .link:focus-visible { outline: 2px solid var(--text-3); outline-offset: 2px; border-radius: 3px; }
104
+
105
+ /* rows: files, findings, claims; all the same quiet card */
106
+ .rows { display: flex; flex-direction: column; gap: 2px; }
107
+ .row { display: flex; align-items: center; gap: 10px; min-height: 42px; padding: 9px 14px; border-radius: 3px; background: var(--card); text-align: left; width: 100%; transition: background-color 140ms ease-out, border-color 140ms ease-out; }
108
+ .row:first-child { border-top-left-radius: var(--r-lg); border-top-right-radius: var(--r-lg); }
109
+ .row:last-child { border-bottom-left-radius: var(--r-lg); border-bottom-right-radius: var(--r-lg); }
110
+ .row .grow { flex: 1; min-width: 0; }
111
+ .row.tall { align-items: flex-start; padding: 12px 14px; }
112
+ .row p { margin: 0; }
113
+ .row .sub { color: var(--text-2); font-size: var(--fs-sm); margin-top: 3px; }
114
+ .fname { font-weight: 500; white-space: nowrap; }
115
+ .fpath { color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: var(--fs-sm); }
116
+ .stat { font: var(--fs-mono) var(--mono); letter-spacing: 0; white-space: nowrap; display: inline-flex; gap: 6px; }
117
+ .fmark { width: 14px; height: 14px; flex: none; display: inline-flex; align-items: center; justify-content: center; color: var(--text-3); }
118
+ .fmark svg { width: 12px; height: 12px; stroke-width: 2; }
119
+ .fmark.added { color: var(--green); } .fmark.deleted { color: var(--red); } .fmark.renamed { color: var(--text-2); }
120
+ .sbar { display: inline-flex; gap: 2px; flex: none; }
121
+ .sbar i { width: 4px; height: 8px; border-radius: 1px; background: var(--line-2); }
122
+ .sbar i.a { background: var(--green); } .sbar i.d { background: var(--red); }
123
+ /* lists of findings and claims: one card, hairline dividers, a small mark per item */
124
+ .li { all: unset; box-sizing: border-box; display: flex; align-items: flex-start; gap: 12px; width: 100%; padding: 13px 16px 14px; }
125
+ .li.file-li { align-items: center; gap: 10px; padding: 11px 16px; }
126
+ .file-list { display: flex; flex-direction: column; gap: 2px; }
127
+ .file-list .li { background: var(--card); border-radius: 3px; }
128
+ .file-list .li:first-child { border-top-left-radius: var(--r-lg); border-top-right-radius: var(--r-lg); }
129
+ .file-list .li:last-child { border-bottom-left-radius: var(--r-lg); border-bottom-right-radius: var(--r-lg); }
130
+ button.li.file-li { cursor: pointer; text-align: left; transition: background-color 120ms ease-out; }
131
+ button.li.file-li:focus-visible { outline: 2px solid var(--text-3); outline-offset: -2px; }
132
+ @media (hover: hover) and (pointer: fine) { button.li.file-li:hover { background: var(--hover); } }
133
+ .files-more { color: var(--text-2); font-size: var(--fs-sm); }
134
+ .mark { width: 18px; height: 18px; border-radius: 50%; flex: none; margin-top: 2px; display: inline-flex; align-items: center; justify-content: center; }
135
+ .mark svg { width: 11px; height: 11px; stroke-width: 2; }
136
+ .mark.ok { background: var(--green-bg); color: var(--green); }
137
+ .mark.fail { background: var(--red-bg); color: var(--red); }
138
+ .mark.neutral { background: var(--amber-bg); color: var(--amber); }
139
+ /* findings: titles only, one opens at a time */
140
+ .acc-list { display: flex; flex-direction: column; gap: 2px; }
141
+ .acc { border-radius: 3px; background: var(--card); overflow: hidden; }
142
+ .acc:first-child { border-top-left-radius: var(--r-lg); border-top-right-radius: var(--r-lg); }
143
+ .acc:last-child { border-bottom-left-radius: var(--r-lg); border-bottom-right-radius: var(--r-lg); }
144
+ .acc-head { all: unset; box-sizing: border-box; display: flex; align-items: center; gap: 10px; width: 100%; padding: 12px 16px; }
145
+ button.acc-head { cursor: pointer; transition: background-color 120ms ease-out; }
146
+ button.acc-head:focus-visible { outline: 2px solid var(--text-3); outline-offset: -2px; }
147
+ @media (hover: hover) and (pointer: fine) { button.acc-head:hover { background: var(--hover); } }
148
+ .acc-title { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
149
+ .acc[data-open] .acc-title { white-space: normal; }
150
+ .acc-chev { display: inline-flex; width: 14px; flex: none; color: var(--text-3); transition: transform 150ms var(--ease); }
151
+ .acc[data-open] .acc-chev { transform: rotate(90deg); }
152
+ .acc-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 160ms var(--ease); }
153
+ .acc[data-open] .acc-body { grid-template-rows: 1fr; }
154
+ .acc-body > div { overflow: hidden; }
155
+ .acc-inner { padding: 0 16px 14px 40px; display: flex; flex-direction: column; align-items: flex-start; gap: 12px; opacity: 0; transform: translateY(-4px); transition: opacity 120ms ease-out, transform 160ms var(--ease); }
156
+ .acc[data-open] .acc-inner { opacity: 1; transform: none; }
157
+ /* claims: one that did not hold is a finding, tagged; the ones that held are a quiet line under the list */
158
+ .claim-q { font-style: normal; }
159
+ .claim-by { font-size: var(--fs-sm); color: var(--text-3); }
160
+ .acc-title .claim-by { margin-left: 4px; }
161
+ /* a chip: a short status, e.g. a claim's verdict or a step's state */
162
+ .chip { flex: none; display: inline-flex; align-items: center; height: 20px; padding: 0 7px; border-radius: 5px; font-size: var(--fs-xs); font-weight: 500; letter-spacing: .01em; white-space: nowrap; background: var(--raised); color: var(--text-2); }
163
+ .chip.fail { background: var(--red-bg); color: var(--red); } .chip.ok, .chip.done { background: var(--green-bg); color: var(--green); } .chip.merged { background: color-mix(in srgb, #8b5cf6 12%, transparent); color: #8b5cf6; } .chip.neutral { background: var(--amber-bg); color: var(--amber); }
164
+ .chip.run { animation: pulse 700ms ease-in-out infinite alternate; }
165
+ .held { margin-top: 10px; }
166
+ .held-none { margin: 10px 0 0; font-size: var(--fs-sm); color: var(--text-3); }
167
+ .held-btn { all: unset; box-sizing: border-box; display: inline-flex; align-items: center; gap: 8px; padding: 4px 6px; margin-left: -6px; border-radius: var(--r-sm); font-size: var(--fs-sm); color: var(--text-3); cursor: pointer; transition: color 120ms ease-out, background-color 120ms ease-out; }
168
+ .held-btn:focus-visible { outline: 2px solid var(--text-3); outline-offset: 2px; }
169
+ @media (hover: hover) and (pointer: fine) { .held-btn:hover { color: var(--text-2); background: var(--hover); } }
170
+ .held[data-open] .acc-chev { transform: rotate(90deg); }
171
+ .held[data-open] .acc-body { grid-template-rows: 1fr; }
172
+ .held-ok { display: inline-flex; flex: none; color: var(--green); }
173
+ .held-ok svg { width: 12px; height: 12px; stroke-width: 2; }
174
+ .held-list { list-style: none; margin: 0; padding: 8px 0 0 22px; display: flex; flex-direction: column; gap: 8px; opacity: 0; transform: translateY(-4px); transition: opacity 120ms ease-out, transform 160ms var(--ease); }
175
+ .held[data-open] .held-list { opacity: 1; transform: none; }
176
+ .held-list li { display: flex; align-items: flex-start; gap: 10px; font-size: var(--fs-sm); line-height: var(--lh); }
177
+ .held-list .held-ok { margin-top: 3px; }
178
+ .held-text { flex: 1; min-width: 0; color: var(--text-2); }
179
+ .iname { display: inline-flex; align-items: baseline; gap: 6px; min-width: 0; white-space: nowrap; overflow: hidden; }
180
+ .iname b { font-weight: 500; color: var(--text); }
181
+ .iname span { color: var(--text-3); overflow: hidden; text-overflow: ellipsis; }
182
+
183
+ /* the rail: the PR, then every stop of the review */
184
+ .rail { display: flex; flex-direction: column; gap: 2px; padding: 16px 10px 12px; border-right: 1px solid var(--line); background: var(--panel); overflow: auto; min-height: 0; height: 100vh; }
185
+ .rail .pr { padding: 6px 10px 18px; display: flex; flex-direction: column; gap: 6px; }
186
+ .rail .pr .r { font-size: var(--fs-sm); color: var(--text-3); display: flex; align-items: center; gap: 6px; text-decoration: none; }
187
+ .rail .pr a.r:hover { color: var(--text-2); }
188
+ .rail .pr b { font-weight: 500; font-size: var(--fs-sm); text-wrap: balance; }
189
+ .rail .sh { font-size: var(--fs-sm); color: var(--text-3); padding: 14px 10px 6px; }
190
+ .rail button { all: unset; box-sizing: border-box; cursor: pointer; display: flex; gap: 10px; align-items: flex-start; padding: 6px 10px; border-radius: 7px; font-size: var(--fs-sm); color: var(--text-2); transition: background-color 140ms ease-out, color 140ms ease-out; }
191
+ .rail button:hover { background: var(--hover); color: var(--text); }
192
+ .rail button[aria-current="true"] { background: var(--press); color: var(--text); }
193
+ .rail .mk { width: 16px; height: 16px; flex: none; margin-top: 1px; border-radius: 50%; border: 1px solid var(--line-2); display: inline-flex; align-items: center; justify-content: center; font: var(--fs-xs) var(--mono); letter-spacing: 0; color: var(--text-3); }
194
+ .rail .seen .mk { background: var(--text-2); border-color: var(--text-2); color: var(--panel); }
195
+ .rail .seen .mk svg { width: 10px; height: 10px; stroke-width: 2; }
196
+ .rail .sub { padding-left: 36px; }
197
+ .rail .sub .mk { width: 14px; height: 14px; border-color: var(--line); }
198
+ .rail .sub.seen { color: var(--text-3); }
199
+ .rail .sub.seen .mk { background: none; border-color: transparent; color: var(--green); }
200
+ .rail .gap { flex: 1; }
201
+ .rail-foot { display: flex; gap: 2px; padding: 0 2px; }
202
+ /* as far from the bottom as from the left: 10px of rail and 2px of foot */
203
+ .rail .rail-foot .icon-btn { width: 24px; height: 24px; padding: 0; align-items: center; justify-content: center; color: var(--text-3); }
204
+ .rail .rail-foot .icon-btn:hover { color: var(--text); }
205
+ /* folded: a strip of the marks; their titles show on hover */
206
+ [data-rail-strip] body { grid-template-columns: 52px minmax(0, 1fr); }
207
+ [data-rail-strip] .rail { align-items: center; padding-left: 8px; padding-right: 8px; }
208
+ [data-rail-strip] .rail .pr, [data-rail-strip] .rail .sh, [data-rail-strip] .rail .sub, [data-rail-strip] .rail button > span:not(.mk) { display: none; }
209
+ [data-rail-strip] .rail button:not(.icon-btn) { width: 36px; height: 32px; padding: 0; justify-content: center; align-items: center; }
210
+ [data-rail-strip] .rail button .mk { margin-top: 0; }
211
+ [data-rail-strip] .rail-foot { align-self: flex-start; padding: 0 0 0 4px; }
212
+ [data-rail-strip] .rail-foot .theme { display: none; }
213
+
214
+ /* overview */
215
+ .orient { max-width: 720px; margin: 0 auto; padding: 64px 24px 96px; display: flex; flex-direction: column; gap: 44px; }
216
+ .ba { display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 14px 16px; margin: 0; }
217
+ .ba dt { font-size: var(--fs-sm); font-weight: 500; color: var(--text-3); padding-top: 2px; }
218
+ .ba dt.after { color: var(--text-2); }
219
+ .ba dd { margin: 0; line-height: var(--lh-text); color: var(--text-2); text-wrap: pretty; }
220
+ .ba dd.after { color: var(--text); }
221
+ .ba code { white-space: nowrap; }
222
+ .card { background: var(--card); border-radius: var(--r-lg); }
223
+ .card.pad { padding: 24px; }
224
+ .card .cap { color: var(--text-3); font-size: var(--fs-sm); margin-top: 20px; padding-top: 14px; border-top: 1px solid var(--line); }
225
+ .card > .fig > .fig-head:only-child { display: none; }
226
+ .cta { display: flex; align-items: center; gap: 8px; }
227
+
228
+ /* flow */
229
+ svg.flow { width: 100%; height: auto; display: block; overflow: visible; margin: 0 auto; }
230
+ .fnode rect { fill: var(--card); stroke: var(--line-2); stroke-width: 1; transition: fill 240ms ease-out, stroke 240ms ease-out; }
231
+ .fnode.changed rect { stroke: var(--text-2); stroke-dasharray: 4 3; }
232
+ .fnode.here rect { stroke: var(--text); stroke-width: 1.25; }
233
+ .fnode.ok rect { fill: var(--green-bg); stroke: var(--green); stroke-dasharray: none; }
234
+ .fnode.fail rect { fill: var(--red-bg); stroke: var(--red); stroke-dasharray: none; }
235
+ .fnode text { fill: var(--text); font: 500 var(--fs-sm) var(--sans); }
236
+ .fnode text.sub { fill: var(--text-3); font: 400 var(--fs-mono) var(--mono); }
237
+ .fnode text.lab { font: 500 var(--fs-mono) var(--sans); }
238
+ .fnode.ok text.lab { fill: var(--green); } .fnode.fail text.lab { fill: var(--red); }
239
+ /* a flow beside a chapter: its parts down a line, a column per instance with what happened there */
240
+ .fcmp { display: grid; font-size: var(--fs-sm); line-height: var(--lh-tight); }
241
+ .fcmp-row { display: contents; }
242
+ .fcmp-row > * { display: flex; align-items: center; min-width: 0; min-height: 36px; padding: 6px 10px 6px 0; }
243
+ .fcmp-head > * { min-height: 0; padding-top: 0; padding-bottom: 6px; color: var(--text-3); }
244
+ .fcmp-row.here > * { background: var(--hover); }
245
+ .fcmp-row.here > :first-child { border-radius: var(--r) 0 0 var(--r); }
246
+ .fcmp-row.here > :last-child { border-radius: 0 var(--r) var(--r) 0; }
247
+ .fcmp-node { position: relative; gap: 12px; padding-left: 8px; color: var(--text-2); }
248
+ .fcmp-node i { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--bg); box-shadow: inset 0 0 0 1.5px var(--line-2); z-index: 1; }
249
+ .fcmp-row.here .fcmp-node i { background: color-mix(in srgb, var(--bg), var(--text) 3.5%); }
250
+ .fcmp-node.changed { color: var(--text); }
251
+ .fcmp-node.changed i { box-shadow: inset 0 0 0 1.5px var(--text-2); }
252
+ /* the line through the dots, each row drawing the half above and below its dot, so it joins at any row height */
253
+ .fcmp-node::before, .fcmp-node::after { content: ""; position: absolute; left: 12px; border-left: 1px solid var(--line-2); }
254
+ .fcmp-node::before { top: 0; bottom: 50%; }
255
+ .fcmp-node::after { top: 50%; bottom: 0; }
256
+ .fcmp-row.first .fcmp-node::before, .fcmp-row.last .fcmp-node::after { display: none; }
257
+ .fcmp-node > span, .fcmp-cell > span { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }
258
+ .fcmp-cell { color: var(--text-2); }
259
+ .fcmp-cell > span { font-weight: 500; animation: arrive 320ms var(--ease); }
260
+ .fcmp-cell > b { width: 5px; height: 5px; border-radius: 50%; background: var(--text-3); animation: arrive 320ms var(--ease); }
261
+ .fcmp-cell.ok > span { color: var(--green); } .fcmp-cell.ok > b { background: var(--green); }
262
+ .fcmp-cell.fail > span { color: var(--red); } .fcmp-cell.fail > b { background: var(--red); }
263
+ @keyframes arrive { from { opacity: 0; transform: translateY(3px); } }
264
+ .fedge { stroke: var(--line-2); stroke-width: 1.25; fill: none; transition: stroke 240ms ease-out; }
265
+ .fedge.lit { stroke: var(--text-2); }
266
+ .arrow { fill: var(--text-3); }
267
+ .packet { fill: var(--text); }
268
+
269
+ /* chapter: the guide on the left, the evidence on the right */
270
+ .chapter { height: 100%; display: grid; grid-template-columns: minmax(340px, 400px) minmax(0, 1fr); }
271
+ .guide { overflow: auto; padding: 24px 32px 24px; display: flex; flex-direction: column; gap: 20px; border-right: 1px solid var(--line); background: var(--panel); }
272
+ .guide .h { font-size: var(--fs-xl); font-weight: 500; letter-spacing: var(--ls-xl); line-height: var(--lh-tight); margin: 0 0 12px; text-wrap: balance; }
273
+ .guide .clamp { display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; }
274
+ .show-more { all: unset; align-self: flex-start; cursor: pointer; margin-top: 2px; font-size: var(--fs-sm); color: var(--text-3); transition: color 120ms ease-out; }
275
+ .show-more:hover { color: var(--text); }
276
+ .show-more:focus-visible { outline: 2px solid var(--text-3); outline-offset: 2px; border-radius: 3px; }
277
+ /* each instance a column: before a run what should happen, after it what happened in color, then what should have */
278
+ .cols { display: grid; gap: 0 24px; }
279
+ .col { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
280
+ .col + .col { padding-left: 12px; margin-left: -12px; border-left: 1px solid var(--line); }
281
+ .col b { font-size: var(--fs-sm); font-weight: 500; color: var(--text-2); }
282
+ .col p { margin: 0; font-size: var(--fs-sm); line-height: var(--lh); color: var(--text); text-wrap: pretty; }
283
+ .col .got { font-size: var(--fs); font-weight: 500; animation: rise 220ms var(--ease); }
284
+ .col .got.ok { color: var(--green); } .col .got.fail { color: var(--red); }
285
+ .col .should { font-size: var(--fs-sm); line-height: var(--lh); color: var(--text-3); text-wrap: pretty; }
286
+ .col .show-more { margin-top: -4px; }
287
+ .events { margin-top: 12px; background: var(--card); border-radius: var(--r-lg); overflow: hidden; }
288
+ .events-head { all: unset; box-sizing: border-box; display: flex; align-items: center; gap: 10px; width: 100%; padding: 11px 14px; font-size: var(--fs-sm); cursor: pointer; transition: background-color 120ms ease-out; }
289
+ .events-head:disabled { cursor: default; }
290
+ .events-head:focus-visible { outline: 2px solid var(--text-3); outline-offset: -2px; }
291
+ @media (hover: hover) and (pointer: fine) { .events-head:not(:disabled):hover { background: var(--raised); } }
292
+ .events[data-open] .acc-chev { transform: rotate(90deg); }
293
+ .events-title { flex: 1; font-weight: 500; }
294
+ .events-title .c { margin-left: 6px; font-weight: 400; color: var(--text-3); }
295
+ .events[data-open] .acc-body { grid-template-rows: 1fr; }
296
+ .events-lines { padding: 0 14px 12px 38px; font: var(--fs-mono)/var(--lh-code) var(--mono); letter-spacing: 0; color: var(--text-2); opacity: 0; transform: translateY(-4px); transition: opacity 120ms ease-out, transform 160ms var(--ease); }
297
+ .events[data-open] .events-lines { opacity: 1; transform: none; }
298
+ .events-lines div { white-space: pre-wrap; word-break: break-word; }
299
+ .events-lines b { font-weight: 500; color: var(--text); margin-right: 8px; }
300
+ .code-link { all: unset; box-sizing: border-box; display: flex; align-items: center; gap: 10px; width: 100%; padding: 11px 14px; border-radius: var(--r-lg); background: var(--card); cursor: pointer; font-size: var(--fs-sm); transition: background-color 120ms ease-out; }
301
+ .code-link .fpath { flex: 1; }
302
+ .code-link:focus-visible { outline: 2px solid var(--text-3); outline-offset: 2px; }
303
+ @media (hover: hover) and (pointer: fine) { .code-link:hover { background: var(--raised); } }
304
+ pre.failed { margin: 0; padding: 10px 12px; border-radius: var(--r); background: var(--red-bg); color: var(--red); font: var(--fs-mono)/var(--lh-code) var(--mono); letter-spacing: 0; white-space: pre-wrap; max-height: 200px; overflow: auto; }
305
+ /* previous and next, by chapter title, with the keys that do the same */
306
+ .pager { margin-top: auto; display: flex; justify-content: space-between; gap: 16px; }
307
+ .pager button { all: unset; display: inline-flex; align-items: center; gap: 8px; flex: 0 1 auto; min-width: 0; max-width: calc(50% - 8px); font-size: var(--fs-sm); color: var(--text-3); cursor: pointer; transition: color 120ms ease-out; }
308
+ .pager button span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
309
+ .pager button:last-child { color: var(--text-2); }
310
+ .pager button:hover { color: var(--text); }
311
+ .pager button:focus-visible { outline: 2px solid var(--text-3); outline-offset: 2px; border-radius: 3px; }
312
+
313
+
314
+ /* the evidence: the live apps alone, or a column of evidence that scrolls */
315
+ .evidence { min-width: 0; min-height: 0; overflow: auto; background: var(--bg); }
316
+ .evidence > .live:only-child { height: 100%; padding: 16px; }
317
+ .evidence.code-view { padding: 16px; }
318
+ .code-link[aria-pressed="true"] { background: var(--raised); }
319
+ .evidence.scroll { padding: 24px 28px 64px; display: flex; flex-direction: column; gap: 36px; }
320
+ .evidence.scroll > .live { flex: none; }
321
+ .evidence.scroll .live .frame { max-height: 70vh; }
322
+ .live { display: flex; flex-direction: column; gap: 12px; min-height: 0; }
323
+ .live-bar { flex: none; display: flex; align-items: center; gap: 12px; }
324
+ .icon-btn { all: unset; flex: none; width: 28px; height: 28px; border-radius: 6px; display: inline-flex; align-items: center; justify-content: center; color: var(--text-3); cursor: pointer; transition: background-color 120ms ease-out, color 120ms ease-out; }
325
+ .icon-btn:hover { background: var(--hover); color: var(--text); }
326
+ .icon-btn:active { transform: scale(.94); }
327
+ .icon-btn:focus-visible { outline: 2px solid var(--text-3); outline-offset: 2px; }
328
+ .icon-btn[aria-pressed="true"] { color: var(--text-2); }
329
+ .live-right { margin-left: auto; min-width: 0; display: flex; align-items: center; gap: 10px; }
330
+ .live-labels { flex: none; display: grid; gap: 12px; min-height: 28px; }
331
+ .live-label { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: var(--fs-sm); }
332
+ .live-label b { font-weight: 500; }
333
+ .live-label .icon-btn:last-child { margin-left: auto; }
334
+ .live-label .lamp { border-radius: 2px; }
335
+ .live-label .lamp.ok { background: var(--green); } .live-label .lamp.fail { background: var(--red); }
336
+ .live-bar .modes .lamp { margin-right: 6px; border-radius: 2px; }
337
+ .live-bar .modes .lamp.ok { background: var(--green); } .live-bar .modes .lamp.fail { background: var(--red); }
338
+ .live-body { flex: 1; min-height: 0; display: flex; align-items: flex-start; }
339
+ .live-body.wide { display: grid; gap: 12px; align-items: start; }
340
+ .live-body > .frame { flex: 1; }
341
+ /* a desktop-shaped window, as wide as there is room for and no taller than the panel */
342
+ .live .frame { aspect-ratio: 16 / 10; max-height: 100%; }
343
+ /* the guide folded away */
344
+ [data-guide-off] .chapter { grid-template-columns: minmax(0, 1fr); }
345
+ [data-guide-off] .chapter > .guide { display: none; }
346
+ .frame { position: relative; display: flex; flex-direction: column; min-width: 0; min-height: 0; border-radius: var(--r-lg); overflow: hidden; background: var(--card); border: 1px solid var(--line); box-shadow: var(--shadow); }
347
+ .fview { position: relative; flex: 1; min-height: 0; display: flex; }
348
+ .fview iframe { border: 0; flex: 1; width: 100%; background: #fff; }
349
+ .down { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 32px; text-align: center; background: var(--raised); color: var(--text-3); font-size: var(--fs-sm); }
350
+ .down b { color: var(--text-2); font-weight: 500; font-size: var(--fs); }
351
+ .down span { max-width: 300px; }
352
+
353
+ /* results that are not visible in the app */
354
+ .outcomes { background: var(--card); border-radius: var(--r-lg); }
355
+ .outcomes > .oe { margin: 0; padding: 14px 16px; color: var(--text-3); font-size: var(--fs-sm); }
356
+ .outcome { padding: 14px 16px; min-width: 0; animation: fade 200ms ease-out; }
357
+ .outcome + .outcome { border-top: 1px solid var(--line); }
358
+ .outcome .oh { display: flex; align-items: baseline; gap: 10px; font-size: var(--fs-sm); min-width: 0; }
359
+ .outcome .oh .lamp { align-self: center; border-radius: 2px; }
360
+ .outcome .on { flex: none; color: var(--text-2); }
361
+ .outcome .ot { flex: 1; min-width: 0; font-weight: 500; color: var(--text); }
362
+ .outcome.ok .lamp { background: var(--green); } .outcome.fail .lamp { background: var(--red); } .outcome.neutral .lamp { background: var(--text-2); }
363
+ .outcome.wait .lamp { animation: pulse 700ms ease-in-out infinite alternate; }
364
+ .outcome.wait .ot, .outcome.none .ot { color: var(--text-3); font-weight: 400; }
365
+ .outcome .os { margin: 4px 0 0 17px; font-size: var(--fs-sm); color: var(--text-2); }
366
+ .outcome .ob { margin: 12px 0 0; padding: 12px 14px; border-radius: var(--r); background: var(--bg); font: var(--fs-mono)/var(--lh-code) var(--mono); letter-spacing: 0; color: var(--text-2); white-space: pre-wrap; word-break: break-word; }
367
+
368
+ /* screenshots and comparisons */
369
+ .fig { margin: 0; display: flex; flex-direction: column; gap: 10px; min-width: 0; }
370
+ .fig-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 28px; }
371
+ .fig-title { font-size: var(--fs-sm); font-weight: 500; color: var(--text); }
372
+ .fig-actions { display: flex; align-items: center; gap: 4px; }
373
+ .fig figcaption { color: var(--text-3); font-size: var(--fs-sm); }
374
+ .media { all: unset; box-sizing: border-box; display: block; width: 100%; border-radius: 10px; border: 1px solid var(--line); background: var(--raised); overflow: hidden; cursor: zoom-in; transition: border-color 140ms ease-out; }
375
+ .media:hover { border-color: var(--line-2); }
376
+ .media.still { cursor: default; }
377
+ video.media { height: auto; max-height: 560px; object-fit: contain; cursor: pointer; }
378
+ .media img, .media canvas { display: block; width: 100%; height: auto; max-height: 560px; object-fit: contain; }
379
+ .tagged { position: relative; min-width: 0; }
380
+ .tag { position: absolute; top: 8px; left: 8px; display: inline-flex; align-items: center; height: 20px; padding: 0 7px; border-radius: 5px; font-size: var(--fs-xs); font-weight: 500; letter-spacing: .01em; background: color-mix(in srgb, var(--panel) 88%, transparent); backdrop-filter: blur(6px); border: 1px solid var(--line-2); color: var(--text); pointer-events: none; }
381
+ .tag.r { left: auto; right: 8px; }
382
+ .cmp-side { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; align-items: start; }
383
+ .cmp-slider { position: relative; cursor: ew-resize; user-select: none; touch-action: none; }
384
+ .cmp-slider img { pointer-events: none; -webkit-user-drag: none; }
385
+ .cmp-slider img.top { position: absolute; inset: 0; height: 100%; }
386
+ .cmp-slider:focus-visible { outline: 2px solid var(--text-3); outline-offset: 2px; }
387
+ /* a white line with a soft shadow, so it reads on light and dark screenshots, and a grip with arrows */
388
+ .cmp-slider .handle { position: absolute; top: 0; bottom: 0; width: 0; pointer-events: none; }
389
+ .cmp-slider .handle::before { content: ""; position: absolute; top: 0; bottom: 0; left: -1px; width: 2px; background: #fff; box-shadow: 0 0 0 1px rgba(0,0,0,.12), 0 0 8px rgba(0,0,0,.18); }
390
+ .cmp-slider .grip { position: absolute; top: 50%; left: 0; width: 34px; height: 24px; transform: translate(-50%, -50%); border-radius: 99px; background: #fff; color: #1b1b1f; display: flex; align-items: center; justify-content: center; box-shadow: 0 0 0 1px rgba(0,0,0,.08), 0 2px 8px rgba(0,0,0,.2); transition: transform 150ms var(--ease); }
391
+ .cmp-slider .grip svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
392
+ .cmp-slider.dragging .grip { transform: translate(-50%, -50%) scale(.94); }
393
+ .cmp-note { color: var(--text-3); font-size: var(--fs-sm); margin-top: 8px; }
394
+ .zoom { position: fixed; inset: 0; z-index: 50; display: grid; place-items: center; padding: 40px; background: rgba(10,10,12,.78); backdrop-filter: blur(4px); cursor: zoom-out; animation: fade 160ms ease-out; }
395
+ .zoom img { max-width: 100%; max-height: 100%; border-radius: 10px; box-shadow: 0 24px 64px rgba(0,0,0,.5); }
396
+
397
+ /* changes */
398
+ .changes { height: 100%; }
399
+ .groups { height: 100%; overflow: auto; padding: 40px 48px 120px; display: flex; flex-direction: column; gap: 56px; }
400
+ .group { max-width: 1040px; width: 100%; }
401
+ .group .head { display: grid; gap: 2px; margin-bottom: 16px; max-width: 640px; }
402
+ .group .head .h { font-size: var(--fs-lg); line-height: var(--lh-tight); font-weight: 500; letter-spacing: var(--ls-lg); margin: 0; }
403
+ .file { border-radius: var(--r-lg); overflow: hidden; background: var(--card); }
404
+ .file + .file { margin-top: 12px; }
405
+ .fh { display: flex; align-items: center; gap: 10px; height: 44px; padding: 0 10px 0 14px; border-bottom: 1px solid var(--line); font-size: var(--fs-sm); }
406
+ .fh .fpath { flex: 1; }
407
+ .reviewed { display: inline-flex; align-items: center; gap: 7px; color: var(--text-2); font-size: var(--fs-sm); cursor: pointer; user-select: none; padding: 0 4px; }
408
+ .reviewed input { appearance: none; width: 15px; height: 15px; border-radius: 4px; border: 1px solid var(--line-2); margin: 0; display: grid; place-content: center; cursor: pointer; transition: background-color 140ms ease-out; }
409
+ .reviewed input:checked { background: var(--green); border-color: var(--green); }
410
+ .reviewed input:checked::after { content: ""; width: 7px; height: 4px; border: solid #fff; border-width: 0 0 1.5px 1.5px; transform: rotate(-45deg) translate(1px, -1px); }
411
+ .file.closed .fh { border-bottom-color: transparent; }
412
+ .fh-toggle { all: unset; flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; align-self: stretch; cursor: pointer; }
413
+ .group .h .count { margin-left: 6px; color: var(--text-3); font-weight: 400; }
414
+ .file-stack .file.other { border-radius: 3px; }
415
+ .file-stack .file.other + .file.other { margin-top: 2px; }
416
+ .file-stack .file.other:first-child { border-top-left-radius: var(--r-lg); border-top-right-radius: var(--r-lg); }
417
+ .file-stack .file.other:last-child { border-bottom-left-radius: var(--r-lg); border-bottom-right-radius: var(--r-lg); }
418
+ .file.other .chev { display: inline-flex; color: var(--text-3); transition: transform 160ms var(--ease); }
419
+ .file.other .fh-toggle[aria-expanded="true"] .chev { transform: rotate(90deg); }
420
+ .file.other.done .fname { color: var(--text-2); }
421
+ .fh-threads { display: inline-flex; align-items: center; gap: 5px; color: var(--text-3); font-size: var(--fs-sm); }
422
+ .fh-toggle:focus-visible { outline: 2px solid var(--text-3); outline-offset: 2px; border-radius: 4px; }
423
+ .diff { font: var(--fs-mono)/var(--lh-code) var(--mono); letter-spacing: 0; }
424
+ .dl { display: grid; grid-template-columns: 52px minmax(0, 1fr); }
425
+ .dl .ln { text-align: right; padding: 0 14px 0 0; color: var(--text-3); user-select: none; border-left: 2px solid transparent; }
426
+ /* long lines wrap, the rest of the line indented under its start */
427
+ .dl .code { white-space: pre-wrap; overflow-wrap: anywhere; padding: 0 16px 0 calc(4ch + 12px); text-indent: -4ch; }
428
+ .dl .a { background: var(--add); } .dl .ln.a { border-left-color: var(--green); color: var(--green); }
429
+ .dl .d { background: var(--del); } .dl .ln.d { border-left-color: var(--red); color: var(--red); }
430
+ /* comments: a + in the gutter on hover, drag it for several lines; threads sit under their line */
431
+ .dl .lr { display: contents; }
432
+ .dl .ln { position: relative; }
433
+ /* on the edge between the number and the code, level with a wrapped line's first row */
434
+ .add-c { all: unset; position: absolute; z-index: 1; right: -8px; top: calc((1lh - 16px) / 2); width: 16px; height: 16px; display: grid; place-items: center; border-radius: 5px; background: var(--btn); color: var(--btn-text); cursor: pointer; opacity: 0; transform: scale(.85); transition: opacity 120ms ease-out, transform 120ms ease-out; }
435
+ .add-c svg.i { width: 11px; height: 11px; stroke-width: 1.75; }
436
+ .dl .lr:hover .add-c, .add-c:focus-visible { opacity: 1; transform: scale(1); }
437
+ .diff.picking .add-c { opacity: 0; }
438
+ .diff.picking { user-select: none; cursor: ns-resize; }
439
+ .dl .lr.sel > div { background: var(--sel); }
440
+ .dl .lr.sel > .ln { border-left-color: var(--text-3); color: var(--text-2); }
441
+ .dl-span { grid-column: 1 / -1; padding: 10px 16px 10px 52px; border-block: 1px solid var(--line); background: var(--panel); font: var(--fs-sm)/var(--lh) var(--sans); letter-spacing: var(--ls); }
442
+ .dl-span + .dl-span { border-top: 0; padding-top: 0; }
443
+ .loose { display: flex; flex-direction: column; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--line); background: var(--panel); font: var(--fs-sm)/var(--lh) var(--sans); letter-spacing: var(--ls); }
444
+ .thread { max-width: 720px; border-radius: var(--r-lg); background: var(--card); box-shadow: 0 0 0 1px var(--line-2); overflow: hidden; }
445
+ .thread-top { display: flex; align-items: center; gap: 12px; padding: 8px 14px; border-bottom: 1px solid var(--line); color: var(--text-3); }
446
+ .thread-state { color: var(--text-3); }
447
+ .thread-state.resolved { display: inline-flex; align-items: center; gap: 6px; color: var(--text-2); }
448
+ .thread-state.resolved svg.i { color: var(--green); }
449
+ .thread-hide { margin-left: auto; color: var(--text-3); }
450
+ .thread.folded { all: unset; box-sizing: border-box; max-width: 720px; width: 100%; display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 14px; border-radius: var(--r-lg); background: var(--card); box-shadow: 0 0 0 1px var(--line); color: var(--text-2); cursor: pointer; transition: background-color 120ms ease-out; }
451
+ .thread.folded svg.i { color: var(--green); }
452
+ .thread.folded b { font-weight: 500; color: var(--text); flex: none; }
453
+ .thread-gist { min-width: 0; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text-3); }
454
+ .thread-count { flex: none; color: var(--text-3); }
455
+ @media (hover: hover) and (pointer: fine) { .thread.folded:hover { background: var(--raised); } }
456
+ .thread.folded:focus-visible { outline: 2px solid var(--text-3); outline-offset: 2px; }
457
+ .note { padding: 12px 14px; }
458
+ .note + .note { border-top: 1px solid var(--line); }
459
+ .note-head { display: flex; align-items: center; gap: 8px; height: 22px; }
460
+ .note-head b { font-weight: 500; }
461
+ .note-when { color: var(--text-3); }
462
+ .note-tag { display: inline-flex; align-items: center; height: 18px; padding: 0 6px; border-radius: 5px; background: var(--raised); color: var(--text-2); font-size: var(--fs-xs); font-weight: 500; }
463
+ .note-tag.pending { background: var(--amber-bg); color: var(--amber); }
464
+ .note-tag.agent { gap: 5px; }
465
+ .note-tag.agent .lamp { width: 5px; height: 5px; background: currentColor; animation: pulse 700ms ease-in-out infinite alternate; }
466
+ .note-tag.agent.done { background: var(--green-bg); color: var(--green); }
467
+ .note-tag.agent.stopped { background: var(--red-bg); color: var(--red); }
468
+ .note-foot.stopped { display: flex; align-items: center; gap: 10px; color: var(--text-2); font-size: var(--fs-sm); }
469
+ .note-tag.mono { font-family: var(--mono); letter-spacing: 0; }
470
+ .note-foot { margin-top: 8px; padding-left: 26px; }
471
+ .note .composer-error { padding-left: 26px; }
472
+ .composer-field { position: relative; }
473
+ .composer-field textarea { padding-right: 40px; }
474
+ .composer-tool { all: unset; position: absolute; top: 6px; right: 6px; width: 26px; height: 26px; display: grid; place-items: center; border-radius: var(--r-sm); color: var(--text-3); cursor: pointer; transition: color 120ms ease-out, background-color 120ms ease-out; }
475
+ .composer-tool:hover { color: var(--text); background: var(--hover); }
476
+ .composer-tool:focus-visible { outline: 2px solid var(--text-3); }
477
+ .composer-bar .ask svg.i { width: 12px; height: 12px; }
478
+ .composer-bar .ask:first-child { margin-left: -6px; }
479
+ .composer-hint { color: var(--text-3); font-size: var(--fs-xs); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
480
+ .composer-hint kbd { height: 17px; }
481
+ .composer-label { display: flex; align-items: center; gap: 10px; }
482
+ .to-agent { display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 8px; border-radius: 6px; background: var(--raised); color: var(--text); font-size: var(--fs-xs); font-weight: 500; animation: pop 140ms var(--ease); }
483
+ .to-agent .dot { width: 6px; height: 6px; border-radius: 2px; background: var(--green); }
484
+ .mention-offer { position: absolute; left: 10px; top: 36px; z-index: 5; display: flex; align-items: center; gap: 10px; padding: 6px 10px; border-radius: var(--r); background: var(--card); box-shadow: var(--shadow-float), 0 0 0 1px var(--line); font-size: var(--fs-sm); animation: pop 140ms var(--ease); }
485
+ .mention-offer b { font: 500 var(--fs-mono) var(--mono); letter-spacing: 0; }
486
+ .mention-offer span { color: var(--text-3); font-size: var(--fs-xs); }
487
+ .listening { display: inline-flex; align-items: center; gap: 6px; color: var(--text-3); font-size: var(--fs-sm); white-space: nowrap; }
488
+ .listening.on { color: var(--text-2); } .listening.on .lamp { background: var(--green); }
489
+ /* the footer under every page: whether your agent listens on the left (local reviews), the agent on the right */
490
+ .foot .listening { font-size: var(--fs-xs); }
491
+ .foot { position: relative; flex: none; display: flex; align-items: center; gap: 12px; height: 28px; padding: 0 6px 0 12px; border-top: 1px solid var(--line); background: var(--bg); font-size: var(--fs-sm); }
492
+ .foot .grow { flex: 1; }
493
+ .agent-btn { all: unset; display: inline-flex; align-items: center; gap: 5px; height: 20px; padding: 0 6px; border-radius: 5px; font-size: var(--fs-xs); color: var(--text-2); font-weight: 500; cursor: pointer; transition: background-color 120ms ease-out, color 120ms ease-out; }
494
+ .agent-btn:hover, .agent-btn[aria-expanded="true"] { background: var(--hover); color: var(--text); }
495
+ .agent-btn:focus-visible { outline: 2px solid var(--text-3); outline-offset: 2px; }
496
+ .agent-btn svg.i { width: 12px; height: 12px; }
497
+ .agent-btn.busy svg.i { color: var(--text); animation: pulse 700ms ease-in-out infinite alternate; }
498
+ .agent-btn.new svg.i { color: var(--text); fill: currentColor; }
499
+ .agent-btn.stopped svg.i { color: var(--red); }
500
+ /* the chat opens up from the agent button */
501
+ .chat { position: absolute; z-index: 30; right: 8px; bottom: calc(100% + 8px); width: min(400px, calc(100vw - 32px)); height: min(560px, calc(100vh - 120px)); display: flex; flex-direction: column; border-radius: var(--r-lg); background: var(--card); box-shadow: var(--shadow-float), 0 0 0 1px var(--line); transform-origin: bottom right; animation: pop 180ms var(--ease); }
502
+ .chat-head { display: flex; align-items: center; gap: 6px; padding: 8px 8px 8px 16px; border-bottom: 1px solid var(--line); }
503
+ .chat-head b { font-weight: 500; }
504
+ .chat-where { color: var(--text-3); font-size: var(--fs-xs); }
505
+ .chat-head .grow { flex: 1; }
506
+ .chat.docked { position: static; width: 100%; height: auto; border-radius: 0; box-shadow: none; animation: none; }
507
+ .chat-list { flex: 1; min-height: 0; overflow: auto; padding: 16px; display: flex; flex-direction: column; gap: 14px; }
508
+ .chat-empty { margin: auto 0; color: var(--text-3); text-align: center; text-wrap: pretty; line-height: var(--lh-text); padding: 0 12px; }
509
+ .msg { display: flex; flex-direction: column; gap: 4px; max-width: 88%; min-width: 0; animation: rise 200ms var(--ease); }
510
+ .msg.reviewer { align-self: flex-end; align-items: flex-end; }
511
+ .msg.reviewer .msg-body { padding: 8px 12px; border-radius: 12px 12px 4px 12px; background: var(--raised); }
512
+ .msg .note-body { margin: 0; padding: 0; }
513
+ .msg-from { color: var(--text-3); font-size: var(--fs-xs); }
514
+ .msg-from.mono { font-family: var(--mono); letter-spacing: 0; }
515
+ .msg.typing, .msg.stopped { flex-direction: row; align-items: center; gap: 8px; color: var(--text-3); font-size: var(--fs-sm); }
516
+ .sailing { flex: none; overflow: hidden; border-radius: 3px; --water: var(--text-3); }
517
+ .sailing .sea { fill: var(--water); }
518
+ .sailing .sea.back { fill: color-mix(in srgb, var(--water) 45%, var(--card)); }
519
+ .sailing .boat { fill: var(--text-2); transform-origin: 15px 14px; animation: ride 2.4s ease-in-out infinite; }
520
+ .sailing .wave { animation: roll 3.2s linear infinite; }
521
+ .sailing .wave.slow { animation-duration: 5.6s; }
522
+ @keyframes roll { to { transform: translateX(-16px); } }
523
+ @keyframes ride { 0%, 100% { transform: translateY(-1px) rotate(-5deg); } 50% { transform: translateY(1px) rotate(5deg); } }
524
+ .msg.stopped { color: var(--red); display: block; }
525
+ .chat-error { padding: 0 16px; }
526
+ /* the input: the context it sends with (the page, a selection), the message, and send, in one box */
527
+ .chat-box { margin: 0 10px 10px; display: flex; flex-direction: column; border-radius: var(--r-lg); background: var(--raised); box-shadow: inset 0 0 0 1px transparent; cursor: text; transition: box-shadow 120ms ease-out; }
528
+ .chat-box:focus-within { box-shadow: inset 0 0 0 1px var(--line-2); }
529
+ .chat-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 8px 8px 0; min-width: 0; }
530
+ .ctx-chip { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; height: 22px; padding: 0 7px; border-radius: 6px; background: var(--card); box-shadow: 0 0 0 1px var(--line); color: var(--text-2); font-size: var(--fs-xs); cursor: default; animation: pop 140ms var(--ease); }
531
+ .ctx-chip > span { min-width: 0; max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
532
+ .ctx-chip svg.i { width: 12px; height: 12px; flex: none; color: var(--text-3); }
533
+ .ctx-chip button { all: unset; display: grid; place-items: center; width: 16px; height: 16px; margin-right: -4px; border-radius: 4px; color: var(--text-3); cursor: pointer; }
534
+ .ctx-chip button:hover { background: var(--hover); color: var(--text); }
535
+ .ctx-chip button svg.i { width: 10px; height: 10px; }
536
+ .chip-hint { color: var(--text-3); font-size: var(--fs-xs); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
537
+ .chip-hint kbd { height: 16px; min-width: 16px; font-size: 10px; background: var(--card); }
538
+ .chat-box textarea { display: block; width: 100%; min-height: 38px; max-height: 200px; resize: none; padding: 8px 12px 2px; border: 0; background: transparent; color: var(--text); font: var(--fs-sm)/var(--lh-text) var(--sans); letter-spacing: var(--ls); outline: none; }
539
+ .chat-box textarea::placeholder { color: var(--text-3); }
540
+ .chat-box-bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 2px 6px 6px 12px; }
541
+ .chat-box .send { all: unset; flex: none; display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: var(--btn); color: var(--btn-text); cursor: pointer; transition: opacity 120ms ease-out, transform 120ms ease-out; }
542
+ .chat-box .send:disabled { opacity: .25; cursor: default; }
543
+ .chat-box .send:not(:disabled):active { transform: scale(.94); }
544
+ .chat-box .send:focus-visible { outline: 2px solid var(--text-3); outline-offset: 2px; }
545
+ .chat-box .send svg.i { width: 14px; height: 14px; stroke-width: 1.75; }
546
+ .msg-body { max-width: 100%; min-width: 0; }
547
+ .msg-quote { margin: 2px 0 8px; border-radius: var(--r); background: var(--card); box-shadow: 0 0 0 1px var(--line); overflow: hidden; text-align: left; }
548
+ .msg-quote-head { display: flex; align-items: center; gap: 6px; padding: 5px 10px; border-bottom: 1px solid var(--line); color: var(--text-3); font: var(--fs-xs) var(--mono); letter-spacing: 0; }
549
+ .msg-quote-head svg.i { width: 12px; height: 12px; flex: none; }
550
+ .msg-quote.comment .msg-quote-head { font-family: var(--sans); letter-spacing: var(--ls); }
551
+ .msg-quote-body { padding: 7px 10px 8px; max-height: 9em; overflow: hidden; font-size: var(--fs-sm); -webkit-mask-image: linear-gradient(to bottom, #000 75%, transparent); mask-image: linear-gradient(to bottom, #000 75%, transparent); }
552
+ .msg-quote-body .note-body { margin: 0; padding: 0; line-height: 1.5; }
553
+ .msg-quote-head span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
554
+ .msg-quote pre { margin: 0; padding: 7px 10px 8px; max-height: calc(5 * 1.6em + 15px); overflow: hidden; font: var(--fs-mono)/1.6 var(--mono); letter-spacing: 0; color: var(--text); white-space: pre-wrap; word-break: break-word; }
555
+ .msg-quote pre.code { white-space: pre; }
556
+ .msg-quote pre.long { -webkit-mask-image: linear-gradient(to bottom, #000 60%, transparent); mask-image: linear-gradient(to bottom, #000 60%, transparent); }
557
+ .rail .pr .update { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin-top: 6px; font-size: var(--fs-sm); color: var(--text-3); line-height: 1.4; }
558
+ .note-actions { margin-left: auto; display: flex; gap: 2px; }
559
+ .note-head .refer { margin-left: auto; width: 22px; height: 22px; }
560
+ .note-head .refer + .note-actions { margin-left: 0; }
561
+ .note-head .refer svg.i { width: 13px; height: 13px; }
562
+ .note-body { margin-top: 6px; padding-left: 26px; color: var(--text); line-height: var(--lh-text); overflow-wrap: anywhere; }
563
+ .note-body p, .note-body ul, .note-body ol, .note-body blockquote, .note-body table, .note-body h1, .note-body h2, .note-body h3, .note-body h4 { margin: 0 0 8px; }
564
+ .note-body > :last-child { margin-bottom: 0; }
565
+ .note-body ul, .note-body ol { padding-left: 20px; }
566
+ .note-body li { margin: 2px 0; }
567
+ .note-body li > p { margin: 0; }
568
+ .note-body li::marker { color: var(--text-3); }
569
+ .note-body ul.contains-task-list { list-style: none; padding-left: 4px; }
570
+ .note-body .task-list-item input { margin: 0 6px 0 0; vertical-align: -1px; }
571
+ .note-body h1, .note-body h2, .note-body h3, .note-body h4 { font-size: var(--fs); font-weight: 500; }
572
+ .note-body blockquote { padding-left: 10px; border-left: 2px solid var(--line-2); color: var(--text-2); }
573
+ .note-body em { font-style: italic; }
574
+ .note-body hr { border: 0; border-top: 1px solid var(--line); margin: 10px 0; }
575
+ .note-body table { border-collapse: collapse; font-size: var(--fs-sm); display: block; overflow-x: auto; }
576
+ .note-body th, .note-body td { padding: 4px 10px; border: 1px solid var(--line-2); text-align: left; }
577
+ .note-body th { font-weight: 500; background: var(--raised); }
578
+ .note-body code { font: .9em var(--mono); letter-spacing: 0; padding: 1px 4px; border-radius: 4px; background: var(--raised); }
579
+ .note-body b, .note-body strong { font-weight: 500; }
580
+ .code-block { margin: 0 0 8px; padding: 10px 12px; border-radius: var(--r); background: var(--raised); font: var(--fs-mono)/var(--lh-code) var(--mono); letter-spacing: 0; overflow-x: auto; }
581
+ .suggestion { margin: 0 0 8px; border-radius: var(--r); box-shadow: 0 0 0 1px var(--line-2); overflow: hidden; font: var(--fs-mono)/var(--lh-code) var(--mono); letter-spacing: 0; }
582
+ .suggestion-head { padding: 6px 12px; border-bottom: 1px solid var(--line); font: 500 var(--fs-sm) var(--sans); letter-spacing: var(--ls); color: var(--text-2); }
583
+ .suggestion .dl { grid-template-columns: 28px minmax(0, 1fr); }
584
+ .suggestion .ln { padding-right: 10px; }
585
+ .suggestion .code { padding-left: calc(4ch + 6px); }
586
+ .reply { all: unset; box-sizing: border-box; display: block; width: 100%; padding: 10px 14px 10px 40px; border-top: 1px solid var(--line); color: var(--text-3); cursor: text; transition: color 120ms ease-out; }
587
+ .reply:hover { color: var(--text-2); }
588
+ .reply:focus-visible { outline: 2px solid var(--text-3); outline-offset: -2px; }
589
+ .composer { padding: 12px 14px; }
590
+ .note + .composer, .thread-top + .composer { border-top: 1px solid var(--line); }
591
+ .composer-label { margin-bottom: 8px; color: var(--text-2); font-weight: 500; }
592
+ .composer textarea { display: block; width: 100%; min-height: 64px; max-height: 360px; resize: none; padding: 9px 11px; border: 0; border-radius: var(--r); background: var(--raised); color: var(--text); font: var(--fs-sm)/var(--lh-text) var(--sans); letter-spacing: var(--ls); outline: none; box-shadow: inset 0 0 0 1px transparent; transition: box-shadow 120ms ease-out; }
593
+ .composer textarea:focus { box-shadow: inset 0 0 0 1px var(--line-2); }
594
+ .composer textarea::placeholder { color: var(--text-3); }
595
+ .composer-error { margin-top: 8px; color: var(--red); }
596
+ .composer-bar { display: flex; align-items: center; gap: 4px; margin-top: 8px; }
597
+ .composer-bar .grow { flex: 1; }
598
+ .btn:disabled { opacity: 1; color: var(--text-3); cursor: default; }
599
+ .btn.primary:disabled { background: var(--raised); color: var(--text-3); }
600
+ .more { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 14px 0 20px; color: var(--text-2); font: var(--fs-sm) var(--sans); cursor: pointer; background: transparent; border: 0; border-block: 1px solid var(--line); text-align: left; transition: color 140ms ease-out, background-color 140ms ease-out; }
601
+ .more:first-child { border-top: 0; }
602
+ .more:last-child { border-bottom: 0; }
603
+ .more:hover { color: var(--text); background: var(--hover); }
604
+ .tok-kw { color: var(--kw); } .tok-str { color: var(--str); } .tok-num { color: var(--num); } .tok-fn { color: var(--fn); } .tok-com { color: var(--com); font-style: italic; } .tok-ty { color: var(--ty); }
605
+
606
+ /* finishing: the drafts, a summary, a verdict, and where they go */
607
+ .field { display: block; width: 100%; min-height: 96px; resize: vertical; padding: 12px 14px; border: 0; border-radius: var(--r-lg); background: var(--card); color: var(--text); font: var(--fs)/var(--lh-text) var(--sans); letter-spacing: var(--ls); outline: none; box-shadow: inset 0 0 0 1px transparent; transition: box-shadow 120ms ease-out; }
608
+ .field:focus { box-shadow: inset 0 0 0 1px var(--line-2); }
609
+ .field::placeholder { color: var(--text-3); }
610
+ /* the pull request page: the PR and its checks, and a panel with what a merge needs */
611
+ .prp-gates { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 40px; align-items: start; max-width: 1120px; margin: 0 auto; padding: 48px 32px 80px; }
612
+ .prp-main { display: flex; flex-direction: column; gap: 32px; min-width: 0; }
613
+ .prp-desc { padding: 16px 18px; }
614
+ .prp-desc .note-body { margin: 0; padding: 0; }
615
+ .prp-clamp { max-height: 9.6em; overflow: hidden; -webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent); mask-image: linear-gradient(to bottom, #000 70%, transparent); }
616
+ .prp-desc .show-more { margin-top: 6px; }
617
+ .prp-label { align-items: center; }
618
+ .prp-label .btn { margin-left: auto; }
619
+ .prp-label .btn svg.i { width: 12px; height: 12px; }
620
+ .prp-dim { color: var(--text-3); font-size: var(--fs-sm); }
621
+ .prp-st { flex: none; display: grid; place-items: center; width: 18px; height: 18px; border-radius: 50%; color: #fff; background: var(--text-3); }
622
+ .prp-st svg.i { width: 11px; height: 11px; stroke-width: 2; }
623
+ .prp-st.pass { background: var(--green); } .prp-st.fail { background: var(--red); } .prp-st.warn { background: var(--amber); } .prp-st.merged { background: #8b5cf6; }
624
+ .prp-st.pending { background: transparent; border: 2px solid var(--amber); border-right-color: transparent; animation: spin 900ms linear infinite; }
625
+ @keyframes spin { to { transform: rotate(360deg); } }
626
+ .prp-wf { border-radius: var(--r-lg); background: var(--card); overflow: hidden; }
627
+ .prp-wf + .prp-wf { margin-top: 8px; }
628
+ .prp-wf-h { all: unset; box-sizing: border-box; width: 100%; display: flex; align-items: center; gap: 12px; padding: 12px 14px; cursor: pointer; font-size: var(--fs-sm); transition: background-color 120ms ease-out; }
629
+ .prp-wf-h:hover { background: var(--hover); }
630
+ .prp-wf-h:focus-visible { outline: 2px solid var(--text-3); outline-offset: -2px; }
631
+ .prp-wf-h b { font-weight: 500; }
632
+ .prp-wf-h .chev { display: flex; color: var(--text-3); transition: transform 180ms var(--ease); }
633
+ .prp-wf-h[aria-expanded="true"] .chev { transform: rotate(90deg); }
634
+ .prp-jobs { border-top: 1px solid var(--line); padding: 4px 0; animation: fade 160ms ease-out; }
635
+ .prp-job .grow, .prp-wf-h .grow { flex: 1; min-width: 0; }
636
+ .prp-job { display: flex; align-items: center; gap: 12px; padding: 7px 14px 7px 44px; font-size: var(--fs-sm); }
637
+ .prp-job .prp-st { width: 14px; height: 14px; } .prp-job .prp-st svg.i { width: 9px; height: 9px; }
638
+ .prp-panel { position: sticky; top: 24px; display: flex; flex-direction: column; gap: 14px; padding: 18px; border-radius: var(--r-lg); background: var(--card); }
639
+ .prp-panel h2 { margin: 0; font-size: var(--fs-lg); font-weight: 500; letter-spacing: var(--ls-lg); }
640
+ .prp-panel hr { width: 100%; margin: 2px 0; border: 0; border-top: 1px solid var(--line); }
641
+ .prp-gate { display: flex; gap: 10px; align-items: flex-start; font-size: var(--fs-sm); }
642
+ .prp-gate .prp-st { margin-top: 1px; }
643
+ .prp-gate b { display: block; font-weight: 500; }
644
+ .prp-gate span span { display: block; color: var(--text-3); font-size: var(--fs-xs); }
645
+ .prp-acts { display: flex; flex-direction: column; gap: 10px; }
646
+ .prp-acts .prp-methods { grid-template-columns: repeat(3, 1fr); }
647
+ .prp-confirm { display: flex; gap: 8px; } .prp-confirm .btn { flex: 1; justify-content: center; }
648
+ .prp-acts > .btn { justify-content: center; }
649
+ .skel { display: block; border-radius: 5px; background: linear-gradient(90deg, var(--raised) 30%, color-mix(in srgb, var(--raised) 55%, var(--card)) 50%, var(--raised) 70%) 0 0 / 300% 100%; animation: sheen 1.4s ease-in-out infinite; }
650
+ .skel-stack { display: flex; flex-direction: column; gap: 10px; }
651
+ .skel-row { display: flex; align-items: center; gap: 12px; padding: 14px; }
652
+ .skel-dot { flex: none; width: 18px; height: 18px; border-radius: 50%; }
653
+ @keyframes sheen { from { background-position: 100% 0; } to { background-position: 0 0; } }
654
+ /* Finish on a PR: the comments, then a panel that stays in view */
655
+ .fin { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 40px; align-items: start; max-width: 1120px; margin: 0 auto; padding: 48px 32px 80px; }
656
+ .fin-main { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
657
+ .fin-main > .title { margin-bottom: 12px; }
658
+ .fin-file { border-radius: var(--r-lg); background: var(--card); overflow: hidden; }
659
+ .fin-fh { display: flex; gap: 8px; align-items: baseline; padding: 10px 14px; border-bottom: 1px solid var(--line); font-size: var(--fs-sm); }
660
+ .fin-fh b { font-weight: 500; } .fin-fh span { color: var(--text-3); }
661
+ .fin-c { padding: 12px 14px; }
662
+ .fin-c + .fin-c { border-top: 1px solid var(--line); }
663
+ .fin-c.posted { opacity: .7; }
664
+ .fin-c .note-body { margin: 0; padding: 0; }
665
+ .fin-c .composer { padding: 0; }
666
+ .fin-snip { margin-bottom: 10px; padding: 6px 0; border-radius: var(--r); background: var(--raised); font: var(--fs-mono)/var(--lh-code) var(--mono); letter-spacing: 0; overflow: hidden; }
667
+ .fin-snip > div { display: grid; grid-template-columns: 40px minmax(0, 1fr); }
668
+ .fin-snip .n { text-align: right; padding-right: 10px; color: var(--text-3); user-select: none; }
669
+ .fin-snip .s { white-space: pre; overflow: hidden; text-overflow: ellipsis; padding-right: 12px; }
670
+ .fin-snip .a { background: var(--add); } .fin-snip .d { background: var(--del); }
671
+ .fin-bar { display: flex; align-items: center; gap: 4px; margin-top: 8px; }
672
+ .fin-tags { flex: 1; display: flex; gap: 6px; }
673
+ .fin-panel { position: sticky; top: 24px; display: flex; flex-direction: column; gap: 16px; padding: 18px; border-radius: var(--r-lg); background: var(--card); }
674
+ .fin-panel h2 { margin: 0; font-size: var(--fs-lg); font-weight: 500; letter-spacing: var(--ls-lg); }
675
+ .fin-panel .field { min-height: 96px; resize: none; border-radius: var(--r); background: var(--raised); }
676
+ .meters { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
677
+ .meter > div:first-child { color: var(--text-2); font-size: var(--fs-sm); }
678
+ .meter .track { display: flex; gap: 3px; margin-top: 6px; }
679
+ .meter .track i { flex: 1; height: 4px; border-radius: 2px; background: var(--raised); }
680
+ .meter .track i.on { background: var(--green); }
681
+ .vswitch { display: grid; grid-template-columns: auto auto 1fr; gap: 2px; padding: 3px; border-radius: var(--r); background: var(--raised); }
682
+ .vswitch button { all: unset; display: flex; align-items: center; justify-content: center; height: 28px; padding: 0 12px; border-radius: calc(var(--r) - 3px); font-size: var(--fs-sm); font-weight: 500; color: var(--text-2); cursor: pointer; white-space: nowrap; transition: background-color 140ms ease-out, color 140ms ease-out; }
683
+ .vswitch button:hover { color: var(--text); }
684
+ .vswitch button[aria-checked="true"] { background: var(--card); color: var(--text); box-shadow: 0 1px 2px rgba(0,0,0,.08); }
685
+ .vswitch button:focus-visible { outline: 2px solid var(--text-3); outline-offset: 1px; }
686
+ .fin-actions { display: flex; gap: 8px; }
687
+ .fin-ask .grow { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
688
+ .fin-q { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
689
+ .fin-a { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-3); font-size: var(--fs-xs); }
690
+ .fin-actions .btn { flex: 1; justify-content: center; }
691
+ .btn .count { display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; background: color-mix(in srgb, var(--btn-text) 18%, transparent); font-size: var(--fs-xs); }
692
+ .post { display: flex; flex-direction: column; gap: 16px; }
693
+ .post b { font-weight: 500; color: var(--text); }
694
+ .post-skip { color: var(--text-3); }
695
+ .post-error { color: var(--red); }
696
+ .changes .cta { margin-top: 8px; }