// Scope selected workspace and modal rules from the fixed REA CSS export. No original app access. import { readFile, writeFile } from 'node:fs/promises' import { createHash } from 'node:crypto' import { resolve } from 'node:path' import postcss from 'postcss' const directory = resolve('.tmp/rea-css-recovered') const manifest = JSON.parse(await readFile(resolve(directory, 'manifest.json'), 'utf8')) const evidenceId = 'ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94' if (manifest.sourceEvidenceId !== evidenceId) throw new Error('Workspace CSS evidence changed') const sheets = [] for (const file of manifest.files) { const bytes = await readFile(resolve(directory, file.file)) if (createHash('sha256').update(bytes).digest('hex') !== file.sha256) throw new Error(`Fixed REA CSS digest mismatch: ${file.file}`) sheets.push({ file: file.file, root: postcss.parse(bytes, { from: file.file }) }) } const output = postcss.root() let ruleCount = 0 const selected = (file, selector) => file === 'contexts-BkjwYSZT.css' ? /create-workspace-modal|workspace-more|workspace-context-action|workspace-new-task|conversation-section|conversation-group-empty|conversation-show-more|conversation-agent-card|collapsible-section/.test(selector) : file === 'src-CBaV_A3S.css' ? /_13lf4_/.test(selector) : file === 'src-Bh3YZ35H.css' ? /^\.wb-modal|^\.wb-input(?:[\s.:_\[-]|$)/.test(selector) : false function project(node, file) { if (node.type === 'rule') { const selectors = node.selectors.filter(selector => selected(file, selector)) if (!selectors.length) return null ruleCount++ return node.clone({ selector: selectors.map(selector => `.workspace-source ${selector}`).join(',') }) } if (node.type === 'atrule' && node.nodes && !/keyframes$/.test(node.name)) { const children = node.nodes.map(child => project(child, file)).filter(Boolean) return children.length ? node.clone({ nodes: children }) : null } return null } // Preserve primitive-before-feature ordering and all media conditions. for (const file of ['src-Bh3YZ35H.css', 'src-CBaV_A3S.css', 'contexts-BkjwYSZT.css']) { const sheet = sheets.find(sheet => sheet.file === file) for (const node of sheet.root.nodes) { const projected = project(node, file); if (projected) output.append(projected) } } const needed = new Set() const refs = text => [...text.matchAll(/var\((--[\w-]+)/g)].map(match => match[1]) for (const ref of refs(output.toString())) needed.add(ref) let changed = true while (changed) { changed = false for (const sheet of sheets) sheet.root.walkDecls(decl => { if (!needed.has(decl.prop)) return for (const ref of refs(decl.value)) if (!needed.has(ref)) { needed.add(ref); changed = true } }) } const tokens = postcss.root() for (const sheet of sheets) sheet.root.walkRules(rule => { if (!rule.selectors.some(selector => selector === ':root' || /data-theme.*dark/.test(selector))) return const declarations = rule.nodes.filter(node => node.type === 'decl' && needed.has(node.prop)) if (!declarations.length) return const dark = !rule.selectors.includes(':root') && rule.selectors.some(selector => /dark/.test(selector)) tokens.append(postcss.rule({ selector: dark ? '[data-theme="dark"] .workspace-source' : '.workspace-source', nodes: declarations.map(decl => decl.clone()) })) }) const adapters = ` /* Host DOM/accessibility adapters; source rule bodies above remain intact. */ .workspace-source{--cb-font-size-offset:0;--cb-sidebar-bg:var(--yc-bg-secondary);--cb-text-primary:var(--yc-text-primary);font-family:var(--vscode-font-family, "PingFang SC", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif)} .workspace-source .workspace-ui-button{border:0;padding:0;background:transparent;font:inherit;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;flex-shrink:0} .workspace-source .conversation-section-label button{border:0;padding:0;background:transparent} .workspace-source .collapsible-section-title{gap:8px;padding:0} .workspace-source .collapsible-section-label{font-size:14px;line-height:22px;font-weight:400} .workspace-source .workspace-group-actions{display:flex;align-items:center;gap:4px} .workspace-source .workspace-group-header:focus-within ._customButton_13lf4_31{opacity:1;visibility:visible} .workspace-source .workspace-group-selected .collapsible-section-label{font-weight:500} .workspace-source .conversation-section-content{min-width:0} .workspace-source .workspace-source-task{padding:5px 12px;min-height:32px;gap:8px;display:flex;align-items:center} .workspace-source .workspace-source-task .sidebar__item-title{font-size:14px;line-height:22px} .workspace-source .workspace-source-task .sidebar__item-time{font-size:11px;line-height:20px} .workspace-source .workspace-source-task[data-selected=true] .sidebar__item-title{font-weight:600} .workspace-source .conversation-section-label:focus-within .conversation-section-add-btn,.workspace-source .conversation-section-label:focus-within .conversation-section-compact-btn{visibility:visible;opacity:1} .workspace-source .workspace-attach-row{padding:8px 12px;background:transparent;border:0;color:var(--wb-color-text-tertiary);font:inherit;font-size:12px;text-align:left;cursor:pointer} .workspace-source .workspace-attach-row:hover{color:var(--wb-color-text-primary)} .workspace-source .workspace-menu-remove{color:var(--wb-color-text-primary)} .workspace-source .workspace-dialog-error{color:var(--yc-status-error);font-size:13px;line-height:20px;margin-top:12px} .workspace-source .workspace-dialog-long-name{overflow-wrap:anywhere;white-space:normal} .workspace-source .wb-modal__overlay{position:fixed;inset:0;z-index:1100;box-sizing:border-box} .workspace-source .wb-modal{box-sizing:border-box;width:480px;max-width:calc(100vw - 32px)} .workspace-source .wb-modal__close{width:24px;height:24px;border:0;background:transparent;color:var(--wb-button-ghost-fg,#000000e6);display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0} .workspace-source .wb-modal__close svg{width:16px;height:16px} .workspace-source .wb-input-wrapper{box-sizing:border-box;display:flex;align-items:center;width:100%} .workspace-source .create-workspace-modal__input>input{width:100%;min-width:0;background:transparent;border:0;outline:0;padding:0;font:inherit;font-size:14px;line-height:22px;color:var(--wb-color-text-primary)} .workspace-source .workspace-dialog-clear{border:0;background:transparent;padding:0;display:flex;width:16px;height:16px;cursor:pointer;color:var(--wb-color-text-tertiary)} .workspace-source .workspace-dialog-clear svg{width:14px;height:14px} .workspace-source .create-workspace-modal__confirm,.workspace-source .create-workspace-modal__cancel{cursor:pointer} .workspace-source .create-workspace-modal__cancel:disabled{opacity:.5;cursor:default} @media(prefers-reduced-motion:reduce){.workspace-source .wb-modal,.workspace-source .wb-modal__overlay{transition:none}} ` const text = `/* Generated from fixed REA Evidence ${evidenceId} by scripts/rea/recover-workspace-styles.mjs. * Runtime JSX: ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb, WorkBuddy 5.8.2. * Scope: local workspace sections, source CollapsibleSection primitives, create modal, context menu. * ${ruleCount} selected rules; source nesting/media conditions retained. */\n${tokens.toString()}\n${output.toString()}\n${adapters}` postcss.parse(text) await writeFile(resolve('src/renderer/src/components/workspace-source.css'), text) console.log(JSON.stringify({ evidenceId, ruleCount, tokens: needed.size, bytes: Buffer.byteLength(text) }))