Site polish: de-warm the palette, refine chrome, clean up /designing (#176)

* fix(home): command-wheel contrast, slop copy, line-length

Address P1/P2/P3 findings from /impeccable critique of the homepage:

- Command wheel (The Language): off-center command names floored at
  ~1.43:1 contrast were illegible (WCAG 1.4.3 fail) and hid most of the
  23-command vocabulary. Raise the fisheye opacity floor 0.25 -> 0.62,
  MIN_SCALE 0.35 -> 0.52, and lift the base color from --ks-text-muted to
  --ks-text. Off-center now measures >=4.59:1; full list stays scannable
  while gold + size + weight still carry focus.
- Slop section copy: rewrite all 7 discipline cards off the uniform
  "No X. No Y. No Z." triad into varied cadence with positives, and lead
  the section with what Impeccable does instead of the "Skills can't..."
  negation pivot. Drops the en-dash joiners too.
- Line length: cap .downloads-rebuild-note (was unbounded, ~102ch) and
  tighten the homepage .section-lead 68ch -> 62ch (rendered ~86 actual
  chars/line).

The diagonal plinth ramp on the slop grid is intentionally kept per
design preference.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(home): de-warm and brighten the text ramp

Warmth now lives only in the gold accents and surfaces, not the type.
Body, headings, and the secondary tiers read crisp on lacquer instead of
mushing into the warm floor:

- --ks-champagne 84% .035 82 -> 91% .006 90 (headings/strong, now neutral;
  token name kept for compatibility)
- --ks-text 81% .03 82 -> 88% .008 90 (body)
- --ks-text-muted / -faint / -mute-deep lifted and de-warmed to match

DESIGN.md frontmatter + prose synced to the new values.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(home): outlined testimonials + cleaner hero boundary

Testimonials:
- Flatten the double container: drop the t-plinth shelf wrapper (markup +
  CSS); the marquee sits directly in the section and carries its inset.
- Outlined cards: no fill, 1px solid neutral border (oklch .64 0 0 / .22),
  no dead drop-shadow. Removes the mushy gray-on-gray blend and the stacked
  dotted-divider + gold-hairline chrome.
- Section has no background of its own (rides the body lacquer gradient) and
  no top padding, so cards sit right under the hero divider.

Hero:
- Drop the bottom fade and the top nav scrim; the kintsugi art runs at full
  strength. A 1px neutral border-bottom (matching the card border) marks the
  testimonials boundary instead of a wash.
- "How it works" is the kit ghost link (white), not an outlined button.

Foundation/slop cards: lift the surface 9% -> 15% so they read as raised
specimen cards instead of vanishing into the ground.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(live): quieter, more refined picker chrome

Gold is reserved for the brand mark and the active control instead of
ringing every container. Applied to the homepage demo, /live-mode, and the
real injected picker (skill/scripts/live-browser.js, rebuilt into the
harness dirs):

- Container: neutral 1px hairline + tight neutral shadow (was a 1.5px gold
  border + gold halo ring); radius 10px -> 8px.
- Active toggle: crisp graphite pill with gold text (was a murky kinpaku-dim
  wash).
- Internal control borders (action pill / input / count): neutral hairline
  (was a warm gold rule); configure-row controls share one 30px baseline.
- Pick outline: crisp 1.5px line, no soft gold glow ring; tighter radius.
- Demo browser chrome: small uniform neutral dots, neutral URL pill, slimmer
  bar; frame edge neutral hairline + tighter shadow that registers on dark.

DESIGN.md "Live Mode Picker" spec + "Picker Is Brand Rule" updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(design): neutral default hairline (--ks-rule)

The default border/divider token was a warm gold hairline, used ~200x as
the site-wide default border — so every small label, pill, counter, card,
and divider carried warmth. Redefine it neutral so borders read clean;
gold stays where it signals.

- --ks-rule oklch(58% 0.065 82 / 0.32) -> oklch(78% 0 0 / 0.16)
- --ks-rule-strong (active/focus/brand borders) unchanged, still gold
- GitHub star pill: explicit near-white border (oklch 92% 0 0 / 0.18)
- DESIGN.md hairline mirror + prose synced

Verified across home, /design-system, and /docs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(home): testimonials separator + visible star-pill border

- Move the dotted accent to the bottom of the testimonials (neutral dots)
  as a deliberate separator into the slop section; drop the oversized
  bottom padding to 1em so cards sit near the separator.
- Star-counter pill: solid oklch(80% 0 0) border. The previous near-white
  at 0.32 alpha rendered as faded mid-gray on the near-black pill; a solid
  light border reads as the intended white hairline.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(design): neutralize body text (--ks-text)

Drop the last bit of warm chroma from the body text token; it still read
slightly warm at 0.008 chroma.

--ks-text oklch(88% 0.008 90) -> oklch(88% 0 0)  (pure neutral)

DESIGN.md mirror + prose synced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(design): neutral text everywhere

Zero the residual warm chroma across the rest of the text ramp so no text
tier carries warmth (warmth lives only in gold accents + surfaces).

- --ks-champagne 91% .006 90 -> 91% 0 0
- --ks-text-muted 72% .01 90  -> 72% 0 0
- --ks-text-faint 62% .008 90 -> 62% 0 0
- --ks-text-mute-deep 52% .008 90 -> 52% 0 0

(--ks-text was already neutralized.) DESIGN.md mirror + prose synced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(home): crisp, neutral Desloppification section

- Foundation card background: oklch(15% .004 95) -> oklch(15% 0 0) (neutral
  graphite) so cards read crisp, not warm.
- Plinth hatch: kinpaku gold -> neutral (oklch 80% 0 0 / .07) on a neutral
  base; the gold hatch was washing the section champagne.
- Remove the plinth bottom mask-fade so the pedestals end on a clean edge.

Gold stays only on the card icons as the accent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(home): drop the homepage warm-token overrides

The homepage redefined --ks-rule, --ks-rule-strong, and --ks-muted to warm
values locally (an old "busier surfaces" tweak), so homepage borders and
secondary text stayed champagne even after the global de-warm. That's why
the Desloppification cards still read warm.

- Remove the --ks-rule / --ks-rule-strong overrides; inherit the global
  tokens (neutral default border, gold strong/active border).
- Alias --ks-muted to the global --ks-text-muted (no divergent value);
  legacy code still reads the --ks-muted name.

Result: all homepage borders + secondary text are neutral; gold stays on
accents (icons, mark, CTAs, active/focus).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(design): canonical code tokens (inline + block)

Code styling was all over the place: homepage inline code was gold-on-gold,
the slop CLI was a one-off gold-on-raised-lacquer, downloads used a separate
--card-cmd-* set, docs used yet another. Add one shared token set and point
the canonical surfaces at it.

New :root tokens:
- --ks-code-fg / --ks-code-bg / --ks-code-radius      (inline: neutral chip)
- --ks-code-block-fg / -bg / -border / -radius        (block/CLI: lacquer terminal)
- --ks-code-cmd                                        (code that's a command link)

Migrated: homepage inline code (was gold -> neutral chip), slop-teaser-cli
(the "weird color" -> neutral terminal), downloads-cmd, and the docs inline +
fenced-block rules (now the token source of truth; block text also neutralized).

Remaining pages (designing, changelog/faq, detector, case studies) swept next.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(design): sweep remaining pages onto code tokens

Point the rest of the site's code rules at the shared code tokens so inline
code and blocks are consistent everywhere:

- Inline code (designing, changelog, faq): gold -> neutral chip
  (--ks-code-fg / --ks-code-bg).
- Detector rule pills + table cells: code text -> --ks-code-fg.
- Neon-mirai case-study code block -> --ks-code-block-* tokens.

Command tags (the gold /command pills: spread-flow-cmd, docs-flow-cmd,
designing-phase-cmd, why-ci-cmd, etc.) are intentionally left as their own
interactive category, not generic code.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(home): polish "The Language" section

- Command tags (/polish, /adapt): gold command text on a neutral code chip
  (--ks-code-cmd / --ks-code-bg), dropping the muddy gold-tint border.
- Commands panel kept as the solid oklch(0.17 0 0) panel (no border).
- Demo preview cleaned up to a single framed split: strip the grid ::before,
  the gold-grid/radial-glow container background, and the inner drop-shadow;
  before-half inherits the panel, after-half is near-black, with one thin
  neutral border on the demo itself (caption sits outside it).
- Periodic table: crisp flat neutral graphite tiles. Removed the JS-inlined
  category bg (var(--cat-*-bg)) + 1.5px colored border + hover drop-shadow,
  the gold-leaf ::before texture, the ::after accent line, the inset box-shadow,
  and the gold hover glow. Now a 1px neutral border, white symbols, readable
  neutral names, and a clean neutral-border hover with no shadow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(design): roomier inline-code padding

Inline code chips were tight top/bottom (the homepage one was only 0.05em).
Add a --ks-code-pad token (0.3em 0.5em) and point every inline-code rule at
it so the chips have consistent breathing room.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(home): drop non-steering commands from the command palette

impeccable, init, extract, document, and live are setup/management commands,
not steering verbs. Filter them out of the palette (fisheye + mobile carousel)
via a shared PALETTE_EXCLUDED set. They stay in the periodic table, which is
rendered separately by framework-viz.js.

Palette: 23 -> 18 commands.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(designing): flatten the pre-ship nested box

The pre-ship cards were a box-in-box: a legacy .designing-polish-grid panel
(cream bg + L/R/B border + padding, from docs-visuals.css) wrapping cards that
already have their own border + fill. Override the grid to a plain transparent
layout so the three cards are the only surface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(designing): remove step counter + flatten design-debt boxes

- Drop the cryptic "03 · 04" pre-ship step counter (.designing-polish-band-meta)
  and tighten the band to a single bottom hairline.
- Design-debt: flatten the box-in-box (bento plinth > tile > stage). The
  .designing-maintain-stage no longer adds its own border + fill; the demo
  sits directly in the bento tile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(designing): neutralize code/terminal/panel surfaces

The terminal block, surface-cmd chips, command pills, live-frame, and other
dark panels used a slightly-warm dark fill (oklch 1X% 0.006 95). Drop the warm
chroma so they read neutral like the rest of the de-warmed site; the page
ground + deep surfaces stay lacquer-warm.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(designing): neutralize inline code + live-mock picker chrome

- Inline code: the phase-sub and avoid-title code were still gold; point them
  at --ks-code-fg so all inline code reads neutral (gold stays only on command
  *links*).
- docs-viz-live mock: bring the duplicated picker chrome in line with the
  refactored neutral treatment — neutral 1px container borders (no gold halo),
  neutral active "Pick" pill (was the kinpaku-dim wash), crisp pick outline
  (no glow), tighter radii.
- CTAs (SEND ME ONE, Accept): pale-cream kinpaku-pale -> solid kinpaku gold.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(designing): flatten lanes + avoid sections

- Brand/Product lane mock cards: drop the inner border+fill box; the mock sits
  directly in the bento tile, separated by a top hairline (no plinth>tile>mock
  nesting).
- "What to avoid" list: flatten the boxed list cards into a clean divided list
  (hairline separators, no per-item border/fill).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(designing): clean up the Brand/Product lanes

- Drop the bento plinth (0.17 fill + 8px gutter that drew the weird gutter
  "borders") and the tile fill; the two lanes sit on the page split by a single
  center hairline.
- Brand mock title used the pinstripe display face at 1.6rem (reads broken at
  that size, the "champagne text"); switch it to the clean body face so it
  matches the product mock title.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(site): update GitHub star count to 31k

31,188 stars as of now; header pill + aria-label were stale at 30k.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Add Neo Kinpaku light mode across the site.

Wire theme persistence and a header toggle, then layer light-mode overrides for docs viz contrast, command demos, live-mode pathway cards, and the designing/home surfaces.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(designing): replace em dashes flagged by prose validator

Brand/Product lane copy used em dashes ("the deliverable —", "the task —");
swap for colons per STYLE.md so the Cloudflare build's validateProse passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(designing): address Cursor bugbot nits

- Fold the duplicate .designing-avoid { gap: 0 } override into the original
  rule (the gap: 18px was dead code).
- Drop the leftover el.style.boxShadow = 'none' in the periodic-tile deactivate
  handler — activate no longer sets a box-shadow, so this only left a dead
  inline none that could suppress a future CSS shadow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Paul Bakaus
2026-05-29 03:50:23 -07:00
committed by GitHub
co-authored by Claude Opus 4.8 Cursor
parent 63074dd362
commit c8e973b324
40 changed files with 2687 additions and 680 deletions
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
+21 -12
View File
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
+21 -12
View File
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
+21 -12
View File
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
+18 -18
View File
@@ -18,18 +18,18 @@ colors:
graphite-2: "oklch(19% 0.008 95)" # one step up from graphite
# Text
champagne: "oklch(84% 0.035 82)" # headlines, <strong>
text-warm: "oklch(81% 0.03 82)" # body
text-muted: "oklch(63% 0.024 82)" # captions, meta
text-faint: "oklch(52% 0.018 82)" # subdued
text-mute-deep: "oklch(48% 0.018 82)" # disabled
champagne: "oklch(91% 0 0)" # headlines, <strong> — neutral white (name kept for compat)
text-warm: "oklch(88% 0 0)" # body — neutral near-white
text-muted: "oklch(72% 0 0)" # captions, meta
text-faint: "oklch(62% 0 0)" # subdued
text-mute-deep: "oklch(52% 0 0)" # disabled
# Gold ramp
kinpaku-pale: "oklch(86% 0.07 84)" # hover lift, pale fills
kinpaku-rich: "oklch(77% 0.13 82)" # active CTA, severity-medium
kinpaku-deep: "oklch(61% 0.085 78)" # borders against the brand
gold-hairline: "oklch(58% 0.065 82 / 0.32)" # default rule
gold-hairline-strong: "oklch(74% 0.09 82 / 0.6)" # active rule
gold-hairline: "oklch(78% 0 0 / 0.16)" # default rule — neutral (name kept for compat)
gold-hairline-strong: "oklch(74% 0.09 82 / 0.6)" # active rule — gold
# Patina ramp
patina-pale: "oklch(82% 0.07 188)" # hover lift on patina
@@ -272,16 +272,16 @@ Do not hand-type oklch values or font sizes in page CSS. If a value isn't in the
- **Kinpaku Rich** (`oklch(77% 0.13 82)`): Active CTA fill and severity-medium markers.
- **Kinpaku Deep** (`oklch(61% 0.085 78)`): Secondary gold for borders, subdued icons, and large technical diagrams.
- **Kinpaku Pale** (`oklch(86% 0.07 84)`): Hover lift and pale fills.
- **Gold Hairline** (`oklch(58% 0.065 82 / 0.32)`): Default border and divider. The homepage's busier surfaces lift this to alpha 0.48 locally.
- **Strong Gold Hairline** (`oklch(74% 0.09 82 / 0.6)`): Active borders, focus outlines, and structural anchors.
- **Default Hairline** (`oklch(78% 0 0 / 0.16)`): Default border and divider. Neutral, so borders and labels don't carry warmth (token name `gold-hairline` / `--ks-rule` is legacy).
- **Strong Gold Hairline** (`oklch(74% 0.09 82 / 0.6)`): Active borders, focus outlines, and structural anchors. Stays gold — this is where the hairline is meant to read as brand.
### Text
- **Champagne** (`oklch(84% 0.035 82)`): Headlines, `<strong>`, important labels.
- **Warm Text** (`oklch(81% 0.03 82)`): Body copy on dark surfaces.
- **Muted Text** (`oklch(63% 0.024 82)`): Metadata, captions, secondary labels. The homepage lifts this to 65% on busier tile backgrounds.
- **Faint Text** (`oklch(52% 0.018 82)`): Subdued labels.
- **Mute Deep** (`oklch(48% 0.018 82)`): Disabled copy.
- **Champagne** (`oklch(91% 0 0)`): Headlines, `<strong>`, important labels. The brightest text tier, fully neutral (token name is legacy). Text carries no warmth at any tier; the gold accents and surfaces do.
- **Body Text** (`oklch(88% 0 0)`): Body copy on dark surfaces. Neutral and bright so reading copy reads crisp, not mushy.
- **Muted Text** (`oklch(72% 0 0)`): Metadata, captions, secondary labels.
- **Faint Text** (`oklch(62% 0 0)`): Subdued labels.
- **Mute Deep** (`oklch(52% 0 0)`): Disabled copy.
### Secondary and State
@@ -387,16 +387,16 @@ The footer can carry the strongest oxidation accent. Use the gold seam plus pati
The global bottom bar and the contextual bar (configure / cycling / accept) share one chrome treatment. Source of truth: `skill/scripts/live-browser.js` (`barPaletteForTheme`, `initGlobalBar`, `initBar`). Homepage and `/live-mode` demos mirror it via `.live-demo-gbar` and `.live-demo-ctx` in `site/styles/kinpaku-kit.css`.
- **Surface:** Lacquer Deep (`oklch(4% 0.004 95)`), always. Picker chrome does not adapt to the host page's light/dark theme.
- **Border:** 1.5px solid Kinpaku Gold (`oklch(84% 0.19 80.46)`).
- **Shadow:** `0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)` (kinpaku halo + drop shadow).
- **Border:** 1px solid neutral hairline (`oklch(92% 0 0 / 0.13)`), radius 8px. The bar reads as a quiet precise tool; gold is reserved for the brand mark and the active control, not the container outline.
- **Shadow:** `0 16px 36px -12px oklch(0% 0 0 / 0.6)` (tight neutral drop, no gold halo ring).
- **Brand mark:** Impeccable carved-tile icon (same SVG paths as `site/components/Header.astro` / `favicon.svg`), kinpaku fill on transparent ground. Not a "/" slash or rounded-square placeholder.
- **Default controls:** Champagne labels at rest (`oklch(84% 0.035 82)`), muted icons (`oklch(63% 0.024 82)`).
- **Active toggle:** Kinpaku-dim pill background (`oklch(78% 0.12 82 / 0.18)`) with kinpaku text.
- **Active toggle:** Crisp graphite pill (`oklch(27% 0 0)`) with kinpaku text/icon. The gold carries the "selected" signal; the pill itself is neutral, not a kinpaku-dim wash.
- **Exit hover:** Vermilion (`oklch(58% 0.15 35)`), not a neutral gray lift.
- **Context bar internals:** Graphite-2 pills, gold hairline dividers, kinpaku Go/Accept CTAs with lacquer-deep text.
- **DESIGN.md toggle icon:** Four-quadrant swatch; bottom-right uses warm charcoal (`oklch(34% 0.014 82)`) so the tile reads against lacquer-deep, not void-black.
**The Picker Is Brand Rule.** Live mode UI is Impeccable product chrome, not host-page chrome. It always ships the full kinpaku border, lacquer-deep fill, and carved-tile mark.
**The Picker Is Brand Rule.** Live mode UI is Impeccable product chrome, not host-page chrome. It always ships the lacquer-deep fill, the carved-tile mark, and gold on the mark + active control. Brand reads through the mark and the gold accent rather than a gold border ringing the bar; the container itself stays a quiet neutral-edged tool.
## 7. Do and Do Not
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();
+18 -2
View File
@@ -34,9 +34,25 @@ const { activeNav } = Astro.props;
<a href="/slop" data-nav="slop" aria-current={activeNav === 'slop' ? 'page' : undefined}>Slop</a>
<a href="/live-mode" data-nav="live" aria-current={activeNav === 'live' ? 'page' : undefined}>Live</a>
</nav>
<a href="https://github.com/pbakaus/impeccable" class="site-header-github" target="_blank" rel="noopener" aria-label="Impeccable on GitHub, 30k stars">
<button
type="button"
class="theme-toggle"
data-theme-toggle
aria-label="Switch to light mode"
title="Light mode"
data-next-theme="light"
>
<svg class="theme-toggle-icon--light" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true">
<circle cx="12" cy="12" r="4.5"/>
<path d="M12 2v2M12 20v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M2 12h2M20 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
</svg>
<svg class="theme-toggle-icon--dark" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true">
<path d="M21 14.5A8.5 8.5 0 0 1 9.5 3a7 7 0 1 0 11.5 11.5z"/>
</svg>
</button>
<a href="https://github.com/pbakaus/impeccable" class="site-header-github" target="_blank" rel="noopener" aria-label="Impeccable on GitHub, 31k stars">
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"/></svg>
<span class="site-header-github-label">30k</span>
<span class="site-header-github-label">31k</span>
<svg class="site-header-github-star" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2l2.76 6.36L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l7.24-.91L12 2z"/></svg>
</a>
</div>
-2
View File
@@ -19,7 +19,6 @@ const rowB = all.slice(half);
---
<section class="testimonials-section" id="testimonials" aria-label="What people say about Impeccable">
<div class="t-plinth t-plinth--shelf">
<div class="t-marquee" aria-hidden="false">
<div class="t-marquee-row">
@@ -71,5 +70,4 @@ const rowB = all.slice(half);
</div>
</div>
</div>
</section>
+20
View File
@@ -6,6 +6,7 @@ import Footer from '../components/Footer.astro';
// to re-import from page-level stylesheets.
import '../styles/kinpaku-tokens.css';
import '../styles/kinpaku-kit.css';
import '../styles/light-mode.css';
import '../styles/footer.css';
interface Props {
@@ -63,6 +64,21 @@ const resolvedOgDescription = ogDescription || description;
<title>{title}</title>
<meta name="description" content={description}>
<meta name="theme-color" content="#010101">
<script is:inline>
(function () {
try {
var t = localStorage.getItem('impeccable-theme');
var root = document.documentElement;
if (t === 'light') {
root.classList.add('light');
var meta = document.querySelector('meta[name="theme-color"]');
if (meta) meta.setAttribute('content', '#f7f4ef');
} else {
root.classList.add('dark');
}
} catch (e) {}
})();
</script>
{noIndex && <meta name="robots" content="noindex">}
{canonical && <link rel="canonical" href={canonical}>}
@@ -97,5 +113,9 @@ const resolvedOgDescription = ogDescription || description;
</main>
{!hideFooter && <Footer />}
<slot name="scripts" />
<script>
import { initThemeToggle } from '../scripts/utils/theme.js';
initThemeToggle();
</script>
</body>
</html>
+16
View File
@@ -41,6 +41,22 @@ import '../../styles/design-system.css';
<a href="#components">Components</a>
<a href="#proof">Proof</a>
</nav>
<button
type="button"
class="theme-toggle"
data-theme-toggle
aria-label="Switch to light mode"
title="Light mode"
data-next-theme="light"
>
<svg class="theme-toggle-icon--light" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true">
<circle cx="12" cy="12" r="4.5"/>
<path d="M12 2v2M12 20v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M2 12h2M20 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
</svg>
<svg class="theme-toggle-icon--dark" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" aria-hidden="true">
<path d="M21 14.5A8.5 8.5 0 0 1 9.5 3a7 7 0 1 0 11.5 11.5z"/>
</svg>
</button>
<a class="ks-button ks-button-primary" href="#actions">
Start audit
<span class="ks-button-arrow" aria-hidden="true">
+16 -6
View File
@@ -391,17 +391,27 @@ import '../../styles/designing-kinpaku.css';
<div class="designing-phase-body">
<div class="ks-bento designing-lanes">
<article class="ks-bento-tile ks-bento-tile--span-6">
<p class="designing-lane-rule">Design IS the product. Marketing, landing, editorial, long-form, portfolio.</p>
<p class="designing-lane-rule"><strong>Brand.</strong> Design is the deliverable: landing pages, campaigns, editorial, portfolios. Distinctive type, committed palette, image-led heroes. The impression is the product.</p>
<div class="designing-lane-mock designing-lane-mock--brand" aria-hidden="true">
<span class="designing-lane-mock-label">No. 04 &middot; Dispatch</span>
<span class="designing-lane-mock-title">Letters, occasionally.</span>
<span class="designing-lane-mock-label">Issue 04 · Dispatch</span>
<span class="designing-lane-mock-title"><span class="designing-lane-mock-accent">Shape</span> the story.</span>
</div>
</article>
<article class="ks-bento-tile ks-bento-tile--span-6">
<p class="designing-lane-rule">Design serves the task. App UI, admin, dashboards, tools.</p>
<p class="designing-lane-rule"><strong>Product.</strong> Design serves the task: app UI, admin, dashboards, tools. Fluent density, semantic states, repeatable components. Users are here to finish something.</p>
<div class="designing-lane-mock designing-lane-mock--product" aria-hidden="true">
<span class="designing-lane-mock-label">Newsletter</span>
<span class="designing-lane-mock-title">Subscribe to updates</span>
<div class="designing-lane-product-row">
<span class="designing-lane-product-k">Users</span>
<span class="designing-lane-product-v">12,482</span>
</div>
<div class="designing-lane-product-row">
<span class="designing-lane-product-k">Active now</span>
<span class="designing-lane-product-v">1,207</span>
</div>
<div class="designing-lane-product-row">
<span class="designing-lane-product-k">Conversion</span>
<span class="designing-lane-product-v">4.8%</span>
</div>
</div>
</article>
</div>
+10 -23
View File
@@ -71,7 +71,7 @@ import '../styles/testimonials.css';
</svg>
</span>
</a>
<a href="/designing" class="ks-button ks-button-secondary">How it works</a>
<a href="/designing" class="ks-button ks-button-ghost">How it works</a>
</div>
<div class="hero-rebuild-logos" aria-label="AI coding harnesses Impeccable works with">
@@ -250,7 +250,7 @@ import '../styles/testimonials.css';
<div class="slop-teaser-head">
<h2 id="slop-teaser-title" class="slop-teaser-title">Desloppification</h2>
<p class="slop-teaser-body">
Skills can't make a model fundamentally better at design. What they can do is remove inherent bias: the AI slop tells, the bad defaults, across every design discipline. That's what Impeccable does.
Impeccable strips the AI slop tells and bad defaults out of every design discipline, from type to motion to copy. A skill can't make the model a better designer; it can clear the reflexes that make its output look generated.
</p>
<div class="slop-teaser-actions">
<a class="slop-teaser-cta-primary" href="/slop">
@@ -541,11 +541,13 @@ import '../styles/testimonials.css';
<span class="why-live-pick-note">more elegant<span class="why-live-pick-caret"></span></span>
</div>
</div>
<div class="why-live-gbar">
<span class="why-live-gbar-brand">/</span>
<span class="why-live-gbar-cmd">bolder</span>
<span class="why-live-gbar-count">&times;3</span>
<span class="why-live-gbar-go">Go &rarr;</span>
<div class="why-live-ctx live-demo-ctx" data-phase="configuring">
<div class="live-demo-ctx-row live-demo-ctx-row--configure">
<span class="live-demo-ctx-pill">bolder<span class="live-demo-ctx-pill-caret" aria-hidden="true">&#x25BE;</span></span>
<span class="live-demo-ctx-input"><span class="live-demo-ctx-caret"></span></span>
<span class="live-demo-ctx-count">&times;3</span>
<span class="live-demo-ctx-go">Go <span aria-hidden="true">&rarr;</span></span>
</div>
</div>
</div>
</div>
@@ -659,22 +661,7 @@ import '../styles/testimonials.css';
</li>
</ul>
<ol class="downloads-rebuild-examples">
<li>
<code><span class="downloads-rebuild-slash">/</span>impeccable redo this hero</code>
<span>Let the skill pick the approach. No command names to memorize.</span>
</li>
<li>
<code><span class="downloads-rebuild-slash">/</span>impeccable audit checkout</code>
<span>Reach for a command by name. Type <code>/impeccable</code> alone to see all 23.</span>
</li>
<li>
<code><span class="downloads-rebuild-slash">/</span>impeccable pin audit</code>
<span>Pin your favorites. <code>/audit</code> becomes a standalone shortcut.</span>
</li>
</ol>
<p class="downloads-rebuild-more">Go deeper: <a href="/designing">Designing with Impeccable</a> &middot; <a href="/docs">the command docs</a></p>
<p class="downloads-rebuild-more">Get started: <a href="/designing">Designing with Impeccable</a> &middot; <a href="/docs">the command docs</a></p>
</div>
</section>
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

+1 -6
View File
@@ -240,15 +240,13 @@ export class PeriodicTable {
el.style.cssText = `
width: 56px;
height: 64px;
background: ${colors.bg};
border: 1.5px solid ${colors.border};
border-radius: 5px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
transition: transform 0.15s ease, box-shadow 0.15s ease;
transition: transform 0.15s ease, border-color 0.15s ease;
position: relative;
font-family: inherit;
padding: 0;
@@ -328,19 +326,16 @@ export class PeriodicTable {
// Hover/focus: show tooltip
const activate = () => {
el.style.transform = 'translateY(-2px)';
el.style.boxShadow = `0 4px 12px ${colors.border}40`;
this.showTooltip(el, cmd);
if (this.activeElement && this.activeElement !== el) {
this.activeElement.style.transform = 'translateY(0)';
this.activeElement.style.boxShadow = 'none';
}
this.activeElement = el;
};
const deactivate = () => {
el.style.transform = 'translateY(0)';
el.style.boxShadow = 'none';
this.hideTooltip();
};
+14 -3
View File
@@ -9,6 +9,11 @@ let sourceCache = {}; // Cache fetched source content
const MOBILE_BREAKPOINT = 900;
// Setup / management commands that aren't "steering" verbs. They're kept off
// the command palette (fisheye + mobile carousel) but still appear in the
// periodic table (rendered separately by framework-viz.js).
const PALETTE_EXCLUDED = new Set(['impeccable', 'init', 'extract', 'document', 'live']);
function isMobile() {
return window.innerWidth <= MOBILE_BREAKPOINT;
}
@@ -75,7 +80,7 @@ function renderDesktopLayout(container, commands) {
// too (when they were rendered as 'impeccable craft' etc.) but are now
// first-class sub-commands that should appear in the gallery.
const deprecated = new Set(['teach-impeccable', 'frontend-design', 'arrange', 'normalize', 'onboard', 'impeccable craft', 'impeccable teach', 'impeccable extract']);
const filteredCommands = commands.filter(c => !deprecated.has(c.id));
const filteredCommands = commands.filter(c => !deprecated.has(c.id) && !PALETTE_EXCLUDED.has(c.id));
const categoryOrder = ['create', 'evaluate', 'refine', 'simplify', 'harden', 'system'];
const categoryLabelsShort = {
@@ -308,7 +313,7 @@ function setupFisheyeList(commands, headerIndices = []) {
// to a fractional "center index" which drives everything.
const BASE_H = 36; // height of the center (scale=1) item
const MIN_SCALE = 0.35;
const MIN_SCALE = 0.52; // off-center items stay legibly sized, not microscopic
const RADIUS = 5;
const count = items.length;
const listH = list.clientHeight;
@@ -367,7 +372,10 @@ function setupFisheyeList(commands, headerIndices = []) {
items.forEach((item, i) => {
const h = heights[i];
const scale = getScale(Math.abs(i - center));
const opacity = 0.25 + (scale - MIN_SCALE) / (1 - MIN_SCALE) * 0.75;
// Floor at 0.62 so off-center command names stay readable (WCAG): the
// full vocabulary is the point of this view. Focus still reads clearly
// via scale + the gold/weight active state, not by crushing legibility.
const opacity = 0.62 + (scale - MIN_SCALE) / (1 - MIN_SCALE) * 0.38;
item.style.top = `${y}px`;
item.style.transform = `scale(${scale})`;
@@ -478,6 +486,9 @@ function truncateDescription(text, maxLen = 120) {
// ============================================
function renderMobileLayout(container, commands) {
// Keep setup/management commands off the palette (they stay in the periodic
// table); match the desktop fisheye filter.
commands = commands.filter(c => !PALETTE_EXCLUDED.has(c.id));
// Build carousel pills
// Carousel pills show bare command names for sub-commands, and /impeccable
// for the root entry.
+7 -7
View File
@@ -34,13 +34,13 @@ export const skillFocusAreas = {
// detail line communicates what bad-default we catch — not what we teach.
export const slopFocusAreas = {
'impeccable': [
{ area: 'Typography', detail: 'No Inter monoculture. No flat hierarchy. No all-caps body.' },
{ area: 'Color & Contrast', detail: 'No purple gradients. No sub-WCAG text. No washed pastels.' },
{ area: 'Spatial Design', detail: 'No cards in cards. No identical grids. No template layouts.' },
{ area: 'Responsive', detail: 'No stiff breakpoints. No mobile-as-afterthought.' },
{ area: 'Interaction', detail: 'No modal abuse. No generic CTAs. No gradient text.' },
{ area: 'Motion', detail: 'No bouncy easing. No decorative fades. No spring overshoot.' },
{ area: 'UX Writing', detail: 'No "Welcome to our platform." No em dashes. No "let\'s dive in".' }
{ area: 'Typography', detail: 'A type scale with real contrast, set in a face chosen on purpose, not Inter by reflex.' },
{ area: 'Color & Contrast', detail: 'Palettes that clear WCAG and commit to a hue. The purple-gradient default never ships.' },
{ area: 'Spatial Design', detail: 'Structure from spacing and rhythm, not a grid of identical cards nested in more cards.' },
{ area: 'Responsive', detail: 'Built for the small screen first, with breakpoints that follow the content.' },
{ area: 'Interaction', detail: 'Honest states and clear affordances, without defaulting to a modal or gradient text.' },
{ area: 'Motion', detail: 'Motion that eases like physics and settles. Nothing bounces or springs past its mark.' },
{ area: 'UX Writing', detail: 'Specific copy that names what the thing does, not "Welcome to our platform."' }
]
};
+22 -34
View File
@@ -1,56 +1,44 @@
// Theme toggle - supports light, dark, and system preference
// Theme toggle light / dark with localStorage persistence.
const STORAGE_KEY = 'impeccable-theme';
function getStoredTheme() {
export function getStoredTheme() {
return localStorage.getItem(STORAGE_KEY);
}
function setStoredTheme(theme) {
export function setStoredTheme(theme) {
localStorage.setItem(STORAGE_KEY, theme);
}
function applyTheme(theme) {
export function applyTheme(theme) {
const html = document.documentElement;
const resolved = theme === 'light' ? 'light' : 'dark';
// Remove both classes first
html.classList.remove('light', 'dark');
html.classList.add(resolved);
if (theme === 'light') {
html.classList.add('light');
} else if (theme === 'dark') {
html.classList.add('dark');
const meta = document.querySelector('meta[name="theme-color"]');
if (meta) {
meta.setAttribute('content', resolved === 'light' ? '#f7f4ef' : '#010101');
}
// 'system' = no class, falls back to media query
// Update active state on buttons
document.querySelectorAll('.theme-toggle-btn').forEach(btn => {
btn.classList.toggle('active', btn.dataset.theme === theme);
document.querySelectorAll('[data-theme-toggle]').forEach((btn) => {
const next = resolved === 'light' ? 'dark' : 'light';
btn.setAttribute('aria-label', resolved === 'light' ? 'Switch to dark mode' : 'Switch to light mode');
btn.setAttribute('title', resolved === 'light' ? 'Dark mode' : 'Light mode');
btn.dataset.nextTheme = next;
});
}
export function initThemeToggle() {
const toggle = document.querySelector('.theme-toggle');
if (!toggle) return;
const stored = getStoredTheme();
applyTheme(stored === 'light' ? 'light' : 'dark');
// Get stored theme or default to system
const storedTheme = getStoredTheme() || 'system';
applyTheme(storedTheme);
// Handle button clicks
toggle.addEventListener('click', (e) => {
const btn = e.target.closest('.theme-toggle-btn');
if (!btn) return;
const theme = btn.dataset.theme;
setStoredTheme(theme);
applyTheme(theme);
});
// Listen for system preference changes (only matters when in 'system' mode)
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
if (getStoredTheme() === 'system' || !getStoredTheme()) {
applyTheme('system');
}
document.querySelectorAll('[data-theme-toggle]').forEach((btn) => {
btn.addEventListener('click', () => {
const next = btn.dataset.nextTheme || (document.documentElement.classList.contains('light') ? 'dark' : 'light');
setStoredTheme(next);
applyTheme(next);
});
});
}
+10 -8
View File
@@ -98,10 +98,11 @@
.cf-items strong { color: var(--ks-champagne); font-weight: 600; }
.cf-items code {
font-family: var(--ks-mono);
font-size: 0.92em;
color: var(--ks-kinpaku);
background: transparent;
padding: 0;
font-size: 0.84em;
color: var(--ks-code-fg);
background: var(--ks-code-bg);
padding: var(--ks-code-pad);
border-radius: var(--ks-code-radius);
}
.cf-items a {
color: var(--ks-patina);
@@ -329,10 +330,11 @@
.cf-faq-answer strong { color: var(--ks-champagne); font-weight: 600; }
.cf-faq-answer code {
font-family: var(--ks-mono);
font-size: 0.92em;
color: var(--ks-kinpaku);
background: transparent;
padding: 0;
font-size: 0.84em;
color: var(--ks-code-fg);
background: var(--ks-code-bg);
padding: var(--ks-code-pad);
border-radius: var(--ks-code-radius);
}
.cf-faq-answer a {
color: var(--ks-patina);
+12 -1
View File
@@ -46,11 +46,22 @@
max-width: 100%;
}
.kinpaku-system-page a {
.kinpaku-system-page a:not(.ks-brand) {
color: inherit;
text-decoration: none;
}
/* Brand lockup — kinpaku gold on dark surfaces; html.light swaps to ink
(see light-mode.css) to match impeccable-logo-on-light.svg. */
.kinpaku-system-page a.ks-brand {
color: var(--ks-kinpaku);
}
.kinpaku-system-page a.ks-brand .ks-mark,
.kinpaku-system-page a.ks-brand .ks-wordmark {
color: inherit;
}
.kinpaku-system-page button,
.kinpaku-system-page input,
.kinpaku-system-page select {
+125 -56
View File
@@ -47,10 +47,12 @@
.designing-kinpaku code {
font-family: var(--ks-mono);
color: var(--ks-kinpaku);
background: transparent;
font-size: 0.84em;
color: var(--ks-code-fg);
background: var(--ks-code-bg);
border: 0;
padding: 0;
padding: var(--ks-code-pad);
border-radius: var(--ks-code-radius);
}
/* ============================================================================
@@ -272,8 +274,10 @@
.designing-kinpaku .designing-loop-name {
color: var(--ks-champagne);
font-family: var(--ks-font-display);
font-weight: 300;
/* Pinstripe is single-weight and reads broken at ~1.52rem; wordmark
carries real stroke weight at compass-label scale (cf. iterate-name). */
font-family: var(--ks-font-wordmark);
font-weight: 600;
font-size: clamp(1.5rem, 2.2vw, 2rem);
line-height: 1.05;
letter-spacing: 0.01em;
@@ -444,7 +448,7 @@
============================================================================ */
.designing-kinpaku .designing-phase-sub code {
color: var(--ks-kinpaku);
color: var(--ks-code-fg);
}
.designing-kinpaku .designing-phase-commands {
@@ -459,7 +463,7 @@
display: inline-flex;
align-items: center;
padding: 8px 16px;
background: oklch(11% 0.006 95);
background: oklch(11% 0 0);
border: 1px solid var(--ks-rule);
border-radius: 2px;
color: var(--ks-kinpaku);
@@ -530,7 +534,7 @@
.designing-kinpaku .docs-viz-file-header {
padding: 14px 18px;
border-bottom: 1px solid var(--ks-rule);
background: oklch(13% 0.006 95);
background: oklch(13% 0 0);
display: flex;
align-items: center;
justify-content: space-between;
@@ -740,7 +744,7 @@
frame opposite it. */
.designing-kinpaku .designing-iterate-terminal {
padding: 20px 22px;
background: oklch(13% 0.006 95);
background: oklch(13% 0 0);
border: 1px solid var(--ks-rule);
border-radius: 4px;
font-family: var(--ks-mono);
@@ -763,7 +767,7 @@
/* Live frame mock — restyle docs-viz-live-* on dark surface */
.designing-kinpaku .docs-viz-live-frame {
background: oklch(13% 0.006 95);
background: oklch(13% 0 0);
border: 1px solid var(--ks-rule);
border-radius: 4px;
overflow: hidden;
@@ -774,7 +778,7 @@
gap: 8px;
padding: 10px 14px;
border-bottom: 1px solid var(--ks-rule);
background: oklch(11% 0.006 95);
background: oklch(11% 0 0);
}
.designing-kinpaku .docs-viz-live-dot {
width: 9px;
@@ -804,7 +808,7 @@
}
.designing-kinpaku .docs-viz-live-target {
width: 100%;
background: oklch(11% 0.006 95);
background: oklch(11% 0 0);
border: 1px solid var(--ks-rule);
border-radius: 4px;
padding: 20px;
@@ -832,7 +836,7 @@
.designing-kinpaku .docs-viz-live-btn {
align-self: start;
padding: 8px 14px;
background: var(--ks-kinpaku-pale);
background: var(--ks-kinpaku);
color: var(--ks-lacquer-deep);
border: 0;
border-radius: 2px;
@@ -846,8 +850,7 @@
position: absolute;
inset: 14px 14px 108px;
border: 1.5px solid var(--ks-kinpaku);
border-radius: 4px;
box-shadow: 0 0 0 4px oklch(78% 0.12 82 / 0.1);
border-radius: 3px;
pointer-events: none;
}
/* top: auto is required — the base/legacy rule sets top: 16px, and leaving it
@@ -863,11 +866,9 @@
gap: 6px;
padding: 6px;
background: var(--ks-lacquer-deep);
border: 1.5px solid var(--ks-kinpaku);
border-radius: 6px;
box-shadow:
0 0 0 1px oklch(78% 0.12 82 / 0.18),
0 6px 18px oklch(0% 0 0 / 0.4);
border: 1px solid oklch(92% 0 0 / 0.13);
border-radius: 8px;
box-shadow: 0 6px 18px -4px oklch(0% 0 0 / 0.5);
}
.designing-kinpaku .docs-viz-live-ctx-nav,
.designing-kinpaku .docs-viz-live-ctx-discard,
@@ -885,7 +886,7 @@
padding: 4px 6px;
}
.designing-kinpaku .docs-viz-live-ctx-accept {
background: var(--ks-kinpaku-pale);
background: var(--ks-kinpaku);
color: var(--ks-lacquer-deep);
border-radius: 3px;
font-weight: 500;
@@ -916,11 +917,9 @@
padding: 5px 7px;
max-width: calc(100% - 24px);
background: var(--ks-lacquer-deep);
border: 1.5px solid var(--ks-kinpaku);
border-radius: 9px;
box-shadow:
0 0 0 1px oklch(78% 0.12 82 / 0.18),
0 10px 28px oklch(0% 0 0 / 0.28);
border: 1px solid oklch(92% 0 0 / 0.13);
border-radius: 8px;
box-shadow: 0 10px 28px -6px oklch(0% 0 0 / 0.5);
}
.designing-kinpaku .docs-viz-live-gbar-mark {
display: inline-flex;
@@ -944,7 +943,7 @@
flex-shrink: 0;
}
.designing-kinpaku .docs-viz-live-gbar-btn.is-active {
background: oklch(78% 0.12 82 / 0.18);
background: oklch(27% 0 0);
color: var(--ks-kinpaku);
}
.designing-kinpaku .docs-viz-live-gbar-btn-mono {
@@ -1029,13 +1028,12 @@
the 3-col grid below, not as a card competing with them. */
.designing-kinpaku .designing-polish-band {
display: grid;
grid-template-columns: auto 1fr auto;
grid-template-columns: auto 1fr;
align-items: center;
gap: 20px;
padding: 18px 0;
background: transparent;
border: 0;
border-top: 1px solid var(--ks-rule);
border-bottom: 1px solid var(--ks-rule);
border-radius: 0;
margin-bottom: 36px;
@@ -1061,16 +1059,18 @@
text-underline-offset: 4px;
}
.designing-kinpaku .designing-polish-band-meta {
color: var(--ks-muted);
font-family: var(--ks-mono);
font-size: 0.7rem;
letter-spacing: 0.18em;
display: none; /* cryptic "03 · 04" step counter — removed */
}
.designing-kinpaku .designing-polish-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 24px;
/* Flatten the legacy outer box (docs-visuals adds a cream bg + L/R/B border +
padding); the cards are the only surface, no box-in-box. */
background: none;
border: 0;
padding: 0;
}
@media (max-width: 900px) {
.designing-kinpaku .designing-polish-grid { grid-template-columns: 1fr; }
@@ -1131,7 +1131,7 @@
gap: 10px;
margin: 2px 0;
padding: 11px 14px;
background: oklch(13% 0.006 95);
background: oklch(13% 0 0);
border: 1px solid var(--ks-rule);
border-radius: 4px;
font-family: var(--ks-mono);
@@ -1150,10 +1150,11 @@
}
.designing-kinpaku .designing-maintain-stage {
background: var(--ks-lacquer-raised);
border: 1px solid var(--ks-rule);
border-radius: 4px;
padding: 28px;
/* No inner box — the demo sits directly in the bento tile (removing the
box-in-box: plinth > tile > stage). */
background: transparent;
border: 0;
padding: 8px 0;
min-height: 180px;
display: grid;
place-items: center;
@@ -1211,7 +1212,7 @@
display: inline-flex;
align-items: center;
padding: 5px 11px;
background: oklch(13% 0.006 95);
background: oklch(13% 0 0);
border: 1px solid var(--ks-rule);
border-radius: 3px;
color: var(--ks-muted);
@@ -1226,7 +1227,7 @@
.designing-kinpaku .designing-extract-after {
justify-self: end;
padding: 8px 18px;
background: var(--ks-kinpaku-pale);
background: var(--ks-kinpaku);
color: var(--ks-lacquer-deep);
border-radius: 2px;
font-family: var(--ks-font);
@@ -1269,6 +1270,26 @@
margin-bottom: 24px;
}
/* Flatten the bento plinth: drop the 0.17 plinth fill + 8px gutter (which drew
the weird gutter "borders") and the 0.07 tile fill. The two lanes sit on the
page, split by a single center hairline. */
.designing-kinpaku .ks-bento.designing-lanes {
background: transparent;
border: 0;
border-radius: 0;
gap: 0;
}
.designing-kinpaku .designing-lanes .ks-bento-tile {
background: transparent;
padding: 0 clamp(20px, 3.5vw, 44px);
}
.designing-kinpaku .designing-lanes .ks-bento-tile:first-child {
padding-left: 0;
}
.designing-kinpaku .designing-lanes .ks-bento-tile + .ks-bento-tile {
border-left: 1px solid var(--ks-rule);
}
.designing-kinpaku .designing-lane-kind {
color: var(--ks-kinpaku);
font-family: var(--ks-mono);
@@ -1283,41 +1304,85 @@
.designing-kinpaku .designing-lane-rule {
color: var(--ks-text);
font-size: 1rem;
line-height: 1.6;
line-height: 1.65;
margin: 0;
text-wrap: pretty;
}
.designing-kinpaku .designing-lane-rule strong {
color: var(--ks-champagne);
font-weight: 600;
}
/* The brand mock title used the pinstripe display face at ~1.6rem, which reads
broken/washed at that size (Two-Face rule); use the clean body face. */
.designing-kinpaku .designing-lane-mock-title {
font-family: var(--ks-font);
font-weight: 500;
}
.designing-kinpaku .designing-lane-mock {
margin-top: 6px;
padding: 24px;
background: oklch(11% 0.006 95);
margin-top: 18px;
padding: 20px 18px;
background: var(--ks-lacquer-raised);
border: 1px solid var(--ks-rule);
border-radius: 4px;
min-height: 110px;
min-height: 120px;
display: flex;
flex-direction: column;
gap: 10px;
justify-content: center;
}
.designing-kinpaku .designing-lane-mock--brand {
align-items: flex-start;
}
.designing-kinpaku .designing-lane-mock--product {
align-items: flex-start;
align-items: stretch;
padding: 0;
gap: 0;
}
.designing-kinpaku .designing-lane-mock-label {
color: var(--ks-patina);
font-family: var(--ks-mono);
font-size: 0.66rem;
font-size: 0.62rem;
letter-spacing: 0.2em;
text-transform: uppercase;
}
.designing-kinpaku .designing-lane-mock--brand .designing-lane-mock-title {
color: var(--ks-champagne);
font-family: var(--ks-font-display);
font-weight: 300;
font-size: 1.6rem;
font-family: var(--ks-font);
font-weight: 500;
font-size: 1.35rem;
line-height: 1.15;
}
.designing-kinpaku .designing-lane-mock-accent {
color: var(--ks-kinpaku);
}
.designing-kinpaku .designing-lane-product-row {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 16px;
padding: 12px 16px;
border-bottom: 1px solid var(--ks-rule);
}
.designing-kinpaku .designing-lane-product-row:last-child {
border-bottom: 0;
}
.designing-kinpaku .designing-lane-product-k {
font-family: var(--ks-mono);
font-size: 0.62rem;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--ks-text-muted);
}
.designing-kinpaku .designing-lane-product-v {
font-family: var(--ks-font);
font-size: 0.92rem;
font-weight: 500;
color: var(--ks-champagne);
}
/* Legacy single-line product mock title — kept for any downstream refs. */
.designing-kinpaku .designing-lane-mock--product .designing-lane-mock-title {
color: var(--ks-champagne);
font-family: var(--ks-font);
@@ -1344,16 +1409,20 @@
margin: 0;
padding: 0;
display: grid;
gap: 18px;
gap: 0; /* divided list: items separated by hairlines, not gaps */
}
.designing-kinpaku .designing-avoid li {
display: grid;
grid-template-columns: 28px 1fr;
gap: 14px;
padding: 22px 24px;
background: var(--ks-lacquer-raised);
border: 1px solid var(--ks-rule);
border-radius: 2px;
padding: 22px 0;
background: transparent;
border: 0;
border-bottom: 1px solid var(--ks-rule);
border-radius: 0;
}
.designing-kinpaku .designing-avoid li:last-child {
border-bottom: 0;
}
.designing-kinpaku .designing-avoid-x {
color: var(--ks-vermilion);
@@ -1370,7 +1439,7 @@
font-size: 1rem;
margin-bottom: 6px;
}
.designing-kinpaku .designing-avoid-title code { color: var(--ks-kinpaku); }
.designing-kinpaku .designing-avoid-title code { color: var(--ks-code-fg); }
.designing-kinpaku .designing-avoid-desc {
color: var(--ks-text);
font-size: 0.94rem;
+2 -2
View File
@@ -396,7 +396,7 @@
padding: 0;
overflow: hidden;
background: transparent;
color: var(--ks-champagne);
color: var(--ks-code-fg);
font-family: var(--ks-mono);
text-overflow: ellipsis;
white-space: nowrap;
@@ -471,7 +471,7 @@
.detector-table-panel td code {
padding: 0;
background: transparent;
color: var(--ks-champagne);
color: var(--ks-code-fg);
font-family: var(--ks-mono);
font-size: 0.8125rem;
}
+14 -10
View File
@@ -1044,17 +1044,17 @@
.docs-kinpaku .prose code {
font-family: var(--ks-mono);
font-size: 0.84em;
color: var(--ks-champagne);
background: var(--ks-graphite-2);
color: var(--ks-code-fg);
background: var(--ks-code-bg);
border: 0;
padding: 4px 7px;
border-radius: 3px;
padding: var(--ks-code-pad);
border-radius: var(--ks-code-radius);
}
/* Inline code that is itself a link — get the kinpaku cue back, since
the link semantic is the meaningful one. */
.docs-kinpaku .prose a code {
color: var(--ks-kinpaku);
color: var(--ks-code-cmd);
}
/* Fenced code blocks — deep lacquer terminal. Shiki injects inline
@@ -1067,10 +1067,10 @@
.docs-kinpaku .prose pre.astro-code {
margin: 0;
padding: 22px 24px;
background: var(--ks-lacquer-deep) !important;
color: oklch(86% 0.025 82) !important;
border: 1px solid var(--ks-rule);
border-radius: 2px;
background: var(--ks-code-block-bg) !important;
color: var(--ks-code-block-fg) !important;
border: 1px solid var(--ks-code-block-border);
border-radius: var(--ks-code-block-radius);
overflow-x: auto;
font-family: var(--ks-mono);
font-size: 0.84rem;
@@ -1227,7 +1227,7 @@
background: var(--ks-lacquer-raised);
}
.docs-kinpaku .docs-command-demo .split-comparison {
.docs-kinpaku .docs-command-demo :is(.split-comparison, .demo-split-comparison) {
max-width: none;
margin: 0;
padding: 0;
@@ -1253,6 +1253,9 @@
}
.docs-kinpaku .docs-command-demo .split-after {
/* Doc.astro initSplitCompare uses skewAngle: 0 — vertical seam, not the
angled default from sub-pages.css / main.css. */
clip-path: polygon(50% 0%, 100% 0%, 100% 100%, 50% 100%);
background:
linear-gradient(90deg, oklch(8% 0.006 95 / 0.92), oklch(10% 0.006 95 / 0.96)),
radial-gradient(circle at 82% 26%, oklch(78% 0.12 82 / 0.14), transparent 12rem);
@@ -1261,6 +1264,7 @@
.docs-kinpaku .docs-command-demo .split-divider {
background: var(--ks-kinpaku);
box-shadow: 0 0 20px oklch(78% 0.12 82 / 0.4);
transform: translateX(-50%) !important;
}
.docs-kinpaku .docs-command-demo .demo-caption {
+4 -4
View File
@@ -3347,10 +3347,10 @@
.neon-case-command .code-block {
margin: 0;
padding: var(--spacing-md);
background: var(--ks-lacquer);
color: var(--ks-champagne);
border: 1px solid var(--ks-rule);
border-radius: 2px;
background: var(--ks-code-block-bg);
color: var(--ks-code-block-fg);
border: 1px solid var(--ks-code-block-border);
border-radius: var(--ks-code-block-radius);
overflow-x: auto;
font-family: var(--ks-mono);
font-size: 0.8125rem;
+247 -185
View File
@@ -6,18 +6,12 @@
@import "./kinpaku-tokens.css";
.home-kinpaku {
/* Intentional overrides: the homepage uses brighter rule alphas because
bento tile borders need to read against busy backgrounds. The default
--ks-rule from kinpaku-tokens.css is the quieter doctrinal value used
on /design-system and elsewhere. */
--ks-rule: oklch(58% 0.065 82 / 0.48);
--ks-rule-strong: oklch(74% 0.09 82 / 0.68);
/* --ks-rule / --ks-rule-strong inherit the global tokens (neutral default,
gold strong); the homepage no longer diverges on border color. */
/* Slightly lighter muted text on the homepage's busier surfaces. The
default --ks-text-muted (63% L) is used everywhere else; here we lift
to 65% so captions stay readable against bento tile fills. Kept under
the old --ks-muted name for code-churn reasons. */
--ks-muted: oklch(65% 0.024 82);
/* Legacy alias — homepage code reads --ks-muted; map it to the global muted
text token (no divergent value). */
--ks-muted: var(--ks-text-muted);
/* Legacy alias — homepage code still reads --ks-faint and --ks-oxide. The
forward names live in kinpaku-tokens.css as --ks-text-faint and
@@ -98,12 +92,13 @@
(3) keep the chip treatment subtle so it doesn't drag attention off the
prose. */
.home-kinpaku code {
color: oklch(82% 0.11 82);
background: oklch(78% 0.12 82 / 0.08);
border: 1px solid oklch(78% 0.12 82 / 0.14);
border-radius: 3px;
color: var(--ks-code-fg);
background: var(--ks-code-bg);
border: 0;
border-radius: var(--ks-code-radius);
font-family: var(--ks-mono);
font-size: 0.88em;
padding: 0.05em 0.4em;
padding: var(--ks-code-pad);
}
.home-kinpaku ::selection {
@@ -214,7 +209,7 @@
.home-kinpaku .section-lead,
.home-kinpaku .section-subtitle {
max-width: 68ch;
max-width: 62ch; /* 68ch rendered ~86 actual chars/line; tighten into the band */
color: var(--ks-text);
font-size: 1.02rem;
line-height: 1.8;
@@ -233,7 +228,6 @@
.home-kinpaku .downloads-rebuild-note,
.home-kinpaku .why-panel-title,
.home-kinpaku .live-demo-support-v,
.home-kinpaku .downloads-rebuild-examples span,
.home-kinpaku .downloads-rebuild-extras strong,
.home-kinpaku .downloads-rebuild-extras span {
text-wrap: balance;
@@ -907,7 +901,10 @@
padding: 24px;
border: 1px solid var(--ks-rule);
border-radius: 4px;
background: oklch(9% 0.006 95 / 0.92);
/* Was 9% on a 7% ground (~1 level in sRGB): the card body vanished into the
page and only the hairline hinted at an edge. Lift to a clear raised
neutral tone so the specimen card reads as a crisp object. */
background: oklch(15% 0 0);
}
.home-kinpaku .foundation-column:hover .foundation-card {
@@ -940,15 +937,11 @@
.home-kinpaku .foundation-plinth {
border-color: var(--ks-rule);
/* Neutral hatch (was kinpaku gold, which washed the section champagne) on a
neutral base, for a crisp pedestal that matches the de-warmed section. */
background:
repeating-linear-gradient(45deg, oklch(78% 0.12 82 / 0.12), oklch(78% 0.12 82 / 0.12) 1px, transparent 1px, transparent 9px),
oklch(10% 0.006 95 / 0.42);
/* Soften the bottom so the plinth fades into the section bg like a real
shadow instead of terminating in a hard horizontal line. Mask fades the
bottom 45% of the element, taking the diagonal stripes + side borders
down with it. */
-webkit-mask-image: linear-gradient(to bottom, black 0%, black 55%, transparent 100%);
mask-image: linear-gradient(to bottom, black 0%, black 55%, transparent 100%);
repeating-linear-gradient(45deg, oklch(80% 0 0 / 0.07), oklch(80% 0 0 / 0.07) 1px, transparent 1px, transparent 9px),
oklch(10% 0 0 / 0.42);
}
.home-kinpaku .language-intro-row {
@@ -982,6 +975,8 @@
surface (flat oklch(0.17 0 0), no border, no shadow). All inner demo
surfaces sit transparently on top — no plinth-in-plinth, no nested rings. */
.home-kinpaku .magazine-container {
/* Solid panel, no border. The demo preview inside gets its own thin border
(see .spread-demo-area below) and inherits this fill. */
border: 0;
border-radius: 2px;
background: oklch(0.17 0 0);
@@ -989,7 +984,7 @@
}
.home-kinpaku .fisheye-item {
color: var(--ks-muted);
color: var(--ks-text);
font-family: var(--ks-font);
font-size: 1.18rem;
}
@@ -1018,13 +1013,23 @@
}
.home-kinpaku .spread-flow-cmd {
color: var(--ks-kinpaku);
background: oklch(78% 0.12 82 / 0.08);
border: 1px solid oklch(78% 0.12 82 / 0.18);
color: var(--ks-code-cmd);
background: var(--ks-code-bg);
border: 0;
border-radius: var(--ks-code-radius);
}
/* Inner demo surfaces are transparent — the plinth lives on the outer
.magazine-container; these sit on top with no chrome of their own. */
/* The demo's frame is the .split-container's own border; the caption sits
outside it. Strip the leftover chrome: no grid ::before, no inner shadow. */
.home-kinpaku .spread-demo-area .split-container {
box-shadow: none;
}
.home-kinpaku .spread-demo-area .split-container::before {
display: none;
}
/* Inner demo surfaces are transparent — they sit on the panel inside the
framed .split-container, with no chrome of their own. */
.home-kinpaku .spread-demo-area .demo-split-comparison .split-container,
.home-kinpaku .terminal-preview .demo-split-comparison .split-container,
.home-kinpaku .demo-container,
@@ -1115,14 +1120,16 @@
--ptable-accent: var(--ks-kinpaku);
width: clamp(64px, 5vw, 76px) !important;
height: clamp(76px, 5.8vw, 90px) !important;
border-width: 1px !important;
/* Crisp neutral card. Was a category-tinted gradient bg + strong colored
border + muddy multi-inset shadow that read as dim blobs; now a clean
graphite tile with a neutral hairline. Category is cued by the group label
and the accent line below, not a muddy fill. */
background: oklch(15% 0 0) !important;
border: 1px solid var(--ks-rule) !important;
border-radius: 4px !important;
overflow: hidden;
isolation: isolate;
box-shadow:
inset 0 0 0 1px oklch(100% 0 0 / 0.035),
inset 0 -18px 34px oklch(2% 0.004 95 / 0.28),
0 18px 42px oklch(2% 0.004 95 / 0.22) !important;
box-shadow: none !important;
}
.home-kinpaku #framework-viz-container .ptable-element--create {
@@ -1149,40 +1156,20 @@
--ptable-accent: var(--cat-system-text);
}
/* No gold-leaf texture overlay (was washing the tile bg) and no bottom accent
line — the tile is a clean flat neutral surface. */
.home-kinpaku #framework-viz-container .ptable-element::before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
background:
radial-gradient(circle at 74% 12%, oklch(100% 0 0 / 0.09), transparent 32%),
url("/assets/neo-kinpaku/kinpaku-gold-leaf.png") center / 190px auto;
mix-blend-mode: screen;
opacity: 0.055;
pointer-events: none;
content: none;
}
.home-kinpaku #framework-viz-container .ptable-element::after {
content: "";
position: absolute;
left: 12px;
right: 12px;
bottom: 9px;
z-index: 0;
height: 1px;
background: linear-gradient(90deg, transparent, var(--ptable-accent), transparent);
opacity: 0.24;
pointer-events: none;
content: none;
}
.home-kinpaku #framework-viz-container .ptable-element:is(:hover, :focus-visible) {
transform: translateY(-3px) !important;
border-color: var(--ptable-accent) !important;
box-shadow:
inset 0 0 0 1px oklch(100% 0 0 / 0.05),
0 0 0 1px oklch(78% 0.12 82 / 0.12),
0 22px 48px oklch(2% 0.004 95 / 0.36),
0 0 26px oklch(78% 0.12 82 / 0.16) !important;
border-color: oklch(85% 0 0 / 0.4) !important;
box-shadow: none !important;
}
.home-kinpaku #framework-viz-container .ptable-number,
@@ -1201,16 +1188,17 @@
.home-kinpaku #framework-viz-container .ptable-symbol {
font-size: clamp(1.45rem, 1.8vw, 1.8rem) !important;
font-weight: 300 !important;
font-weight: 400 !important;
letter-spacing: 0.01em;
color: var(--ks-champagne) !important;
}
.home-kinpaku #framework-viz-container .ptable-name {
max-width: 64px !important;
color: var(--ptable-accent) !important;
font-size: 0.54rem !important;
color: var(--ks-text-muted) !important;
font-size: 0.56rem !important;
letter-spacing: 0.04em;
opacity: 0.72 !important;
opacity: 1 !important;
}
.home-kinpaku #framework-viz-container .ptable-alpha {
@@ -1222,12 +1210,14 @@
.home-kinpaku .spread-demo-area .demo-split-comparison .split-before,
.home-kinpaku .terminal-preview .demo-split-comparison .split-before {
background: oklch(10% 0.006 95);
/* Left half inherits the panel fill — no separate background. */
background: transparent;
}
.home-kinpaku .spread-demo-area .demo-split-comparison .split-after,
.home-kinpaku .terminal-preview .demo-split-comparison .split-after {
background: oklch(8% 0.006 95);
/* Right half is near-black: the clean before/after contrast. */
background: oklch(2% 0 0);
}
.home-kinpaku .demo-caption,
@@ -1262,12 +1252,12 @@
}
.home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison .split-container {
background:
linear-gradient(90deg, oklch(78% 0.12 82 / 0.028) 1px, transparent 1px),
linear-gradient(180deg, oklch(78% 0.12 82 / 0.022) 1px, transparent 1px),
radial-gradient(circle at 74% 48%, oklch(70% 0.105 190 / 0.055), transparent 18rem),
oklch(7% 0.005 95);
background-size: 36px 36px, 36px 36px, auto, auto;
/* No grid lines, no radial glow — the container is transparent so the before
half shows the panel fill and the after half its own near-black. A thin
neutral border frames the demo itself (the caption sits outside it). */
background: transparent;
border: 1px solid var(--ks-rule);
border-radius: 4px;
}
.home-kinpaku :is(.spread-demo-area, .terminal-preview, .mobile-demo-area) .demo-split-comparison .split-before,
@@ -1490,7 +1480,6 @@
— dropped, the bento structure carries the brand voice now. */
.home-kinpaku .why-terminal,
.home-kinpaku .why-productmd-file,
.home-kinpaku .why-register,
.home-kinpaku .why-ci-window,
.home-kinpaku .why-browser,
.home-kinpaku .why-dm-grid,
@@ -1501,6 +1490,104 @@
border-radius: 4px;
}
.home-kinpaku .why-register {
background: transparent;
border: 0;
border-radius: 0;
gap: 10px;
}
.home-kinpaku .why-register-label {
color: var(--ks-text-muted);
font-family: var(--ks-mono);
font-size: 0.62rem;
letter-spacing: 0.2em;
}
.home-kinpaku .why-register-mock--brand,
.home-kinpaku .why-register-mock--product {
border: 1px solid var(--ks-rule);
border-radius: 4px;
background: var(--ks-lacquer-raised);
}
.home-kinpaku .why-brand-hero-mono {
color: var(--ks-text-muted);
}
.home-kinpaku .why-brand-hero-title {
color: var(--ks-champagne);
font-family: var(--ks-font-wordmark);
font-weight: 300;
}
.home-kinpaku .why-brand-hero-title em {
color: var(--ks-kinpaku);
font-style: italic;
}
.home-kinpaku .why-product-k {
color: var(--ks-text-muted);
}
.home-kinpaku .why-product-v {
color: var(--ks-champagne);
}
.home-kinpaku .why-product-row {
border-color: var(--ks-rule);
}
.home-kinpaku .why-productmd-file,
.home-kinpaku .why-terminal {
overflow: hidden;
border: 1px solid var(--ks-rule);
}
.home-kinpaku .why-productmd-header,
.home-kinpaku .why-productmd-footer,
.home-kinpaku .why-terminal-header {
border-radius: 0;
}
/* Bento window chrome dots — one subtle traffic-light set across mocks. */
.home-kinpaku :is(
.why-terminal-dot,
.why-live-dot,
.why-visual--extension .why-browser-dot,
.why-visual--v2 .v2-new-browser-dot
) {
width: 7px;
height: 7px;
border-radius: 50%;
flex-shrink: 0;
opacity: 0.5;
background: oklch(58% 0.012 95);
}
.home-kinpaku :is(
.why-terminal-dot,
.why-live-dot,
.why-visual--extension .why-browser-dot,
.why-visual--v2 .v2-new-browser-dot
):nth-child(1) {
background: var(--ks-kinpaku-deep);
}
.home-kinpaku :is(
.why-terminal-dot,
.why-live-dot,
.why-visual--extension .why-browser-dot,
.why-visual--v2 .v2-new-browser-dot
):nth-child(2) {
background: var(--ks-patina-deep);
}
.home-kinpaku .why-terminal-header,
.home-kinpaku .why-live-chrome {
gap: 5px;
}
.home-kinpaku .why-panel-title {
color: var(--ks-champagne);
font-size: 2rem;
@@ -1519,8 +1606,7 @@
.home-kinpaku .why-productmd-k,
.home-kinpaku .why-terminal-ok,
.home-kinpaku .why-terminal-path,
.home-kinpaku .why-dm-badge,
.home-kinpaku .why-ci-status {
.home-kinpaku .why-dm-badge {
color: var(--ks-patina);
}
@@ -1550,6 +1636,9 @@
.home-kinpaku .why-ci-header {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
min-height: 54px;
padding: 14px 18px 14px 72px;
border-bottom: 1px solid var(--ks-rule);
@@ -1561,29 +1650,35 @@
position: absolute;
left: 22px;
top: 50%;
width: 34px;
height: 9px;
width: 31px;
height: 7px;
transform: translateY(-50%);
background:
radial-gradient(circle at 4px 50%, var(--ks-kinpaku) 0 3px, transparent 3.5px),
radial-gradient(circle at 17px 50%, var(--ks-patina) 0 3px, transparent 3.5px),
radial-gradient(circle at 30px 50%, var(--ks-kinpaku-deep) 0 3px, transparent 3.5px);
opacity: 0.88;
radial-gradient(circle at 3.5px 50%, var(--ks-kinpaku-deep) 0 3.5px, transparent 3.6px),
radial-gradient(circle at 13.5px 50%, var(--ks-patina-deep) 0 3.5px, transparent 3.6px),
radial-gradient(circle at 23.5px 50%, oklch(58% 0.012 95) 0 3.5px, transparent 3.6px);
opacity: 0.5;
}
.home-kinpaku .why-ci-branch {
font-family: var(--ks-mono);
color: var(--ks-champagne);
font-size: 0.78rem;
letter-spacing: 0.03em;
}
.home-kinpaku .why-ci-status {
.home-kinpaku .why-ci-status,
.home-kinpaku .why-ci-status--fail {
font-family: var(--ks-mono);
font-size: 0.62rem;
letter-spacing: 0.12em;
text-transform: uppercase;
padding: 5px 13px;
border: 1px solid oklch(58% 0.15 35 / 0.3);
color: var(--ks-patina);
background:
linear-gradient(90deg, oklch(58% 0.15 35 / 0.22), oklch(58% 0.15 35 / 0.1));
box-shadow: inset 0 0 0 1px oklch(100% 0 0 / 0.02);
border-radius: 999px;
border: 1px solid oklch(58% 0.15 35 / 0.42);
color: oklch(74% 0.14 35);
background: oklch(58% 0.15 35 / 0.14);
box-shadow: none;
}
.home-kinpaku .why-ci-body {
@@ -1652,9 +1747,13 @@
}
.home-kinpaku .why-visual--live {
padding: 0;
flex: 1;
padding: clamp(16px, 2vw, 22px);
overflow: hidden;
min-height: 240px;
min-height: min(280px, 42vw);
display: flex;
align-items: stretch;
justify-content: center;
background:
linear-gradient(90deg, oklch(78% 0.12 82 / 0.018) 1px, transparent 1px),
linear-gradient(180deg, oklch(78% 0.12 82 / 0.015) 1px, transparent 1px),
@@ -1665,7 +1764,8 @@
.home-kinpaku .why-live-frame {
position: relative;
margin: 24px clamp(20px, 3vw, 32px) 0;
width: 100%;
margin: 0;
border: 1px solid oklch(78% 0.12 82 / 0.22);
border-radius: 6px;
background:
@@ -1675,25 +1775,17 @@
inset 0 0 0 1px oklch(100% 0 0 / 0.02),
0 18px 50px oklch(2% 0.004 95 / 0.32);
overflow: hidden;
display: flex;
flex-direction: column;
}
.home-kinpaku .why-live-chrome {
display: flex;
align-items: center;
gap: 5px;
padding: 9px 14px;
border-bottom: 1px solid var(--ks-rule);
background: oklch(13% 0.006 95);
}
.home-kinpaku .why-live-dot {
width: 7px;
height: 7px;
border-radius: 50%;
background: oklch(58% 0.018 82);
opacity: 0.55;
}
.home-kinpaku .why-live-dot:nth-child(1) { background: var(--ks-kinpaku-deep); }
.home-kinpaku .why-live-dot:nth-child(2) { background: var(--ks-patina-deep); }
.home-kinpaku .why-live-url {
margin-left: 12px;
padding: 3px 10px;
@@ -1707,8 +1799,12 @@
.home-kinpaku .why-live-stage {
position: relative;
min-height: 130px;
padding: 24px;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
min-height: 148px;
padding: 32px 28px;
background:
repeating-linear-gradient(0deg, transparent 0 9px, oklch(100% 0 0 / 0.012) 9px 10px),
oklch(8% 0.006 95);
@@ -1717,9 +1813,9 @@
.home-kinpaku .why-live-pick {
position: relative;
width: max-content;
max-width: calc(100% - 8px);
padding: 18px 22px;
margin: 12px auto 4px;
max-width: min(100%, 320px);
padding: 20px 24px;
margin: 0;
border: 2px solid var(--ks-kinpaku);
border-radius: 3px;
background:
@@ -1732,20 +1828,20 @@
.home-kinpaku .why-live-pick-tag {
display: block;
font-family: var(--ks-mono);
font-size: 0.7rem;
font-size: 0.74rem;
letter-spacing: 0.06em;
color: var(--ks-kinpaku);
}
.home-kinpaku .why-live-pick-note {
position: absolute;
top: -14px;
right: -18px;
padding: 5px 10px;
top: -12px;
right: -14px;
padding: 6px 11px;
background: var(--ks-kinpaku);
border-radius: 2px;
color: oklch(8% 0.006 95);
font-family: var(--ks-mono);
font-size: 0.7rem;
font-size: 0.72rem;
letter-spacing: 0.02em;
white-space: nowrap;
box-shadow: 0 4px 14px oklch(78% 0.12 82 / 0.25);
@@ -1763,46 +1859,35 @@
50% { opacity: 0; }
}
.home-kinpaku .why-live-gbar {
display: flex;
align-items: center;
gap: 10px;
.home-kinpaku .why-live-frame > .why-live-ctx.live-demo-ctx {
position: static;
left: auto;
transform: none;
display: block;
opacity: 1;
z-index: auto;
width: 100%;
max-width: none;
padding: 10px 14px;
border: 0;
border-top: 1px solid var(--ks-rule);
border-radius: 0;
box-shadow: none;
background: oklch(13% 0.006 95);
font-family: var(--ks-mono);
font-size: 0.74rem;
}
.home-kinpaku .why-live-gbar-brand {
width: 18px;
height: 18px;
display: inline-flex;
align-items: center;
justify-content: center;
background: var(--ks-kinpaku);
color: oklch(8% 0.006 95);
border-radius: 3px;
font-weight: 600;
.home-kinpaku .why-live-frame > .why-live-ctx .live-demo-ctx-row--configure {
display: flex;
gap: 6px;
}
.home-kinpaku .why-live-gbar-cmd {
padding: 3px 10px;
border: 1px solid oklch(78% 0.12 82 / 0.3);
border-radius: 3px;
color: var(--ks-kinpaku);
.home-kinpaku .why-live-frame > .why-live-ctx .live-demo-ctx-input {
flex: 1;
min-width: 0;
}
.home-kinpaku .why-live-gbar-count {
padding: 3px 8px;
border: 1px solid var(--ks-rule);
border-radius: 3px;
color: var(--ks-text-muted);
}
.home-kinpaku .why-live-gbar-go {
margin-left: auto;
padding: 4px 12px;
background: var(--ks-kinpaku);
color: oklch(8% 0.006 95);
border-radius: 3px;
font-weight: 500;
.home-kinpaku .why-live-frame > .why-live-ctx .live-demo-ctx-caret {
animation: why-live-caret 1s steps(2, end) infinite;
}
/* ============================================================
@@ -1908,20 +1993,6 @@
linear-gradient(180deg, oklch(13% 0.006 95), oklch(8% 0.005 95));
}
.home-kinpaku .why-visual--extension .why-browser-dot {
width: 8px;
height: 8px;
background: var(--ks-kinpaku-deep);
}
.home-kinpaku .why-visual--extension .why-browser-dot:nth-child(2) {
background: var(--ks-patina);
}
.home-kinpaku .why-visual--extension .why-browser-dot:nth-child(3) {
background: var(--ks-kinpaku);
}
.home-kinpaku .why-visual--extension .why-browser-url {
min-height: 30px;
display: flex;
@@ -2024,14 +2095,11 @@
}
.home-kinpaku .why-visual--designmd-v2 {
gap: 16px;
padding: clamp(18px, 2vw, 26px);
overflow: hidden;
background:
radial-gradient(circle at 13% 24%, oklch(78% 0.12 82 / 0.055), transparent 18rem),
radial-gradient(circle at 88% 18%, oklch(70% 0.105 190 / 0.06), transparent 18rem),
linear-gradient(135deg, oklch(78% 0.12 82 / 0.035), transparent 46%),
oklch(6% 0.005 95 / 0.92);
flex-direction: column;
gap: 14px;
padding: 0;
overflow: visible;
background: transparent;
}
.home-kinpaku .why-dm-header {
@@ -2058,11 +2126,9 @@
}
.home-kinpaku .why-dm-tile {
border-color: var(--ks-rule);
background:
linear-gradient(135deg, oklch(100% 0 0 / 0.024), transparent 38%),
oklch(5% 0.004 95 / 0.78);
box-shadow: inset 0 0 0 1px oklch(78% 0.12 82 / 0.026);
border: 1px solid var(--ks-rule);
background: var(--ks-lacquer-raised);
box-shadow: none;
}
.home-kinpaku .why-dm-tile-meta {
@@ -2298,20 +2364,14 @@
}
.home-kinpaku .why-visual--v2 .v2-new-browser-dots {
display: flex;
gap: 5px;
border-bottom: 1px solid var(--ks-rule);
background:
linear-gradient(90deg, oklch(78% 0.12 82 / 0.08), transparent),
oklch(8% 0.006 95);
}
.home-kinpaku .why-visual--v2 .v2-new-browser-dot {
background: var(--ks-kinpaku-deep);
}
.home-kinpaku .why-visual--v2 .v2-new-browser-dot:nth-child(2) {
background: var(--ks-patina);
}
.home-kinpaku .why-visual--v2 .v2-new-browser-frame {
background:
linear-gradient(90deg, oklch(78% 0.12 82 / 0.035) 1px, transparent 1px),
@@ -2385,10 +2445,12 @@
}
.home-kinpaku .live-demo-frame {
border: 1px solid var(--ks-rule);
border: 1px solid oklch(92% 0 0 / 0.1);
border-radius: 4px;
background: var(--ks-lacquer-raised);
box-shadow: 0 30px 84px oklch(2% 0.004 95 / 0.42);
box-shadow:
inset 0 1px 0 oklch(100% 0 0 / 0.05),
0 20px 48px -14px oklch(0% 0 0 / 0.6);
}
/* Picker chrome (chrome bar, gbar, ctx, outline, comment, stroke, etc.)
+24 -70
View File
@@ -29,6 +29,9 @@
never tucks under the nav; on tall viewports the content still centers. */
padding: 113px 0 96px;
overflow: hidden;
/* Hairline divider into the testimonials below, matching the testimonial
card border color. */
border-bottom: 1px solid oklch(0.64 0 0 / 0.22);
}
/* Header sits on top of the hero image like the /design-system topbar:
@@ -55,10 +58,7 @@
position: absolute;
inset: 0;
z-index: 0;
/* Top scrim darkens the band behind the overlaid nav so the links stay
legible over the bright kintsugi gold, fading out before the hero copy. */
background:
linear-gradient(180deg, oklch(7% 0.006 95 / 0.9) 0%, oklch(7% 0.006 95 / 0.5) 8%, transparent 18%),
url("/assets/neo-kinpaku/candidates/finalists/m-01-v2-01.png") center / cover no-repeat;
filter: saturate(1.2) contrast(1.08);
}
@@ -116,7 +116,9 @@
/* Hero CTAs migrated to .ks-button.ks-button-primary / .ks-button-secondary
(see kinpaku-kit.css). The .hero-rebuild-arrow class is gone too the
arrow now lives in .ks-button-arrow inside the button. */
arrow now lives in .ks-button-arrow inside the button.
"How it works" is the kit ghost variant: plain champagne (white) text, no
border or fill, hovering to gold. */
.hero-rebuild-meta {
margin: 24px 0 0;
@@ -497,13 +499,13 @@
than .home-kinpaku code alone). Keeps the CLI block in the softer code-gold
so the line reads as a terminal command, not a pumpkin headline. */
.home-kinpaku code.slop-teaser-cli {
color: oklch(82% 0.11 82);
color: var(--ks-code-block-fg);
font-family: var(--ks-mono);
font-size: 0.86rem;
background: var(--ks-lacquer-raised);
background: var(--ks-code-block-bg);
padding: 10px 16px;
border: 1px solid var(--ks-rule);
border-radius: 2px;
border: 1px solid var(--ks-code-block-border);
border-radius: var(--ks-code-block-radius);
user-select: all;
}
@@ -553,8 +555,8 @@
--card-fg-strong: var(--ks-champagne);
--card-fg-muted: var(--ks-muted);
--card-accent: var(--ks-kinpaku);
--card-cmd-bg: oklch(0.11 0 0);
--card-cmd-fg: var(--ks-champagne);
--card-cmd-bg: var(--ks-code-block-bg);
--card-cmd-fg: var(--ks-code-block-fg);
--card-copy-border: var(--ks-rule);
--card-copy-fg: var(--ks-kinpaku);
--card-copy-hover-bg: oklch(77% 0.14 82 / 0.08);
@@ -711,6 +713,7 @@
.downloads-rebuild-alts {
grid-column: 1 / -1;
margin: 2px 0 0;
text-align: center;
}
.downloads-rebuild-alts-summary {
display: inline-flex;
@@ -771,7 +774,9 @@
.downloads-rebuild-note {
grid-column: 1 / -1;
margin: 0;
margin: 0 auto;
max-width: 64ch;
text-align: center;
color: var(--card-fg-muted);
font-size: 0.88rem;
}
@@ -782,6 +787,7 @@
.downloads-rebuild-secondary {
grid-column: 1 / -1;
margin: 6px 0 0;
text-align: center;
font-size: 0.84rem;
color: var(--ks-text-muted);
}
@@ -795,8 +801,7 @@
border-bottom-color: var(--ks-patina-pale);
}
/* Closing "go deeper" links under the usage examples point to the full
workflow page and the command docs. */
/* Closing links under the setup extras — workflow + command docs. */
.downloads-rebuild-more {
margin: 30px auto 0;
max-width: 720px;
@@ -814,62 +819,6 @@
border-bottom-color: var(--ks-patina-pale);
}
/* Center-aligned examples: each row is a vertical stack the command line
on top, the description below, both centered horizontally. */
/* Usage examples now sit after the extras (the logical next step once the
skill, extension, CLI, and subscriptions are set up), so the separating
gap moves to the top. */
.downloads-rebuild-examples {
list-style: none;
margin: 48px auto 0;
padding: 48px 0 0;
/* Subtle hairline marking the "now use it" step after the setup block. */
border-top: 1px solid var(--ks-rule);
display: grid;
gap: 22px;
max-width: 720px;
}
.downloads-rebuild-examples li {
display: grid;
grid-template-columns: 1fr;
gap: 6px;
justify-items: center;
text-align: center;
}
/* Strip the global .home-kinpaku code chrome for these example rows. */
.home-kinpaku .downloads-rebuild-examples > li > code {
font-family: var(--ks-mono);
color: var(--card-accent);
font-size: 1rem;
background: transparent;
border: 0;
border-radius: 0;
padding: 0;
letter-spacing: 0.005em;
}
.downloads-rebuild-slash {
opacity: 0.55;
}
.downloads-rebuild-examples span {
color: var(--card-fg);
font-size: 0.94rem;
line-height: 1.5;
}
.home-kinpaku .downloads-rebuild-examples span code {
color: var(--card-fg-strong);
background: transparent;
border: 0;
border-radius: 0;
padding: 0;
font-family: var(--ks-mono);
font-size: 0.86rem;
}
.downloads-rebuild-extras {
list-style: none;
margin: 0 auto;
@@ -950,7 +899,6 @@
@media (max-width: 720px) {
.downloads-rebuild { padding: 64px 0; }
.downloads-rebuild-install { grid-template-columns: 1fr; }
.downloads-rebuild-examples li { grid-template-columns: 1fr; gap: 8px; }
}
/* ============================================================================
@@ -1014,6 +962,12 @@
max-width: 100%;
}
/* The hero-scoped demo-chrome refinements (crisp outline, neutral chrome dots /
URL, quiet gbar border, crisp active-Pick pill, tighter radii, refined frame
elevation) were promoted into the shared picker chrome in kinpaku-kit.css /
live-mode-kinpaku.css / home-kinpaku.css so /live-mode and the injected
picker (skill/scripts/live-browser.js) match. Nothing hero-specific remains. */
/* The stage holds a full (fake) website now, not a centered card. */
.hero-live-demo .live-demo-stage {
display: block;
+52 -19
View File
@@ -892,6 +892,17 @@
font-weight: 400;
}
.kinpaku-chrome .theme-toggle,
.kinpaku-chrome .site-header-github {
height: 36px;
min-height: 36px;
box-sizing: border-box;
}
.kinpaku-chrome .site-header-github {
padding: 0 12px 0 10px;
}
.kinpaku-chrome .site-header-nav a,
.kinpaku-chrome .site-header-github {
color: var(--ks-champagne);
@@ -904,7 +915,7 @@
/* GitHub star pill. Previously home-only; now every kinpaku page gets it. */
.kinpaku-chrome .site-header-github {
border: 1px solid var(--ks-rule);
border: 1px solid oklch(80% 0 0);
border-radius: 999px;
background: oklch(10% 0.006 95 / 0.74);
}
@@ -1099,16 +1110,21 @@
constants are kept in sync with these tokens by hand.
============================================================ */
/* Browser-chrome bar at the top of the mock (URL pill + dots). */
/* Browser-chrome bar at the top of the mock (URL pill + dots). Refined to read
like a precise tool, not a stock screenshot frame: slimmer bar, small uniform
neutral dots, and a clean neutral-edged URL pill (no warm gold hairline). */
.home-kinpaku .live-demo-chrome,
.live-mode-kinpaku .live-demo-chrome {
padding: 9px 14px;
background: var(--ks-graphite);
border-bottom: 1px solid var(--ks-rule);
border-bottom: 1px solid oklch(92% 0 0 / 0.07);
}
.home-kinpaku .live-demo-dot,
.live-mode-kinpaku .live-demo-dot {
background: oklch(28% 0.01 95);
width: 8px;
height: 8px;
background: oklch(34% 0 0);
}
.home-kinpaku .live-demo-url,
@@ -1119,7 +1135,7 @@
color: var(--ks-text-muted);
letter-spacing: 0.04em;
background: transparent;
border: 1px solid var(--ks-rule);
border: 1px solid oklch(92% 0 0 / 0.08);
}
/* Active control surfaces the bottom picker bar and the context bar
@@ -1131,10 +1147,12 @@
.home-kinpaku .live-demo-ctx,
.live-mode-kinpaku .live-demo-ctx {
background: var(--ks-lacquer-deep);
border: 1.5px solid var(--ks-kinpaku);
box-shadow:
0 0 0 1px oklch(78% 0.12 82 / 0.18),
0 10px 28px oklch(0% 0 0 / 0.28);
/* Quiet neutral hairline instead of the loud 1.5px gold border + gold halo.
Gold is reserved for the brand mark and the active control, not the
container outline. */
border: 1px solid oklch(92% 0 0 / 0.13);
border-radius: 8px;
box-shadow: 0 16px 36px -12px oklch(0% 0 0 / 0.6);
color: var(--ks-champagne);
}
@@ -1150,13 +1168,14 @@
background: transparent;
}
/* Active state soft kinpaku-dim pill with kinpaku text. The outer
gbar border carries the loud signal; the active button is the
quieter "currently selected" pill inside. */
/* Active state a crisp neutral pill with kinpaku text. The translucent
kinpaku-dim wash read as a murky smudge; a solid graphite chip with gold
text/icon makes the selected control precise. */
.home-kinpaku .live-demo-gbar-btn.is-active,
.live-mode-kinpaku .live-demo-gbar-btn.is-active {
background: oklch(78% 0.12 82 / 0.18);
background: oklch(27% 0 0);
color: var(--ks-kinpaku);
border-radius: 6px;
}
/* Page chat — collapsed pill with chat + mic; expands on click. */
@@ -1167,9 +1186,9 @@
height: 28px;
width: 88px;
margin: 0 4px 0 6px;
border-radius: 7px;
border-radius: 5px;
background: var(--ks-graphite);
border: 1px solid var(--ks-rule);
border: 1px solid oklch(92% 0 0 / 0.1);
overflow: hidden;
cursor: pointer;
flex-shrink: 0;
@@ -1292,10 +1311,20 @@
.home-kinpaku .live-demo-ctx-pill,
.live-mode-kinpaku .live-demo-ctx-pill {
background: var(--ks-graphite-2);
border: 1px solid var(--ks-rule);
border: 1px solid oklch(92% 0 0 / 0.12);
color: var(--ks-champagne);
}
/* Even heights across the configure row: the pill, input, count, and Go button
share one 30px baseline instead of stepping up and down. */
.home-kinpaku .live-demo-ctx-row--configure > *,
.live-mode-kinpaku .live-demo-ctx-row--configure > * {
height: 30px;
box-sizing: border-box;
display: inline-flex;
align-items: center;
}
.home-kinpaku .live-demo-ctx-pill-caret,
.live-mode-kinpaku .live-demo-ctx-pill-caret {
color: var(--ks-text-muted);
@@ -1304,7 +1333,7 @@
.home-kinpaku .live-demo-ctx-input,
.live-mode-kinpaku .live-demo-ctx-input {
background: var(--ks-graphite);
border: 1px solid var(--ks-rule);
border: 1px solid oklch(92% 0 0 / 0.12);
color: var(--ks-champagne);
}
@@ -1316,7 +1345,7 @@
.home-kinpaku .live-demo-ctx-count,
.live-mode-kinpaku .live-demo-ctx-count {
background: var(--ks-graphite-2);
border: 1px solid var(--ks-rule);
border: 1px solid oklch(92% 0 0 / 0.12);
color: var(--ks-text-muted);
}
@@ -1377,8 +1406,12 @@
.home-kinpaku .live-demo-outline,
.live-mode-kinpaku .live-demo-outline {
border-color: var(--ks-kinpaku);
border-width: 1.5px;
border-radius: 3px;
color: var(--ks-kinpaku);
box-shadow: 0 0 0 4px oklch(78% 0.12 82 / 0.16);
/* No soft gold glow ring (off-brand accent halo); a crisp outline reads as a
precise selection, not a highlighter. */
box-shadow: none;
}
.home-kinpaku .live-demo-annotations,
+93 -10
View File
@@ -15,6 +15,7 @@
*/
:root {
/* color-scheme follows html.light / html.dark class on <html> */
/* ============================================================
Brand anchors. Two anchors carry the brand kinpaku gold for
commitment and brand voice, verdigris patina for state and
@@ -45,22 +46,43 @@
--ks-graphite-2: oklch(19% 0.008 95); /* one step up from graphite */
/* ============================================================
Text. Warm champagne family. Body text reads at 0.92rem on
lacquer; smaller than that loses to the warm noise floor.
Text. The whole text ramp runs near-neutral and bright so copy,
headings, and labels read crisp on lacquer instead of mushing
into the warm floor. Warmth now lives only in the gold accents
and the surfaces, not in the type. (--ks-champagne keeps its name
for compatibility but is no longer warm.)
============================================================ */
--ks-champagne: oklch(84% 0.035 82); /* headlines, <strong> */
--ks-text: oklch(81% 0.03 82); /* body */
--ks-text-muted: oklch(63% 0.024 82); /* captions, meta */
--ks-text-faint: oklch(52% 0.018 82); /* subdued */
--ks-text-mute-deep: oklch(48% 0.018 82); /* disabled */
--ks-champagne: oklch(91% 0 0); /* headlines, <strong> — neutral white */
--ks-text: oklch(88% 0 0); /* body — neutral near-white */
--ks-text-muted: oklch(72% 0 0); /* captions, meta */
--ks-text-faint: oklch(62% 0 0); /* subdued */
--ks-text-mute-deep: oklch(52% 0 0); /* disabled */
/* ============================================================
Rules. Gold hairlines. Default is quiet; "strong" appears on
focus, active state, and structural anchors.
Rules. The default hairline is neutral so borders/dividers/labels
don't carry warmth (warmth lives in the gold accents and surfaces).
"strong" stays gold it appears on focus, active state, and
structural brand anchors where the gold is the signal.
============================================================ */
--ks-rule: oklch(58% 0.065 82 / 0.32);
--ks-rule: oklch(78% 0 0 / 0.16);
--ks-rule-strong: oklch(74% 0.09 82 / 0.6);
/* ============================================================
Code. One treatment site-wide. Inline code is a neutral graphite
chip; blocks / CLI commands are a deep lacquer terminal with a
neutral hairline. Gold is only for code that is itself a command
link (--ks-code-cmd). All code rules read these don't hand-type.
============================================================ */
--ks-code-fg: oklch(91% 0 0); /* inline code text */
--ks-code-bg: var(--ks-graphite-2); /* inline code chip */
--ks-code-radius: 3px;
--ks-code-pad: 0.3em 0.5em; /* inline code chip padding */
--ks-code-block-fg: oklch(86% 0 0); /* block / CLI text */
--ks-code-block-bg: var(--ks-lacquer-deep);
--ks-code-block-border: var(--ks-rule);
--ks-code-block-radius: 2px;
--ks-code-cmd: var(--ks-kinpaku); /* code that's a command link */
/* ============================================================
Typography three faces.
- --ks-font-display: Alumni Sans Pinstripe. Pinstripe horizontal
@@ -124,3 +146,64 @@
============================================================ */
--ks-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
}
html.dark {
color-scheme: dark;
}
/* ============================================================
Light mode warm paper surfaces, dark ink type, kinpaku gold
accents deepened for contrast. Activated via html.light on
<html> (set by theme.js + inline FOUC guard in Base.astro).
============================================================ */
html.light {
color-scheme: light;
/* Brand gold same fills as dark mode (logo, buttons, marks).
Use --ks-kinpaku-ink for small text on paper where bright gold
lacks contrast; never swap the core token to a muddy orange. */
--ks-kinpaku: oklch(84% 0.19 80.46);
--ks-kinpaku-pale: oklch(86% 0.07 84);
--ks-kinpaku-rich: oklch(77% 0.13 82);
--ks-kinpaku-deep: oklch(61% 0.085 78);
--ks-kinpaku-ink: oklch(56% 0.11 82);
/* Text links + active nav on paper — patina, not fill gold. */
--ks-link-on-paper: var(--ks-patina-deep);
--ks-link-on-paper-hover: var(--ks-patina);
--ks-link-on-paper-line: oklch(49% 0.08 188 / 0.42);
--ks-nav-active: var(--ks-patina-deep);
/* Patina — brand values for fills; deep for text on paper. */
--ks-patina: oklch(70% 0.12 188);
--ks-patina-pale: oklch(82% 0.07 188);
--ks-patina-deep: oklch(49% 0.08 188);
--ks-vermilion: oklch(52% 0.16 35);
/* Surfaces — warm paper and cream panels. */
--ks-lacquer: oklch(97% 0.012 95);
--ks-lacquer-deep: oklch(94% 0.014 95);
--ks-lacquer-raised: oklch(99% 0.008 95);
--ks-graphite: oklch(91% 0.012 95);
--ks-graphite-2: oklch(88% 0.014 95);
/* Text — dark ink on paper. */
--ks-champagne: oklch(18% 0.02 95);
--ks-text: oklch(25% 0.018 95);
--ks-text-muted: oklch(45% 0.015 95);
--ks-text-faint: oklch(55% 0.012 95);
--ks-text-mute-deep: oklch(65% 0.01 95);
/* Rules — dark hairlines. */
--ks-rule: oklch(25% 0.02 95 / 0.12);
--ks-rule-strong: oklch(61% 0.085 78 / 0.45);
/* Code — light chips, dark text. */
--ks-code-fg: oklch(28% 0.02 95);
--ks-code-bg: var(--ks-graphite);
--ks-code-block-fg: oklch(30% 0.02 95);
--ks-code-block-bg: var(--ks-lacquer-raised);
--ks-code-block-border: var(--ks-rule);
--ks-code-cmd: var(--ks-kinpaku-ink);
}
File diff suppressed because it is too large Load Diff
+6 -2
View File
@@ -190,10 +190,14 @@
.live-mode-kinpaku .live-demo-frame {
background: var(--ks-lacquer-deep);
border: 1px solid var(--ks-rule);
/* Crisp neutral hairline + tighter, deeper shadow that registers, instead of
a warm gold edge and a broad soft shadow that washes out on dark. */
border: 1px solid oklch(92% 0 0 / 0.1);
border-radius: 4px;
overflow: hidden;
box-shadow: 0 32px 80px oklch(2% 0.004 95 / 0.55);
box-shadow:
inset 0 1px 0 oklch(100% 0 0 / 0.05),
0 20px 48px -14px oklch(0% 0 0 / 0.6);
}
/* All .live-demo-* picker chrome (chrome bar, gbar, ctx, outline,
+21 -44
View File
@@ -10,68 +10,43 @@
spans the full viewport. */
width: 100vw;
margin-left: calc(50% - 50vw);
padding: 20px 0 clamp(56px, 7vw, 96px);
background: var(--ks-lacquer);
/* No background of its own: the body's lacquer gradient is the page ground,
so the section sits on it directly and an opaque fill here would only
duplicate (and, when overlapped, mask) it. */
padding: 0 0 1em;
color: var(--ks-text);
border-top: 0;
overflow: hidden;
}
/* Flat dotted top divider (matches the hero → testimonials boundary). */
.home-kinpaku .testimonials-section::before {
/* Dotted accent at the bottom edge a deliberate separator between the
testimonials and the section below. Neutral dots, matching the de-warmed
borders. (This is the dot rail that used to sit above the section.) */
.home-kinpaku .testimonials-section::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 50%;
width: 100vw;
height: 18px;
transform: translateX(-50%);
background-image: radial-gradient(circle, oklch(0.42 0.014 82) 0.9px, transparent 1.4px);
background-image: radial-gradient(circle, oklch(0.45 0 0) 0.9px, transparent 1.4px);
background-size: 7px 6px;
background-position: 0 1px;
background-repeat: repeat;
pointer-events: none;
}
/* ---------------------------------------------------------------------------
Plinth the tinted graphite shelf the marquee rides on
--------------------------------------------------------------------------- */
.home-kinpaku .t-plinth {
position: relative;
width: 100vw;
padding: 20px 0;
background:
linear-gradient(180deg, oklch(20% 0.01 78) 0%, oklch(17% 0.008 78) 100%);
border-top: 1px solid oklch(78% 0.12 82 / 0.12);
border-bottom: 1px solid oklch(78% 0.12 82 / 0.10);
}
.home-kinpaku .t-plinth--shelf::before,
.home-kinpaku .t-plinth--shelf::after {
content: "";
position: absolute;
left: 0; right: 0;
height: 8px;
pointer-events: none;
z-index: 1;
}
.home-kinpaku .t-plinth--shelf::before {
top: 0;
background: linear-gradient(180deg, oklch(0% 0 0 / 0.18), transparent);
}
.home-kinpaku .t-plinth--shelf::after {
bottom: 0;
background: linear-gradient(0deg, oklch(0% 0 0 / 0.22), transparent);
}
/* ---------------------------------------------------------------------------
Marquee engine
Marquee engine. The cards are outlined and ride directly on the section
ground the old graphite plinth wrapper was removed once it stopped being
a visible shelf, so the marquee carries its own vertical inset here.
--------------------------------------------------------------------------- */
.home-kinpaku .t-marquee {
display: grid;
gap: 14px;
width: 100%;
padding: 22px 0;
}
.home-kinpaku .t-marquee-row { overflow: hidden; }
@@ -119,14 +94,16 @@
transition: transform 200ms ease, background 200ms ease, box-shadow 200ms ease, border-color 200ms ease;
}
/* Plinth-resident card — borderless, slightly raised tone */
/* Outlined card: no fill, just a solid neutral border on the page ground.
On dark, a clean outline separates more honestly than a near-invisible
fill or a dead drop-shadow ever did. */
.home-kinpaku .t-card--plinth {
background: oklch(13% 0.008 95);
border: 1px solid transparent;
box-shadow: 0 1px 0 0 oklch(78% 0.12 82 / 0.06) inset, 0 4px 12px -8px oklch(0% 0 0 / 0.6);
background: none;
border: 1px solid oklch(0.64 0 0 / 0.22);
box-shadow: none;
}
.home-kinpaku .t-card--plinth:hover {
background: oklch(15% 0.012 78);
border-color: oklch(0.64 0 0 / 0.42);
transform: translateY(-1px);
}
+16
View File
@@ -106,3 +106,19 @@ button, input, textarea, select {
--cat-system-border: #78716c;
--cat-system-text: #44403c;
}
/* Light mode legacy aliases — mirror html.light --ks-* tokens. */
html.light {
--color-ink: var(--ks-champagne);
--color-text: var(--ks-text);
--color-paper: var(--ks-lacquer);
--color-cream: var(--ks-lacquer-raised);
--color-charcoal: var(--ks-text);
--color-ash: var(--ks-text-muted);
--color-mist: var(--ks-rule);
--color-bg: var(--ks-lacquer-raised);
--color-accent: var(--ks-kinpaku);
--color-accent-hover: var(--ks-kinpaku-pale);
--color-accent-dim: oklch(77% 0.13 82 / 0.14);
--color-accent-soft: oklch(77% 0.13 82 / 0.24);
}
+21 -12
View File
@@ -46,9 +46,11 @@
mist: 'oklch(90% 0.008 82 / 0.6)', // light hairline
white: 'oklch(99% 0 0)',
};
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css
// Picker bar chrome — mirrors .live-demo-gbar / .live-demo-ctx in kinpaku-kit.css.
// Quiet neutral elevation: no gold halo ring (gold is reserved for the brand
// mark and the active control, not the container outline).
const PICKER_SHADOW =
'0 0 0 1px oklch(78% 0.12 82 / 0.18), 0 10px 28px oklch(0% 0 0 / 0.28)';
'0 16px 36px -12px oklch(0% 0 0 / 0.6)';
const FONT = 'system-ui, -apple-system, sans-serif';
const MONO = 'ui-monospace, SFMono-Regular, Menlo, monospace';
// z-index: detect overlays use 99999, so our UI must be above them
@@ -995,8 +997,8 @@
transform: 'translateY(6px)',
transition: 'opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
background: BP.surface,
border: '1.5px solid ' + BP.border,
borderRadius: '10px',
border: '1px solid ' + BP.border,
borderRadius: '8px',
boxShadow: BP.shadow,
transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
fontFamily: FONT, fontSize: '13px', color: BP.text,
@@ -1071,7 +1073,7 @@
barEl.innerHTML = '';
// Reset bar styling to the kinpaku picker palette
barEl.style.background = BP.surface;
barEl.style.border = '1.5px solid ' + BP.border;
barEl.style.border = '1px solid ' + BP.border;
barEl.style.boxShadow = BP.shadow;
if (mode === 'configure') {
barEl.appendChild(configureKind === 'insert' ? buildInsertConfigureRow() : buildConfigureRow());
@@ -2339,8 +2341,8 @@
transformOrigin: 'bottom left',
transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
padding: '6px',
fontFamily: FONT,
@@ -6122,8 +6124,15 @@ void main() {
return {
surface: C.ink,
surfaceDeep: C.ink,
border: C.brand,
hairline: 'oklch(58% 0.065 82 / 0.48)',
// Quiet neutral hairline (was the loud kinpaku gold border). Gold lives on
// the brand mark and the active control instead.
border: 'oklch(92% 0 0 / 0.13)',
// Crisp graphite pill behind the active toggle (was a murky kinpaku-dim
// wash); the gold text/icon carries the "selected" signal.
toggleActive: 'oklch(27% 0 0)',
// Neutral hairline for internal control borders / dividers (was a warm
// gold rule that read as muddy champagne edges on the pill / input / count).
hairline: 'oklch(92% 0 0 / 0.12)',
text: 'oklch(84% 0.035 82)',
textDim: 'oklch(63% 0.024 82)',
accent: C.brand,
@@ -7032,8 +7041,8 @@ void main() {
display: 'flex', alignItems: 'stretch',
gap: '0',
background: P.surface,
border: '1.5px solid ' + P.border,
borderRadius: '10px',
border: '1px solid ' + P.border,
borderRadius: '8px',
boxShadow: P.shadow,
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
opacity: '0',
@@ -7443,7 +7452,7 @@ void main() {
// Sync one toggle's active state, colors, and slide-label visibility.
function sync(btn, active) {
if (!btn) return;
btn.style.background = active ? P.accentSoft : 'transparent';
btn.style.background = active ? P.toggleActive : 'transparent';
btn.style.color = active ? P.accent : P.textDim;
btn.dataset.active = active ? 'true' : 'false';
if (active && btn._expandLabel) btn._expandLabel();