From 7ab23448f0479e229c3d3b4aea422fbe1a8f3850 Mon Sep 17 00:00:00 2001 From: zenchantlive Date: Wed, 11 Feb 2026 21:29:20 -0800 Subject: [PATCH] Archive stash backlogs into repo docs for traceable recovery --- docs/archive/postcss.config.mjs.experimental | 5 + .../stashes/stash-0-root-leftovers.patch | 166 +++ .../stashes/stash-1-agent-b-backlog.patch | 1087 +++++++++++++++++ 3 files changed, 1258 insertions(+) create mode 100644 docs/archive/postcss.config.mjs.experimental create mode 100644 docs/archive/stashes/stash-0-root-leftovers.patch create mode 100644 docs/archive/stashes/stash-1-agent-b-backlog.patch diff --git a/docs/archive/postcss.config.mjs.experimental b/docs/archive/postcss.config.mjs.experimental new file mode 100644 index 0000000..a34a3d5 --- /dev/null +++ b/docs/archive/postcss.config.mjs.experimental @@ -0,0 +1,5 @@ +export default { + plugins: { + '@tailwindcss/postcss': {}, + }, +}; diff --git a/docs/archive/stashes/stash-0-root-leftovers.patch b/docs/archive/stashes/stash-0-root-leftovers.patch new file mode 100644 index 0000000..fd7babd --- /dev/null +++ b/docs/archive/stashes/stash-0-root-leftovers.patch @@ -0,0 +1,166 @@ +diff --git a/.gitignore b/.gitignore +index eb35607..596f42a 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -3,3 +3,6 @@ node_modules/ + *.tsbuildinfo + .worktrees/ + worktrees/ ++ ++# bv (beads viewer) local config and caches ++.bv/ +diff --git a/src/app/globals.css b/src/app/globals.css +index d17e938..a474080 100644 +--- a/src/app/globals.css ++++ b/src/app/globals.css +@@ -3,15 +3,15 @@ + @tailwind utilities; + + :root { +- --color-bg: #090c14; +- --color-surface: #101827; +- --color-surface-muted: #192336; +- --color-surface-raised: #22314a; +- --color-text-strong: #f6f8ff; +- --color-text-body: #d8e0f1; +- --color-text-muted: #9caccc; +- --color-border-soft: rgba(145, 166, 204, 0.3); +- --color-border-strong: rgba(187, 209, 246, 0.62); ++ --color-bg: #090909; ++ --color-surface: #161616; ++ --color-surface-muted: #212121; ++ --color-surface-raised: #2a2a2a; ++ --color-text-strong: #f5f5f5; ++ --color-text-body: #d0d0d0; ++ --color-text-muted: #9a9a9a; ++ --color-border-soft: rgba(255, 255, 255, 0.15); ++ --color-border-strong: rgba(255, 255, 255, 0.3); + + --status-open: #60a5fa; + --status-progress: #fbbf24; +@@ -38,10 +38,9 @@ body { + + body { + background: +- radial-gradient(circle at 10% 12%, rgba(12, 138, 215, 0.34), transparent 36%), +- radial-gradient(circle at 84% 20%, rgba(250, 122, 91, 0.18), transparent 30%), +- radial-gradient(circle at 68% 88%, rgba(57, 189, 154, 0.14), transparent 36%), +- linear-gradient(155deg, #05070d 0%, #0b1322 42%, #121e34 100%); ++ radial-gradient(circle at 14% 12%, rgba(255, 255, 255, 0.05), transparent 36%), ++ radial-gradient(circle at 84% 18%, rgba(255, 180, 80, 0.06), transparent 32%), ++ linear-gradient(160deg, #070707 0%, #101010 48%, #161616 100%); + color: var(--color-text-body); +- font-family: 'Segoe UI', 'Aptos', Inter, system-ui, sans-serif; ++ font-family: 'DM Sans', 'Segoe UI', Inter, system-ui, sans-serif; + } +diff --git a/src/app/layout.tsx b/src/app/layout.tsx +index ff1ad90..1417e77 100644 +--- a/src/app/layout.tsx ++++ b/src/app/layout.tsx +@@ -1,7 +1,18 @@ + import type { Metadata } from 'next'; ++import { DM_Sans, JetBrains_Mono } from 'next/font/google'; + import type { ReactNode } from 'react'; + import './globals.css'; + ++const dmSans = DM_Sans({ ++ subsets: ['latin'], ++ variable: '--font-ui', ++}); ++ ++const jetbrainsMono = JetBrains_Mono({ ++ subsets: ['latin'], ++ variable: '--font-mono', ++}); ++ + export const metadata: Metadata = { + title: 'BeadBoard', + description: 'Windows-native Beads dashboard', +@@ -10,7 +21,7 @@ export const metadata: Metadata = { + export default function RootLayout({ children }: { children: ReactNode }) { + return ( + +- {children} ++ {children} + + ); + } +diff --git a/src/components/kanban/kanban-controls.tsx b/src/components/kanban/kanban-controls.tsx +index 78b09f4..e1e04f9 100644 +--- a/src/components/kanban/kanban-controls.tsx ++++ b/src/components/kanban/kanban-controls.tsx +@@ -14,7 +14,7 @@ interface KanbanControlsProps { + + export function KanbanControls({ filters, stats, onFiltersChange }: KanbanControlsProps) { + const inputClass = +- 'rounded-xl border border-border-soft bg-surface-muted/78 px-3 py-2.5 text-sm text-text-strong outline-none transition placeholder:text-text-muted focus:border-cyan-300/70 focus:ring-2 focus:ring-cyan-300/20'; ++ 'rounded-xl border border-border-soft bg-surface-muted/78 px-3 py-2.5 text-sm text-text-strong outline-none transition placeholder:text-text-muted focus:border-border-strong focus:ring-2 focus:ring-white/10'; + + return ( +
+@@ -57,7 +57,7 @@ export function KanbanControls({ filters, stats, onFiltersChange }: KanbanContro + type="checkbox" + checked={filters.showClosed ?? false} + onChange={(event) => onFiltersChange({ ...filters, showClosed: event.target.checked })} +- className="h-4 w-4 accent-cyan-400" ++ className="h-4 w-4 accent-amber-400" + /> + Show closed + +diff --git a/src/components/shared/chip.tsx b/src/components/shared/chip.tsx +index c1637e6..e29d49d 100644 +--- a/src/components/shared/chip.tsx ++++ b/src/components/shared/chip.tsx +@@ -7,7 +7,7 @@ interface ChipProps { + + const CHIP_TONE_CLASS: Record, string> = { + default: 'border-border-soft bg-surface-muted/75 text-text-body', +- status: 'border-cyan-300/30 bg-cyan-500/20 text-cyan-50', ++ status: 'border-zinc-300/30 bg-zinc-500/20 text-zinc-100', + priority: 'border-amber-300/30 bg-amber-500/20 text-amber-50', + }; + +diff --git a/tailwind.config.ts b/tailwind.config.ts +index 5ad9067..953965c 100644 +--- a/tailwind.config.ts ++++ b/tailwind.config.ts +@@ -5,8 +5,8 @@ const config: Config = { + theme: { + extend: { + fontFamily: { +- ui: ['Segoe UI', 'Inter', 'system-ui', 'sans-serif'], +- mono: ['JetBrains Mono', 'Consolas', 'monospace'], ++ ui: ['var(--font-ui)', 'Segoe UI', 'Inter', 'system-ui', 'sans-serif'], ++ mono: ['var(--font-mono)', 'Consolas', 'monospace'], + }, + colors: { + bg: 'var(--color-bg)', +diff --git a/tests/guards/kanban-responsive-contract.test.mjs b/tests/guards/kanban-responsive-contract.test.mjs +index 4e02f28..3efabf4 100644 +--- a/tests/guards/kanban-responsive-contract.test.mjs ++++ b/tests/guards/kanban-responsive-contract.test.mjs +@@ -9,11 +9,12 @@ async function read(relativePath) { + return fs.readFile(path.join(ROOT, relativePath), 'utf8'); + } + +-test('kanban board uses intentional horizontal scroll affordances', async () => { ++test('kanban board uses expandable vertical swimlanes', async () => { + const board = await read('src/components/kanban/kanban-board.tsx'); + +- assert.match(board, /snap-x/); +- assert.match(board, /overflow-x-auto/); ++ assert.match(board, /aria-expanded/); ++ assert.match(board, /onActivateStatus/); ++ assert.match(board, /max-h-\[50vh\]/); + }); + + test('kanban page defines mobile detail drawer behavior', async () => { +@@ -21,6 +22,8 @@ test('kanban page defines mobile detail drawer behavior', async () => { + + assert.match(page, /fixed inset-0/); + assert.match(page, /lg:hidden/); ++ assert.match(page, /lg:grid-cols-\[minmax\(0,1fr\)_minmax\(22rem,26rem\)\]/); ++ assert.match(page, /lg:border-l/); + }); + + test('kanban controls use fluid full-width sizing on small viewports', async () => { diff --git a/docs/archive/stashes/stash-1-agent-b-backlog.patch b/docs/archive/stashes/stash-1-agent-b-backlog.patch new file mode 100644 index 0000000..fbaedf1 --- /dev/null +++ b/docs/archive/stashes/stash-1-agent-b-backlog.patch @@ -0,0 +1,1087 @@ +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 ( + +- {children} ++ {children} + + ); + } +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 ( +-
++
+ {KANBAN_STATUSES.map((status) => ( +-
+-
+- {status} +- {columns[status].length} ++
++
++ {status.replace('_', ' ')} ++ {columns[status].length} +
+-
++
+ {columns[status].map((issue) => ( + + ))} +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 = { ++ 0: 'text-priority-0', ++ 1: 'text-priority-1', ++ 2: 'text-priority-2', ++ 3: 'text-priority-3', ++ 4: 'text-priority-4', ++ }; ++ + return ( +