Files
jiahao 6838a5ef43 fix(cds): align tokens to Claude Desktop 3.6556.2 runtime ground truth
Every value below was verified against the running app over the
main-process debugger (webContents.debugger over CDP, reading
getComputedStyle from the live main_window renderer), then re-verified
locally in headless Chrome against cds-theme.css. 9/9 resolved colors now
match the client exactly.

Text colors (all three were wrong):

  text-primary   #151515 -> var(--cds-neutral-900)   #0b0b0b
  text-secondary #525252 -> var(--cds-neutral-600)   #52514e
  text-muted     #8a8a8a -> var(--cds-neutral-400)   #898781

  neutral-N is the official theme ramp: gray-N in light, gray-(900-N) in
  dark. New --cds-neutral-* block defines the flip, so dark mode now
  yields #f0efec / #c3c2b7 / #898781 exactly as the client does.

Accent is blue, not clay (the root misreading):

  The official spec separates the accent role (blue) from the brand role
  (clay). Verified live:

    border-accent  light #86b6ef (blue-250) / dark #0d366b
    text-accent    light #184f95 (blue-600) / dark #6da7ec
    fill-accent    #2a78d6 (blue-450)
    focus-shadow   1px #2a78d6 ring + #cde2fb glow, was clay

  Added --cds-blue-100/250/450/600 and --cds-role-accent-{250,450,600},
  --cds-bg-accent; border-accent/text-accent/focus-shadow now resolve
  through the role chain.

Brand hover direction fixed:

  fill-brand        #c6613f (clay-emphasized, both modes)
  fill-brand-hover  #d97757 (clay) - the client hovers upward, we had
  --cds-clay-hover #cc5a36/#e08264 which went darker. clay-emphasized is
  now a literal #c6613f, no dark override, matching the single
  declaration in the client's stylesheet.

Skeleton dark values:

  base and sheen are the same value in the client:
  hsl(from neutral-900 / 7.5%), i.e. a darkening white wash. Ours were
  white alphas at two different strengths (0.06/0.08).

Shadow system:

  shadow-popover is a pure two-layer drop shadow officially
  (0 8px 24px/0.12, 0 2px 6px/0.08); the inset ring we mixed in is gone.
  shadow-sm/md/lg and shadow-color now use hsl(from gray-900 ...) for
  the offset layer so they follow dark mode; dark shadow-color is
  rgba(0,0,0,0.24) per the live reading.

Sizing and density:

  radius-composer 20px -> calc(.75rem * scale) = 12px, with
  [data-density=comfortable] overriding to 14px (the live app reports
  data-density=comfortable and resolves 14px). gap-xl 1.5rem -> 40px,
  h-control-nested 24px -> 22px, and the full sizing family (radius,
  h-control*, icon, pad-*, gap-*) is now written as
  calc(N * var(--cds-rem-scale, 1)) instead of fixed px, so a host can
  actually drive density. keycap-radius 4px and checkbox-radius 5px per
  the official vanilla tokens.

Skeleton structure:

  .cds-skeleton-sweep is removed from the ::after selector list that also
  carried position:absolute - as a standalone class it pushed the element
  out of the viewport (the bug reproduced in issue #25). The official
  shape is a .cds-skel-sweep-band child inside a .cds-skel-sweep-clip;
  both are now provided. The base class border-radius moves to
  :where() so rounded-full survives on avatar skeletons. data-hold
  three-state reveal timing, the wave/lockstep breathe bindings, the
  RTL :lang() list with animation-direction:reverse, and dual reduced-
  motion guards (prefers-reduced-motion + data-reduce-motion) are added
  per the extracted rules; cds-placeholder-reveal keyframe added.

Tooling:

  check-tokens.mjs strips CSS comments before the orphan-keyframe check;
  a keyframe named only inside a comment used to pass as consumed.

Gate: check:tokens passes (242 tokens, 13 keyframes), typecheck passes,
and the 9-value comparison table against the live client is all-green.
2026-10-26 17:50:11 +08:00
..