@profullstack/agenticjobs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +219 -0
  3. package/bin/agenticjobs-mcp.mjs +2 -0
  4. package/bin/agenticjobs.mjs +2 -0
  5. package/dist/cli/args.d.ts +17 -0
  6. package/dist/cli/args.js +103 -0
  7. package/dist/cli/args.js.map +1 -0
  8. package/dist/cli/format.d.ts +15 -0
  9. package/dist/cli/format.js +24 -0
  10. package/dist/cli/format.js.map +1 -0
  11. package/dist/cli/index.d.ts +13 -0
  12. package/dist/cli/index.js +620 -0
  13. package/dist/cli/index.js.map +1 -0
  14. package/dist/cli/jobfile.d.ts +15 -0
  15. package/dist/cli/jobfile.js +94 -0
  16. package/dist/cli/jobfile.js.map +1 -0
  17. package/dist/client/client.d.ts +105 -0
  18. package/dist/client/client.js +182 -0
  19. package/dist/client/client.js.map +1 -0
  20. package/dist/client/config.d.ts +33 -0
  21. package/dist/client/config.js +92 -0
  22. package/dist/client/config.js.map +1 -0
  23. package/dist/client/fanout.d.ts +35 -0
  24. package/dist/client/fanout.js +77 -0
  25. package/dist/client/fanout.js.map +1 -0
  26. package/dist/client/index.d.ts +4 -0
  27. package/dist/client/index.js +5 -0
  28. package/dist/client/index.js.map +1 -0
  29. package/dist/client/login.d.ts +23 -0
  30. package/dist/client/login.js +45 -0
  31. package/dist/client/login.js.map +1 -0
  32. package/dist/config.d.ts +40 -0
  33. package/dist/config.js +64 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/core/applications.d.ts +67 -0
  36. package/dist/core/applications.js +187 -0
  37. package/dist/core/applications.js.map +1 -0
  38. package/dist/core/auth.d.ts +120 -0
  39. package/dist/core/auth.js +246 -0
  40. package/dist/core/auth.js.map +1 -0
  41. package/dist/core/import.d.ts +52 -0
  42. package/dist/core/import.js +311 -0
  43. package/dist/core/import.js.map +1 -0
  44. package/dist/core/jobs.d.ts +91 -0
  45. package/dist/core/jobs.js +381 -0
  46. package/dist/core/jobs.js.map +1 -0
  47. package/dist/core/orgs.d.ts +21 -0
  48. package/dist/core/orgs.js +111 -0
  49. package/dist/core/orgs.js.map +1 -0
  50. package/dist/core/resumes.d.ts +51 -0
  51. package/dist/core/resumes.js +144 -0
  52. package/dist/core/resumes.js.map +1 -0
  53. package/dist/core/zip.d.ts +17 -0
  54. package/dist/core/zip.js +77 -0
  55. package/dist/core/zip.js.map +1 -0
  56. package/dist/db/index.d.ts +3 -0
  57. package/dist/db/index.js +3 -0
  58. package/dist/db/index.js.map +1 -0
  59. package/dist/db/migrate.d.ts +15 -0
  60. package/dist/db/migrate.js +67 -0
  61. package/dist/db/migrate.js.map +1 -0
  62. package/dist/db/pool.d.ts +13 -0
  63. package/dist/db/pool.js +68 -0
  64. package/dist/db/pool.js.map +1 -0
  65. package/dist/db/seed.d.ts +9 -0
  66. package/dist/db/seed.js +120 -0
  67. package/dist/db/seed.js.map +1 -0
  68. package/dist/directory/announce.d.ts +32 -0
  69. package/dist/directory/announce.js +59 -0
  70. package/dist/directory/announce.js.map +1 -0
  71. package/dist/directory/federate.d.ts +59 -0
  72. package/dist/directory/federate.js +126 -0
  73. package/dist/directory/federate.js.map +1 -0
  74. package/dist/directory/fetch.d.ts +35 -0
  75. package/dist/directory/fetch.js +138 -0
  76. package/dist/directory/fetch.js.map +1 -0
  77. package/dist/directory/index.d.ts +4 -0
  78. package/dist/directory/index.js +5 -0
  79. package/dist/directory/index.js.map +1 -0
  80. package/dist/directory/registry.d.ts +55 -0
  81. package/dist/directory/registry.js +155 -0
  82. package/dist/directory/registry.js.map +1 -0
  83. package/dist/index.d.ts +14 -0
  84. package/dist/index.js +14 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/markup/escape.d.ts +20 -0
  87. package/dist/markup/escape.js +56 -0
  88. package/dist/markup/escape.js.map +1 -0
  89. package/dist/markup/markdown.d.ts +35 -0
  90. package/dist/markup/markdown.js +279 -0
  91. package/dist/markup/markdown.js.map +1 -0
  92. package/dist/markup/resume.d.ts +72 -0
  93. package/dist/markup/resume.js +260 -0
  94. package/dist/markup/resume.js.map +1 -0
  95. package/dist/mcp/protocol.d.ts +56 -0
  96. package/dist/mcp/protocol.js +48 -0
  97. package/dist/mcp/protocol.js.map +1 -0
  98. package/dist/mcp/server.d.ts +21 -0
  99. package/dist/mcp/server.js +73 -0
  100. package/dist/mcp/server.js.map +1 -0
  101. package/dist/mcp/stdio.d.ts +13 -0
  102. package/dist/mcp/stdio.js +85 -0
  103. package/dist/mcp/stdio.js.map +1 -0
  104. package/dist/mcp/tools.d.ts +26 -0
  105. package/dist/mcp/tools.js +351 -0
  106. package/dist/mcp/tools.js.map +1 -0
  107. package/dist/schema/index.d.ts +5 -0
  108. package/dist/schema/index.js +6 -0
  109. package/dist/schema/index.js.map +1 -0
  110. package/dist/schema/instance.d.ts +85 -0
  111. package/dist/schema/instance.js +147 -0
  112. package/dist/schema/instance.js.map +1 -0
  113. package/dist/schema/job.d.ts +151 -0
  114. package/dist/schema/job.js +73 -0
  115. package/dist/schema/job.js.map +1 -0
  116. package/dist/schema/jsonld.d.ts +18 -0
  117. package/dist/schema/jsonld.js +120 -0
  118. package/dist/schema/jsonld.js.map +1 -0
  119. package/dist/schema/query.d.ts +47 -0
  120. package/dist/schema/query.js +103 -0
  121. package/dist/schema/query.js.map +1 -0
  122. package/dist/schema/text.d.ts +27 -0
  123. package/dist/schema/text.js +117 -0
  124. package/dist/schema/text.js.map +1 -0
  125. package/dist/server/app.d.ts +13 -0
  126. package/dist/server/app.js +57 -0
  127. package/dist/server/app.js.map +1 -0
  128. package/dist/server/deps.d.ts +20 -0
  129. package/dist/server/deps.js +2 -0
  130. package/dist/server/deps.js.map +1 -0
  131. package/dist/server/middleware.d.ts +39 -0
  132. package/dist/server/middleware.js +100 -0
  133. package/dist/server/middleware.js.map +1 -0
  134. package/dist/server/routes/api.d.ts +20 -0
  135. package/dist/server/routes/api.js +584 -0
  136. package/dist/server/routes/api.js.map +1 -0
  137. package/dist/server/routes/descriptor.d.ts +11 -0
  138. package/dist/server/routes/descriptor.js +31 -0
  139. package/dist/server/routes/descriptor.js.map +1 -0
  140. package/dist/server/routes/discovery.d.ts +12 -0
  141. package/dist/server/routes/discovery.js +305 -0
  142. package/dist/server/routes/discovery.js.map +1 -0
  143. package/dist/server/routes/mcp.d.ts +19 -0
  144. package/dist/server/routes/mcp.js +85 -0
  145. package/dist/server/routes/mcp.js.map +1 -0
  146. package/dist/server/routes/openapi.d.ts +11 -0
  147. package/dist/server/routes/openapi.js +297 -0
  148. package/dist/server/routes/openapi.js.map +1 -0
  149. package/dist/server/routes/pages.d.ts +11 -0
  150. package/dist/server/routes/pages.js +445 -0
  151. package/dist/server/routes/pages.js.map +1 -0
  152. package/dist/server/routes/passkey.d.ts +20 -0
  153. package/dist/server/routes/passkey.js +198 -0
  154. package/dist/server/routes/passkey.js.map +1 -0
  155. package/dist/server/routes/specs.d.ts +10 -0
  156. package/dist/server/routes/specs.js +42 -0
  157. package/dist/server/routes/specs.js.map +1 -0
  158. package/dist/server/serve.d.ts +11 -0
  159. package/dist/server/serve.js +79 -0
  160. package/dist/server/serve.js.map +1 -0
  161. package/dist/tui/index.d.ts +13 -0
  162. package/dist/tui/index.js +266 -0
  163. package/dist/tui/index.js.map +1 -0
  164. package/dist/tui/state.d.ts +63 -0
  165. package/dist/tui/state.js +136 -0
  166. package/dist/tui/state.js.map +1 -0
  167. package/dist/tui/types.d.ts +2 -0
  168. package/dist/tui/types.js +2 -0
  169. package/dist/tui/types.js.map +1 -0
  170. package/dist/tui/views.d.ts +11 -0
  171. package/dist/tui/views.js +197 -0
  172. package/dist/tui/views.js.map +1 -0
  173. package/dist/views/auth.d.ts +21 -0
  174. package/dist/views/auth.js +5 -0
  175. package/dist/views/auth.js.map +1 -0
  176. package/dist/views/docs.d.ts +17 -0
  177. package/dist/views/docs.js +40 -0
  178. package/dist/views/docs.js.map +1 -0
  179. package/dist/views/jobs.d.ts +49 -0
  180. package/dist/views/jobs.js +44 -0
  181. package/dist/views/jobs.js.map +1 -0
  182. package/dist/views/layout.d.ts +58 -0
  183. package/dist/views/layout.js +36 -0
  184. package/dist/views/layout.js.map +1 -0
  185. package/dist/views/me.d.ts +27 -0
  186. package/dist/views/me.js +6 -0
  187. package/dist/views/me.js.map +1 -0
  188. package/dist/views/network.d.ts +21 -0
  189. package/dist/views/network.js +17 -0
  190. package/dist/views/network.js.map +1 -0
  191. package/dist/views/post.d.ts +22 -0
  192. package/dist/views/post.js +20 -0
  193. package/dist/views/post.js.map +1 -0
  194. package/docs/openjob.md +200 -0
  195. package/docs/openresume.md +143 -0
  196. package/migrations/0001_init.sql +109 -0
  197. package/migrations/0002_auth.sql +82 -0
  198. package/migrations/0003_directory.sql +27 -0
  199. package/migrations/0004_resumes.sql +63 -0
  200. package/migrations/0005_application_drafts.sql +20 -0
  201. package/package.json +92 -0
  202. package/web/public/app.css +731 -0
  203. package/web/public/app.js +173 -0
  204. package/web/public/icon.svg +5 -0
  205. package/web/public/sw.js +64 -0
  206. package/web/public/tokens.css +153 -0
