@passioncode-ai/fabric-agent-adapter 0.8.3 → 0.10.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 (26) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/README.md +14 -3
  3. package/package.json +1 -1
  4. package/plugins/fabric-agent-adapter/.claude-plugin/plugin.json +1 -1
  5. package/plugins/fabric-agent-adapter/hooks/hooks.json +17 -0
  6. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/SKILL.md +3 -3
  7. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py +2 -2
  8. package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +21 -8
  9. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/demo.html +110 -0
  10. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.css +198 -0
  11. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/fabric-dashboard.js +253 -0
  12. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/kit.json +28 -0
  13. package/plugins/fabric-agent-adapter/skills/building-fabric-services/assets/dashboard-kit/themes.json +350 -0
  14. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-kit.md +133 -0
  15. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard.md +4 -3
  16. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md +25 -3
  17. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/remote-placement.md +7 -4
  18. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/surfaces-and-auth.md +19 -2
  19. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_dashboard_layout.mjs +295 -0
  20. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py +88 -5
  21. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/dashboard_kit.py +437 -0
  22. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-service.mjs +143 -17
  23. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_service.py +195 -36
  24. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/sample-remote-service.mjs +9 -1
  25. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/sample_service.py +29 -4
  26. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +3 -3
@@ -0,0 +1,253 @@
1
+ /* fabric-dashboard-kit@1.0.0 · fabric-dashboard/0.1 (Fabric Agent Contract DEC-0036)
2
+ Load it same-origin with <script src="fabric-dashboard.js" defer></script>: no inline script, no
3
+ eval, nothing from a CDN. It applies the host's appearance (ED-6, ED-8), folds navigation that
4
+ does not fit into a More menu (ED-3), makes wide boxes keyboard-reachable (ED-4) and keeps
5
+ anchors below the sticky chrome (ED-5). Without it the page still holds: the navigation wraps.
6
+ Do not edit in place; `dashboard_kit.py install` replaces it on an upgrade. */
7
+ (function (root) {
8
+ 'use strict';
9
+
10
+ var KIT = 'fabric-dashboard-kit';
11
+ var VERSION = '1.0.0';
12
+ /* fabric-dashboard-kit:theme-ids:begin */
13
+ var THEMES = ['graphite', 'fabric', 'paper', 'forest', 'ocean', 'ember', 'contrast'];
14
+ /* fabric-dashboard-kit:theme-ids:end */
15
+ var DEFAULT_THEME = 'graphite';
16
+ var COOKIE = 'fabric_appearance';
17
+ var STORE_KEY = 'fabric-dashboard:appearance';
18
+ var THEME_ID = /^[a-z][a-z0-9-]{0,31}$/;
19
+
20
+ /** The carrier cookie's value as {scheme, theme}, or null when absent or of an unknown version.
21
+ Fields that are missing or malformed are left out; the page then uses its defaults. */
22
+ function parseAppearance(cookieHeader) {
23
+ if (typeof cookieHeader !== 'string' || !cookieHeader) return null;
24
+ var parts = cookieHeader.split(';');
25
+ for (var i = 0; i < parts.length; i++) {
26
+ var part = parts[i].replace(/^\s+/, '');
27
+ if (part.indexOf(COOKIE + '=') !== 0) continue;
28
+ var raw = part.slice(COOKIE.length + 1);
29
+ if (raw.charAt(0) === '"' && raw.charAt(raw.length - 1) === '"') raw = raw.slice(1, -1);
30
+ var fields = {};
31
+ try { raw = decodeURIComponent(raw); } catch (e) { return null; }
32
+ raw.split('&').forEach(function (pair) {
33
+ var eq = pair.indexOf('=');
34
+ if (eq > 0) fields[pair.slice(0, eq)] = pair.slice(eq + 1);
35
+ });
36
+ if (fields.v !== '1') return null;
37
+ var out = {};
38
+ if (fields.scheme === 'light' || fields.scheme === 'dark') out.scheme = fields.scheme;
39
+ if (fields.theme && THEME_ID.test(fields.theme)) out.theme = fields.theme;
40
+ return out;
41
+ }
42
+ return null;
43
+ }
44
+
45
+ /** What the page shows: the host's choice wins over the stored one (ED-6); an unknown theme is
46
+ the default theme; a missing scheme follows prefers-color-scheme (returned as null). */
47
+ function resolveAppearance(host, stored, themes, applies) {
48
+ themes = themes || THEMES;
49
+ applies = applies || ['scheme', 'theme'];
50
+ var source = host || stored || {};
51
+ var theme = applies.indexOf('theme') >= 0 ? source.theme : undefined;
52
+ var scheme = applies.indexOf('scheme') >= 0 ? source.scheme : undefined;
53
+ return {
54
+ theme: theme && themes.indexOf(theme) >= 0 ? theme : DEFAULT_THEME,
55
+ scheme: scheme === 'light' || scheme === 'dark' ? scheme : null,
56
+ host: !!host
57
+ };
58
+ }
59
+
60
+ var api = { kit: KIT, version: VERSION, themes: THEMES.slice(), parseAppearance: parseAppearance, resolveAppearance: resolveAppearance };
61
+ if (typeof module === 'object' && module.exports) module.exports = api;
62
+ if (typeof document === 'undefined') return;
63
+
64
+ var doc = document;
65
+ var html = doc.documentElement;
66
+ root.FabricDashboard = api;
67
+
68
+ function readStored() {
69
+ try {
70
+ var v = JSON.parse(root.localStorage.getItem(STORE_KEY) || 'null');
71
+ return v && typeof v === 'object' ? v : null;
72
+ } catch (e) { return null; }
73
+ }
74
+ function writeStored(v) {
75
+ try { root.localStorage.setItem(STORE_KEY, JSON.stringify(v)); } catch (e) { /* private window: the choice lasts this visit */ }
76
+ }
77
+ function applies() {
78
+ var declared = html.getAttribute('data-fd-appearance');
79
+ return declared == null ? ['scheme', 'theme'] : declared.split(/\s+/).filter(Boolean);
80
+ }
81
+
82
+ function applyAppearance() {
83
+ var host = parseAppearance(doc.cookie);
84
+ var a = resolveAppearance(host, readStored(), THEMES, applies());
85
+ if (a.theme === DEFAULT_THEME) html.removeAttribute('data-theme'); else html.setAttribute('data-theme', a.theme);
86
+ if (a.scheme) html.setAttribute('data-scheme', a.scheme); else html.removeAttribute('data-scheme');
87
+ if (a.host) html.setAttribute('data-fd-host-appearance', ''); else html.removeAttribute('data-fd-host-appearance');
88
+ syncPickers(a);
89
+ return a;
90
+ }
91
+
92
+ /* ---- the page's own appearance controls (hidden while the host owns appearance) ---- */
93
+ function syncPickers(a) {
94
+ var themePickers = doc.querySelectorAll('select[data-fd-theme-picker]');
95
+ for (var i = 0; i < themePickers.length; i++) themePickers[i].value = a.theme;
96
+ var schemePickers = doc.querySelectorAll('select[data-fd-scheme-picker]');
97
+ for (var j = 0; j < schemePickers.length; j++) schemePickers[j].value = a.scheme || 'auto';
98
+ }
99
+ function setupPickers() {
100
+ var themePickers = doc.querySelectorAll('select[data-fd-theme-picker]');
101
+ for (var i = 0; i < themePickers.length; i++) {
102
+ var sel = themePickers[i];
103
+ sel.setAttribute('data-fd-appearance-control', '');
104
+ if (!sel.options.length) {
105
+ THEMES.forEach(function (id) {
106
+ var opt = doc.createElement('option');
107
+ opt.value = id;
108
+ opt.textContent = id.charAt(0).toUpperCase() + id.slice(1);
109
+ sel.appendChild(opt);
110
+ });
111
+ }
112
+ sel.addEventListener('change', function (e) {
113
+ var stored = readStored() || {};
114
+ stored.theme = e.target.value;
115
+ writeStored(stored);
116
+ applyAppearance();
117
+ });
118
+ }
119
+ var schemePickers = doc.querySelectorAll('select[data-fd-scheme-picker]');
120
+ for (var j = 0; j < schemePickers.length; j++) {
121
+ var s = schemePickers[j];
122
+ s.setAttribute('data-fd-appearance-control', '');
123
+ if (!s.options.length) {
124
+ [['auto', 'System'], ['light', 'Light'], ['dark', 'Dark']].forEach(function (o) {
125
+ var opt = doc.createElement('option');
126
+ opt.value = o[0];
127
+ opt.textContent = o[1];
128
+ s.appendChild(opt);
129
+ });
130
+ }
131
+ s.addEventListener('change', function (e) {
132
+ var stored = readStored() || {};
133
+ if (e.target.value === 'auto') delete stored.scheme; else stored.scheme = e.target.value;
134
+ writeStored(stored);
135
+ applyAppearance();
136
+ });
137
+ }
138
+ }
139
+
140
+ function watchAppearance() {
141
+ if (root.cookieStore && typeof root.cookieStore.addEventListener === 'function') {
142
+ root.cookieStore.addEventListener('change', function (e) {
143
+ var touched = [].concat(e.changed || [], e.deleted || []);
144
+ for (var i = 0; i < touched.length; i++) if (touched[i].name === COOKIE) { applyAppearance(); return; }
145
+ });
146
+ }
147
+ doc.addEventListener('visibilitychange', function () { if (!doc.hidden) applyAppearance(); });
148
+ root.addEventListener('focus', applyAppearance);
149
+ }
150
+
151
+ /* ---- navigation: fold what does not fit into More (ED-3) ---- */
152
+ function foldNav(nav) {
153
+ var list = nav.querySelector('.fd-nav-list');
154
+ if (!list) return;
155
+ nav.classList.add('fd-nav--fold');
156
+ var more = nav.querySelector(':scope > .fd-more');
157
+ if (!more) {
158
+ more = doc.createElement('details');
159
+ more.className = 'fd-more';
160
+ var summary = doc.createElement('summary');
161
+ summary.textContent = nav.getAttribute('data-fd-more-label') || 'More';
162
+ var menu = doc.createElement('ul');
163
+ menu.className = 'fd-more-list';
164
+ more.appendChild(summary);
165
+ more.appendChild(menu);
166
+ nav.appendChild(more);
167
+ more.addEventListener('click', function (e) {
168
+ if (e.target.closest && e.target.closest('a')) more.open = false;
169
+ });
170
+ more.addEventListener('keydown', function (e) {
171
+ if (e.key === 'Escape' && more.open) { more.open = false; summary.focus(); }
172
+ });
173
+ doc.addEventListener('click', function (e) { if (more.open && !more.contains(e.target)) more.open = false; });
174
+ }
175
+ var menuList = more.querySelector('.fd-more-list');
176
+ var summaryEl = more.querySelector('summary');
177
+ var label = nav.getAttribute('data-fd-more-label') || 'More';
178
+
179
+ function layout() {
180
+ // Put every item back in its place, then move the last ones out until the rest fit.
181
+ while (menuList.firstChild) list.appendChild(menuList.firstChild);
182
+ more.hidden = true;
183
+ if (list.scrollWidth <= list.clientWidth + 1) { summaryEl.textContent = label; return; }
184
+ more.hidden = false;
185
+ var items = list.children;
186
+ while (items.length > 1 && list.scrollWidth > list.clientWidth + 1) {
187
+ menuList.insertBefore(items[items.length - 1], menuList.firstChild);
188
+ }
189
+ if (list.scrollWidth > list.clientWidth + 1 && items.length) menuList.insertBefore(items[0], menuList.firstChild);
190
+ var current = menuList.querySelector('[aria-current]');
191
+ summaryEl.textContent = current ? label + ': ' + current.textContent.trim() : label + ' (' + menuList.children.length + ')';
192
+ }
193
+ layout();
194
+ if (typeof root.ResizeObserver === 'function') new root.ResizeObserver(function () { layout(); }).observe(nav);
195
+ else root.addEventListener('resize', layout);
196
+ }
197
+
198
+ /* ---- wide boxes: keyboard-reachable, with a name, marked when they overflow (ED-4) ---- */
199
+ var FOCUSABLE = 'a[href], button, input, select, textarea, [tabindex]';
200
+ function prepareScrollBox(box) {
201
+ if (!box.querySelector(FOCUSABLE) && !box.hasAttribute('tabindex')) {
202
+ box.setAttribute('tabindex', '0');
203
+ if (!box.hasAttribute('role')) box.setAttribute('role', 'region');
204
+ if (!box.hasAttribute('aria-label') && !box.hasAttribute('aria-labelledby')) {
205
+ var caption = box.querySelector('caption');
206
+ box.setAttribute('aria-label', box.getAttribute('data-fd-label') || (caption && caption.textContent.trim()) || 'Scrollable content');
207
+ }
208
+ }
209
+ function mark() {
210
+ if (box.scrollWidth > box.clientWidth + 1) box.setAttribute('data-fd-overflow', '');
211
+ else box.removeAttribute('data-fd-overflow');
212
+ }
213
+ mark();
214
+ if (typeof root.ResizeObserver === 'function') new root.ResizeObserver(mark).observe(box);
215
+ }
216
+
217
+ /* ---- sticky chrome: at most min(120 px, a quarter of the height) stays pinned (ED-5) ---- */
218
+ function measureChrome() {
219
+ var chrome = doc.querySelector('.fd-chrome');
220
+ if (!chrome) return;
221
+ function set() {
222
+ var height = Math.ceil(chrome.getBoundingClientRect().height);
223
+ var limit = Math.min(parseFloat(getComputedStyle(html).getPropertyValue('--fd-chrome-max')) || 120, root.innerHeight / 4);
224
+ var header = chrome.querySelector('.fd-header');
225
+ var lift = 0;
226
+ if (height > limit && header) lift = Math.min(Math.ceil(header.getBoundingClientRect().height), height);
227
+ html.style.setProperty('--fd-chrome-top', lift ? -lift + 'px' : '0px');
228
+ html.style.setProperty('--fd-chrome-h', Math.max(0, height - lift) + 'px');
229
+ }
230
+ set();
231
+ if (typeof root.ResizeObserver === 'function') new root.ResizeObserver(set).observe(chrome);
232
+ root.addEventListener('resize', set);
233
+ }
234
+
235
+ function init() {
236
+ html.classList.add('fd-js');
237
+ setupPickers();
238
+ applyAppearance();
239
+ watchAppearance();
240
+ var navs = doc.querySelectorAll('nav.fd-nav');
241
+ for (var i = 0; i < navs.length; i++) if (!navs[i].hasAttribute('data-fd-no-fold')) foldNav(navs[i]);
242
+ var boxes = doc.querySelectorAll('.fd-scroll');
243
+ for (var j = 0; j < boxes.length; j++) prepareScrollBox(boxes[j]);
244
+ measureChrome();
245
+ }
246
+
247
+ api.applyAppearance = applyAppearance;
248
+ api.prepareScrollBox = prepareScrollBox;
249
+ api.foldNav = foldNav;
250
+ // Apply the theme before first paint when loaded without defer; the rest waits for the DOM.
251
+ applyAppearance();
252
+ if (doc.readyState === 'loading') doc.addEventListener('DOMContentLoaded', init); else init();
253
+ })(typeof window !== 'undefined' ? window : this);
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "fabric-dashboard-kit",
3
+ "version": "1.0.0",
4
+ "profile": "fabric-dashboard/0.1",
5
+ "decision": "DEC-0036",
6
+ "declarationKey": "https://fabric.passioncode.ai/agent-contract/extensions/dashboard/0.1",
7
+ "minWidth": 360,
8
+ "themes": [
9
+ "graphite",
10
+ "fabric",
11
+ "paper",
12
+ "forest",
13
+ "ocean",
14
+ "ember",
15
+ "contrast"
16
+ ],
17
+ "files": {
18
+ "fabric-dashboard.css": "3993e6ab5e58d5229bc4dc245aa634fcf88a4f59502e1de90d3d3cfef70528a2",
19
+ "fabric-dashboard.js": "bac615a40c85d8c668588528f9e21dac800aa01fefb56b8ee573c30520ce74a7",
20
+ "themes.json": "511839f1a1a83eb37fadfd132791474497d5c28c5091700b9aa31ad076e359b5"
21
+ },
22
+ "history": {
23
+ "1.0.0": {
24
+ "fabric-dashboard.css": "3993e6ab5e58d5229bc4dc245aa634fcf88a4f59502e1de90d3d3cfef70528a2",
25
+ "fabric-dashboard.js": "bac615a40c85d8c668588528f9e21dac800aa01fefb56b8ee573c30520ce74a7"
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,350 @@
1
+ {
2
+ "kit": "fabric-dashboard-kit",
3
+ "profile": "fabric-dashboard/0.1",
4
+ "default": "graphite",
5
+ "tokens": {
6
+ "bg": "app ground",
7
+ "panel": "cards, bars, dialogs, inputs",
8
+ "panel-2": "inset, table headers, quiet tiles",
9
+ "ink": "primary text",
10
+ "muted": "secondary text, labels, metadata (AA on every surface)",
11
+ "border": "decorative 1px hairline",
12
+ "border-strong": "stronger decorative edge",
13
+ "edge": "a border that carries meaning: inputs, selected rows, scroll-box edges (3:1)",
14
+ "accent": "the one accent: primary button fill, links on panel, focus ring",
15
+ "accent-weak": "accent tint for selected fills",
16
+ "accent-ink": "text on the accent",
17
+ "ok": "done, healthy",
18
+ "ok-weak": "its tint",
19
+ "warn": "a person is needed",
20
+ "warn-weak": "its tint",
21
+ "danger": "failed, error",
22
+ "danger-weak": "its tint",
23
+ "info": "running, working",
24
+ "info-weak": "its tint"
25
+ },
26
+ "themes": {
27
+ "graphite": {
28
+ "name": "Graphite",
29
+ "character": "neutral grey with one blue accent; the SHELEG Design workbench token layer verbatim, plus the edge token",
30
+ "light": {
31
+ "bg": "#f7f8fa",
32
+ "panel": "#ffffff",
33
+ "panel-2": "#f7f8fa",
34
+ "ink": "#1a1f2b",
35
+ "muted": "#5b6472",
36
+ "border": "#e6e9ef",
37
+ "border-strong": "#d7dce4",
38
+ "edge": "#828b98",
39
+ "accent": "#2f6feb",
40
+ "accent-weak": "#eaf0fe",
41
+ "accent-ink": "#ffffff",
42
+ "ok": "#1a7f37",
43
+ "ok-weak": "#e6f4ea",
44
+ "warn": "#9a6700",
45
+ "warn-weak": "#fff3d6",
46
+ "danger": "#d1242f",
47
+ "danger-weak": "#fde8e9",
48
+ "info": "#2f6feb",
49
+ "info-weak": "#eaf0fe"
50
+ },
51
+ "dark": {
52
+ "bg": "#0f1218",
53
+ "panel": "#161b24",
54
+ "panel-2": "#1b212c",
55
+ "ink": "#e8ecf3",
56
+ "muted": "#8a93a6",
57
+ "border": "#232a36",
58
+ "border-strong": "#2c3441",
59
+ "edge": "#697383",
60
+ "accent": "#4b8bff",
61
+ "accent-weak": "#1b2740",
62
+ "accent-ink": "#0f1218",
63
+ "ok": "#3fb960",
64
+ "ok-weak": "#12281a",
65
+ "warn": "#d9a93f",
66
+ "warn-weak": "#2b2210",
67
+ "danger": "#e5534b",
68
+ "danger-weak": "#2d1517",
69
+ "info": "#4b8bff",
70
+ "info-weak": "#1b2740"
71
+ }
72
+ },
73
+ "fabric": {
74
+ "name": "Fabric",
75
+ "character": "the PassionCode.ai plum violet on warm grey",
76
+ "light": {
77
+ "bg": "#f7f5f8",
78
+ "panel": "#ffffff",
79
+ "panel-2": "#f2eef4",
80
+ "ink": "#211725",
81
+ "muted": "#655769",
82
+ "border": "#e9e3ec",
83
+ "border-strong": "#d9d0de",
84
+ "edge": "#8f8296",
85
+ "accent": "#6b2185",
86
+ "accent-weak": "#f4e9f7",
87
+ "accent-ink": "#ffffff",
88
+ "ok": "#246b3b",
89
+ "ok-weak": "#e4f3e8",
90
+ "warn": "#8a4b0b",
91
+ "warn-weak": "#fff0dc",
92
+ "danger": "#a82f44",
93
+ "danger-weak": "#fde8ec",
94
+ "info": "#345da7",
95
+ "info-weak": "#e8efff"
96
+ },
97
+ "dark": {
98
+ "bg": "#110c15",
99
+ "panel": "#1b1420",
100
+ "panel-2": "#231a29",
101
+ "ink": "#fff9f0",
102
+ "muted": "#b6aabc",
103
+ "border": "#2e2334",
104
+ "border-strong": "#3a2e41",
105
+ "edge": "#7a6a80",
106
+ "accent": "#d4a3ea",
107
+ "accent-weak": "#2f1d38",
108
+ "accent-ink": "#110c15",
109
+ "ok": "#79d49a",
110
+ "ok-weak": "#12291c",
111
+ "warn": "#f6ba75",
112
+ "warn-weak": "#332314",
113
+ "danger": "#ff969f",
114
+ "danger-weak": "#35191f",
115
+ "info": "#a6bfff",
116
+ "info-weak": "#18243d"
117
+ }
118
+ },
119
+ "paper": {
120
+ "name": "Paper",
121
+ "character": "warm cream paper with a brown accent",
122
+ "light": {
123
+ "bg": "#faf6ee",
124
+ "panel": "#fffdf8",
125
+ "panel-2": "#f3ede1",
126
+ "ink": "#2b241a",
127
+ "muted": "#6b5f4d",
128
+ "border": "#ebe3d4",
129
+ "border-strong": "#ddd2bf",
130
+ "edge": "#8d806d",
131
+ "accent": "#8a4a12",
132
+ "accent-weak": "#f6eadb",
133
+ "accent-ink": "#ffffff",
134
+ "ok": "#2f6b2f",
135
+ "ok-weak": "#e7f1e2",
136
+ "warn": "#8a5a00",
137
+ "warn-weak": "#fbefd2",
138
+ "danger": "#b02a20",
139
+ "danger-weak": "#fbe5e1",
140
+ "info": "#2c5d8a",
141
+ "info-weak": "#e5eef6"
142
+ },
143
+ "dark": {
144
+ "bg": "#17140f",
145
+ "panel": "#1f1b15",
146
+ "panel-2": "#27221a",
147
+ "ink": "#f3ece0",
148
+ "muted": "#b3a690",
149
+ "border": "#302a21",
150
+ "border-strong": "#3d362b",
151
+ "edge": "#7b7161",
152
+ "accent": "#e3a565",
153
+ "accent-weak": "#33261a",
154
+ "accent-ink": "#17140f",
155
+ "ok": "#86c48a",
156
+ "ok-weak": "#15261a",
157
+ "warn": "#e0b25a",
158
+ "warn-weak": "#2e2412",
159
+ "danger": "#f0877c",
160
+ "danger-weak": "#331a17",
161
+ "info": "#8fb8e0",
162
+ "info-weak": "#172433"
163
+ }
164
+ },
165
+ "forest": {
166
+ "name": "Forest",
167
+ "character": "cool green-grey with a green accent",
168
+ "light": {
169
+ "bg": "#f4f8f4",
170
+ "panel": "#ffffff",
171
+ "panel-2": "#edf3ee",
172
+ "ink": "#16231a",
173
+ "muted": "#526356",
174
+ "border": "#dfe8e1",
175
+ "border-strong": "#cddbd0",
176
+ "edge": "#77897c",
177
+ "accent": "#1f7a45",
178
+ "accent-weak": "#e3f2e8",
179
+ "accent-ink": "#ffffff",
180
+ "ok": "#1f7a45",
181
+ "ok-weak": "#e3f2e8",
182
+ "warn": "#8a5d00",
183
+ "warn-weak": "#fbf0d4",
184
+ "danger": "#b8312a",
185
+ "danger-weak": "#fbe6e4",
186
+ "info": "#2a6496",
187
+ "info-weak": "#e4eef7"
188
+ },
189
+ "dark": {
190
+ "bg": "#0d1410",
191
+ "panel": "#131c16",
192
+ "panel-2": "#18231c",
193
+ "ink": "#e4efe7",
194
+ "muted": "#8fa595",
195
+ "border": "#1f2c23",
196
+ "border-strong": "#29382e",
197
+ "edge": "#637568",
198
+ "accent": "#5cc98a",
199
+ "accent-weak": "#173322",
200
+ "accent-ink": "#0d1410",
201
+ "ok": "#5cc98a",
202
+ "ok-weak": "#173322",
203
+ "warn": "#d8ad4a",
204
+ "warn-weak": "#2b2311",
205
+ "danger": "#ec6a5e",
206
+ "danger-weak": "#2f1714",
207
+ "info": "#7fb2e5",
208
+ "info-weak": "#152435"
209
+ }
210
+ },
211
+ "ocean": {
212
+ "name": "Ocean",
213
+ "character": "blue-grey with a teal accent",
214
+ "light": {
215
+ "bg": "#f3f7f9",
216
+ "panel": "#ffffff",
217
+ "panel-2": "#ebf2f5",
218
+ "ink": "#132029",
219
+ "muted": "#4f6370",
220
+ "border": "#dde7ec",
221
+ "border-strong": "#ccdae1",
222
+ "edge": "#738892",
223
+ "accent": "#0b6e8a",
224
+ "accent-weak": "#e0f1f6",
225
+ "accent-ink": "#ffffff",
226
+ "ok": "#1b7a4a",
227
+ "ok-weak": "#e2f3ea",
228
+ "warn": "#8f5f00",
229
+ "warn-weak": "#fcf0d3",
230
+ "danger": "#c0352b",
231
+ "danger-weak": "#fce6e3",
232
+ "info": "#1f5fae",
233
+ "info-weak": "#e3edfa"
234
+ },
235
+ "dark": {
236
+ "bg": "#0b1217",
237
+ "panel": "#111a21",
238
+ "panel-2": "#16212a",
239
+ "ink": "#e2edf3",
240
+ "muted": "#8aa2b1",
241
+ "border": "#1c2a34",
242
+ "border-strong": "#263741",
243
+ "edge": "#607480",
244
+ "accent": "#3fc0d8",
245
+ "accent-weak": "#123039",
246
+ "accent-ink": "#0b1217",
247
+ "ok": "#4fc58a",
248
+ "ok-weak": "#11291d",
249
+ "warn": "#dcac45",
250
+ "warn-weak": "#2c2310",
251
+ "danger": "#ef6b60",
252
+ "danger-weak": "#311714",
253
+ "info": "#6fa8f0",
254
+ "info-weak": "#13233a"
255
+ }
256
+ },
257
+ "ember": {
258
+ "name": "Ember",
259
+ "character": "warm sand with an orange accent",
260
+ "light": {
261
+ "bg": "#fbf6f2",
262
+ "panel": "#ffffff",
263
+ "panel-2": "#f6ede6",
264
+ "ink": "#2a1b14",
265
+ "muted": "#6e5649",
266
+ "border": "#efe2d8",
267
+ "border-strong": "#e2d1c4",
268
+ "edge": "#958072",
269
+ "accent": "#b04a0c",
270
+ "accent-weak": "#fbebe0",
271
+ "accent-ink": "#ffffff",
272
+ "ok": "#2a7340",
273
+ "ok-weak": "#e4f2e7",
274
+ "warn": "#8a5800",
275
+ "warn-weak": "#fbefd3",
276
+ "danger": "#b42324",
277
+ "danger-weak": "#fbe4e3",
278
+ "info": "#2b5f9e",
279
+ "info-weak": "#e4edf8"
280
+ },
281
+ "dark": {
282
+ "bg": "#16100c",
283
+ "panel": "#1e1611",
284
+ "panel-2": "#271d16",
285
+ "ink": "#f6ebe3",
286
+ "muted": "#b8a194",
287
+ "border": "#30241c",
288
+ "border-strong": "#3e2f25",
289
+ "edge": "#7e6a5e",
290
+ "accent": "#ff8f4d",
291
+ "accent-weak": "#3a2112",
292
+ "accent-ink": "#16100c",
293
+ "ok": "#78c88e",
294
+ "ok-weak": "#132719",
295
+ "warn": "#e3b04f",
296
+ "warn-weak": "#2e2410",
297
+ "danger": "#f4776f",
298
+ "danger-weak": "#351816",
299
+ "info": "#86b2ef",
300
+ "info-weak": "#162338"
301
+ }
302
+ },
303
+ "contrast": {
304
+ "name": "Contrast",
305
+ "character": "maximum contrast: black and white, no tints in the ground",
306
+ "light": {
307
+ "bg": "#ffffff",
308
+ "panel": "#ffffff",
309
+ "panel-2": "#f2f2f2",
310
+ "ink": "#000000",
311
+ "muted": "#2b2b2b",
312
+ "border": "#000000",
313
+ "border-strong": "#000000",
314
+ "edge": "#000000",
315
+ "accent": "#0033cc",
316
+ "accent-weak": "#e6ecff",
317
+ "accent-ink": "#ffffff",
318
+ "ok": "#005c1f",
319
+ "ok-weak": "#e3f5e8",
320
+ "warn": "#6b4200",
321
+ "warn-weak": "#fff1d1",
322
+ "danger": "#b00010",
323
+ "danger-weak": "#ffe6e8",
324
+ "info": "#0033cc",
325
+ "info-weak": "#e6ecff"
326
+ },
327
+ "dark": {
328
+ "bg": "#000000",
329
+ "panel": "#000000",
330
+ "panel-2": "#141414",
331
+ "ink": "#ffffff",
332
+ "muted": "#e0e0e0",
333
+ "border": "#ffffff",
334
+ "border-strong": "#ffffff",
335
+ "edge": "#ffffff",
336
+ "accent": "#7fb2ff",
337
+ "accent-weak": "#0d1f3d",
338
+ "accent-ink": "#000000",
339
+ "ok": "#5ee08a",
340
+ "ok-weak": "#0a2614",
341
+ "warn": "#ffd166",
342
+ "warn-weak": "#2e2306",
343
+ "danger": "#ff8a8a",
344
+ "danger-weak": "#3a0d0d",
345
+ "info": "#7fb2ff",
346
+ "info-weak": "#0d1f3d"
347
+ }
348
+ }
349
+ }
350
+ }