@kingsleyweb/bun-ui 0.0.0-stage → 3.0.0-rc.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 (240) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -2
  3. package/app/docs/App.tsx +72 -0
  4. package/app/docs/api/client.ts +303 -0
  5. package/app/docs/api/contract.ts +24 -0
  6. package/app/docs/api/docs.ts +38 -0
  7. package/app/docs/api/errors.ts +144 -0
  8. package/app/docs/boot.tsx +58 -0
  9. package/app/docs/components/Badge.tsx +65 -0
  10. package/app/docs/components/Button.tsx +37 -0
  11. package/app/docs/components/Card.tsx +41 -0
  12. package/app/docs/components/ConfirmDialog.tsx +173 -0
  13. package/app/docs/components/CopyButton.tsx +68 -0
  14. package/app/docs/components/Dialog.tsx +230 -0
  15. package/app/docs/components/EmptyState.tsx +34 -0
  16. package/app/docs/components/ErrorView.tsx +70 -0
  17. package/app/docs/components/Field.tsx +93 -0
  18. package/app/docs/components/JsonEditor.tsx +151 -0
  19. package/app/docs/components/JsonView.tsx +338 -0
  20. package/app/docs/components/KeyValue.tsx +63 -0
  21. package/app/docs/components/ProblemBanner.tsx +116 -0
  22. package/app/docs/components/ScreenErrorBoundary.tsx +141 -0
  23. package/app/docs/components/Spinner.tsx +33 -0
  24. package/app/docs/components/Table.tsx +33 -0
  25. package/app/docs/components/Tabs.tsx +226 -0
  26. package/app/docs/components/classNames.ts +4 -0
  27. package/app/docs/components/components.css +691 -0
  28. package/app/docs/components/copy.ts +89 -0
  29. package/app/docs/components/fieldContext.ts +29 -0
  30. package/app/docs/components/inputValues.ts +142 -0
  31. package/app/docs/components/inputs.tsx +387 -0
  32. package/app/docs/components/jsonParse.ts +338 -0
  33. package/app/docs/components/listKeys.ts +30 -0
  34. package/app/docs/config.ts +86 -0
  35. package/app/docs/context.ts +33 -0
  36. package/app/docs/embed.ts +74 -0
  37. package/app/docs/env.d.ts +2 -0
  38. package/app/docs/format.ts +9 -0
  39. package/app/docs/hooks/useUrlTab.ts +16 -0
  40. package/app/docs/main.tsx +11 -0
  41. package/app/docs/queryClient.ts +54 -0
  42. package/app/docs/router.tsx +194 -0
  43. package/app/docs/routing.ts +194 -0
  44. package/app/docs/screens/docs/document.ts +27 -0
  45. package/app/docs/screens/docs/http/OperationView.tsx +407 -0
  46. package/app/docs/screens/docs/http/Sidebar.tsx +190 -0
  47. package/app/docs/screens/docs/http/TryItPanel.tsx +603 -0
  48. package/app/docs/screens/docs/http/http.css +405 -0
  49. package/app/docs/screens/docs/http/index.tsx +395 -0
  50. package/app/docs/screens/docs/http/model.ts +604 -0
  51. package/app/docs/screens/docs/http/tryIt.ts +455 -0
  52. package/app/docs/screens/docs/permissions.ts +6 -0
  53. package/app/docs/screens/docs/schema/Prose.tsx +43 -0
  54. package/app/docs/screens/docs/schema/SchemaTree.tsx +319 -0
  55. package/app/docs/screens/docs/schema/index.ts +30 -0
  56. package/app/docs/screens/docs/schema/resolve.ts +466 -0
  57. package/app/docs/screens/docs/schema/schema.css +137 -0
  58. package/app/docs/screens/docs/schema/skeleton.ts +92 -0
  59. package/app/docs/screens/docs/viewer.tsx +154 -0
  60. package/app/docs/screens/docs/ws/InlineText.tsx +25 -0
  61. package/app/docs/screens/docs/ws/PayloadSchema.tsx +39 -0
  62. package/app/docs/screens/docs/ws/format.ts +82 -0
  63. package/app/docs/screens/docs/ws/index.tsx +286 -0
  64. package/app/docs/screens/docs/ws/items.tsx +786 -0
  65. package/app/docs/screens/docs/ws/model.ts +1178 -0
  66. package/app/docs/screens/docs/ws/panels.tsx +440 -0
  67. package/app/docs/screens/docs/ws/ws.css +231 -0
  68. package/app/docs/shortcuts.ts +94 -0
  69. package/app/docs/styles/base.css +847 -0
  70. package/app/docs/styles/tokens.css +143 -0
  71. package/app/docs/theme.ts +56 -0
  72. package/app/kit/unauthorized.ts +222 -0
  73. package/dist/docs/assets/main-0rchxtv5.js +18 -0
  74. package/dist/docs/assets/main-0rchxtv5.js.map +99 -0
  75. package/dist/docs/assets/main-cqgyvs86.css +1 -0
  76. package/dist/docs/manifest.json +26 -0
  77. package/dist/jobs/assets/AddFlowDialog-h6xkgx9b.js +6 -0
  78. package/dist/jobs/assets/AddFlowDialog-h6xkgx9b.js.map +11 -0
  79. package/dist/jobs/assets/AddFlowDialog-n7gtc84v.css +1 -0
  80. package/dist/jobs/assets/added-cbwsxv3e.js +4 -0
  81. package/dist/jobs/assets/added-cbwsxv3e.js.map +11 -0
  82. package/dist/jobs/assets/bodies-yyw5hmrp.js +6 -0
  83. package/dist/jobs/assets/bodies-yyw5hmrp.js.map +10 -0
  84. package/dist/jobs/assets/channel-tgkvqm8y.js +4 -0
  85. package/dist/jobs/assets/channel-tgkvqm8y.js.map +10 -0
  86. package/dist/jobs/assets/channelChecks-s4yz4yhw.js +4 -0
  87. package/dist/jobs/assets/channelChecks-s4yz4yhw.js.map +10 -0
  88. package/dist/jobs/assets/index-02427smp.css +1 -0
  89. package/dist/jobs/assets/index-09z2cjft.js +4 -0
  90. package/dist/jobs/assets/index-09z2cjft.js.map +16 -0
  91. package/dist/jobs/assets/index-18bn0gvy.css +1 -0
  92. package/dist/jobs/assets/index-47pxmyxn.js +4 -0
  93. package/dist/jobs/assets/index-47pxmyxn.js.map +10 -0
  94. package/dist/jobs/assets/index-4e55z986.js +4 -0
  95. package/dist/jobs/assets/index-4e55z986.js.map +11 -0
  96. package/dist/jobs/assets/index-5c933424.js +4 -0
  97. package/dist/jobs/assets/index-5c933424.js.map +18 -0
  98. package/dist/jobs/assets/index-5kbyqspm.css +1 -0
  99. package/dist/jobs/assets/index-5ng37hk6.css +1 -0
  100. package/dist/jobs/assets/index-5w8w7fvc.css +1 -0
  101. package/dist/jobs/assets/index-71qs5qyx.css +1 -0
  102. package/dist/jobs/assets/index-btpg4r8b.css +1 -0
  103. package/dist/jobs/assets/index-d5r5n0mm.js +4 -0
  104. package/dist/jobs/assets/index-d5r5n0mm.js.map +23 -0
  105. package/dist/jobs/assets/index-e0yy2skq.css +1 -0
  106. package/dist/jobs/assets/index-hs60b25v.js +10 -0
  107. package/dist/jobs/assets/index-hs60b25v.js.map +62 -0
  108. package/dist/jobs/assets/index-k2smrr70.js +4 -0
  109. package/dist/jobs/assets/index-k2smrr70.js.map +9 -0
  110. package/dist/jobs/assets/index-q24jw3w9.js +4 -0
  111. package/dist/jobs/assets/index-q24jw3w9.js.map +32 -0
  112. package/dist/jobs/assets/index-qfb80xen.css +1 -0
  113. package/dist/jobs/assets/index-rtynx6wj.js +4 -0
  114. package/dist/jobs/assets/index-rtynx6wj.js.map +10 -0
  115. package/dist/jobs/assets/live-6k7s6358.js +4 -0
  116. package/dist/jobs/assets/live-6k7s6358.js.map +10 -0
  117. package/dist/jobs/assets/main-0jmeh6mq.js +6 -0
  118. package/dist/jobs/assets/main-0jmeh6mq.js.map +12 -0
  119. package/dist/jobs/assets/main-3yj6bv90.js +5 -0
  120. package/dist/jobs/assets/main-3yj6bv90.js.map +10 -0
  121. package/dist/jobs/assets/main-4g69fn3x.js +5 -0
  122. package/dist/jobs/assets/main-4g69fn3x.js.map +10 -0
  123. package/dist/jobs/assets/main-4gte3eqq.js +5 -0
  124. package/dist/jobs/assets/main-4gte3eqq.js.map +10 -0
  125. package/dist/jobs/assets/main-4j1fcevh.js +5 -0
  126. package/dist/jobs/assets/main-4j1fcevh.js.map +10 -0
  127. package/dist/jobs/assets/main-54qwkz28.css +1 -0
  128. package/dist/jobs/assets/main-5grjvsy7.js +5 -0
  129. package/dist/jobs/assets/main-5grjvsy7.js.map +11 -0
  130. package/dist/jobs/assets/main-5zbx60gq.js +5 -0
  131. package/dist/jobs/assets/main-5zbx60gq.js.map +11 -0
  132. package/dist/jobs/assets/main-9prgjhg4.js +5 -0
  133. package/dist/jobs/assets/main-9prgjhg4.js.map +10 -0
  134. package/dist/jobs/assets/main-a250ffk7.js +17 -0
  135. package/dist/jobs/assets/main-a250ffk7.js.map +115 -0
  136. package/dist/jobs/assets/main-d6ge7w08.js +5 -0
  137. package/dist/jobs/assets/main-d6ge7w08.js.map +10 -0
  138. package/dist/jobs/assets/main-gngzht43.js +5 -0
  139. package/dist/jobs/assets/main-gngzht43.js.map +10 -0
  140. package/dist/jobs/assets/main-hg0hrg8j.js +5 -0
  141. package/dist/jobs/assets/main-hg0hrg8j.js.map +10 -0
  142. package/dist/jobs/assets/main-hm1ng3yg.js +5 -0
  143. package/dist/jobs/assets/main-hm1ng3yg.js.map +12 -0
  144. package/dist/jobs/assets/main-jkvd92z9.js +5 -0
  145. package/dist/jobs/assets/main-jkvd92z9.js.map +10 -0
  146. package/dist/jobs/assets/main-jv5xqd13.js +5 -0
  147. package/dist/jobs/assets/main-jv5xqd13.js.map +21 -0
  148. package/dist/jobs/assets/main-jxre7w93.js +5 -0
  149. package/dist/jobs/assets/main-jxre7w93.js.map +23 -0
  150. package/dist/jobs/assets/main-kwmqkjfx.js +5 -0
  151. package/dist/jobs/assets/main-kwmqkjfx.js.map +11 -0
  152. package/dist/jobs/assets/main-n9cf6bxm.js +5 -0
  153. package/dist/jobs/assets/main-n9cf6bxm.js.map +11 -0
  154. package/dist/jobs/assets/main-pegp0ygb.js +5 -0
  155. package/dist/jobs/assets/main-pegp0ygb.js.map +10 -0
  156. package/dist/jobs/assets/main-qr573853.js +5 -0
  157. package/dist/jobs/assets/main-qr573853.js.map +12 -0
  158. package/dist/jobs/assets/main-rq97rdr4.js +4 -0
  159. package/dist/jobs/assets/main-rq97rdr4.js.map +22 -0
  160. package/dist/jobs/assets/main-szjdmydc.js +5 -0
  161. package/dist/jobs/assets/main-szjdmydc.js.map +13 -0
  162. package/dist/jobs/assets/main-tnbhrm9n.js +7 -0
  163. package/dist/jobs/assets/main-tnbhrm9n.js.map +11 -0
  164. package/dist/jobs/assets/main-ts19j4n0.js +5 -0
  165. package/dist/jobs/assets/main-ts19j4n0.js.map +25 -0
  166. package/dist/jobs/assets/main-w93x1dzs.js +5 -0
  167. package/dist/jobs/assets/main-w93x1dzs.js.map +10 -0
  168. package/dist/jobs/assets/sections-0ksdxs8m.css +1 -0
  169. package/dist/jobs/assets/sections-0y7w4fb4.js +4 -0
  170. package/dist/jobs/assets/sections-0y7w4fb4.js.map +10 -0
  171. package/dist/jobs/assets/sse-mn0t0fh7.js +5 -0
  172. package/dist/jobs/assets/sse-mn0t0fh7.js.map +11 -0
  173. package/dist/jobs/assets/sseChecks-t7tcm7ra.js +4 -0
  174. package/dist/jobs/assets/sseChecks-t7tcm7ra.js.map +10 -0
  175. package/dist/jobs/assets/validation-ysjfy072.js +4 -0
  176. package/dist/jobs/assets/validation-ysjfy072.js.map +9 -0
  177. package/dist/jobs/manifest.json +511 -0
  178. package/dts/docs/assets.d.ts +144 -0
  179. package/dts/docs/assets.d.ts.map +1 -0
  180. package/dts/docs/browser/config.d.ts +61 -0
  181. package/dts/docs/browser/config.d.ts.map +1 -0
  182. package/dts/docs/browser/index.d.ts +12 -0
  183. package/dts/docs/browser/index.d.ts.map +1 -0
  184. package/dts/docs/docsUi.d.ts +42 -0
  185. package/dts/docs/docsUi.d.ts.map +1 -0
  186. package/dts/docs/hosted.d.ts +22 -0
  187. package/dts/docs/hosted.d.ts.map +1 -0
  188. package/dts/docs/index.d.ts +18 -0
  189. package/dts/docs/index.d.ts.map +1 -0
  190. package/dts/docs/shell.d.ts +57 -0
  191. package/dts/docs/shell.d.ts.map +1 -0
  192. package/dts/docs/types.d.ts +137 -0
  193. package/dts/docs/types.d.ts.map +1 -0
  194. package/dts/index.d.ts +21 -0
  195. package/dts/index.d.ts.map +1 -0
  196. package/dts/jobs/assets.d.ts +157 -0
  197. package/dts/jobs/assets.d.ts.map +1 -0
  198. package/dts/jobs/browser/config.d.ts +67 -0
  199. package/dts/jobs/browser/config.d.ts.map +1 -0
  200. package/dts/jobs/browser/index.d.ts +10 -0
  201. package/dts/jobs/browser/index.d.ts.map +1 -0
  202. package/dts/jobs/browser/unauthorized.d.ts +9 -0
  203. package/dts/jobs/browser/unauthorized.d.ts.map +1 -0
  204. package/dts/jobs/index.d.ts +24 -0
  205. package/dts/jobs/index.d.ts.map +1 -0
  206. package/dts/jobs/jobsUi.d.ts +63 -0
  207. package/dts/jobs/jobsUi.d.ts.map +1 -0
  208. package/dts/jobs/shell.d.ts +77 -0
  209. package/dts/jobs/shell.d.ts.map +1 -0
  210. package/dts/jobs/types.d.ts +146 -0
  211. package/dts/jobs/types.d.ts.map +1 -0
  212. package/dts/kit/browser/shared.d.ts +10 -0
  213. package/dts/kit/browser/shared.d.ts.map +1 -0
  214. package/dts/kit/browser/unauthorized.d.ts +74 -0
  215. package/dts/kit/browser/unauthorized.d.ts.map +1 -0
  216. package/dts/kit/unauthorized.d.ts +47 -0
  217. package/dts/kit/unauthorized.d.ts.map +1 -0
  218. package/guides/docs.md +170 -0
  219. package/guides/jobs.md +1120 -0
  220. package/lib/docs/assets.ts +427 -0
  221. package/lib/docs/browser/config.ts +66 -0
  222. package/lib/docs/browser/index.ts +24 -0
  223. package/lib/docs/docsUi.ts +623 -0
  224. package/lib/docs/hosted.ts +31 -0
  225. package/lib/docs/index.ts +37 -0
  226. package/lib/docs/shell.ts +156 -0
  227. package/lib/docs/types.ts +149 -0
  228. package/lib/index.ts +27 -0
  229. package/lib/jobs/assets.ts +448 -0
  230. package/lib/jobs/browser/config.ts +65 -0
  231. package/lib/jobs/browser/index.ts +9 -0
  232. package/lib/jobs/browser/unauthorized.ts +11 -0
  233. package/lib/jobs/index.ts +41 -0
  234. package/lib/jobs/jobsUi.ts +709 -0
  235. package/lib/jobs/shell.ts +205 -0
  236. package/lib/jobs/types.ts +162 -0
  237. package/lib/kit/browser/shared.ts +11 -0
  238. package/lib/kit/browser/unauthorized.ts +114 -0
  239. package/lib/kit/unauthorized.ts +222 -0
  240. package/package.json +198 -4