@@ -0,0 +1,731 @@
1
+ /*
2
+ * Components.
3
+ *
4
+ * Each class mirrors a shadcn/ui component's anatomy - .card + .card-header +
5
+ * .card-title, .badge with variants, .btn with variants and sizes - so the
6
+ * markup reads the way a shadcn app's does even though there is no React and
7
+ * no Tailwind here. Tokens come from tokens.css.
8
+ *
9
+ * Mobile first throughout: every layout is one column until a min-width says
10
+ * otherwise, and nothing depends on hover.
11
+ */
12
+
13
+ @import url('./tokens.css');
14
+
15
+ *,
16
+ *::before,
17
+ *::after {
18
+ box-sizing: border-box;
19
+ }
20
+
21
+ html {
22
+ -webkit-text-size-adjust: 100%;
23
+ }
24
+
25
+ body {
26
+ margin: 0;
27
+ background: var(--background);
28
+ color: var(--foreground);
29
+ font-family: var(--font-sans);
30
+ font-size: 16px;
31
+ line-height: 1.6;
32
+ /* iOS Safari shrinks 16px inputs unless the body agrees they are 16px. */
33
+ -webkit-font-smoothing: antialiased;
34
+ }
35
+
36
+ img {
37
+ max-width: 100%;
38
+ height: auto;
39
+ }
40
+
41
+ a {
42
+ color: var(--primary);
43
+ text-decoration-thickness: 1px;
44
+ text-underline-offset: 2px;
45
+ }
46
+
47
+ a:hover {
48
+ text-decoration-style: solid;
49
+ }
50
+
51
+ :focus-visible {
52
+ outline: 2px solid var(--ring);
53
+ outline-offset: 2px;
54
+ border-radius: calc(var(--radius) - 4px);
55
+ }
56
+
57
+ /* --- layout ------------------------------------------------------------ */
58
+
59
+ .container {
60
+ width: 100%;
61
+ max-width: 72rem;
62
+ margin: 0 auto;
63
+ padding: 0 1rem;
64
+ }
65
+
66
+ .site-header {
67
+ position: sticky;
68
+ top: 0;
69
+ z-index: 20;
70
+ background: color-mix(in oklab, var(--background) 88%, transparent);
71
+ backdrop-filter: blur(8px);
72
+ border-bottom: 1px solid var(--border);
73
+ }
74
+
75
+ .site-header .container {
76
+ display: flex;
77
+ align-items: center;
78
+ gap: 0.75rem;
79
+ min-height: 3.5rem;
80
+ flex-wrap: wrap;
81
+ }
82
+
83
+ .brand {
84
+ display: inline-flex;
85
+ align-items: center;
86
+ gap: 0.5rem;
87
+ font-weight: 650;
88
+ letter-spacing: -0.01em;
89
+ color: var(--foreground);
90
+ text-decoration: none;
91
+ margin-right: auto;
92
+ }
93
+
94
+ .brand-mark {
95
+ display: grid;
96
+ place-items: center;
97
+ width: 1.75rem;
98
+ height: 1.75rem;
99
+ border-radius: calc(var(--radius) - 2px);
100
+ background: var(--primary);
101
+ color: var(--primary-foreground);
102
+ font-size: 0.8rem;
103
+ font-weight: 700;
104
+ flex: none;
105
+ }
106
+
107
+ .nav {
108
+ display: flex;
109
+ gap: 0.25rem;
110
+ align-items: center;
111
+ flex-wrap: wrap;
112
+ }
113
+
114
+ .nav a {
115
+ color: var(--muted-foreground);
116
+ text-decoration: none;
117
+ font-size: 0.9rem;
118
+ font-weight: 500;
119
+ padding: 0.4rem 0.6rem;
120
+ border-radius: calc(var(--radius) - 4px);
121
+ }
122
+
123
+ .nav a:hover,
124
+ .nav a[aria-current='page'] {
125
+ color: var(--foreground);
126
+ background: var(--secondary);
127
+ }
128
+
129
+ main {
130
+ padding: 1.5rem 0 4rem;
131
+ }
132
+
133
+ .site-footer {
134
+ border-top: 1px solid var(--border);
135
+ padding: 2rem 0;
136
+ color: var(--muted-foreground);
137
+ font-size: 0.85rem;
138
+ }
139
+
140
+ .site-footer .container {
141
+ display: flex;
142
+ flex-wrap: wrap;
143
+ gap: 1rem 1.5rem;
144
+ align-items: baseline;
145
+ }
146
+
147
+ .site-footer a {
148
+ color: var(--muted-foreground);
149
+ }
150
+
151
+ .grid-2 {
152
+ display: grid;
153
+ gap: 1.5rem;
154
+ grid-template-columns: 1fr;
155
+ }
156
+
157
+ @media (min-width: 60rem) {
158
+ .grid-2 {
159
+ grid-template-columns: minmax(0, 1fr) 20rem;
160
+ align-items: start;
161
+ }
162
+ .grid-2.reverse {
163
+ grid-template-columns: 20rem minmax(0, 1fr);
164
+ }
165
+ }
166
+
167
+ .stack {
168
+ display: flex;
169
+ flex-direction: column;
170
+ gap: 1rem;
171
+ }
172
+
173
+ .stack-sm {
174
+ display: flex;
175
+ flex-direction: column;
176
+ gap: 0.5rem;
177
+ }
178
+
179
+ .row {
180
+ display: flex;
181
+ flex-wrap: wrap;
182
+ gap: 0.5rem;
183
+ align-items: center;
184
+ }
185
+
186
+ .spread {
187
+ display: flex;
188
+ flex-wrap: wrap;
189
+ gap: 0.75rem;
190
+ align-items: baseline;
191
+ justify-content: space-between;
192
+ }
193
+
194
+ /* --- type -------------------------------------------------------------- */
195
+
196
+ h1,
197
+ h2,
198
+ h3,
199
+ h4 {
200
+ line-height: 1.25;
201
+ letter-spacing: -0.015em;
202
+ margin: 0;
203
+ font-weight: 650;
204
+ }
205
+
206
+ h1 {
207
+ font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.25rem);
208
+ }
209
+ h2 {
210
+ font-size: 1.35rem;
211
+ }
212
+ h3 {
213
+ font-size: 1.1rem;
214
+ }
215
+
216
+ .lede {
217
+ color: var(--muted-foreground);
218
+ font-size: 1.05rem;
219
+ margin: 0.5rem 0 0;
220
+ }
221
+
222
+ .muted {
223
+ color: var(--muted-foreground);
224
+ }
225
+
226
+ .small {
227
+ font-size: 0.85rem;
228
+ }
229
+
230
+ .mono {
231
+ font-family: var(--font-mono);
232
+ font-size: 0.9em;
233
+ }
234
+
235
+ /* --- card -------------------------------------------------------------- */
236
+
237
+ .card {
238
+ background: var(--card);
239
+ color: var(--card-foreground);
240
+ border: 1px solid var(--border);
241
+ border-radius: var(--radius);
242
+ padding: 1.1rem;
243
+ }
244
+
245
+ .card-header {
246
+ display: flex;
247
+ flex-direction: column;
248
+ gap: 0.35rem;
249
+ margin-bottom: 0.75rem;
250
+ }
251
+
252
+ .card-title {
253
+ font-size: 1.05rem;
254
+ font-weight: 650;
255
+ margin: 0;
256
+ }
257
+
258
+ .card-description {
259
+ color: var(--muted-foreground);
260
+ font-size: 0.9rem;
261
+ margin: 0;
262
+ }
263
+
264
+ .card-link {
265
+ display: block;
266
+ color: inherit;
267
+ text-decoration: none;
268
+ transition: border-color 120ms ease, transform 120ms ease;
269
+ }
270
+
271
+ .card-link:hover {
272
+ border-color: color-mix(in oklab, var(--primary) 45%, var(--border));
273
+ }
274
+
275
+ @media (prefers-reduced-motion: no-preference) {
276
+ .card-link:hover {
277
+ transform: translateY(-1px);
278
+ }
279
+ }
280
+
281
+ /* --- badge ------------------------------------------------------------- */
282
+
283
+ .badge {
284
+ display: inline-flex;
285
+ align-items: center;
286
+ gap: 0.3rem;
287
+ border-radius: 999px;
288
+ border: 1px solid var(--border);
289
+ background: var(--secondary);
290
+ color: var(--secondary-foreground);
291
+ padding: 0.15rem 0.55rem;
292
+ font-size: 0.78rem;
293
+ font-weight: 550;
294
+ line-height: 1.5;
295
+ white-space: nowrap;
296
+ }
297
+
298
+ .badge-primary {
299
+ background: color-mix(in oklab, var(--primary) 14%, transparent);
300
+ border-color: color-mix(in oklab, var(--primary) 35%, transparent);
301
+ color: color-mix(in oklab, var(--primary) 82%, var(--foreground));
302
+ }
303
+
304
+ .badge-outline {
305
+ background: transparent;
306
+ }
307
+
308
+ .badge-dot::before {
309
+ content: '';
310
+ width: 0.45rem;
311
+ height: 0.45rem;
312
+ border-radius: 999px;
313
+ background: currentColor;
314
+ flex: none;
315
+ }
316
+
317
+ .badge-welcome {
318
+ color: color-mix(in oklab, var(--agent-welcome) 80%, var(--foreground));
319
+ border-color: color-mix(in oklab, var(--agent-welcome) 40%, transparent);
320
+ background: color-mix(in oklab, var(--agent-welcome) 12%, transparent);
321
+ }
322
+
323
+ .badge-disclose {
324
+ color: color-mix(in oklab, var(--agent-disclose) 78%, var(--foreground));
325
+ border-color: color-mix(in oklab, var(--agent-disclose) 42%, transparent);
326
+ background: color-mix(in oklab, var(--agent-disclose) 14%, transparent);
327
+ }
328
+
329
+ .badge-human {
330
+ color: var(--muted-foreground);
331
+ }
332
+
333
+ .badge-online {
334
+ color: color-mix(in oklab, var(--online) 80%, var(--foreground));
335
+ }
336
+ .badge-offline {
337
+ color: var(--muted-foreground);
338
+ }
339
+
340
+ /* --- button ------------------------------------------------------------ */
341
+
342
+ .btn {
343
+ display: inline-flex;
344
+ align-items: center;
345
+ justify-content: center;
346
+ gap: 0.45rem;
347
+ border-radius: calc(var(--radius) - 2px);
348
+ border: 1px solid transparent;
349
+ background: var(--primary);
350
+ color: var(--primary-foreground);
351
+ /* 2.75rem clears the 44px minimum tap target without looking chunky. */
352
+ min-height: 2.75rem;
353
+ padding: 0 1rem;
354
+ font: inherit;
355
+ font-size: 0.92rem;
356
+ font-weight: 600;
357
+ text-decoration: none;
358
+ cursor: pointer;
359
+ white-space: nowrap;
360
+ }
361
+
362
+ .btn:hover {
363
+ background: color-mix(in oklab, var(--primary) 88%, black);
364
+ }
365
+
366
+ .btn:disabled {
367
+ opacity: 0.55;
368
+ cursor: not-allowed;
369
+ }
370
+
371
+ .btn-secondary {
372
+ background: var(--secondary);
373
+ color: var(--secondary-foreground);
374
+ border-color: var(--border);
375
+ }
376
+
377
+ .btn-secondary:hover {
378
+ background: color-mix(in oklab, var(--secondary) 85%, var(--foreground) 8%);
379
+ }
380
+
381
+ .btn-ghost {
382
+ background: transparent;
383
+ color: var(--foreground);
384
+ }
385
+
386
+ .btn-ghost:hover {
387
+ background: var(--secondary);
388
+ }
389
+
390
+ .btn-destructive {
391
+ background: var(--destructive);
392
+ color: var(--destructive-foreground);
393
+ }
394
+
395
+ .btn-sm {
396
+ min-height: 2.25rem;
397
+ padding: 0 0.7rem;
398
+ font-size: 0.85rem;
399
+ }
400
+
401
+ .btn-block {
402
+ width: 100%;
403
+ }
404
+
405
+ /* --- form -------------------------------------------------------------- */
406
+
407
+ .field {
408
+ display: flex;
409
+ flex-direction: column;
410
+ gap: 0.35rem;
411
+ }
412
+
413
+ .label {
414
+ font-size: 0.88rem;
415
+ font-weight: 600;
416
+ }
417
+
418
+ .hint {
419
+ font-size: 0.82rem;
420
+ color: var(--muted-foreground);
421
+ }
422
+
423
+ .input,
424
+ .textarea,
425
+ .select {
426
+ width: 100%;
427
+ background: var(--background);
428
+ color: var(--foreground);
429
+ border: 1px solid var(--input);
430
+ border-radius: calc(var(--radius) - 2px);
431
+ padding: 0.6rem 0.7rem;
432
+ font: inherit;
433
+ /* Anything under 16px makes iOS Safari zoom the page on focus. */
434
+ font-size: 16px;
435
+ min-height: 2.75rem;
436
+ }
437
+
438
+ .textarea {
439
+ min-height: 9rem;
440
+ resize: vertical;
441
+ line-height: 1.55;
442
+ }
443
+
444
+ .textarea.code {
445
+ font-family: var(--font-mono);
446
+ font-size: 0.9rem;
447
+ min-height: 26rem;
448
+ }
449
+
450
+ .input:focus-visible,
451
+ .textarea:focus-visible,
452
+ .select:focus-visible {
453
+ outline: 2px solid var(--ring);
454
+ outline-offset: 1px;
455
+ border-color: var(--ring);
456
+ }
457
+
458
+ .field-error .input,
459
+ .field-error .textarea {
460
+ border-color: var(--destructive);
461
+ }
462
+
463
+ .error-text {
464
+ color: var(--destructive);
465
+ font-size: 0.82rem;
466
+ }
467
+
468
+ fieldset {
469
+ border: 1px solid var(--border);
470
+ border-radius: var(--radius);
471
+ padding: 1rem;
472
+ margin: 0;
473
+ }
474
+
475
+ legend {
476
+ font-size: 0.85rem;
477
+ font-weight: 600;
478
+ padding: 0 0.4rem;
479
+ }
480
+
481
+ /* --- alert ------------------------------------------------------------- */
482
+
483
+ .alert {
484
+ border: 1px solid var(--border);
485
+ border-left-width: 3px;
486
+ border-radius: calc(var(--radius) - 2px);
487
+ padding: 0.75rem 0.9rem;
488
+ background: var(--card);
489
+ font-size: 0.9rem;
490
+ }
491
+
492
+ .alert-error {
493
+ border-left-color: var(--destructive);
494
+ color: color-mix(in oklab, var(--destructive) 75%, var(--foreground));
495
+ }
496
+
497
+ .alert-success {
498
+ border-left-color: var(--success);
499
+ }
500
+
501
+ .alert-warning {
502
+ border-left-color: var(--warning);
503
+ }
504
+
505
+ .alert-info {
506
+ border-left-color: var(--primary);
507
+ }
508
+
509
+ /* --- job list ---------------------------------------------------------- */
510
+
511
+ .job-list {
512
+ display: flex;
513
+ flex-direction: column;
514
+ gap: 0.75rem;
515
+ list-style: none;
516
+ margin: 0;
517
+ padding: 0;
518
+ }
519
+
520
+ .job-card {
521
+ display: flex;
522
+ flex-direction: column;
523
+ gap: 0.5rem;
524
+ }
525
+
526
+ .job-card .job-title {
527
+ font-size: 1.05rem;
528
+ font-weight: 650;
529
+ margin: 0;
530
+ }
531
+
532
+ .job-card .job-org {
533
+ color: var(--muted-foreground);
534
+ font-size: 0.9rem;
535
+ }
536
+
537
+ .job-meta {
538
+ display: flex;
539
+ flex-wrap: wrap;
540
+ gap: 0.4rem;
541
+ align-items: center;
542
+ }
543
+
544
+ .job-salary {
545
+ font-weight: 600;
546
+ font-variant-numeric: tabular-nums;
547
+ }
548
+
549
+ .filters {
550
+ display: flex;
551
+ flex-direction: column;
552
+ gap: 0.75rem;
553
+ }
554
+
555
+ @media (min-width: 40rem) {
556
+ .filters-inline {
557
+ display: grid;
558
+ grid-template-columns: 1fr auto;
559
+ gap: 0.5rem;
560
+ align-items: end;
561
+ }
562
+ }
563
+
564
+ .empty {
565
+ border: 1px dashed var(--border);
566
+ border-radius: var(--radius);
567
+ padding: 2.5rem 1rem;
568
+ text-align: center;
569
+ color: var(--muted-foreground);
570
+ }
571
+
572
+ /* --- prose (rendered Markdown) ----------------------------------------- */
573
+
574
+ .prose {
575
+ max-width: 68ch;
576
+ }
577
+
578
+ .prose > :first-child {
579
+ margin-top: 0;
580
+ }
581
+
582
+ .prose h2,
583
+ .prose h3,
584
+ .prose h4 {
585
+ margin: 1.75rem 0 0.6rem;
586
+ }
587
+
588
+ .prose p,
589
+ .prose ul,
590
+ .prose ol,
591
+ .prose blockquote,
592
+ .prose pre {
593
+ margin: 0 0 1rem;
594
+ }
595
+
596
+ .prose ul,
597
+ .prose ol {
598
+ padding-left: 1.25rem;
599
+ }
600
+
601
+ .prose li {
602
+ margin: 0.25rem 0;
603
+ }
604
+
605
+ .prose blockquote {
606
+ border-left: 3px solid var(--border);
607
+ padding-left: 1rem;
608
+ color: var(--muted-foreground);
609
+ }
610
+
611
+ .prose code {
612
+ font-family: var(--font-mono);
613
+ font-size: 0.88em;
614
+ background: var(--muted);
615
+ padding: 0.1em 0.35em;
616
+ border-radius: 4px;
617
+ }
618
+
619
+ .prose pre {
620
+ background: var(--muted);
621
+ border: 1px solid var(--border);
622
+ border-radius: calc(var(--radius) - 2px);
623
+ padding: 0.9rem;
624
+ overflow-x: auto;
625
+ }
626
+
627
+ .prose pre code {
628
+ background: none;
629
+ padding: 0;
630
+ }
631
+
632
+ .prose hr {
633
+ border: 0;
634
+ border-top: 1px solid var(--border);
635
+ margin: 1.75rem 0;
636
+ }
637
+
638
+ /* Wide content scrolls inside itself; the page never scrolls sideways. */
639
+ .table-wrap {
640
+ overflow-x: auto;
641
+ margin: 0 0 1rem;
642
+ }
643
+
644
+ .prose table {
645
+ border-collapse: collapse;
646
+ width: 100%;
647
+ font-size: 0.92rem;
648
+ }
649
+
650
+ .prose th,
651
+ .prose td {
652
+ border: 1px solid var(--border);
653
+ padding: 0.45rem 0.6rem;
654
+ text-align: left;
655
+ }
656
+
657
+ .prose th {
658
+ background: var(--muted);
659
+ font-weight: 600;
660
+ }
661
+
662
+ /* --- misc -------------------------------------------------------------- */
663
+
664
+ .code-block {
665
+ background: var(--muted);
666
+ border: 1px solid var(--border);
667
+ border-radius: calc(var(--radius) - 2px);
668
+ padding: 0.9rem;
669
+ overflow-x: auto;
670
+ font-family: var(--font-mono);
671
+ font-size: 0.85rem;
672
+ margin: 0;
673
+ }
674
+
675
+ .device-code {
676
+ font-family: var(--font-mono);
677
+ font-size: clamp(1.5rem, 1rem + 3vw, 2.5rem);
678
+ font-weight: 700;
679
+ letter-spacing: 0.18em;
680
+ text-align: center;
681
+ padding: 1rem;
682
+ background: var(--muted);
683
+ border-radius: var(--radius);
684
+ margin: 1rem 0;
685
+ }
686
+
687
+ .pagination {
688
+ display: flex;
689
+ gap: 0.5rem;
690
+ justify-content: center;
691
+ margin-top: 1.5rem;
692
+ }
693
+
694
+ .skip-link {
695
+ position: absolute;
696
+ left: -9999px;
697
+ }
698
+
699
+ .skip-link:focus {
700
+ left: 1rem;
701
+ top: 0.5rem;
702
+ z-index: 50;
703
+ background: var(--card);
704
+ padding: 0.5rem 0.75rem;
705
+ border-radius: calc(var(--radius) - 2px);
706
+ border: 1px solid var(--border);
707
+ }
708
+
709
+ .visually-hidden {
710
+ position: absolute;
711
+ width: 1px;
712
+ height: 1px;
713
+ overflow: hidden;
714
+ clip: rect(0 0 0 0);
715
+ white-space: nowrap;
716
+ }
717
+
718
+ .source-list {
719
+ list-style: none;
720
+ margin: 0;
721
+ padding: 0;
722
+ font-size: 0.85rem;
723
+ color: var(--muted-foreground);
724
+ }
725
+
726
+ .source-list li {
727
+ display: flex;
728
+ gap: 0.5rem;
729
+ justify-content: space-between;
730
+ padding: 0.2rem 0;
731
+ }