import assert from 'node:assert/strict' import fs from 'node:fs' import crypto from 'node:crypto' import postcss from 'postcss' const original = fs.readFileSync('.tmp/rea-css-recovered/src-CyXHA0IC.css', 'utf8') assert.equal(crypto.createHash('sha256').update(original).digest('hex'), 'a5e26b537bb50323aefbf25abddad52e288dd3868598be8d255d70886fe77cfe') const output = fs.readFileSync('src/renderer/src/workbuddy/conversation/tool-result-source.css', 'utf8') const ancestors = node => { const chain = [] for (let parent = node.parent; parent && parent.type !== 'root'; parent = parent.parent) { if (parent.type === 'atrule') chain.unshift(`@${parent.name} ${parent.params}`) } return chain } const collect = css => { const records = [] postcss.parse(css).walkRules(rule => { if (!rule.selector.includes('.cr-tool-exp__content-shell') && !rule.selector.includes('.cr-tool-btn')) return records.push({ selector: rule.selector, conditions: ancestors(rule), declarations: rule.nodes.map(node => node.toString()) }) }) return records } const actual = collect(output) assert.deepEqual(actual, collect(original), 'tool motion declarations must retain their original media/support conditions and order') const reduced = actual.filter(rule => rule.declarations.includes('transition:none')) assert.equal(reduced.length, 3) assert.ok(reduced.every(rule => rule.conditions.includes('@media (prefers-reduced-motion:reduce)')), 'reduce-only motion suppression must never become a global rule') assert.ok(actual.some(rule => !rule.conditions.length && rule.declarations.some(value => value.includes('height .28s')))) assert.ok(actual.some(rule => rule.selector === '.cr-tool-btn' && rule.declarations.includes('height:20px'))) assert.ok(actual.some(rule => rule.selector === '.cr-tool-btn--primary' && rule.declarations.some(value => value.includes('--cr-status-success')))) assert.ok(actual.some(rule => rule.selector === '.cr-tool-btn--danger' && rule.declarations.some(value => value.includes('--cr-status-error')))) console.log('Tool CSS recovery retains source approval buttons, motion declarations and media conditions.')