@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.
- package/LICENSE +21 -0
- package/README.md +219 -0
- package/bin/agenticjobs-mcp.mjs +2 -0
- package/bin/agenticjobs.mjs +2 -0
- package/dist/cli/args.d.ts +17 -0
- package/dist/cli/args.js +103 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/format.d.ts +15 -0
- package/dist/cli/format.js +24 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.js +620 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/jobfile.d.ts +15 -0
- package/dist/cli/jobfile.js +94 -0
- package/dist/cli/jobfile.js.map +1 -0
- package/dist/client/client.d.ts +105 -0
- package/dist/client/client.js +182 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/config.d.ts +33 -0
- package/dist/client/config.js +92 -0
- package/dist/client/config.js.map +1 -0
- package/dist/client/fanout.d.ts +35 -0
- package/dist/client/fanout.js +77 -0
- package/dist/client/fanout.js.map +1 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +5 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/login.d.ts +23 -0
- package/dist/client/login.js +45 -0
- package/dist/client/login.js.map +1 -0
- package/dist/config.d.ts +40 -0
- package/dist/config.js +64 -0
- package/dist/config.js.map +1 -0
- package/dist/core/applications.d.ts +67 -0
- package/dist/core/applications.js +187 -0
- package/dist/core/applications.js.map +1 -0
- package/dist/core/auth.d.ts +120 -0
- package/dist/core/auth.js +246 -0
- package/dist/core/auth.js.map +1 -0
- package/dist/core/import.d.ts +52 -0
- package/dist/core/import.js +311 -0
- package/dist/core/import.js.map +1 -0
- package/dist/core/jobs.d.ts +91 -0
- package/dist/core/jobs.js +381 -0
- package/dist/core/jobs.js.map +1 -0
- package/dist/core/orgs.d.ts +21 -0
- package/dist/core/orgs.js +111 -0
- package/dist/core/orgs.js.map +1 -0
- package/dist/core/resumes.d.ts +51 -0
- package/dist/core/resumes.js +144 -0
- package/dist/core/resumes.js.map +1 -0
- package/dist/core/zip.d.ts +17 -0
- package/dist/core/zip.js +77 -0
- package/dist/core/zip.js.map +1 -0
- package/dist/db/index.d.ts +3 -0
- package/dist/db/index.js +3 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrate.d.ts +15 -0
- package/dist/db/migrate.js +67 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/pool.d.ts +13 -0
- package/dist/db/pool.js +68 -0
- package/dist/db/pool.js.map +1 -0
- package/dist/db/seed.d.ts +9 -0
- package/dist/db/seed.js +120 -0
- package/dist/db/seed.js.map +1 -0
- package/dist/directory/announce.d.ts +32 -0
- package/dist/directory/announce.js +59 -0
- package/dist/directory/announce.js.map +1 -0
- package/dist/directory/federate.d.ts +59 -0
- package/dist/directory/federate.js +126 -0
- package/dist/directory/federate.js.map +1 -0
- package/dist/directory/fetch.d.ts +35 -0
- package/dist/directory/fetch.js +138 -0
- package/dist/directory/fetch.js.map +1 -0
- package/dist/directory/index.d.ts +4 -0
- package/dist/directory/index.js +5 -0
- package/dist/directory/index.js.map +1 -0
- package/dist/directory/registry.d.ts +55 -0
- package/dist/directory/registry.js +155 -0
- package/dist/directory/registry.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/markup/escape.d.ts +20 -0
- package/dist/markup/escape.js +56 -0
- package/dist/markup/escape.js.map +1 -0
- package/dist/markup/markdown.d.ts +35 -0
- package/dist/markup/markdown.js +279 -0
- package/dist/markup/markdown.js.map +1 -0
- package/dist/markup/resume.d.ts +72 -0
- package/dist/markup/resume.js +260 -0
- package/dist/markup/resume.js.map +1 -0
- package/dist/mcp/protocol.d.ts +56 -0
- package/dist/mcp/protocol.js +48 -0
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/server.d.ts +21 -0
- package/dist/mcp/server.js +73 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/stdio.d.ts +13 -0
- package/dist/mcp/stdio.js +85 -0
- package/dist/mcp/stdio.js.map +1 -0
- package/dist/mcp/tools.d.ts +26 -0
- package/dist/mcp/tools.js +351 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/index.js +6 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/instance.d.ts +85 -0
- package/dist/schema/instance.js +147 -0
- package/dist/schema/instance.js.map +1 -0
- package/dist/schema/job.d.ts +151 -0
- package/dist/schema/job.js +73 -0
- package/dist/schema/job.js.map +1 -0
- package/dist/schema/jsonld.d.ts +18 -0
- package/dist/schema/jsonld.js +120 -0
- package/dist/schema/jsonld.js.map +1 -0
- package/dist/schema/query.d.ts +47 -0
- package/dist/schema/query.js +103 -0
- package/dist/schema/query.js.map +1 -0
- package/dist/schema/text.d.ts +27 -0
- package/dist/schema/text.js +117 -0
- package/dist/schema/text.js.map +1 -0
- package/dist/server/app.d.ts +13 -0
- package/dist/server/app.js +57 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/deps.d.ts +20 -0
- package/dist/server/deps.js +2 -0
- package/dist/server/deps.js.map +1 -0
- package/dist/server/middleware.d.ts +39 -0
- package/dist/server/middleware.js +100 -0
- package/dist/server/middleware.js.map +1 -0
- package/dist/server/routes/api.d.ts +20 -0
- package/dist/server/routes/api.js +584 -0
- package/dist/server/routes/api.js.map +1 -0
- package/dist/server/routes/descriptor.d.ts +11 -0
- package/dist/server/routes/descriptor.js +31 -0
- package/dist/server/routes/descriptor.js.map +1 -0
- package/dist/server/routes/discovery.d.ts +12 -0
- package/dist/server/routes/discovery.js +305 -0
- package/dist/server/routes/discovery.js.map +1 -0
- package/dist/server/routes/mcp.d.ts +19 -0
- package/dist/server/routes/mcp.js +85 -0
- package/dist/server/routes/mcp.js.map +1 -0
- package/dist/server/routes/openapi.d.ts +11 -0
- package/dist/server/routes/openapi.js +297 -0
- package/dist/server/routes/openapi.js.map +1 -0
- package/dist/server/routes/pages.d.ts +11 -0
- package/dist/server/routes/pages.js +445 -0
- package/dist/server/routes/pages.js.map +1 -0
- package/dist/server/routes/passkey.d.ts +20 -0
- package/dist/server/routes/passkey.js +198 -0
- package/dist/server/routes/passkey.js.map +1 -0
- package/dist/server/routes/specs.d.ts +10 -0
- package/dist/server/routes/specs.js +42 -0
- package/dist/server/routes/specs.js.map +1 -0
- package/dist/server/serve.d.ts +11 -0
- package/dist/server/serve.js +79 -0
- package/dist/server/serve.js.map +1 -0
- package/dist/tui/index.d.ts +13 -0
- package/dist/tui/index.js +266 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/state.d.ts +63 -0
- package/dist/tui/state.js +136 -0
- package/dist/tui/state.js.map +1 -0
- package/dist/tui/types.d.ts +2 -0
- package/dist/tui/types.js +2 -0
- package/dist/tui/types.js.map +1 -0
- package/dist/tui/views.d.ts +11 -0
- package/dist/tui/views.js +197 -0
- package/dist/tui/views.js.map +1 -0
- package/dist/views/auth.d.ts +21 -0
- package/dist/views/auth.js +5 -0
- package/dist/views/auth.js.map +1 -0
- package/dist/views/docs.d.ts +17 -0
- package/dist/views/docs.js +40 -0
- package/dist/views/docs.js.map +1 -0
- package/dist/views/jobs.d.ts +49 -0
- package/dist/views/jobs.js +44 -0
- package/dist/views/jobs.js.map +1 -0
- package/dist/views/layout.d.ts +58 -0
- package/dist/views/layout.js +36 -0
- package/dist/views/layout.js.map +1 -0
- package/dist/views/me.d.ts +27 -0
- package/dist/views/me.js +6 -0
- package/dist/views/me.js.map +1 -0
- package/dist/views/network.d.ts +21 -0
- package/dist/views/network.js +17 -0
- package/dist/views/network.js.map +1 -0
- package/dist/views/post.d.ts +22 -0
- package/dist/views/post.js +20 -0
- package/dist/views/post.js.map +1 -0
- package/docs/openjob.md +200 -0
- package/docs/openresume.md +143 -0
- package/migrations/0001_init.sql +109 -0
- package/migrations/0002_auth.sql +82 -0
- package/migrations/0003_directory.sql +27 -0
- package/migrations/0004_resumes.sql +63 -0
- package/migrations/0005_application_drafts.sql +20 -0
- package/package.json +92 -0
- package/web/public/app.css +731 -0
- package/web/public/app.js +173 -0
- package/web/public/icon.svg +5 -0
- package/web/public/sw.js +64 -0
- package/web/public/tokens.css +153 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The only script on the site.
|
|
3
|
+
*
|
|
4
|
+
* Two jobs: register the service worker, and add passkeys where the browser
|
|
5
|
+
* has them. Everything else works with this file blocked - every form is a
|
|
6
|
+
* real form and every link is a real link - which is what lets the CSP be
|
|
7
|
+
* script-src 'self' with no inline anything.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
(function () {
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
if ('serviceWorker' in navigator) {
|
|
14
|
+
window.addEventListener('load', function () {
|
|
15
|
+
navigator.serviceWorker.register('/sw.js').catch(function () {
|
|
16
|
+
/* A board that cannot install is still a board that works. */
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
registerPasskeyButton();
|
|
22
|
+
|
|
23
|
+
var card = document.getElementById('passkey-card');
|
|
24
|
+
var button = document.getElementById('passkey-login');
|
|
25
|
+
var error = document.getElementById('passkey-error');
|
|
26
|
+
|
|
27
|
+
// The button is hidden in the markup and only revealed once the browser has
|
|
28
|
+
// actually been asked, so nobody is offered a sign-in method that will throw.
|
|
29
|
+
if (!card || !button || !window.PublicKeyCredential) return;
|
|
30
|
+
card.hidden = false;
|
|
31
|
+
|
|
32
|
+
/* Adding a passkey from the "You" page, for an account that already exists. */
|
|
33
|
+
function registerPasskeyButton() {
|
|
34
|
+
var add = document.getElementById('passkey-add');
|
|
35
|
+
if (!add || !window.PublicKeyCredential) return;
|
|
36
|
+
add.hidden = false;
|
|
37
|
+
|
|
38
|
+
add.addEventListener('click', function () {
|
|
39
|
+
add.disabled = true;
|
|
40
|
+
var challenge = '';
|
|
41
|
+
|
|
42
|
+
fetch('/auth/passkey/register/start', { method: 'POST', headers: { accept: 'application/json' } })
|
|
43
|
+
.then(function (response) {
|
|
44
|
+
if (!response.ok) throw new Error('Could not start. Are you signed in?');
|
|
45
|
+
return response.json();
|
|
46
|
+
})
|
|
47
|
+
.then(function (options) {
|
|
48
|
+
challenge = options.challenge;
|
|
49
|
+
return navigator.credentials.create({
|
|
50
|
+
publicKey: {
|
|
51
|
+
challenge: decode(options.challenge),
|
|
52
|
+
rp: options.rp,
|
|
53
|
+
user: {
|
|
54
|
+
id: decode(options.user.id),
|
|
55
|
+
name: options.user.name,
|
|
56
|
+
displayName: options.user.displayName
|
|
57
|
+
},
|
|
58
|
+
pubKeyCredParams: options.pubKeyCredParams,
|
|
59
|
+
authenticatorSelection: options.authenticatorSelection,
|
|
60
|
+
excludeCredentials: (options.excludeCredentials || []).map(function (item) {
|
|
61
|
+
return { id: decode(item.id), type: 'public-key' };
|
|
62
|
+
}),
|
|
63
|
+
timeout: 60000
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
})
|
|
67
|
+
.then(function (credential) {
|
|
68
|
+
if (!credential) throw new Error('No passkey was created.');
|
|
69
|
+
return fetch('/auth/passkey/register/verify', {
|
|
70
|
+
method: 'POST',
|
|
71
|
+
headers: { 'content-type': 'application/json' },
|
|
72
|
+
body: JSON.stringify({
|
|
73
|
+
id: credential.id,
|
|
74
|
+
rawId: encode(credential.rawId),
|
|
75
|
+
type: credential.type,
|
|
76
|
+
challenge: challenge,
|
|
77
|
+
response: {
|
|
78
|
+
clientDataJSON: encode(credential.response.clientDataJSON),
|
|
79
|
+
attestationObject: encode(credential.response.attestationObject),
|
|
80
|
+
transports: credential.response.getTransports ? credential.response.getTransports() : []
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
});
|
|
84
|
+
})
|
|
85
|
+
.then(function (response) {
|
|
86
|
+
if (!response.ok) throw new Error('That passkey was not accepted.');
|
|
87
|
+
add.textContent = 'Passkey added';
|
|
88
|
+
})
|
|
89
|
+
.catch(function (problem) {
|
|
90
|
+
add.disabled = false;
|
|
91
|
+
if (problem && problem.name === 'NotAllowedError') return;
|
|
92
|
+
var note = document.getElementById('passkey-add-error');
|
|
93
|
+
if (note) {
|
|
94
|
+
note.textContent = problem && problem.message ? problem.message : 'That did not work.';
|
|
95
|
+
note.hidden = false;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function decode(value) {
|
|
102
|
+
var normal = value.replace(/-/g, '+').replace(/_/g, '/');
|
|
103
|
+
var padded = normal + '==='.slice((normal.length + 3) % 4);
|
|
104
|
+
var binary = atob(padded);
|
|
105
|
+
var bytes = new Uint8Array(binary.length);
|
|
106
|
+
for (var i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i);
|
|
107
|
+
return bytes.buffer;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function encode(buffer) {
|
|
111
|
+
var bytes = new Uint8Array(buffer);
|
|
112
|
+
var binary = '';
|
|
113
|
+
for (var i = 0; i < bytes.length; i += 1) binary += String.fromCharCode(bytes[i]);
|
|
114
|
+
return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function show(message) {
|
|
118
|
+
if (!error) return;
|
|
119
|
+
error.textContent = message;
|
|
120
|
+
error.hidden = false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
button.addEventListener('click', function () {
|
|
124
|
+
button.disabled = true;
|
|
125
|
+
if (error) error.hidden = true;
|
|
126
|
+
|
|
127
|
+
fetch('/auth/passkey/challenge', { method: 'POST', headers: { accept: 'application/json' } })
|
|
128
|
+
.then(function (response) {
|
|
129
|
+
if (!response.ok) throw new Error('This board could not start a passkey sign-in.');
|
|
130
|
+
return response.json();
|
|
131
|
+
})
|
|
132
|
+
.then(function (options) {
|
|
133
|
+
return navigator.credentials.get({
|
|
134
|
+
publicKey: {
|
|
135
|
+
challenge: decode(options.challenge),
|
|
136
|
+
rpId: options.rpId,
|
|
137
|
+
userVerification: 'preferred',
|
|
138
|
+
timeout: 60000,
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
})
|
|
142
|
+
.then(function (credential) {
|
|
143
|
+
if (!credential) throw new Error('No passkey was chosen.');
|
|
144
|
+
return fetch('/auth/passkey/verify', {
|
|
145
|
+
method: 'POST',
|
|
146
|
+
headers: { 'content-type': 'application/json' },
|
|
147
|
+
body: JSON.stringify({
|
|
148
|
+
id: credential.id,
|
|
149
|
+
rawId: encode(credential.rawId),
|
|
150
|
+
type: credential.type,
|
|
151
|
+
response: {
|
|
152
|
+
clientDataJSON: encode(credential.response.clientDataJSON),
|
|
153
|
+
authenticatorData: encode(credential.response.authenticatorData),
|
|
154
|
+
signature: encode(credential.response.signature),
|
|
155
|
+
userHandle: credential.response.userHandle
|
|
156
|
+
? encode(credential.response.userHandle)
|
|
157
|
+
: null,
|
|
158
|
+
},
|
|
159
|
+
}),
|
|
160
|
+
});
|
|
161
|
+
})
|
|
162
|
+
.then(function (response) {
|
|
163
|
+
if (!response.ok) throw new Error('That passkey was not accepted.');
|
|
164
|
+
window.location.href = '/me';
|
|
165
|
+
})
|
|
166
|
+
.catch(function (problem) {
|
|
167
|
+
button.disabled = false;
|
|
168
|
+
// A cancelled prompt is not a failure worth shouting about.
|
|
169
|
+
if (problem && problem.name === 'NotAllowedError') return;
|
|
170
|
+
show(problem && problem.message ? problem.message : 'Passkey sign-in did not work.');
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
})();
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="agenticjobs">
|
|
2
|
+
<rect width="64" height="64" rx="14" fill="#0d7a5f"/>
|
|
3
|
+
<path d="M20 24h24v4H20zm0 8h24v4H20zm0 8h16v4H20z" fill="#fff"/>
|
|
4
|
+
<circle cx="46" cy="42" r="6" fill="#7ee2bd"/>
|
|
5
|
+
</svg>
|
package/web/public/sw.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The service worker.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately small. A job board is a read-mostly site whose content changes
|
|
5
|
+
* daily, so caching pages aggressively would show people closed listings; what
|
|
6
|
+
* is cached is the shell (stylesheet, icon) and an offline fallback, and every
|
|
7
|
+
* document goes to the network first.
|
|
8
|
+
*
|
|
9
|
+
* Bump VERSION on any change here or to the assets listed below. Without a
|
|
10
|
+
* bump, a returning reader keeps the old worker and never sees the change.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const VERSION = 'v1';
|
|
14
|
+
const SHELL = `shell-${VERSION}`;
|
|
15
|
+
const ASSETS = ['/assets/app.css', '/assets/tokens.css', '/assets/icon.svg'];
|
|
16
|
+
|
|
17
|
+
self.addEventListener('install', (event) => {
|
|
18
|
+
event.waitUntil(
|
|
19
|
+
caches
|
|
20
|
+
.open(SHELL)
|
|
21
|
+
.then((cache) => cache.addAll(ASSETS))
|
|
22
|
+
.then(() => self.skipWaiting()),
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
self.addEventListener('activate', (event) => {
|
|
27
|
+
event.waitUntil(
|
|
28
|
+
caches
|
|
29
|
+
.keys()
|
|
30
|
+
.then((keys) => Promise.all(keys.filter((key) => key !== SHELL).map((key) => caches.delete(key))))
|
|
31
|
+
.then(() => self.clients.claim()),
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
self.addEventListener('fetch', (event) => {
|
|
36
|
+
const request = event.request;
|
|
37
|
+
if (request.method !== 'GET') return;
|
|
38
|
+
|
|
39
|
+
const url = new URL(request.url);
|
|
40
|
+
if (url.origin !== self.location.origin) return;
|
|
41
|
+
// Never cache anything under /api or /me: one is live data, the other is a
|
|
42
|
+
// signed-in person's own pages.
|
|
43
|
+
if (url.pathname.startsWith('/api/') || url.pathname.startsWith('/me')) return;
|
|
44
|
+
|
|
45
|
+
if (ASSETS.includes(url.pathname)) {
|
|
46
|
+
event.respondWith(
|
|
47
|
+
caches.match(request).then((hit) => hit || fetch(request)),
|
|
48
|
+
);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
event.respondWith(
|
|
53
|
+
fetch(request).catch(() =>
|
|
54
|
+
caches.match(request).then(
|
|
55
|
+
(hit) =>
|
|
56
|
+
hit ||
|
|
57
|
+
new Response(
|
|
58
|
+
'<!doctype html><meta charset="utf-8"><title>Offline</title><body style="font:16px system-ui;padding:2rem"><h1>Offline</h1><p>This board is not reachable right now.</p>',
|
|
59
|
+
{ status: 503, headers: { 'content-type': 'text/html; charset=utf-8' } },
|
|
60
|
+
),
|
|
61
|
+
),
|
|
62
|
+
),
|
|
63
|
+
);
|
|
64
|
+
});
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* shadcn/ui design tokens, hand-ported.
|
|
3
|
+
*
|
|
4
|
+
* The names are shadcn's own - --background, --foreground, --card, --primary,
|
|
5
|
+
* --muted, --border, --input, --ring, --radius - so anyone who has read a
|
|
6
|
+
* shadcn theme can read this one, and a theme pasted out of the shadcn theme
|
|
7
|
+
* editor drops straight in.
|
|
8
|
+
*
|
|
9
|
+
* What is NOT here is Tailwind or the shadcn CLI. Pages render server-side
|
|
10
|
+
* through Hono's JSX and ship plain CSS, so the React components cannot be
|
|
11
|
+
* used directly; what is ported is their anatomy and their token vocabulary.
|
|
12
|
+
* See components.css, where each class mirrors a shadcn component.
|
|
13
|
+
*
|
|
14
|
+
* Theme resolution has three states and all three are handled:
|
|
15
|
+
* - light lives on bare :root, so a page always has a complete palette
|
|
16
|
+
* - dark is redefined under prefers-color-scheme for the default "system"
|
|
17
|
+
* setting, guarded so an explicit light choice still wins
|
|
18
|
+
* - dark is redefined again under [data-theme="dark"] so the toggle wins in
|
|
19
|
+
* both directions
|
|
20
|
+
* A colour whose only definition sits inside a media query is a colour that
|
|
21
|
+
* disappears the moment somebody picks the other theme.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
:root {
|
|
25
|
+
--radius: 0.625rem;
|
|
26
|
+
|
|
27
|
+
--background: oklch(0.995 0.002 250);
|
|
28
|
+
--foreground: oklch(0.18 0.02 260);
|
|
29
|
+
|
|
30
|
+
--card: oklch(1 0 0);
|
|
31
|
+
--card-foreground: oklch(0.18 0.02 260);
|
|
32
|
+
|
|
33
|
+
--popover: oklch(1 0 0);
|
|
34
|
+
--popover-foreground: oklch(0.18 0.02 260);
|
|
35
|
+
|
|
36
|
+
/* Deep green: hiring, not alerting. Passes AA on white at 5.4:1. */
|
|
37
|
+
--primary: oklch(0.52 0.13 165);
|
|
38
|
+
--primary-foreground: oklch(0.99 0.01 165);
|
|
39
|
+
|
|
40
|
+
--secondary: oklch(0.965 0.006 250);
|
|
41
|
+
--secondary-foreground: oklch(0.28 0.03 260);
|
|
42
|
+
|
|
43
|
+
--muted: oklch(0.965 0.006 250);
|
|
44
|
+
--muted-foreground: oklch(0.53 0.02 258);
|
|
45
|
+
|
|
46
|
+
--accent: oklch(0.955 0.015 175);
|
|
47
|
+
--accent-foreground: oklch(0.28 0.05 175);
|
|
48
|
+
|
|
49
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
50
|
+
--destructive-foreground: oklch(0.985 0 0);
|
|
51
|
+
|
|
52
|
+
--success: oklch(0.596 0.145 163.225);
|
|
53
|
+
--success-foreground: oklch(0.985 0 0);
|
|
54
|
+
|
|
55
|
+
--warning: oklch(0.681 0.162 75.834);
|
|
56
|
+
--warning-foreground: oklch(0.141 0.005 285.823);
|
|
57
|
+
|
|
58
|
+
--border: oklch(0.91 0.006 250);
|
|
59
|
+
--input: oklch(0.885 0.008 250);
|
|
60
|
+
--ring: oklch(0.52 0.13 165);
|
|
61
|
+
|
|
62
|
+
/* Board roles, layered on the shadcn palette rather than beside it. */
|
|
63
|
+
--agent-welcome: oklch(0.596 0.145 163);
|
|
64
|
+
--agent-disclose: oklch(0.681 0.162 76);
|
|
65
|
+
--agent-human: oklch(0.55 0.02 258);
|
|
66
|
+
--online: oklch(0.62 0.16 158);
|
|
67
|
+
--offline: oklch(0.6 0.02 258);
|
|
68
|
+
|
|
69
|
+
--font-sans: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto,
|
|
70
|
+
'Helvetica Neue', Arial, sans-serif;
|
|
71
|
+
--font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
|
|
72
|
+
'Liberation Mono', monospace;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@media (prefers-color-scheme: dark) {
|
|
76
|
+
:root:not([data-theme='light']) {
|
|
77
|
+
--background: oklch(0.16 0.012 260);
|
|
78
|
+
--foreground: oklch(0.96 0.004 250);
|
|
79
|
+
|
|
80
|
+
--card: oklch(0.205 0.014 260);
|
|
81
|
+
--card-foreground: oklch(0.96 0.004 250);
|
|
82
|
+
|
|
83
|
+
--popover: oklch(0.205 0.014 260);
|
|
84
|
+
--popover-foreground: oklch(0.96 0.004 250);
|
|
85
|
+
|
|
86
|
+
--primary: oklch(0.72 0.15 165);
|
|
87
|
+
--primary-foreground: oklch(0.16 0.03 165);
|
|
88
|
+
|
|
89
|
+
--secondary: oklch(0.27 0.015 260);
|
|
90
|
+
--secondary-foreground: oklch(0.96 0.004 250);
|
|
91
|
+
|
|
92
|
+
--muted: oklch(0.27 0.015 260);
|
|
93
|
+
--muted-foreground: oklch(0.71 0.015 256);
|
|
94
|
+
|
|
95
|
+
--accent: oklch(0.3 0.03 175);
|
|
96
|
+
--accent-foreground: oklch(0.96 0.004 250);
|
|
97
|
+
|
|
98
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
99
|
+
--destructive-foreground: oklch(0.98 0 0);
|
|
100
|
+
|
|
101
|
+
--success: oklch(0.696 0.17 162.48);
|
|
102
|
+
--warning: oklch(0.769 0.188 70.08);
|
|
103
|
+
|
|
104
|
+
--border: oklch(1 0 0 / 12%);
|
|
105
|
+
--input: oklch(1 0 0 / 18%);
|
|
106
|
+
--ring: oklch(0.72 0.15 165);
|
|
107
|
+
|
|
108
|
+
--agent-welcome: oklch(0.696 0.17 162);
|
|
109
|
+
--agent-disclose: oklch(0.769 0.188 70);
|
|
110
|
+
--agent-human: oklch(0.7 0.015 256);
|
|
111
|
+
--online: oklch(0.7 0.17 158);
|
|
112
|
+
--offline: oklch(0.6 0.02 258);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
:root[data-theme='dark'] {
|
|
117
|
+
--background: oklch(0.16 0.012 260);
|
|
118
|
+
--foreground: oklch(0.96 0.004 250);
|
|
119
|
+
|
|
120
|
+
--card: oklch(0.205 0.014 260);
|
|
121
|
+
--card-foreground: oklch(0.96 0.004 250);
|
|
122
|
+
|
|
123
|
+
--popover: oklch(0.205 0.014 260);
|
|
124
|
+
--popover-foreground: oklch(0.96 0.004 250);
|
|
125
|
+
|
|
126
|
+
--primary: oklch(0.72 0.15 165);
|
|
127
|
+
--primary-foreground: oklch(0.16 0.03 165);
|
|
128
|
+
|
|
129
|
+
--secondary: oklch(0.27 0.015 260);
|
|
130
|
+
--secondary-foreground: oklch(0.96 0.004 250);
|
|
131
|
+
|
|
132
|
+
--muted: oklch(0.27 0.015 260);
|
|
133
|
+
--muted-foreground: oklch(0.71 0.015 256);
|
|
134
|
+
|
|
135
|
+
--accent: oklch(0.3 0.03 175);
|
|
136
|
+
--accent-foreground: oklch(0.96 0.004 250);
|
|
137
|
+
|
|
138
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
139
|
+
--destructive-foreground: oklch(0.98 0 0);
|
|
140
|
+
|
|
141
|
+
--success: oklch(0.696 0.17 162.48);
|
|
142
|
+
--warning: oklch(0.769 0.188 70.08);
|
|
143
|
+
|
|
144
|
+
--border: oklch(1 0 0 / 12%);
|
|
145
|
+
--input: oklch(1 0 0 / 18%);
|
|
146
|
+
--ring: oklch(0.72 0.15 165);
|
|
147
|
+
|
|
148
|
+
--agent-welcome: oklch(0.696 0.17 162);
|
|
149
|
+
--agent-disclose: oklch(0.769 0.188 70);
|
|
150
|
+
--agent-human: oklch(0.7 0.015 256);
|
|
151
|
+
--online: oklch(0.7 0.17 158);
|
|
152
|
+
--offline: oklch(0.6 0.02 258);
|
|
153
|
+
}
|