import fs from 'node:fs' const read=p=>fs.readFileSync(p,'utf8') const json=p=>JSON.parse(read(p)) const failures=[] const check=(ok,msg)=>{if(!ok)failures.push(msg)} const tokens=json('packages/kbx-ui/src/tokens/source/kbx.tokens.json') check(Number(tokens.version.split('.')[0])>1 || (Number(tokens.version.split('.')[0])===1 && Number(tokens.version.split('.')[1])>=9),'design token source must be v1.9.0 or newer') check(tokens.themes?.light?.label==='KBX Business Light','light business theme missing') check(tokens.themes?.dark?.label==='KBX Business Dark','dark business theme missing') for(const key of ['semantic.surface.default','semantic.surface.muted','semantic.text.default','semantic.text.muted','semantic.border.default','semantic.action.primary','semantic.status.success','semantic.status.warning','semantic.status.danger','semantic.focus','semantic.state.aiSurface']){ check(Object.hasOwn(tokens.themes?.dark?.overrides??{},key),`dark semantic override missing: ${key}`) } const css=read('packages/kbx-ui/src/tokens/kbx.css') check(css.includes('[data-kbx-theme="dark"]'),'generated dark selector missing') check(css.includes('color-scheme: dark'),'dark color-scheme missing') const main=read('apps/web/src/main.ts') check(main.includes("darkModeSelector: '[data-kbx-theme=\\\"dark\\\"]'"),'PrimeVue dark selector must follow KBX root theme') const theme=read('packages/kbx-ui/src/theme/kbxTheme.ts') for(const token of ["'light' | 'dark'",'applyKbxTheme','nextKbxThemeMode'])check(theme.includes(token),`theme runtime contract missing: ${token}`) const nav=read('packages/kbx-contracts/src/navigation.ts') check(nav.includes("themeMode?: 'light' | 'dark'"),'theme preference contract missing') const store=read('apps/web/src/shell/workspaceStore.ts') check(store.includes("themeMode:'light'")&&store.includes('function toggleTheme()'),'workspace theme preference must be fail-safe and persisted') const frame=read('apps/web/src/shell/KbxAppFrame.vue') check(frame.includes('watch(themeMode,mode=>applyKbxTheme(mode),{immediate:true})'),'AppFrame must apply persisted theme at the document root') check(frame.includes('@theme-toggle="store.toggleTheme"'),'AppFrame must bind header theme control to preference store') const header=read('packages/kbx-ui/src/shell/KbxGlobalHeader.vue') check(header.includes("themeMode?: 'light' | 'dark'")&&header.includes("@click=\"emit('themeToggle')\""),'global header theme control missing') check(header.includes('grid-template-columns:repeat(4,1fr)'),'narrow header must accommodate theme without overflow') const grid=read('packages/kbx-ui/src/theme/kbxGridTheme.ts') for(const token of ['accentColor','borderColor','selectedRowBackgroundColor'])check(grid.includes(token),`AG Grid semantic theme bridge missing: ${token}`) const home=read('packages/kbx-ui/src/shell/KbxHomePage.vue') check(home.includes('v43 theme hierarchy'),'Home themed hierarchy hardening missing') check(home.includes('border-left:var(--kbx-accent-border-width)'),'Home attention must encode priority without whole-row color reliance') const side=read('packages/kbx-ui/src/shell/KbxSideNavigation.vue') check(side.includes('box-shadow:inset var(--kbx-accent-border-width) 0 0 var(--kbx-color-primary)')||side.includes('box-shadow:inset var(--kbx-accent-border-width) 0 0 var(--kbx-color-module-accent)'),'Side nav active state must remain explicit in both themes') const refHtml=read('apps/web/fe-reference/index.html') const refCss=read('apps/web/fe-reference/kbx-fe.css') const refJs=read('apps/web/fe-reference/kbx-fe.js') check(refHtml.includes('id="themeButton"'),'FE Reference must expose theme switching') check(refCss.includes('.kbx-app[data-theme="dark"]'),'FE Reference dark theme missing') check(refJs.includes("theme:'light'")&&refJs.includes("state.theme=state.theme==='dark'?'light':'dark'"),'FE Reference theme state/persistence missing') check(!/background:#fff(?![0-9a-fA-F])/i.test(refCss),'FE Reference contains hard-coded white surfaces that break dark theme') if(failures.length){console.error('Theme/navigation v43 validation failed:');for(const f of failures)console.error(`- ${f}`);process.exit(1)} console.log('Theme/navigation v43 validation passed: semantic Light/Dark, PrimeVue/AG Grid bridge, Home/Shell hierarchy, reference parity.')