beadboard/docs/archive/stashes/stash-1-agent-b-backlog.patch

1088 lines
42 KiB
Diff
Raw Normal View History

2026-03-03 16:43:42 -08:00
diff --git a/package-lock.json b/package-lock.json
index 7a082ab..e0c00b5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,13 +14,29 @@
"react-dom": "19.2.1"
},
"devDependencies": {
+ "@tailwindcss/postcss": "^4.1.18",
"@types/node": "^22.10.0",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
+ "lightningcss-win32-x64-msvc": "^1.30.2",
+ "tailwindcss": "^4.1.18",
"tsx": "^4.21.0",
"typescript": "^5.7.2"
}
},
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/@emnapi/runtime": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
@@ -939,6 +955,56 @@
"url": "https://opencollective.com/libvips"
}
},
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
"node_modules/@next/env": {
"version": "15.5.7",
"resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.7.tgz",
@@ -1082,6 +1148,546 @@
"tslib": "^2.8.0"
}
},
+ "node_modules/@tailwindcss/node": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz",
+ "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/remapping": "^2.3.4",
+ "enhanced-resolve": "^5.18.3",
+ "jiti": "^2.6.1",
+ "lightningcss": "1.30.2",
+ "magic-string": "^0.30.21",
+ "source-map-js": "^1.2.1",
+ "tailwindcss": "4.1.18"
+ }
+ },
+ "node_modules/@tailwindcss/node/node_modules/lightningcss": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
+ "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.30.2",
+ "lightningcss-darwin-arm64": "1.30.2",
+ "lightningcss-darwin-x64": "1.30.2",
+ "lightningcss-freebsd-x64": "1.30.2",
+ "lightningcss-linux-arm-gnueabihf": "1.30.2",
+ "lightningcss-linux-arm64-gnu": "1.30.2",
+ "lightningcss-linux-arm64-musl": "1.30.2",
+ "lightningcss-linux-x64-gnu": "1.30.2",
+ "lightningcss-linux-x64-musl": "1.30.2",
+ "lightningcss-win32-arm64-msvc": "1.30.2",
+ "lightningcss-win32-x64-msvc": "1.30.2"
+ }
+ },
+ "node_modules/@tailwindcss/node/node_modules/lightningcss-android-arm64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz",
+ "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@tailwindcss/node/node_modules/lightningcss-darwin-arm64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
+ "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@tailwindcss/node/node_modules/lightningcss-darwin-x64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz",
+ "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@tailwindcss/node/node_modules/lightningcss-freebsd-x64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz",
+ "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@tailwindcss/node/node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz",
+ "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@tailwindcss/node/node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz",
+ "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@tailwindcss/node/node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz",
+ "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@tailwindcss/node/node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz",
+ "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@tailwindcss/node/node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz",
+ "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@tailwindcss/node/node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz",
+ "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@tailwindcss/oxide": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz",
+ "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ },
+ "optionalDependencies": {
+ "@tailwindcss/oxide-android-arm64": "4.1.18",
+ "@tailwindcss/oxide-darwin-arm64": "4.1.18",
+ "@tailwindcss/oxide-darwin-x64": "4.1.18",
+ "@tailwindcss/oxide-freebsd-x64": "4.1.18",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.1.18",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.1.18",
+ "@tailwindcss/oxide-linux-x64-musl": "4.1.18",
+ "@tailwindcss/oxide-wasm32-wasi": "4.1.18",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.1.18"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-android-arm64": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz",
+ "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz",
+ "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz",
+ "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz",
+ "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz",
+ "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz",
+ "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz",
+ "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz",
+ "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz",
+ "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz",
+ "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==",
+ "bundleDependencies": [
+ "@napi-rs/wasm-runtime",
+ "@emnapi/core",
+ "@emnapi/runtime",
+ "@tybys/wasm-util",
+ "@emnapi/wasi-threads",
+ "tslib"
+ ],
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.7.1",
+ "@emnapi/runtime": "^1.7.1",
+ "@emnapi/wasi-threads": "^1.1.0",
+ "@napi-rs/wasm-runtime": "^1.1.0",
+ "@tybys/wasm-util": "^0.10.1",
+ "tslib": "^2.4.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz",
+ "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz",
+ "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/postcss": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.18.tgz",
+ "integrity": "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "@tailwindcss/node": "4.1.18",
+ "@tailwindcss/oxide": "4.1.18",
+ "postcss": "^8.4.41",
+ "tailwindcss": "4.1.18"
+ }
+ },
+ "node_modules/@tailwindcss/postcss/node_modules/postcss": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
"node_modules/@types/node": {
"version": "22.19.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.11.tgz",
@@ -1149,12 +1755,26 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "devOptional": true,
"license": "Apache-2.0",
- "optional": true,
"engines": {
"node": ">=8"
}
},
+ "node_modules/enhanced-resolve": {
+ "version": "5.19.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz",
+ "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.3.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
"node_modules/esbuild": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz",
@@ -1225,6 +1845,53 @@
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/jiti": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
+ "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz",
+ "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
"node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
@@ -1457,6 +2124,27 @@
}
}
},
+ "node_modules/tailwindcss": {
+ "version": "4.1.18",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
+ "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tapable": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
+ "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
diff --git a/package.json b/package.json
index d74369c..f4adadb 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
"start": "next start",
"lint": "next lint",
"typecheck": "tsc --noEmit",
- "test": "node --test tests/bootstrap.test.mjs && node --import tsx --test tests/lib/parser.test.ts && node --import tsx --test tests/lib/pathing.test.ts && node --import tsx --test tests/lib/kanban.test.ts && node --import tsx --test tests/lib/read-issues.test.ts && node --test tests/guards/no-direct-jsonl-write.test.mjs"
+ "test": "node --test tests/bootstrap.test.mjs && node --import tsx --test tests/lib/parser.test.ts && node --import tsx --test tests/lib/pathing.test.ts && node --import tsx --test tests/lib/kanban.test.ts && node --import tsx --test tests/lib/read-issues.test.ts && node --test tests/guards/no-direct-jsonl-write.test.mjs && node --test tests/guards/no-inline-style-in-kanban.test.mjs"
},
"dependencies": {
"next": "15.5.7",
@@ -17,9 +17,12 @@
"react-dom": "19.2.1"
},
"devDependencies": {
+ "@tailwindcss/postcss": "^4.1.18",
"@types/node": "^22.10.0",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
+ "lightningcss-win32-x64-msvc": "^1.30.2",
+ "tailwindcss": "^4.1.18",
"tsx": "^4.21.0",
"typescript": "^5.7.2"
}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index dd3008b..1d731f8 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,5 +1,18 @@
import type { Metadata } from 'next';
import type { ReactNode } from 'react';
+import { DM_Sans, JetBrains_Mono } from 'next/font/google';
+
+import './globals.css';
+
+const sans = DM_Sans({
+ subsets: ['latin'],
+ variable: '--font-sans',
+});
+
+const mono = JetBrains_Mono({
+ subsets: ['latin'],
+ variable: '--font-mono',
+});
export const metadata: Metadata = {
title: 'BeadBoard',
@@ -9,7 +22,7 @@ export const metadata: Metadata = {
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
- <body>{children}</body>
+ <body className={`${sans.variable} ${mono.variable} font-sans`}>{children}</body>
</html>
);
}
diff --git a/src/components/kanban/kanban-board.tsx b/src/components/kanban/kanban-board.tsx
index 34eea9d..8d61fa0 100644
--- a/src/components/kanban/kanban-board.tsx
+++ b/src/components/kanban/kanban-board.tsx
@@ -12,22 +12,23 @@ interface KanbanBoardProps {
}
export function KanbanBoard({ columns, selectedIssueId, onSelect }: KanbanBoardProps) {
+ const statusTone: Record<(typeof KANBAN_STATUSES)[number], string> = {
+ open: 'text-status-open',
+ in_progress: 'text-status-in-progress',
+ blocked: 'text-status-blocked',
+ deferred: 'text-status-deferred',
+ closed: 'text-status-closed',
+ };
+
return (
- <section
- style={{
- display: 'grid',
- gridTemplateColumns: 'repeat(5, minmax(220px, 1fr))',
- gap: '0.8rem',
- overflowX: 'auto',
- }}
- >
+ <section className="grid min-w-[1120px] grid-cols-5 gap-3 overflow-x-auto">
{KANBAN_STATUSES.map((status) => (
- <div key={status} style={{ background: '#edf2f7', borderRadius: 14, padding: '0.65rem', minHeight: 320 }}>
- <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '0.55rem' }}>
- <strong style={{ fontSize: '0.85rem', color: '#1f2937' }}>{status}</strong>
- <span style={{ fontSize: '0.8rem', color: '#475569' }}>{columns[status].length}</span>
+ <div key={status} className="min-h-80 rounded-lg border border-border bg-surface-2 p-3">
+ <div className="mb-2 flex items-center justify-between">
+ <strong className={`text-xs font-bold uppercase tracking-[0.06em] ${statusTone[status]}`}>{status.replace('_', ' ')}</strong>
+ <span className="text-xs text-muted">{columns[status].length}</span>
</div>
- <div style={{ display: 'grid', gap: '0.55rem' }}>
+ <div className="grid gap-2">
{columns[status].map((issue) => (
<KanbanCard key={issue.id} issue={issue} selected={selectedIssueId === issue.id} onSelect={onSelect} />
))}
diff --git a/src/components/kanban/kanban-card.tsx b/src/components/kanban/kanban-card.tsx
index 04df80b..51b5924 100644
--- a/src/components/kanban/kanban-card.tsx
+++ b/src/components/kanban/kanban-card.tsx
@@ -11,32 +11,32 @@ interface KanbanCardProps {
}
export function KanbanCard({ issue, selected, onSelect }: KanbanCardProps) {
+ const priorityTone: Record<number, string> = {
+ 0: 'text-priority-0',
+ 1: 'text-priority-1',
+ 2: 'text-priority-2',
+ 3: 'text-priority-3',
+ 4: 'text-priority-4',
+ };
+
return (
<button
type="button"
onClick={() => onSelect(issue)}
- style={{
- width: '100%',
- textAlign: 'left',
- border: selected ? '2px solid #0f766e' : '1px solid #d7dee8',
- borderRadius: 12,
- padding: '0.7rem',
- background: '#ffffff',
- cursor: 'pointer',
- }}
+ className={`w-full cursor-pointer rounded-md border bg-surface p-3 text-left transition hover:-translate-y-0.5 hover:shadow-sm ${selected ? 'border-status-open ring-2 ring-status-open/25' : 'border-border'}`}
>
- <div style={{ fontSize: '0.74rem', color: '#5e6b7a' }}>{issue.id}</div>
- <div style={{ fontWeight: 700, color: '#0f1720', margin: '0.15rem 0 0.5rem' }}>{issue.title}</div>
- <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.35rem', marginBottom: '0.45rem' }}>
- <Chip>P{issue.priority}</Chip>
+ <div className="font-mono text-[0.7rem] text-muted">{issue.id}</div>
+ <div className="mb-2 mt-1 text-sm font-bold text-foreground">{issue.title}</div>
+ <div className="mb-2 flex flex-wrap gap-1.5">
+ <Chip className={priorityTone[issue.priority] ?? 'text-priority-4'}>P{issue.priority}</Chip>
<Chip>{issue.issue_type}</Chip>
<Chip>deps {issue.dependencies.length}</Chip>
</div>
- <div style={{ fontSize: '0.8rem', color: '#314152' }}>
+ <div className="text-xs text-muted">
{issue.assignee ? `@${issue.assignee}` : 'unassigned'}
</div>
{issue.labels.length > 0 ? (
- <div style={{ marginTop: '0.45rem', display: 'flex', flexWrap: 'wrap', gap: '0.35rem' }}>
+ <div className="mt-2 flex flex-wrap gap-1.5">
{issue.labels.slice(0, 3).map((label) => (
<Chip key={`${issue.id}-${label}`}>#{label}</Chip>
))}
diff --git a/src/components/kanban/kanban-controls.tsx b/src/components/kanban/kanban-controls.tsx
index cedefee..4535149 100644
--- a/src/components/kanban/kanban-controls.tsx
+++ b/src/components/kanban/kanban-controls.tsx
@@ -12,21 +12,21 @@ interface KanbanControlsProps {
export function KanbanControls({ filters, stats, onFiltersChange }: KanbanControlsProps) {
return (
- <section style={{ display: 'grid', gap: '0.75rem' }}>
- <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.6rem' }}>
+ <section className="grid gap-3">
+ <div className="flex flex-wrap gap-2">
<input
type="search"
value={filters.query ?? ''}
onChange={(event) => onFiltersChange({ ...filters, query: event.target.value })}
placeholder="Search by id/title/labels"
- style={{ flex: 1, minWidth: 260, borderRadius: 10, border: '1px solid #cbd5e1', padding: '0.5rem 0.6rem' }}
+ className="min-w-[260px] flex-1 rounded-md border border-border bg-surface px-3 py-2 text-sm outline-none ring-0 transition placeholder:text-muted focus:border-ring focus:ring-2 focus:ring-ring/20"
/>
<input
type="text"
value={filters.type ?? ''}
onChange={(event) => onFiltersChange({ ...filters, type: event.target.value })}
placeholder="Type (task/bug/feature)"
- style={{ width: 190, borderRadius: 10, border: '1px solid #cbd5e1', padding: '0.5rem 0.6rem' }}
+ className="w-[190px] rounded-md border border-border bg-surface px-3 py-2 text-sm outline-none transition placeholder:text-muted focus:border-ring focus:ring-2 focus:ring-ring/20"
/>
<input
type="number"
@@ -35,18 +35,19 @@ export function KanbanControls({ filters, stats, onFiltersChange }: KanbanContro
value={filters.priority ?? ''}
onChange={(event) => onFiltersChange({ ...filters, priority: event.target.value })}
placeholder="Priority"
- style={{ width: 110, borderRadius: 10, border: '1px solid #cbd5e1', padding: '0.5rem 0.6rem' }}
+ className="w-[110px] rounded-md border border-border bg-surface px-3 py-2 text-sm outline-none transition placeholder:text-muted focus:border-ring focus:ring-2 focus:ring-ring/20"
/>
- <label style={{ display: 'inline-flex', alignItems: 'center', gap: '0.45rem', color: '#334155', fontSize: '0.9rem' }}>
+ <label className="inline-flex items-center gap-2 text-sm text-foreground">
<input
type="checkbox"
checked={filters.showClosed ?? false}
+ className="size-4 accent-status-closed"
onChange={(event) => onFiltersChange({ ...filters, showClosed: event.target.checked })}
/>
Show closed
</label>
</div>
- <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.6rem' }}>
+ <div className="flex flex-wrap gap-2">
<StatPill label="Total" value={stats.total} />
<StatPill label="Open" value={stats.open} />
<StatPill label="Active" value={stats.active} />
diff --git a/src/components/kanban/kanban-detail.tsx b/src/components/kanban/kanban-detail.tsx
index 954d47d..ecf9b9d 100644
--- a/src/components/kanban/kanban-detail.tsx
+++ b/src/components/kanban/kanban-detail.tsx
@@ -11,35 +11,35 @@ interface KanbanDetailProps {
export function KanbanDetail({ issue }: KanbanDetailProps) {
if (!issue) {
return (
- <aside style={{ border: '1px solid #d7dee8', borderRadius: 14, padding: '0.9rem', background: '#ffffff' }}>
- <strong style={{ color: '#0f1720' }}>Details</strong>
- <p style={{ color: '#475569' }}>Select a card to inspect full issue details.</p>
+ <aside className="rounded-lg border border-border bg-surface p-4">
+ <strong className="text-foreground">Details</strong>
+ <p className="mt-1 text-sm text-muted">Select a card to inspect full issue details.</p>
</aside>
);
}
return (
- <aside style={{ border: '1px solid #d7dee8', borderRadius: 14, padding: '0.9rem', background: '#ffffff' }}>
- <div style={{ display: 'flex', justifyContent: 'space-between', gap: '0.5rem', alignItems: 'start' }}>
+ <aside className="rounded-lg border border-border bg-surface p-4">
+ <div className="flex items-start justify-between gap-2">
<div>
- <div style={{ fontSize: '0.76rem', color: '#475569' }}>{issue.id}</div>
- <h2 style={{ margin: '0.1rem 0 0.3rem', fontSize: '1.2rem', color: '#0f1720' }}>{issue.title}</h2>
+ <div className="font-mono text-xs text-muted">{issue.id}</div>
+ <h2 className="mt-1 text-xl font-bold text-foreground">{issue.title}</h2>
</div>
<Chip>{issue.status}</Chip>
</div>
- {issue.description ? <p style={{ color: '#334155' }}>{issue.description}</p> : null}
- <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.4rem', marginBottom: '0.5rem' }}>
+ {issue.description ? <p className="mt-2 text-sm text-foreground">{issue.description}</p> : null}
+ <div className="mb-3 mt-3 flex flex-wrap gap-1.5">
<Chip>priority {issue.priority}</Chip>
<Chip>{issue.issue_type}</Chip>
<Chip>{issue.assignee ? `@${issue.assignee}` : 'unassigned'}</Chip>
<Chip>{issue.dependencies.length} dependencies</Chip>
</div>
- <div style={{ fontSize: '0.84rem', color: '#334155' }}>
+ <div className="grid gap-1 text-sm text-foreground">
<div><strong>Created:</strong> {issue.created_at || '-'}</div>
<div><strong>Updated:</strong> {issue.updated_at || '-'}</div>
</div>
{issue.labels.length > 0 ? (
- <div style={{ marginTop: '0.6rem', display: 'flex', flexWrap: 'wrap', gap: '0.35rem' }}>
+ <div className="mt-3 flex flex-wrap gap-1.5">
{issue.labels.map((label) => (
<Chip key={`${issue.id}-${label}`}>#{label}</Chip>
))}
diff --git a/src/components/kanban/kanban-page.tsx b/src/components/kanban/kanban-page.tsx
index a2e91f9..dae6d8f 100644
--- a/src/components/kanban/kanban-page.tsx
+++ b/src/components/kanban/kanban-page.tsx
@@ -33,21 +33,13 @@ export function KanbanPage({ issues }: KanbanPageProps) {
);
return (
- <main
- style={{
- minHeight: '100vh',
- padding: '1.2rem',
- background: 'linear-gradient(140deg, #f8fafc, #edf3f7 50%, #f8fbf9)',
- color: '#0f1720',
- fontFamily: 'Segoe UI, system-ui, sans-serif',
- }}
- >
- <header style={{ marginBottom: '0.9rem' }}>
- <h1 style={{ margin: 0, fontSize: '1.9rem' }}>BeadBoard Kanban</h1>
- <p style={{ margin: '0.35rem 0 0', color: '#475569' }}>Tracer Bullet 1 baseline from live `.beads/issues.jsonl`</p>
+ <main className="min-h-screen bg-gradient-to-br from-background via-surface-2 to-background px-4 py-5 text-foreground md:px-5">
+ <header className="mb-4">
+ <h1 className="text-3xl font-black tracking-tight">BeadBoard Kanban</h1>
+ <p className="mt-1 text-sm text-muted">Tracer Bullet 1 baseline from live `.beads/issues.jsonl`</p>
</header>
<KanbanControls filters={filters} stats={stats} onFiltersChange={setFilters} />
- <section style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) 320px', gap: '0.9rem', marginTop: '0.9rem' }}>
+ <section className="mt-4 grid gap-4 xl:grid-cols-[minmax(0,1fr)_340px]">
<KanbanBoard
columns={columns}
selectedIssueId={selectedIssue?.id ?? null}
diff --git a/src/components/shared/chip.tsx b/src/components/shared/chip.tsx
index b5150f8..7e92959 100644
--- a/src/components/shared/chip.tsx
+++ b/src/components/shared/chip.tsx
@@ -2,20 +2,13 @@ import type { ReactNode } from 'react';
interface ChipProps {
children: ReactNode;
+ className?: string;
}
-export function Chip({ children }: ChipProps) {
+export function Chip({ children, className }: ChipProps) {
return (
<span
- style={{
- border: '1px solid #d7dee8',
- borderRadius: 999,
- padding: '0.2rem 0.55rem',
- fontSize: '0.75rem',
- fontWeight: 600,
- color: '#1f2a38',
- background: '#f7fafc',
- }}
+ className={`inline-flex items-center rounded-full border border-border bg-surface-2 px-2 py-0.5 text-[0.72rem] font-semibold text-foreground ${className ?? ''}`}
>
{children}
</span>
diff --git a/src/components/shared/stat-pill.tsx b/src/components/shared/stat-pill.tsx
index c76422c..ff84023 100644
--- a/src/components/shared/stat-pill.tsx
+++ b/src/components/shared/stat-pill.tsx
@@ -5,17 +5,9 @@ interface StatPillProps {
export function StatPill({ label, value }: StatPillProps) {
return (
- <div
- style={{
- border: '1px solid #d7dee8',
- borderRadius: 12,
- padding: '0.6rem 0.8rem',
- background: '#ffffff',
- minWidth: 90,
- }}
- >
- <div style={{ fontSize: '0.7rem', textTransform: 'uppercase', letterSpacing: '0.05em', color: '#5e6b7a' }}>{label}</div>
- <div style={{ fontSize: '1.05rem', fontWeight: 700, color: '#0f1720' }}>{value}</div>
+ <div className="min-w-[88px] rounded-md border border-border bg-surface px-3 py-2">
+ <div className="text-[0.65rem] uppercase tracking-[0.08em] text-muted">{label}</div>
+ <div className="text-lg font-bold text-foreground">{value}</div>
</div>
);
}