mastermind-md 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 (52) hide show
  1. package/.claude/skills/master/SKILL.md +10 -0
  2. package/.claude/skills/mastermind/SKILL.md +61 -0
  3. package/.claude/skills/mastermind/reference/demo.md +35 -0
  4. package/LICENSE +21 -0
  5. package/README.md +135 -0
  6. package/assets/agent/global.md +12 -0
  7. package/bin/mastermind.js +17 -0
  8. package/dist/cli/index.js +1284 -0
  9. package/dist/cli/index.js.map +1 -0
  10. package/dist/server/index.js +1752 -0
  11. package/dist/server/index.js.map +1 -0
  12. package/dist/ui/assets/FindBar-CSKdPrxm.js +1 -0
  13. package/dist/ui/assets/RenameDialog-C6yP_6D8.js +1 -0
  14. package/dist/ui/assets/SettingsPanel-C6-wwvJr.js +1 -0
  15. package/dist/ui/assets/SourceEditor-DN44HaIZ.js +37 -0
  16. package/dist/ui/assets/TranslatedView-G29rKesM.js +1 -0
  17. package/dist/ui/assets/index-Bhf9eUP2.css +1 -0
  18. package/dist/ui/assets/index-cMAuoyhV.js +99 -0
  19. package/dist/ui/assets/jsx-runtime-BrnrUjgG.js +1 -0
  20. package/dist/ui/assets/react-DoK4WR2u.js +1 -0
  21. package/dist/ui/index.html +16 -0
  22. package/package.json +91 -0
  23. package/themes/carbon/theme.json +11 -0
  24. package/themes/carbon/tokens.css +67 -0
  25. package/themes/cobalt/theme.json +11 -0
  26. package/themes/cobalt/tokens.css +67 -0
  27. package/themes/fonts/BricolageGrotesque-Variable.woff2 +0 -0
  28. package/themes/fonts/CrimsonPro-Variable.woff2 +0 -0
  29. package/themes/fonts/Fraunces-Variable.woff2 +0 -0
  30. package/themes/fonts/GeistSans-Variable.woff2 +0 -0
  31. package/themes/fonts/HankenGrotesk-Variable.woff2 +0 -0
  32. package/themes/fonts/Inter-Variable.woff2 +0 -0
  33. package/themes/fonts/JetBrainsMono-Variable.woff2 +0 -0
  34. package/themes/fonts/Lora-Variable.woff2 +0 -0
  35. package/themes/fonts/Manrope-Variable.woff2 +0 -0
  36. package/themes/fonts/Newsreader-Variable.woff2 +0 -0
  37. package/themes/fonts/Outfit-Variable.woff2 +0 -0
  38. package/themes/fonts/SpaceGrotesk-Variable.woff2 +0 -0
  39. package/themes/fonts/SplineSansMono-Variable.woff2 +0 -0
  40. package/themes/fonts/UbuntuSansMono-Variable.woff2 +0 -0
  41. package/themes/grid/fonts/GeistMono-Variable.woff2 +0 -0
  42. package/themes/grid/fonts/SchibstedGrotesk-Variable.woff2 +0 -0
  43. package/themes/grid/theme.json +11 -0
  44. package/themes/grid/tokens.css +67 -0
  45. package/themes/nacht/theme.json +11 -0
  46. package/themes/nacht/tokens.css +67 -0
  47. package/themes/rose/theme.json +11 -0
  48. package/themes/rose/tokens.css +67 -0
  49. package/themes/sepia/theme.json +11 -0
  50. package/themes/sepia/tokens.css +67 -0
  51. package/themes/slate/theme.json +11 -0
  52. package/themes/slate/tokens.css +67 -0
