Fix light-mode command demo contrast (#370)

Scope dark compatibility rules to dark mode and guard the homepage and docs theme contracts.

AI-assisted-by: OpenAI Codex
This commit is contained in:
Abdul Wahab
2026-07-14 07:53:39 -07:00
committed by GitHub
parent f2049c2b76
commit 8259c28209
2 changed files with 62 additions and 13 deletions
+17 -13
View File
@@ -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;
+45
View File
@@ -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\);/
);
});
});