@@ -0,0 +1,847 @@
1
+ /* Base styles and component classes. Tokens live in tokens.css. */
2
+ *,
3
+ *::before,
4
+ *::after {
5
+ box-sizing: border-box;
6
+ }
7
+
8
+ html,
9
+ body {
10
+ margin: 0;
11
+ padding: 0;
12
+ }
13
+
14
+ body {
15
+ background: var(--bg);
16
+ color: var(--text);
17
+ font-family: var(--font-sans);
18
+ font-size: var(--text-md);
19
+ line-height: 1.45;
20
+ -webkit-font-smoothing: antialiased;
21
+ }
22
+
23
+ a {
24
+ color: var(--accent);
25
+ }
26
+
27
+ code {
28
+ font-family: var(--font-mono);
29
+ font-size: 0.92em;
30
+ }
31
+
32
+ :focus-visible {
33
+ outline: 2px solid var(--focus);
34
+ outline-offset: 2px;
35
+ }
36
+
37
+ .visually-hidden {
38
+ position: absolute !important;
39
+ width: 1px;
40
+ height: 1px;
41
+ padding: 0;
42
+ margin: -1px;
43
+ overflow: hidden;
44
+ clip: rect(0 0 0 0);
45
+ white-space: nowrap;
46
+ border: 0;
47
+ }
48
+
49
+ .muted {
50
+ color: var(--text-muted);
51
+ }
52
+
53
+ .skip-link {
54
+ position: absolute;
55
+ left: var(--space-2);
56
+ top: -40px;
57
+ padding: var(--space-2) var(--space-3);
58
+ background: var(--surface);
59
+ border: 1px solid var(--border);
60
+ border-radius: var(--radius-sm);
61
+ z-index: 10;
62
+ }
63
+
64
+ .skip-link:focus {
65
+ top: var(--space-2);
66
+ }
67
+
68
+ /* ---- Frame ---- */
69
+ .app {
70
+ min-height: 100vh;
71
+ display: flex;
72
+ flex-direction: column;
73
+ }
74
+
75
+ .app-header {
76
+ position: sticky;
77
+ top: 0;
78
+ z-index: 5;
79
+ display: flex;
80
+ flex-wrap: wrap;
81
+ align-items: center;
82
+ gap: var(--space-2) var(--space-4);
83
+ min-height: var(--header-height);
84
+ padding: var(--space-2) var(--space-4);
85
+ background: var(--surface);
86
+ border-bottom: 1px solid var(--border);
87
+ }
88
+
89
+ .app-brand {
90
+ font-weight: 650;
91
+ font-size: var(--text-lg);
92
+ color: var(--text);
93
+ text-decoration: none;
94
+ }
95
+
96
+ .app-chips {
97
+ display: flex;
98
+ flex-wrap: wrap;
99
+ gap: var(--space-2);
100
+ min-width: 0;
101
+ }
102
+
103
+ .app-header-end {
104
+ display: flex;
105
+ align-items: center;
106
+ gap: var(--space-2);
107
+ margin-left: auto;
108
+ min-width: 0;
109
+ }
110
+
111
+ .app-body {
112
+ flex: 1;
113
+ display: flex;
114
+ min-height: 0;
115
+ }
116
+
117
+ .app-nav {
118
+ flex: 0 0 var(--nav-width);
119
+ padding: var(--space-4) var(--space-2);
120
+ border-right: 1px solid var(--border);
121
+ background: var(--surface);
122
+ }
123
+
124
+ .app-nav ul {
125
+ list-style: none;
126
+ margin: 0;
127
+ padding: 0;
128
+ display: flex;
129
+ flex-direction: column;
130
+ gap: var(--space-1);
131
+ }
132
+
133
+ .app-nav-link {
134
+ display: block;
135
+ padding: var(--space-2) var(--space-3);
136
+ border-radius: var(--radius-sm);
137
+ color: var(--text);
138
+ text-decoration: none;
139
+ white-space: nowrap;
140
+ }
141
+
142
+ .app-nav .app-nav-sub {
143
+ margin-top: var(--space-1);
144
+ padding-left: var(--space-3);
145
+ }
146
+
147
+ .app-nav-sub .app-nav-link {
148
+ font-size: var(--text-sm);
149
+ }
150
+
151
+ .app-nav-link:hover {
152
+ background: var(--surface-2);
153
+ }
154
+
155
+ .app-nav-link[aria-current="page"] {
156
+ background: var(--info-bg);
157
+ color: var(--info-text);
158
+ font-weight: 600;
159
+ }
160
+
161
+ .app-main {
162
+ flex: 1;
163
+ min-width: 0;
164
+ padding: var(--space-5);
165
+ }
166
+
167
+ .app-main:focus {
168
+ outline: none;
169
+ }
170
+
171
+ .screen {
172
+ display: flex;
173
+ flex-direction: column;
174
+ gap: var(--space-4);
175
+ max-width: 1400px;
176
+ }
177
+
178
+ .screen-title {
179
+ margin: 0;
180
+ font-size: var(--text-xl);
181
+ }
182
+
183
+ .bootstrap-screen {
184
+ min-height: 100vh;
185
+ display: flex;
186
+ flex-direction: column;
187
+ align-items: center;
188
+ justify-content: center;
189
+ gap: var(--space-4);
190
+ padding: var(--space-4);
191
+ }
192
+
193
+ .bootstrap-title {
194
+ margin: 0;
195
+ font-size: var(--text-xl);
196
+ }
197
+
198
+ /* ---- Components ---- */
199
+ .btn {
200
+ display: inline-flex;
201
+ align-items: center;
202
+ gap: var(--space-2);
203
+ padding: var(--space-2) var(--space-3);
204
+ border: 1px solid var(--border);
205
+ border-radius: var(--radius-sm);
206
+ background: var(--surface);
207
+ color: var(--text);
208
+ font: inherit;
209
+ font-size: var(--text-sm);
210
+ cursor: pointer;
211
+ }
212
+
213
+ .btn:hover {
214
+ background: var(--surface-2);
215
+ }
216
+
217
+ .btn:disabled {
218
+ opacity: 0.55;
219
+ cursor: not-allowed;
220
+ }
221
+
222
+ .btn-primary {
223
+ background: var(--accent);
224
+ border-color: var(--accent);
225
+ color: var(--accent-contrast);
226
+ }
227
+
228
+ .btn-primary:hover {
229
+ background: var(--accent);
230
+ filter: brightness(1.08);
231
+ }
232
+
233
+ .btn-danger {
234
+ background: var(--danger);
235
+ border-color: var(--danger);
236
+ color: var(--danger-contrast);
237
+ }
238
+
239
+ .btn-danger:hover {
240
+ background: var(--danger);
241
+ filter: brightness(1.08);
242
+ }
243
+
244
+ .btn-ghost {
245
+ background: transparent;
246
+ border-color: transparent;
247
+ }
248
+
249
+ .btn-sm {
250
+ padding: var(--space-1) var(--space-2);
251
+ font-size: var(--text-xs);
252
+ }
253
+
254
+ .badge {
255
+ display: inline-flex;
256
+ align-items: center;
257
+ gap: var(--space-1);
258
+ padding: 2px var(--space-2);
259
+ border-radius: var(--radius-pill);
260
+ font-size: var(--text-xs);
261
+ font-weight: 550;
262
+ white-space: nowrap;
263
+ max-width: 100%;
264
+ overflow: hidden;
265
+ text-overflow: ellipsis;
266
+ }
267
+
268
+ .badge-neutral {
269
+ background: var(--neutral-bg);
270
+ color: var(--neutral-text);
271
+ }
272
+
273
+ .badge-info {
274
+ background: var(--info-bg);
275
+ color: var(--info-text);
276
+ }
277
+
278
+ .badge-success {
279
+ background: var(--success-bg);
280
+ color: var(--success-text);
281
+ }
282
+
283
+ .badge-warning {
284
+ background: var(--warning-bg);
285
+ color: var(--warning-text);
286
+ }
287
+
288
+ .badge-danger {
289
+ background: var(--danger-bg);
290
+ color: var(--danger-text);
291
+ }
292
+
293
+ .badge-accent {
294
+ background: var(--accent);
295
+ color: var(--accent-contrast);
296
+ }
297
+
298
+ .chip {
299
+ display: inline-flex;
300
+ align-items: baseline;
301
+ gap: var(--space-1);
302
+ padding: 2px var(--space-2);
303
+ border: 1px solid var(--border);
304
+ border-radius: var(--radius-pill);
305
+ font-size: var(--text-xs);
306
+ max-width: 100%;
307
+ }
308
+
309
+ .chip-label {
310
+ color: var(--text-muted);
311
+ }
312
+
313
+ .chip-value {
314
+ font-weight: 600;
315
+ overflow: hidden;
316
+ text-overflow: ellipsis;
317
+ white-space: nowrap;
318
+ }
319
+
320
+ .live-dot {
321
+ width: 6px;
322
+ height: 6px;
323
+ border-radius: 50%;
324
+ background: currentColor;
325
+ }
326
+
327
+ .card {
328
+ background: var(--surface);
329
+ border: 1px solid var(--border);
330
+ border-radius: var(--radius);
331
+ box-shadow: var(--shadow);
332
+ min-width: 0;
333
+ }
334
+
335
+ .card-header {
336
+ display: flex;
337
+ flex-wrap: wrap;
338
+ align-items: center;
339
+ justify-content: space-between;
340
+ gap: var(--space-3);
341
+ padding: var(--space-3) var(--space-4);
342
+ border-bottom: 1px solid var(--border);
343
+ }
344
+
345
+ .card-title {
346
+ margin: 0;
347
+ font-size: var(--text-lg);
348
+ }
349
+
350
+ .card-body {
351
+ padding: var(--space-4);
352
+ }
353
+
354
+ .input {
355
+ width: 100%;
356
+ min-width: 0;
357
+ padding: var(--space-2) var(--space-3);
358
+ border: 1px solid var(--border-strong);
359
+ border-radius: var(--radius-sm);
360
+ background: var(--surface);
361
+ color: var(--text);
362
+ font: inherit;
363
+ font-size: var(--text-sm);
364
+ }
365
+
366
+ .search {
367
+ flex: 0 1 260px;
368
+ min-width: 0;
369
+ }
370
+
371
+ /*
372
+ * A search placed straight in a screen's column (the Workers page, the queue
373
+ * filter under a card title): there the flex basis above would be a HEIGHT,
374
+ * and the box grew 260px tall. Size it by width instead.
375
+ */
376
+ .screen > .search,
377
+ .queues-search {
378
+ flex: none;
379
+ width: min(100%, 260px);
380
+ }
381
+
382
+ .table-wrap {
383
+ overflow: auto;
384
+ max-height: 70vh;
385
+ border: 1px solid var(--border);
386
+ border-radius: var(--radius-sm);
387
+ }
388
+
389
+ .table {
390
+ width: 100%;
391
+ border-collapse: separate;
392
+ border-spacing: 0;
393
+ font-size: var(--text-sm);
394
+ }
395
+
396
+ .table th,
397
+ .table td {
398
+ padding: var(--space-2) var(--space-3);
399
+ border-bottom: 1px solid var(--border);
400
+ text-align: left;
401
+ vertical-align: middle;
402
+ white-space: nowrap;
403
+ }
404
+
405
+ .table thead th {
406
+ position: sticky;
407
+ top: 0;
408
+ z-index: 1;
409
+ background: var(--surface-2);
410
+ font-weight: 600;
411
+ }
412
+
413
+ .table tbody tr:hover {
414
+ background: var(--surface-2);
415
+ }
416
+
417
+ .table .num {
418
+ text-align: right;
419
+ font-variant-numeric: tabular-nums;
420
+ }
421
+
422
+ /* Dimmed by colour alone: an opacity on top would take it below 4.5:1. */
423
+ .table .zero {
424
+ color: var(--text-muted);
425
+ }
426
+
427
+ .queue-name {
428
+ font-weight: 500;
429
+ }
430
+
431
+ .queue-paused {
432
+ margin-left: var(--space-2);
433
+ }
434
+
435
+ .empty-state {
436
+ padding: var(--space-5) var(--space-4);
437
+ text-align: center;
438
+ color: var(--text-muted);
439
+ }
440
+
441
+ .empty-state-title {
442
+ margin: 0 0 var(--space-1);
443
+ font-size: inherit;
444
+ font-weight: 600;
445
+ color: var(--text);
446
+ }
447
+
448
+ .empty-state-description {
449
+ margin: 0;
450
+ }
451
+
452
+ .empty-state-action {
453
+ margin-top: var(--space-3);
454
+ }
455
+
456
+ .error-view {
457
+ display: flex;
458
+ flex-direction: column;
459
+ align-items: flex-start;
460
+ gap: var(--space-2);
461
+ padding: var(--space-3) var(--space-4);
462
+ border: 1px solid var(--danger);
463
+ border-radius: var(--radius-sm);
464
+ background: var(--danger-bg);
465
+ color: var(--danger-text);
466
+ max-width: 640px;
467
+ }
468
+
469
+ .error-view p {
470
+ margin: 0;
471
+ }
472
+
473
+ .error-view-title {
474
+ margin: 0;
475
+ font-size: inherit;
476
+ font-weight: 650;
477
+ }
478
+
479
+ .error-view-issues {
480
+ margin: 0;
481
+ padding-left: var(--space-4);
482
+ }
483
+
484
+ .notice {
485
+ margin: var(--space-3) 0 0;
486
+ padding: var(--space-2) var(--space-3);
487
+ border-radius: var(--radius-sm);
488
+ background: var(--warning-bg);
489
+ color: var(--warning-text);
490
+ font-size: var(--text-sm);
491
+ }
492
+
493
+ .spinner-wrap {
494
+ display: inline-flex;
495
+ align-items: center;
496
+ gap: var(--space-2);
497
+ color: var(--text-muted);
498
+ }
499
+
500
+ .spinner {
501
+ width: 16px;
502
+ height: 16px;
503
+ border: 2px solid var(--border);
504
+ border-top-color: var(--accent);
505
+ border-radius: 50%;
506
+ animation: spin 0.8s linear infinite;
507
+ }
508
+
509
+ @keyframes spin {
510
+ to {
511
+ transform: rotate(360deg);
512
+ }
513
+ }
514
+
515
+ /*
516
+ * Reduced motion: no transition or animation anywhere, whichever stylesheet
517
+ * declares it (a screen's chunk included), except the spinner, which keeps
518
+ * turning slowly: a spinner that stops no longer says "busy".
519
+ */
520
+ @media (prefers-reduced-motion: reduce) {
521
+ *,
522
+ *::before,
523
+ *::after {
524
+ animation-duration: 0.01ms !important;
525
+ animation-iteration-count: 1 !important;
526
+ transition-duration: 0.01ms !important;
527
+ transition-delay: 0s !important;
528
+ scroll-behavior: auto !important;
529
+ }
530
+
531
+ .spinner {
532
+ animation-duration: 2.4s !important;
533
+ animation-iteration-count: infinite !important;
534
+ }
535
+ }
536
+
537
+ /* Job states */
538
+ .state-badge {
539
+ display: inline-flex;
540
+ align-items: center;
541
+ gap: 6px;
542
+ white-space: nowrap;
543
+ }
544
+
545
+ .state-dot {
546
+ width: 8px;
547
+ height: 8px;
548
+ border-radius: 50%;
549
+ background: var(--state-color, var(--text-muted));
550
+ flex: none;
551
+ }
552
+
553
+ .state-waiting {
554
+ --state-color: var(--state-waiting);
555
+ }
556
+ .state-delayed {
557
+ --state-color: var(--state-delayed);
558
+ }
559
+ .state-active {
560
+ --state-color: var(--state-active);
561
+ }
562
+ .state-completed {
563
+ --state-color: var(--state-completed);
564
+ }
565
+ .state-failed {
566
+ --state-color: var(--state-failed);
567
+ }
568
+ .state-dead {
569
+ --state-color: var(--state-dead);
570
+ }
571
+ .state-waiting-children {
572
+ --state-color: var(--state-waiting-children);
573
+ }
574
+
575
+ /* Stats */
576
+ .overview-summary {
577
+ display: flex;
578
+ flex-direction: column;
579
+ gap: var(--space-3);
580
+ }
581
+
582
+ .stat-grid {
583
+ display: grid;
584
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
585
+ gap: var(--space-3);
586
+ margin: 0;
587
+ }
588
+
589
+ .stat {
590
+ padding: var(--space-3);
591
+ border: 1px solid var(--border);
592
+ border-radius: var(--radius-sm);
593
+ background: var(--surface);
594
+ min-width: 0;
595
+ }
596
+
597
+ .stat-state {
598
+ border-top: 3px solid var(--state-color);
599
+ }
600
+
601
+ .stat dd {
602
+ margin: 0;
603
+ }
604
+
605
+ .stat-label {
606
+ font-size: var(--text-sm);
607
+ color: var(--text-muted);
608
+ }
609
+
610
+ .stat-value {
611
+ font-size: var(--text-xl);
612
+ font-weight: 650;
613
+ font-variant-numeric: tabular-nums;
614
+ overflow-wrap: anywhere;
615
+ }
616
+
617
+ .stat-hint {
618
+ font-size: var(--text-xs);
619
+ color: var(--text-muted);
620
+ }
621
+
622
+ /*
623
+ * "Over the range": a full-width band under the totals, not a tile in their
624
+ * grid. In the grid its figures stacked into one tall column and stretched the
625
+ * other tiles to match; here each group is one row of compact cells — a small
626
+ * label over its number, like the state row above — and the two groups sit
627
+ * side by side, wrapping under each other only on a narrow screen.
628
+ */
629
+ .range-band {
630
+ margin-top: var(--space-3);
631
+ padding: var(--space-3);
632
+ border: 1px solid var(--border);
633
+ border-radius: var(--radius-sm);
634
+ background: var(--surface);
635
+ }
636
+
637
+ .range-band-head {
638
+ display: flex;
639
+ flex-wrap: wrap;
640
+ align-items: baseline;
641
+ gap: var(--space-2);
642
+ margin: 0 0 var(--space-2);
643
+ font-size: var(--text-sm);
644
+ }
645
+
646
+ .range-band-title {
647
+ font-weight: 600;
648
+ }
649
+
650
+ .range-band-groups {
651
+ display: flex;
652
+ flex-wrap: wrap;
653
+ gap: var(--space-3) var(--space-5);
654
+ }
655
+
656
+ .range-group {
657
+ flex: 0 1 auto;
658
+ min-width: 0;
659
+ }
660
+
661
+ /* The added-by-state group has eight cells to the finished group's two. */
662
+ .range-group-wide {
663
+ flex: 1 1 32rem;
664
+ }
665
+
666
+ .range-group-title {
667
+ margin: 0 0 var(--space-1);
668
+ font-size: var(--text-xs);
669
+ font-weight: 600;
670
+ color: var(--text-muted);
671
+ }
672
+
673
+ .range-cells {
674
+ display: flex;
675
+ flex-wrap: wrap;
676
+ gap: var(--space-1) var(--space-4);
677
+ margin: 0;
678
+ }
679
+
680
+ .range-cell dt {
681
+ font-size: var(--text-xs);
682
+ color: var(--text-muted);
683
+ white-space: nowrap;
684
+ }
685
+
686
+ .range-cell dd {
687
+ margin: 0;
688
+ font-weight: 600;
689
+ font-variant-numeric: tabular-nums;
690
+ }
691
+
692
+ /*
693
+ * Set apart by weight, not a divider: when the cells wrap, a left border would
694
+ * be left hanging at the start of the next line.
695
+ */
696
+ .range-cell-total dt {
697
+ font-weight: 600;
698
+ color: var(--text);
699
+ }
700
+
701
+ .range-note {
702
+ margin: var(--space-1) 0 0;
703
+ font-size: var(--text-xs);
704
+ color: var(--text-muted);
705
+ }
706
+
707
+ /* Sparkline */
708
+ .sparkline-cell {
709
+ display: inline-flex;
710
+ align-items: center;
711
+ min-width: 120px;
712
+ min-height: 28px;
713
+ }
714
+
715
+ .sparkline {
716
+ display: block;
717
+ overflow: visible;
718
+ }
719
+
720
+ .sparkline polyline {
721
+ fill: none;
722
+ stroke-width: 1.5;
723
+ stroke-linejoin: round;
724
+ stroke-linecap: round;
725
+ }
726
+
727
+ .sparkline-primary {
728
+ stroke: var(--state-completed);
729
+ }
730
+
731
+ .sparkline-secondary {
732
+ stroke: var(--state-failed);
733
+ opacity: 0.8;
734
+ }
735
+
736
+ .sparkline-baseline {
737
+ stroke: var(--border);
738
+ stroke-width: 1;
739
+ }
740
+
741
+ .sparkline-placeholder {
742
+ display: block;
743
+ width: 120px;
744
+ height: 2px;
745
+ background: var(--border);
746
+ }
747
+
748
+ /* ---- Narrow screens: the nav becomes a scrolling row under the header ---- */
749
+ @media (max-width: 720px) {
750
+ .app-body {
751
+ flex-direction: column;
752
+ }
753
+
754
+ .app-nav {
755
+ flex: none;
756
+ padding: var(--space-2);
757
+ border-right: 0;
758
+ border-bottom: 1px solid var(--border);
759
+ overflow-x: auto;
760
+ }
761
+
762
+ .app-nav ul {
763
+ flex-direction: row;
764
+ }
765
+
766
+ /* A parent and its children sit on the one row. */
767
+ .app-nav li {
768
+ display: flex;
769
+ gap: var(--space-1);
770
+ }
771
+
772
+ .app-nav .app-nav-sub {
773
+ margin-top: 0;
774
+ padding-left: 0;
775
+ }
776
+
777
+ .app-main {
778
+ padding: var(--space-4);
779
+ }
780
+
781
+ .app-header {
782
+ position: static;
783
+ padding: var(--space-2) var(--space-4);
784
+ }
785
+
786
+ .app-header-end {
787
+ margin-left: 0;
788
+ width: 100%;
789
+ justify-content: space-between;
790
+ }
791
+
792
+ .live-status {
793
+ min-width: 0;
794
+ overflow: hidden;
795
+ }
796
+
797
+ .search {
798
+ flex-basis: 100%;
799
+ }
800
+
801
+ .stat-grid {
802
+ grid-template-columns: repeat(2, minmax(0, 1fr));
803
+ }
804
+ }
805
+
806
+ /* The Overview's title row: the heading left, the range control right. */
807
+ .overview-header {
808
+ display: flex;
809
+ flex-wrap: wrap;
810
+ align-items: flex-start;
811
+ justify-content: space-between;
812
+ gap: var(--space-3);
813
+ margin-bottom: var(--space-4);
814
+ }
815
+
816
+ .overview-header .screen-title {
817
+ margin: 0;
818
+ }
819
+
820
+ /* The range control and its toggle, stacked at the right of the title row. */
821
+ .overview-range {
822
+ display: flex;
823
+ flex-direction: column;
824
+ align-items: flex-end;
825
+ gap: var(--space-2);
826
+ margin-left: auto;
827
+ }
828
+
829
+ /* Narrow: the control drops under the heading and fills the width. */
830
+ @media (max-width: 720px) {
831
+ .overview-range {
832
+ align-items: stretch;
833
+ margin-left: 0;
834
+ width: 100%;
835
+ }
836
+ }
837
+
838
+ /* The queue filter, under the Queues card's title and above its table. */
839
+ .queues-search {
840
+ margin-bottom: var(--space-3);
841
+ }
842
+
843
+ /* The standalone viewer has no app shell: the page padding the jobs UI's
844
+ `.app-main` gives its screens. */
845
+ .docs-viewer {
846
+ padding: var(--space-5);
847
+ }