@@ -0,0 +1 @@
1
+ import{r as e}from"./react-DoK4WR2u.js";var t=e((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),n=e(((e,n)=>{n.exports=t()}));export{n as t};
@@ -0,0 +1 @@
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},c=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},l=(n,r,a)=>(a=n==null?{}:e(i(n)),c(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n)),u=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},T=Object.prototype.hasOwnProperty;function E(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function D(e,t){return E(e.type,t,e.props)}function O(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function k(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var A=/\/+/g;function j(e,t){return typeof e==`object`&&e&&e.key!=null?k(``+e.key):t.toString(36)}function M(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function N(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,N(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+j(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(A,`$&/`)+`/`),N(o,r,i,``,function(e){return e})):o!=null&&(O(o)&&(o=D(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(A,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u<e.length;u++)a=e[u],s=l+j(a,u),c+=N(a,r,i,s,o);else if(u=m(e),typeof u==`function`)for(e=u.call(e),u=0;!(a=e.next()).done;)a=a.value,s=l+j(a,u++),c+=N(a,r,i,s,o);else if(s===`object`){if(typeof e.then==`function`)return N(M(e),r,i,a,o);throw r=String(e),Error(`Objects are not valid as a React child (found: `+(r===`[object Object]`?`object with keys {`+Object.keys(e).join(`, `)+`}`:r)+`). If you meant to render a collection of children, use an array instead.`)}return c}function P(e,t,n){if(e==null)return e;var r=[],i=0;return N(e,r,``,``,function(e){return t.call(n,e,i++)}),r}function F(e){if(e._status===-1){var t=e._result;t=t(),t.then(function(t){(e._status===0||e._status===-1)&&(e._status=1,e._result=t)},function(t){(e._status===0||e._status===-1)&&(e._status=2,e._result=t)}),e._status===-1&&(e._status=0,e._result=t)}if(e._status===1)return e._result.default;throw e._result}var I=typeof reportError==`function`?reportError:function(e){if(typeof window==`object`&&typeof window.ErrorEvent==`function`){var t=new window.ErrorEvent(`error`,{bubbles:!0,cancelable:!0,message:typeof e==`object`&&e&&typeof e.message==`string`?String(e.message):String(e),error:e});if(!window.dispatchEvent(t))return}else if(typeof process==`object`&&typeof process.emit==`function`){process.emit(`uncaughtException`,e);return}console.error(e)},L={map:P,forEach:function(e,t,n){P(e,function(){t.apply(this,arguments)},n)},count:function(e){var t=0;return P(e,function(){t++}),t},toArray:function(e){return P(e,function(e){return e})||[]},only:function(e){if(!O(e))throw Error(`React.Children.only expected to receive a single React element child.`);return e}};e.Activity=f,e.Children=L,e.Component=v,e.Fragment=r,e.Profiler=a,e.PureComponent=b,e.StrictMode=i,e.Suspense=l,e.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=w,e.__COMPILER_RUNTIME={__proto__:null,c:function(e){return w.H.useMemoCache(e)}},e.cache=function(e){return function(){return e.apply(null,arguments)}},e.cacheSignal=function(){return null},e.cloneElement=function(e,t,n){if(e==null)throw Error(`The argument must be a React element, but you passed `+e+`.`);var r=g({},e.props),i=e.key;if(t!=null)for(a in t.key!==void 0&&(i=``+t.key),t)!T.call(t,a)||a===`key`||a===`__self`||a===`__source`||a===`ref`&&t.ref===void 0||(r[a]=t[a]);var a=arguments.length-2;if(a===1)r.children=n;else if(1<a){for(var o=Array(a),s=0;s<a;s++)o[s]=arguments[s+2];r.children=o}return E(e.type,i,r)},e.createContext=function(e){return e={$$typeof:s,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null},e.Provider=e,e.Consumer={$$typeof:o,_context:e},e},e.createElement=function(e,t,n){var r,i={},a=null;if(t!=null)for(r in t.key!==void 0&&(a=``+t.key),t)T.call(t,r)&&r!==`key`&&r!==`__self`&&r!==`__source`&&(i[r]=t[r]);var o=arguments.length-2;if(o===1)i.children=n;else if(1<o){for(var s=Array(o),c=0;c<o;c++)s[c]=arguments[c+2];i.children=s}if(e&&e.defaultProps)for(r in o=e.defaultProps,o)i[r]===void 0&&(i[r]=o[r]);return E(e,a,i)},e.createRef=function(){return{current:null}},e.forwardRef=function(e){return{$$typeof:c,render:e}},e.isValidElement=O,e.lazy=function(e){return{$$typeof:d,_payload:{_status:-1,_result:e},_init:F}},e.memo=function(e,t){return{$$typeof:u,type:e,compare:t===void 0?null:t}},e.startTransition=function(e){var t=w.T,n={};w.T=n;try{var r=e(),i=w.S;i!==null&&i(n,r),typeof r==`object`&&r&&typeof r.then==`function`&&r.then(C,I)}catch(e){I(e)}finally{t!==null&&n.types!==null&&(t.types=n.types),w.T=t}},e.unstable_useCacheRefresh=function(){return w.H.useCacheRefresh()},e.use=function(e){return w.H.use(e)},e.useActionState=function(e,t,n){return w.H.useActionState(e,t,n)},e.useCallback=function(e,t){return w.H.useCallback(e,t)},e.useContext=function(e){return w.H.useContext(e)},e.useDebugValue=function(){},e.useDeferredValue=function(e,t){return w.H.useDeferredValue(e,t)},e.useEffect=function(e,t){return w.H.useEffect(e,t)},e.useEffectEvent=function(e){return w.H.useEffectEvent(e)},e.useId=function(){return w.H.useId()},e.useImperativeHandle=function(e,t,n){return w.H.useImperativeHandle(e,t,n)},e.useInsertionEffect=function(e,t){return w.H.useInsertionEffect(e,t)},e.useLayoutEffect=function(e,t){return w.H.useLayoutEffect(e,t)},e.useMemo=function(e,t){return w.H.useMemo(e,t)},e.useOptimistic=function(e,t){return w.H.useOptimistic(e,t)},e.useReducer=function(e,t,n){return w.H.useReducer(e,t,n)},e.useRef=function(e){return w.H.useRef(e)},e.useState=function(e){return w.H.useState(e)},e.useSyncExternalStore=function(e,t,n){return w.H.useSyncExternalStore(e,t,n)},e.useTransition=function(){return w.H.useTransition()},e.version=`19.2.7`})),d=o(((e,t)=>{t.exports=u()})),f=l(d(),1),p=e=>{let t,n=new Set,r=(e,r)=>{let i=typeof e==`function`?e(t):e;if(!Object.is(i,t)){let e=t;t=r??(typeof i!=`object`||!i)?i:Object.assign({},t,i),n.forEach(n=>n(t,e))}},i=()=>t,a={setState:r,getState:i,getInitialState:()=>o,subscribe:e=>(n.add(e),()=>n.delete(e))},o=t=e(r,i,a);return a},m=(e=>e?p(e):p),h=e=>e;function g(e,t=h){let n=f.useSyncExternalStore(e.subscribe,f.useCallback(()=>t(e.getState()),[e,t]),f.useCallback(()=>t(e.getInitialState()),[e,t]));return f.useDebugValue(n),n}var _=e=>{let t=m(e),n=e=>g(t,e);return Object.assign(n,t),n},v=(e=>e?_(e):_);export{l as a,s as i,d as n,o as r,v as t};
@@ -0,0 +1,16 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Mastermind</title>
7
+ <link id="theme-tokens" rel="stylesheet" href="/themes/grid/tokens.css" />
8
+ <script type="module" crossorigin src="/assets/index-cMAuoyhV.js"></script>
9
+ <link rel="modulepreload" crossorigin href="/assets/react-DoK4WR2u.js">
10
+ <link rel="modulepreload" crossorigin href="/assets/jsx-runtime-BrnrUjgG.js">
11
+ <link rel="stylesheet" crossorigin href="/assets/index-Bhf9eUP2.css">
12
+ </head>
13
+ <body>
14
+ <div id="root"></div>
15
+ </body>
16
+ </html>
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "mastermind-md",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Review Markdown with your coding agent — local-first, CriticMarkup review loop, bilingual, the file is the protocol",
6
+ "license": "MIT",
7
+ "author": "Kevin Ding <kevincentding@gmail.com>",
8
+ "homepage": "https://github.com/Jingquank/Mastermind#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/Jingquank/Mastermind.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/Jingquank/Mastermind/issues"
15
+ },
16
+ "keywords": [
17
+ "markdown",
18
+ "review",
19
+ "criticmarkup",
20
+ "ai-agents",
21
+ "claude",
22
+ "cli",
23
+ "bilingual",
24
+ "local-first"
25
+ ],
26
+ "engines": {
27
+ "node": ">=20"
28
+ },
29
+ "bin": {
30
+ "mastermind": "bin/mastermind.js",
31
+ "mastermind-md": "bin/mastermind.js"
32
+ },
33
+ "files": [
34
+ "dist/",
35
+ "bin/",
36
+ "themes/",
37
+ ".claude/skills/",
38
+ "assets/agent/",
39
+ "README.md",
40
+ "LICENSE"
41
+ ],
42
+ "scripts": {
43
+ "build": "rm -rf dist && vite build && tsup",
44
+ "dev": "concurrently -k \"MASTERMIND_PORT=5199 tsx watch src/server/index.ts\" \"vite\"",
45
+ "test": "vitest run",
46
+ "test:watch": "vitest",
47
+ "typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.node.json",
48
+ "prepare": "npm run build",
49
+ "prepack": "npm run build"
50
+ },
51
+ "dependencies": {
52
+ "@codemirror/lang-markdown": "^6.5.0",
53
+ "@codemirror/language": "^6.12.3",
54
+ "@codemirror/state": "^6.6.0",
55
+ "@codemirror/view": "^6.43.1",
56
+ "@hono/node-server": "^2.0.4",
57
+ "@lezer/highlight": "^1.2.3",
58
+ "@radix-ui/react-icons": "^1.3.2",
59
+ "chokidar": "^5.0.0",
60
+ "codemirror": "^6.0.2",
61
+ "commander": "^15.0.0",
62
+ "diff": "^9.0.0",
63
+ "hono": "^4.12.25",
64
+ "mdast-util-to-markdown": "^2.1.2",
65
+ "radix-ui": "^1.5.0",
66
+ "react": "^19.2.7",
67
+ "react-dom": "^19.2.7",
68
+ "remark-gfm": "^4.0.1",
69
+ "remark-parse": "^11.0.0",
70
+ "remark-stringify": "^11.0.0",
71
+ "slot-text": "^0.2.2",
72
+ "unified": "^11.0.5",
73
+ "unist-util-visit": "^5.1.0",
74
+ "zustand": "^5.0.14"
75
+ },
76
+ "devDependencies": {
77
+ "@types/mdast": "^4.0.4",
78
+ "@types/node": "^25.9.3",
79
+ "@types/react": "^19.2.17",
80
+ "@types/react-dom": "^19.2.3",
81
+ "@types/unist": "^3.0.3",
82
+ "@vitejs/plugin-react": "^6.0.2",
83
+ "concurrently": "^10.0.3",
84
+ "jsdom": "^29.1.1",
85
+ "tsup": "^8.5.1",
86
+ "tsx": "^4.22.4",
87
+ "typescript": "^6.0.3",
88
+ "vite": "^8.0.16",
89
+ "vitest": "^4.1.8"
90
+ }
91
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "carbon",
3
+ "name": "Carbon",
4
+ "appearance": "dark",
5
+ "fonts": [
6
+ { "family": "Schibsted Grotesk", "src": "/themes/grid/fonts/SchibstedGrotesk-Variable.woff2", "weight": "400 900" },
7
+ { "family": "Geist Mono", "src": "/themes/grid/fonts/GeistMono-Variable.woff2", "weight": "100 900" }
8
+ ],
9
+ "grain": { "enabled": false },
10
+ "swatch": { "bg": "#08090a", "ink": "#9a9ca0", "accent": "#7c93b0" }
11
+ }
@@ -0,0 +1,67 @@
1
+ [data-theme='carbon'] {
2
+ /* Carbon (near-black, steel blue-gray).
3
+ v0.4: Radix-rigor 12-step OKLCH scales (anchored to the v0.3 Swiss values),
4
+ with semantic tokens mapped onto the steps. Marks stay hand-tuned. */
5
+
6
+ /* ---- Layer 1: raw scales (values differ per theme) ---- */
7
+ --gray-1: oklch(0.139 0.003 246.256);
8
+ --gray-2: oklch(0.187 0.006 271.067);
9
+ --gray-3: oklch(0.209 0.006 254.388);
10
+ --gray-4: oklch(0.232 0.006 254.388);
11
+ --gray-5: oklch(0.254 0.006 254.388);
12
+ --gray-6: oklch(0.276 0.008 264.438);
13
+ --gray-7: oklch(0.331 0.006 254.388);
14
+ --gray-8: oklch(0.386 0.006 254.388);
15
+ --gray-9: oklch(0.44 0.006 254.388);
16
+ --gray-10: oklch(0.495 0.007 255.514);
17
+ --gray-11: oklch(0.692 0.006 264.522);
18
+ --gray-12: oklch(0.958 0.002 247.84);
19
+ --accent-1: oklch(0.205 0.005 254.388);
20
+ --accent-2: oklch(0.245 0.008 254.388);
21
+ --accent-3: oklch(0.3 0.014 254.388);
22
+ --accent-4: oklch(0.36 0.02 254.388);
23
+ --accent-5: oklch(0.42 0.027 254.388);
24
+ --accent-6: oklch(0.485 0.034 254.388);
25
+ --accent-7: oklch(0.56 0.04 254.388);
26
+ --accent-8: oklch(0.65 0.046 254.388);
27
+ --accent-9: oklch(0.656 0.051 254.388);
28
+ --accent-10: oklch(0.74 0.049 254.388);
29
+ --accent-11: oklch(0.77 0.043 256.264);
30
+ --accent-12: oklch(0.93 0.038 254.388);
31
+
32
+ /* ---- Layer 2: semantic mapping (identical names across all themes) ---- */
33
+ --color-bg: var(--gray-1);
34
+ --color-bg-elevated: var(--gray-2);
35
+ --color-text: var(--gray-12);
36
+ --color-text-muted: var(--gray-11);
37
+ --color-text-faint: var(--gray-10);
38
+ --color-border: var(--gray-6);
39
+ --color-border-hover: var(--gray-7);
40
+ --color-accent: var(--accent-9);
41
+ --color-accent-dim: var(--accent-11);
42
+ --color-on-accent: #0a0e14;
43
+ --color-cta-bg: var(--accent-9);
44
+ --color-cta-text: #0a0e14;
45
+ --focus-ring: var(--accent-8);
46
+ --color-selection: color-mix(in oklab, var(--color-text) 16%, transparent);
47
+ --color-accent-surface: color-mix(in oklab, var(--color-accent) 16%, transparent);
48
+ --color-invert-bg: #f4f4f1;
49
+ --color-invert-bg-elevated: #ffffff;
50
+ --color-invert-text: #141414;
51
+ --color-invert-text-muted: rgba(20, 20, 20, 0.62);
52
+ --color-invert-border: rgba(20, 20, 20, 0.14);
53
+
54
+ /* ---- Layer 3: review / mark semantics (hand-tuned, de-conflicted from accent) ---- */
55
+ --review-insert-text: #4fc76e;
56
+ --review-insert-bg: rgba(79, 199, 110, 0.16);
57
+ --review-insert-border: #4fc76e;
58
+ --review-delete-text: #f0664a;
59
+ --review-delete-bg: rgba(240, 102, 74, 0.16);
60
+ --review-delete-border: rgba(240, 102, 74, 0.5);
61
+ --review-highlight-bg: rgba(232, 190, 58, 0.2);
62
+ --review-highlight-border: rgba(232, 190, 58, 0.55);
63
+ --review-comment-anchor: #c9a8ff;
64
+ --review-comment-active-bg: rgba(201, 168, 255, 0.16);
65
+
66
+ color-scheme: dark;
67
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "cobalt",
3
+ "name": "Cobalt",
4
+ "appearance": "light",
5
+ "fonts": [
6
+ { "family": "Schibsted Grotesk", "src": "/themes/grid/fonts/SchibstedGrotesk-Variable.woff2", "weight": "400 900" },
7
+ { "family": "Geist Mono", "src": "/themes/grid/fonts/GeistMono-Variable.woff2", "weight": "100 900" }
8
+ ],
9
+ "grain": { "enabled": false },
10
+ "swatch": { "bg": "#fcfcfa", "ink": "#66665f", "accent": "#2f6df0" }
11
+ }
@@ -0,0 +1,67 @@
1
+ [data-theme='cobalt'] {
2
+ /* Cobalt (light, electric blue).
3
+ v0.4: Radix-rigor 12-step OKLCH scales (anchored to the v0.3 Swiss values),
4
+ with semantic tokens mapped onto the steps. Marks stay hand-tuned. */
5
+
6
+ /* ---- Layer 1: raw scales (values differ per theme) ---- */
7
+ --gray-1: oklch(0.991 0.003 106.447);
8
+ --gray-2: oklch(0.96 0.004 106.474);
9
+ --gray-3: oklch(0.947 0.004 262.665);
10
+ --gray-4: oklch(0.935 0.004 262.665);
11
+ --gray-5: oklch(0.922 0.004 262.665);
12
+ --gray-6: oklch(0.909 0.008 98.888);
13
+ --gray-7: oklch(0.85 0.004 262.665);
14
+ --gray-8: oklch(0.791 0.004 262.665);
15
+ --gray-9: oklch(0.732 0.004 262.665);
16
+ --gray-10: oklch(0.674 0.015 88.723);
17
+ --gray-11: oklch(0.508 0.011 106.779);
18
+ --gray-12: oklch(0.191 0 89.876);
19
+ --accent-1: oklch(0.984 0.019 262.665);
20
+ --accent-2: oklch(0.968 0.033 262.665);
21
+ --accent-3: oklch(0.943 0.058 262.665);
22
+ --accent-4: oklch(0.913 0.083 262.665);
23
+ --accent-5: oklch(0.877 0.11 262.665);
24
+ --accent-6: oklch(0.832 0.137 262.665);
25
+ --accent-7: oklch(0.776 0.164 262.665);
26
+ --accent-8: oklch(0.702 0.187 262.665);
27
+ --accent-9: oklch(0.572 0.208 262.665);
28
+ --accent-10: oklch(0.552 0.201 262.665);
29
+ --accent-11: oklch(0.481 0.185 262.832);
30
+ --accent-12: oklch(0.353 0.154 262.665);
31
+
32
+ /* ---- Layer 2: semantic mapping (identical names across all themes) ---- */
33
+ --color-bg: var(--gray-1);
34
+ --color-bg-elevated: var(--gray-2);
35
+ --color-text: var(--gray-12);
36
+ --color-text-muted: var(--gray-11);
37
+ --color-text-faint: var(--gray-10);
38
+ --color-border: var(--gray-6);
39
+ --color-border-hover: var(--gray-7);
40
+ --color-accent: var(--accent-9);
41
+ --color-accent-dim: var(--accent-11);
42
+ --color-on-accent: #ffffff;
43
+ --color-cta-bg: var(--accent-9);
44
+ --color-cta-text: #ffffff;
45
+ --focus-ring: var(--gray-12);
46
+ --color-selection: color-mix(in oklab, var(--color-text) 12%, transparent);
47
+ --color-accent-surface: color-mix(in oklab, var(--color-accent) 10%, transparent);
48
+ --color-invert-bg: #141414;
49
+ --color-invert-bg-elevated: #1f1f1e;
50
+ --color-invert-text: #f4f4f1;
51
+ --color-invert-text-muted: rgba(244, 244, 241, 0.66);
52
+ --color-invert-border: rgba(244, 244, 241, 0.16);
53
+
54
+ /* ---- Layer 3: review / mark semantics (hand-tuned, de-conflicted from accent) ---- */
55
+ --review-insert-text: #1b7a35;
56
+ --review-insert-bg: rgba(27, 122, 53, 0.1);
57
+ --review-insert-border: #1b7a35;
58
+ --review-delete-text: #a23618;
59
+ --review-delete-bg: rgba(162, 54, 24, 0.1);
60
+ --review-delete-border: rgba(162, 54, 24, 0.45);
61
+ --review-highlight-bg: rgba(224, 176, 18, 0.22);
62
+ --review-highlight-border: rgba(224, 176, 18, 0.55);
63
+ --review-comment-anchor: #7c3aed;
64
+ --review-comment-active-bg: rgba(124, 58, 237, 0.1);
65
+
66
+ color-scheme: light;
67
+ }
Binary file
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "grid",
3
+ "name": "Grid",
4
+ "appearance": "light",
5
+ "fonts": [
6
+ { "family": "Schibsted Grotesk", "src": "/themes/grid/fonts/SchibstedGrotesk-Variable.woff2", "weight": "400 900" },
7
+ { "family": "Geist Mono", "src": "/themes/grid/fonts/GeistMono-Variable.woff2", "weight": "100 900" }
8
+ ],
9
+ "grain": { "enabled": false },
10
+ "swatch": { "bg": "#fcfcfa", "ink": "#66665f", "accent": "#e5241b" }
11
+ }
@@ -0,0 +1,67 @@
1
+ [data-theme='grid'] {
2
+ /* Swiss International — Grid (light, red flagship). The default theme.
3
+ v0.4: Radix-rigor 12-step OKLCH scales (anchored to the v0.3 Swiss values),
4
+ with semantic tokens mapped onto the steps. Marks stay hand-tuned. */
5
+
6
+ /* ---- Layer 1: raw scales (values differ per theme) ---- */
7
+ --gray-1: oklch(0.991 0.003 106.447);
8
+ --gray-2: oklch(0.96 0.004 106.474);
9
+ --gray-3: oklch(0.947 0.004 29.049);
10
+ --gray-4: oklch(0.935 0.004 29.049);
11
+ --gray-5: oklch(0.922 0.004 29.049);
12
+ --gray-6: oklch(0.909 0.008 98.888);
13
+ --gray-7: oklch(0.85 0.004 29.049);
14
+ --gray-8: oklch(0.791 0.004 29.049);
15
+ --gray-9: oklch(0.732 0.004 29.049);
16
+ --gray-10: oklch(0.674 0.015 88.723);
17
+ --gray-11: oklch(0.508 0.011 106.779);
18
+ --gray-12: oklch(0.191 0 89.876);
19
+ --accent-1: oklch(0.984 0.02 29.049);
20
+ --accent-2: oklch(0.968 0.036 29.049);
21
+ --accent-3: oklch(0.943 0.063 29.049);
22
+ --accent-4: oklch(0.913 0.09 29.049);
23
+ --accent-5: oklch(0.877 0.119 29.049);
24
+ --accent-6: oklch(0.832 0.149 29.049);
25
+ --accent-7: oklch(0.776 0.178 29.049);
26
+ --accent-8: oklch(0.702 0.203 29.049);
27
+ --accent-9: oklch(0.592 0.225 29.049);
28
+ --accent-10: oklch(0.552 0.218 29.049);
29
+ --accent-11: oklch(0.517 0.199 29.182);
30
+ --accent-12: oklch(0.353 0.167 29.049);
31
+
32
+ /* ---- Layer 2: semantic mapping (identical names across all themes) ---- */
33
+ --color-bg: var(--gray-1);
34
+ --color-bg-elevated: var(--gray-2);
35
+ --color-text: var(--gray-12);
36
+ --color-text-muted: var(--gray-11);
37
+ --color-text-faint: var(--gray-10);
38
+ --color-border: var(--gray-6);
39
+ --color-border-hover: var(--gray-7);
40
+ --color-accent: var(--accent-9);
41
+ --color-accent-dim: var(--accent-11);
42
+ --color-on-accent: #ffffff;
43
+ --color-cta-bg: var(--accent-9);
44
+ --color-cta-text: #ffffff;
45
+ --focus-ring: var(--gray-12);
46
+ --color-selection: color-mix(in oklab, var(--color-text) 12%, transparent);
47
+ --color-accent-surface: color-mix(in oklab, var(--color-accent) 10%, transparent);
48
+ --color-invert-bg: #141414;
49
+ --color-invert-bg-elevated: #1f1f1e;
50
+ --color-invert-text: #f4f4f1;
51
+ --color-invert-text-muted: rgba(244, 244, 241, 0.66);
52
+ --color-invert-border: rgba(244, 244, 241, 0.16);
53
+
54
+ /* ---- Layer 3: review / mark semantics (hand-tuned, de-conflicted from accent) ---- */
55
+ --review-insert-text: #1b7a35;
56
+ --review-insert-bg: rgba(27, 122, 53, 0.1);
57
+ --review-insert-border: #1b7a35;
58
+ --review-delete-text: #a23618;
59
+ --review-delete-bg: rgba(162, 54, 24, 0.1);
60
+ --review-delete-border: rgba(162, 54, 24, 0.45);
61
+ --review-highlight-bg: rgba(224, 176, 18, 0.22);
62
+ --review-highlight-border: rgba(224, 176, 18, 0.55);
63
+ --review-comment-anchor: #2f5fd0;
64
+ --review-comment-active-bg: rgba(47, 95, 208, 0.1);
65
+
66
+ color-scheme: light;
67
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "nacht",
3
+ "name": "Mint",
4
+ "appearance": "dark",
5
+ "fonts": [
6
+ { "family": "Schibsted Grotesk", "src": "/themes/grid/fonts/SchibstedGrotesk-Variable.woff2", "weight": "400 900" },
7
+ { "family": "Geist Mono", "src": "/themes/grid/fonts/GeistMono-Variable.woff2", "weight": "100 900" }
8
+ ],
9
+ "grain": { "enabled": false },
10
+ "swatch": { "bg": "#282a36", "ink": "#9aa3c4", "accent": "#50fa7b" }
11
+ }
@@ -0,0 +1,67 @@
1
+ [data-theme='nacht'] {
2
+ /* Mint (dark, spring green — Dracula-based).
3
+ v0.4: Radix-rigor 12-step OKLCH scales (anchored to the v0.3 Swiss values),
4
+ with semantic tokens mapped onto the steps. Marks stay hand-tuned. */
5
+
6
+ /* ---- Layer 1: raw scales (values differ per theme) ---- */
7
+ --gray-1: oklch(0.288 0.022 277.509);
8
+ --gray-2: oklch(0.34 0.027 276.046);
9
+ --gray-3: oklch(0.356 0.006 148.025);
10
+ --gray-4: oklch(0.371 0.006 148.025);
11
+ --gray-5: oklch(0.387 0.006 148.025);
12
+ --gray-6: oklch(0.403 0.032 277.832);
13
+ --gray-7: oklch(0.442 0.006 148.025);
14
+ --gray-8: oklch(0.481 0.006 148.025);
15
+ --gray-9: oklch(0.521 0.006 148.025);
16
+ --gray-10: oklch(0.56 0.08 270.086);
17
+ --gray-11: oklch(0.72 0.049 273.138);
18
+ --gray-12: oklch(0.977 0.008 106.545);
19
+ --accent-1: oklch(0.205 0.02 148.025);
20
+ --accent-2: oklch(0.245 0.035 148.025);
21
+ --accent-3: oklch(0.3 0.061 148.025);
22
+ --accent-4: oklch(0.36 0.088 148.025);
23
+ --accent-5: oklch(0.42 0.116 148.025);
24
+ --accent-6: oklch(0.485 0.145 148.025);
25
+ --accent-7: oklch(0.56 0.173 148.025);
26
+ --accent-8: oklch(0.65 0.198 148.025);
27
+ --accent-9: oklch(0.871 0.22 148.025);
28
+ --accent-10: oklch(0.74 0.213 148.025);
29
+ --accent-11: oklch(0.748 0.201 148.012);
30
+ --accent-12: oklch(0.93 0.162 148.025);
31
+
32
+ /* ---- Layer 2: semantic mapping (identical names across all themes) ---- */
33
+ --color-bg: var(--gray-1);
34
+ --color-bg-elevated: var(--gray-2);
35
+ --color-text: var(--gray-12);
36
+ --color-text-muted: var(--gray-11);
37
+ --color-text-faint: var(--gray-10);
38
+ --color-border: var(--gray-6);
39
+ --color-border-hover: var(--gray-7);
40
+ --color-accent: var(--accent-9);
41
+ --color-accent-dim: var(--accent-11);
42
+ --color-on-accent: #0b2016;
43
+ --color-cta-bg: var(--accent-9);
44
+ --color-cta-text: #0b2016;
45
+ --focus-ring: var(--accent-8);
46
+ --color-selection: color-mix(in oklab, var(--color-text) 16%, transparent);
47
+ --color-accent-surface: color-mix(in oklab, var(--color-accent) 16%, transparent);
48
+ --color-invert-bg: #f4f4f1;
49
+ --color-invert-bg-elevated: #ffffff;
50
+ --color-invert-text: #141414;
51
+ --color-invert-text-muted: rgba(20, 20, 20, 0.62);
52
+ --color-invert-border: rgba(20, 20, 20, 0.14);
53
+
54
+ /* ---- Layer 3: review / mark semantics (hand-tuned, de-conflicted from accent) ---- */
55
+ --review-insert-text: #4fc76e;
56
+ --review-insert-bg: rgba(79, 199, 110, 0.16);
57
+ --review-insert-border: #4fc76e;
58
+ --review-delete-text: #f0664a;
59
+ --review-delete-bg: rgba(240, 102, 74, 0.16);
60
+ --review-delete-border: rgba(240, 102, 74, 0.5);
61
+ --review-highlight-bg: rgba(232, 190, 58, 0.2);
62
+ --review-highlight-border: rgba(232, 190, 58, 0.55);
63
+ --review-comment-anchor: #bd93f9;
64
+ --review-comment-active-bg: rgba(189, 147, 249, 0.16);
65
+
66
+ color-scheme: dark;
67
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "rose",
3
+ "name": "Rose",
4
+ "appearance": "light",
5
+ "fonts": [
6
+ { "family": "Schibsted Grotesk", "src": "/themes/grid/fonts/SchibstedGrotesk-Variable.woff2", "weight": "400 900" },
7
+ { "family": "Geist Mono", "src": "/themes/grid/fonts/GeistMono-Variable.woff2", "weight": "100 900" }
8
+ ],
9
+ "grain": { "enabled": false },
10
+ "swatch": { "bg": "#fcfcfa", "ink": "#66665f", "accent": "#d6336c" }
11
+ }
@@ -0,0 +1,67 @@
1
+ [data-theme='rose'] {
2
+ /* Rose (warm light, muted magenta).
3
+ v0.4: Radix-rigor 12-step OKLCH scales (anchored to the v0.3 Swiss values),
4
+ with semantic tokens mapped onto the steps. Marks stay hand-tuned. */
5
+
6
+ /* ---- Layer 1: raw scales (values differ per theme) ---- */
7
+ --gray-1: oklch(0.991 0.003 106.447);
8
+ --gray-2: oklch(0.96 0.004 106.474);
9
+ --gray-3: oklch(0.947 0.004 5.248);
10
+ --gray-4: oklch(0.935 0.004 5.248);
11
+ --gray-5: oklch(0.922 0.004 5.248);
12
+ --gray-6: oklch(0.909 0.008 98.888);
13
+ --gray-7: oklch(0.85 0.004 5.248);
14
+ --gray-8: oklch(0.791 0.004 5.248);
15
+ --gray-9: oklch(0.732 0.004 5.248);
16
+ --gray-10: oklch(0.674 0.015 88.723);
17
+ --gray-11: oklch(0.508 0.011 106.779);
18
+ --gray-12: oklch(0.191 0 89.876);
19
+ --accent-1: oklch(0.984 0.018 5.248);
20
+ --accent-2: oklch(0.968 0.032 5.248);
21
+ --accent-3: oklch(0.943 0.056 5.248);
22
+ --accent-4: oklch(0.913 0.08 5.248);
23
+ --accent-5: oklch(0.877 0.107 5.248);
24
+ --accent-6: oklch(0.832 0.133 5.248);
25
+ --accent-7: oklch(0.776 0.159 5.248);
26
+ --accent-8: oklch(0.702 0.181 5.248);
27
+ --accent-9: oklch(0.588 0.201 5.248);
28
+ --accent-10: oklch(0.552 0.195 5.248);
29
+ --accent-11: oklch(0.514 0.183 4.481);
30
+ --accent-12: oklch(0.353 0.149 5.248);
31
+
32
+ /* ---- Layer 2: semantic mapping (identical names across all themes) ---- */
33
+ --color-bg: var(--gray-1);
34
+ --color-bg-elevated: var(--gray-2);
35
+ --color-text: var(--gray-12);
36
+ --color-text-muted: var(--gray-11);
37
+ --color-text-faint: var(--gray-10);
38
+ --color-border: var(--gray-6);
39
+ --color-border-hover: var(--gray-7);
40
+ --color-accent: var(--accent-9);
41
+ --color-accent-dim: var(--accent-11);
42
+ --color-on-accent: #ffffff;
43
+ --color-cta-bg: var(--accent-9);
44
+ --color-cta-text: #ffffff;
45
+ --focus-ring: var(--gray-12);
46
+ --color-selection: color-mix(in oklab, var(--color-text) 12%, transparent);
47
+ --color-accent-surface: color-mix(in oklab, var(--color-accent) 10%, transparent);
48
+ --color-invert-bg: #141414;
49
+ --color-invert-bg-elevated: #1f1f1e;
50
+ --color-invert-text: #f4f4f1;
51
+ --color-invert-text-muted: rgba(244, 244, 241, 0.66);
52
+ --color-invert-border: rgba(244, 244, 241, 0.16);
53
+
54
+ /* ---- Layer 3: review / mark semantics (hand-tuned, de-conflicted from accent) ---- */
55
+ --review-insert-text: #1b7a35;
56
+ --review-insert-bg: rgba(27, 122, 53, 0.1);
57
+ --review-insert-border: #1b7a35;
58
+ --review-delete-text: #a23618;
59
+ --review-delete-bg: rgba(162, 54, 24, 0.1);
60
+ --review-delete-border: rgba(162, 54, 24, 0.45);
61
+ --review-highlight-bg: rgba(224, 176, 18, 0.22);
62
+ --review-highlight-border: rgba(224, 176, 18, 0.55);
63
+ --review-comment-anchor: #2f5fd0;
64
+ --review-comment-active-bg: rgba(47, 95, 208, 0.1);
65
+
66
+ color-scheme: light;
67
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "sepia",
3
+ "name": "Sepia",
4
+ "appearance": "light",
5
+ "fonts": [
6
+ { "family": "Schibsted Grotesk", "src": "/themes/grid/fonts/SchibstedGrotesk-Variable.woff2", "weight": "400 900" },
7
+ { "family": "Geist Mono", "src": "/themes/grid/fonts/GeistMono-Variable.woff2", "weight": "100 900" }
8
+ ],
9
+ "grain": { "enabled": false },
10
+ "swatch": { "bg": "#f1ece0", "ink": "#6e655a", "accent": "#c8841c" }
11
+ }
@@ -0,0 +1,67 @@
1
+ [data-theme='sepia'] {
2
+ /* Swiss International — Sepia (warm paper, ochre).
3
+ v0.4: Radix-rigor 12-step OKLCH scales (anchored to the v0.3 Swiss values),
4
+ with semantic tokens mapped onto the steps. Marks stay hand-tuned. */
5
+
6
+ /* ---- Layer 1: raw scales (values differ per theme) ---- */
7
+ --gray-1: oklch(0.944 0.017 88.001);
8
+ --gray-2: oklch(0.968 0.014 88.683);
9
+ --gray-3: oklch(0.944 0.004 70.928);
10
+ --gray-4: oklch(0.921 0.004 70.928);
11
+ --gray-5: oklch(0.898 0.004 70.928);
12
+ --gray-6: oklch(0.874 0.022 85.948);
13
+ --gray-7: oklch(0.82 0.004 70.928);
14
+ --gray-8: oklch(0.766 0.004 70.928);
15
+ --gray-9: oklch(0.712 0.004 70.928);
16
+ --gray-10: oklch(0.658 0.023 76.438);
17
+ --gray-11: oklch(0.512 0.02 72.867);
18
+ --gray-12: oklch(0.214 0.014 61.811);
19
+ --accent-1: oklch(0.984 0.012 70.928);
20
+ --accent-2: oklch(0.968 0.022 70.928);
21
+ --accent-3: oklch(0.943 0.038 70.928);
22
+ --accent-4: oklch(0.913 0.054 70.928);
23
+ --accent-5: oklch(0.877 0.072 70.928);
24
+ --accent-6: oklch(0.832 0.09 70.928);
25
+ --accent-7: oklch(0.776 0.107 70.928);
26
+ --accent-8: oklch(0.702 0.122 70.928);
27
+ --accent-9: oklch(0.668 0.136 70.928);
28
+ --accent-10: oklch(0.552 0.132 70.928);
29
+ --accent-11: oklch(0.508 0.105 71.812);
30
+ --accent-12: oklch(0.353 0.101 70.928);
31
+
32
+ /* ---- Layer 2: semantic mapping (identical names across all themes) ---- */
33
+ --color-bg: var(--gray-1);
34
+ --color-bg-elevated: var(--gray-2);
35
+ --color-text: var(--gray-12);
36
+ --color-text-muted: var(--gray-11);
37
+ --color-text-faint: var(--gray-10);
38
+ --color-border: var(--gray-6);
39
+ --color-border-hover: var(--gray-7);
40
+ --color-accent: var(--accent-9);
41
+ --color-accent-dim: var(--accent-11);
42
+ --color-on-accent: #2a1b06;
43
+ --color-cta-bg: var(--gray-12);
44
+ --color-cta-text: var(--gray-1);
45
+ --focus-ring: var(--gray-12);
46
+ --color-selection: color-mix(in oklab, var(--color-text) 12%, transparent);
47
+ --color-accent-surface: color-mix(in oklab, var(--color-accent) 14%, transparent);
48
+ --color-invert-bg: #1e1813;
49
+ --color-invert-bg-elevated: #2a231b;
50
+ --color-invert-text: #f4efe4;
51
+ --color-invert-text-muted: rgba(244, 239, 228, 0.66);
52
+ --color-invert-border: rgba(244, 239, 228, 0.16);
53
+
54
+ /* ---- Layer 3: review / mark semantics (hand-tuned, de-conflicted from accent) ---- */
55
+ --review-insert-text: #2c7a3f;
56
+ --review-insert-bg: rgba(44, 122, 63, 0.12);
57
+ --review-insert-border: #2c7a3f;
58
+ --review-delete-text: #a8431f;
59
+ --review-delete-bg: rgba(168, 67, 31, 0.12);
60
+ --review-delete-border: rgba(168, 67, 31, 0.45);
61
+ --review-highlight-bg: rgba(168, 150, 40, 0.24);
62
+ --review-highlight-border: rgba(168, 150, 40, 0.6);
63
+ --review-comment-anchor: #345fc0;
64
+ --review-comment-active-bg: rgba(52, 95, 192, 0.12);
65
+
66
+ color-scheme: light;
67
+ }