diff --git a/site/styles/home-kinpaku.css b/site/styles/home-kinpaku.css index 896b99970..91b5b0e9d 100644 --- a/site/styles/home-kinpaku.css +++ b/site/styles/home-kinpaku.css @@ -1372,27 +1372,31 @@ color: var(--demo-muted) !important; } -/* Amber warning-card text colors hardcoded in the clarify demo (and others) - render as brown-on-brown when the underlying #fff8e1 / #fef3c7 panel gets - swapped for the dark --demo-warning-panel. Map them to readable amber tones - that survive the dark plinth. */ -.home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison [style*="color: #92400e"], -.home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison [style*="color: #854d0e"], -.home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison [style*="color: #78350f"] { +/* In dark mode, hardcoded amber warning text becomes brown-on-brown when its + light panel is swapped for --demo-warning-panel. Map those colors to readable + amber tones on the dark plinth; light mode keeps the original brown text. */ +html.dark .home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison [style*="color: #92400e"], +html.dark .home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison [style*="color: #854d0e"], +html.dark .home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison [style*="color: #78350f"] { color: var(--ks-kinpaku-pale) !important; } -/* Primary CTA buttons that use background: var(--color-ink) — on home-kinpaku - that token maps to champagne (cream) which paints the button cream-on-dark. - The demo wants a dark primary button, so override back to a dark ink and a - light label color. */ -.home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison button[style*="background: var(--color-ink)"], -.home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison [style*="background: var(--color-ink)"] { +/* In dark mode, primary CTAs using background: var(--color-ink) would resolve + to champagne on lacquer. Keep the intended dark button and light label on + the dark plinth; light mode already resolves the inline ink/paper pairing. */ +html.dark .home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison button[style*="background: var(--color-ink)"], +html.dark .home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison [style*="background: var(--color-ink)"] { background: oklch(13% 0.008 95) !important; color: var(--ks-champagne) !important; border-color: var(--demo-border) !important; } +/* Gold remains a fill and display accent on paper. Small demo labels use the + paper-safe patina text token so they retain readable contrast. */ +html.light .home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison [style*="color: var(--color-accent)"] { + color: var(--ks-link-on-paper) !important; +} + .home-kinpaku .ptable-tooltip { background: var(--ks-lacquer-raised) !important; border-color: var(--ks-rule) !important; diff --git a/tests/docs-integrity.test.js b/tests/docs-integrity.test.js index 0025a745f..a824dda4a 100644 --- a/tests/docs-integrity.test.js +++ b/tests/docs-integrity.test.js @@ -2,6 +2,7 @@ import { describe, expect, test } from 'bun:test'; import fs from 'fs'; import path from 'path'; import { ANTIPATTERNS } from '../cli/engine/registry/antipatterns.mjs'; +import { renderCommandDemo } from '../site/scripts/demo-renderer.js'; const ROOT = process.cwd(); @@ -156,4 +157,48 @@ describe('docs integrity', () => { expect(stale).toEqual([]); }); + + test('command demo theme rules stay scoped to their page and theme', () => { + const homeCss = fs.readFileSync(path.join(ROOT, 'site/styles/home-kinpaku.css'), 'utf8'); + const lightCss = fs.readFileSync(path.join(ROOT, 'site/styles/light-mode.css'), 'utf8'); + const docsCss = fs.readFileSync(path.join(ROOT, 'site/styles/docs-kinpaku.css'), 'utf8'); + const demoScope = ':is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison'; + const affectedDemos = { + clarify: ['Save and Continue →'], + quieter: ['View Plans'], + bolder: ['Learn More'], + polish: ['JD', 'Edit Profile'], + }; + + for (const [command, labels] of Object.entries(affectedDemos)) { + const markup = renderCommandDemo(command); + const darkFillCount = markup.split('background: var(--color-ink)').length - 1; + + expect(darkFillCount).toBe(labels.length); + for (const label of labels) expect(markup).toContain(label); + } + + expect(homeCss).toContain( + `html.dark .home-kinpaku ${demoScope} [style*="color: #92400e"]` + ); + expect(homeCss).toContain( + `html.dark .home-kinpaku ${demoScope} [style*="background: var(--color-ink)"]` + ); + expect(homeCss).toContain( + `html.light .home-kinpaku ${demoScope} [style*="color: var(--color-accent)"]` + ); + expect(homeCss).not.toContain( + `\n.home-kinpaku ${demoScope} [style*="color: #92400e"]` + ); + expect(homeCss).not.toContain( + `\n.home-kinpaku ${demoScope} [style*="background: var(--color-ink)"]` + ); + + expect(docsCss).toMatch( + /\.docs-kinpaku \.docs-command-demo \.split-after\s*\{[^}]*background:\s*var\(--ks-lacquer\);/ + ); + expect(lightCss).toMatch( + /html\.light \.docs-kinpaku \.docs-command-demo \.split-after\s*\{[^}]*background:\s*var\(--ks-lacquer-raised\);/ + ); + }); });