@nurix/etna 0.19.51 → 0.19.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/data/harness-index.json +1 -1
  2. package/data/harnesses/apollo/.mcp.json +8 -0
  3. package/data/harnesses/apollo/harness.json +3 -2
  4. package/data/harnesses/apollo/skills/design/SKILL.md +45 -50
  5. package/data/harnesses/apollo/skills/design/data/blueprints/browse.md +38 -0
  6. package/data/harnesses/apollo/skills/design/data/blueprints/creation-flow.md +38 -0
  7. package/data/harnesses/apollo/skills/design/data/blueprints/dashboard.md +38 -0
  8. package/data/harnesses/apollo/skills/design/data/blueprints/grid.md +38 -0
  9. package/data/harnesses/apollo/skills/design/data/blueprints/queue.md +38 -0
  10. package/data/harnesses/apollo/skills/design/data/blueprints/record-detail.md +38 -0
  11. package/data/harnesses/apollo/skills/design/data/blueprints/settings.md +38 -0
  12. package/data/harnesses/apollo/skills/design/data/charts/census.csv +58 -0
  13. package/data/harnesses/apollo/skills/design/data/checklists/browse.md +21 -0
  14. package/data/harnesses/apollo/skills/design/data/checklists/creation-flow.md +20 -0
  15. package/data/harnesses/apollo/skills/design/data/checklists/dashboard.md +21 -0
  16. package/data/harnesses/apollo/skills/design/data/checklists/grid.md +21 -0
  17. package/data/harnesses/apollo/skills/design/data/checklists/queue.md +21 -0
  18. package/data/harnesses/apollo/skills/design/data/checklists/record-detail.md +21 -0
  19. package/data/harnesses/apollo/skills/design/data/checklists/settings.md +21 -0
  20. package/data/harnesses/apollo/skills/design/data/chrome/board-column.md +68 -0
  21. package/data/harnesses/apollo/skills/design/data/chrome/data-table.md +63 -0
  22. package/data/harnesses/apollo/skills/design/data/chrome/side-panel.md +60 -0
  23. package/data/harnesses/apollo/skills/design/data/chrome/sidebar.md +78 -0
  24. package/data/harnesses/apollo/skills/design/data/chrome/stat-cards.md +62 -0
  25. package/data/harnesses/apollo/skills/design/data/chrome/topbar.md +65 -0
  26. package/data/harnesses/apollo/skills/design/data/elevation/ant-design-directional-shadow.md +19 -0
  27. package/data/harnesses/apollo/skills/design/data/elevation/apple-liquid-glass-material.md +18 -0
  28. package/data/harnesses/apollo/skills/design/data/elevation/atlassian-surface-shadow-pairing.md +20 -0
  29. package/data/harnesses/apollo/skills/design/data/elevation/fluent-2-key-ambient-ramp.md +20 -0
  30. package/data/harnesses/apollo/skills/design/data/elevation/github-primer-sparing-shadow.md +19 -0
  31. package/data/harnesses/apollo/skills/design/data/elevation/ibm-carbon-layer-and-border.md +19 -0
  32. package/data/harnesses/apollo/skills/design/data/elevation/linear-dark-surface-ladder.md +17 -0
  33. package/data/harnesses/apollo/skills/design/data/elevation/material-2-key-ambient-dp-ramp.md +19 -0
  34. package/data/harnesses/apollo/skills/design/data/elevation/material-3-tonal-elevation.md +21 -0
  35. package/data/harnesses/apollo/skills/design/data/elevation/neobrutalist-hard-offset.md +19 -0
  36. package/data/harnesses/apollo/skills/design/data/elevation/neumorphic-soft-dual-shadow.md +18 -0
  37. package/data/harnesses/apollo/skills/design/data/elevation/notion-warm-minimal-hairline.md +17 -0
  38. package/data/harnesses/apollo/skills/design/data/elevation/polaris-elevation-inset-bevel.md +21 -0
  39. package/data/harnesses/apollo/skills/design/data/elevation/radix-themes-alpha-ring-scale.md +19 -0
  40. package/data/harnesses/apollo/skills/design/data/elevation/shadcn-neutral-derived-radius.md +19 -0
  41. package/data/harnesses/apollo/skills/design/data/elevation/stripe-brand-tinted-dual-shadow.md +18 -0
  42. package/data/harnesses/apollo/skills/design/data/elevation/tailwind-default-utility-scale.md +19 -0
  43. package/data/harnesses/apollo/skills/design/data/elevation/vercel-geist-shadow-as-border.md +20 -0
  44. package/data/harnesses/apollo/skills/design/data/iconography.md +199 -0
  45. package/data/harnesses/apollo/skills/design/data/motion/accordion-expand.md +18 -0
  46. package/data/harnesses/apollo/skills/design/data/motion/destructive-hold-confirm.md +18 -0
  47. package/data/harnesses/apollo/skills/design/data/motion/drag-dismiss-momentum.md +18 -0
  48. package/data/harnesses/apollo/skills/design/data/motion/empty-state-arrive.md +18 -0
  49. package/data/harnesses/apollo/skills/design/data/motion/hover-lift.md +18 -0
  50. package/data/harnesses/apollo/skills/design/data/motion/modal-center-arrive.md +18 -0
  51. package/data/harnesses/apollo/skills/design/data/motion/number-ticker-roll.md +18 -0
  52. package/data/harnesses/apollo/skills/design/data/motion/onboarding-bounce.md +18 -0
  53. package/data/harnesses/apollo/skills/design/data/motion/panel-slide.md +18 -0
  54. package/data/harnesses/apollo/skills/design/data/motion/press-feedback.md +18 -0
  55. package/data/harnesses/apollo/skills/design/data/motion/progress-linear-loop.md +18 -0
  56. package/data/harnesses/apollo/skills/design/data/motion/route-crossfade.md +18 -0
  57. package/data/harnesses/apollo/skills/design/data/motion/rubber-band-overscroll.md +18 -0
  58. package/data/harnesses/apollo/skills/design/data/motion/skeleton-shimmer.md +18 -0
  59. package/data/harnesses/apollo/skills/design/data/motion/stagger-arrive.md +18 -0
  60. package/data/harnesses/apollo/skills/design/data/motion/toast-enter-stack.md +18 -0
  61. package/data/harnesses/apollo/skills/design/data/motion/tooltip-chain-instant.md +18 -0
  62. package/data/harnesses/apollo/skills/design/data/motion/trigger-anchored-reveal.md +18 -0
  63. package/data/harnesses/apollo/skills/design/data/tells.csv +34 -0
  64. package/data/harnesses/apollo/skills/design/data/voices/bright-collaborator.md +29 -0
  65. package/data/harnesses/apollo/skills/design/data/voices/direct-operator.md +29 -0
  66. package/data/harnesses/apollo/skills/design/data/voices/earnest-helper.md +29 -0
  67. package/data/harnesses/apollo/skills/design/data/voices/editorial-composed.md +29 -0
  68. package/data/harnesses/apollo/skills/design/data/voices/quiet-concierge.md +29 -0
  69. package/data/harnesses/apollo/skills/design/data/voices/warm-guide.md +29 -0
  70. package/data/harnesses/apollo/skills/design/references/compose.md +3 -7
  71. package/data/harnesses/apollo/skills/design/references/content.md +4 -4
  72. package/data/harnesses/apollo/skills/design/references/existing-apps.md +1 -1
  73. package/data/harnesses/apollo/skills/design/references/foundations.md +57 -0
  74. package/data/harnesses/apollo/skills/design/references/intake.md +11 -11
  75. package/data/harnesses/apollo/skills/design/references/object-pass.md +1 -1
  76. package/data/harnesses/apollo/skills/design/references/ship-gate.md +1 -1
  77. package/data/harnesses/apollo/skills/design/scripts/select-chart.mjs +14 -8
  78. package/data/harnesses/apollo/skills/design/scripts/validate-design-md.mjs +1 -1
  79. package/data/harnesses/code/.mcp.json +8 -0
  80. package/data/harnesses/code/harness.json +4 -2
  81. package/data/harnesses/code/skills/design/SKILL.md +45 -50
  82. package/data/harnesses/code/skills/design/data/blueprints/browse.md +38 -0
  83. package/data/harnesses/code/skills/design/data/blueprints/creation-flow.md +38 -0
  84. package/data/harnesses/code/skills/design/data/blueprints/dashboard.md +38 -0
  85. package/data/harnesses/code/skills/design/data/blueprints/grid.md +38 -0
  86. package/data/harnesses/code/skills/design/data/blueprints/queue.md +38 -0
  87. package/data/harnesses/code/skills/design/data/blueprints/record-detail.md +38 -0
  88. package/data/harnesses/code/skills/design/data/blueprints/settings.md +38 -0
  89. package/data/harnesses/code/skills/design/data/charts/census.csv +58 -0
  90. package/data/harnesses/code/skills/design/data/checklists/browse.md +21 -0
  91. package/data/harnesses/code/skills/design/data/checklists/creation-flow.md +20 -0
  92. package/data/harnesses/code/skills/design/data/checklists/dashboard.md +21 -0
  93. package/data/harnesses/code/skills/design/data/checklists/grid.md +21 -0
  94. package/data/harnesses/code/skills/design/data/checklists/queue.md +21 -0
  95. package/data/harnesses/code/skills/design/data/checklists/record-detail.md +21 -0
  96. package/data/harnesses/code/skills/design/data/checklists/settings.md +21 -0
  97. package/data/harnesses/code/skills/design/data/chrome/board-column.md +68 -0
  98. package/data/harnesses/code/skills/design/data/chrome/data-table.md +63 -0
  99. package/data/harnesses/code/skills/design/data/chrome/side-panel.md +60 -0
  100. package/data/harnesses/code/skills/design/data/chrome/sidebar.md +78 -0
  101. package/data/harnesses/code/skills/design/data/chrome/stat-cards.md +62 -0
  102. package/data/harnesses/code/skills/design/data/chrome/topbar.md +65 -0
  103. package/data/harnesses/code/skills/design/data/elevation/ant-design-directional-shadow.md +19 -0
  104. package/data/harnesses/code/skills/design/data/elevation/apple-liquid-glass-material.md +18 -0
  105. package/data/harnesses/code/skills/design/data/elevation/atlassian-surface-shadow-pairing.md +20 -0
  106. package/data/harnesses/code/skills/design/data/elevation/fluent-2-key-ambient-ramp.md +20 -0
  107. package/data/harnesses/code/skills/design/data/elevation/github-primer-sparing-shadow.md +19 -0
  108. package/data/harnesses/code/skills/design/data/elevation/ibm-carbon-layer-and-border.md +19 -0
  109. package/data/harnesses/code/skills/design/data/elevation/linear-dark-surface-ladder.md +17 -0
  110. package/data/harnesses/code/skills/design/data/elevation/material-2-key-ambient-dp-ramp.md +19 -0
  111. package/data/harnesses/code/skills/design/data/elevation/material-3-tonal-elevation.md +21 -0
  112. package/data/harnesses/code/skills/design/data/elevation/neobrutalist-hard-offset.md +19 -0
  113. package/data/harnesses/code/skills/design/data/elevation/neumorphic-soft-dual-shadow.md +18 -0
  114. package/data/harnesses/code/skills/design/data/elevation/notion-warm-minimal-hairline.md +17 -0
  115. package/data/harnesses/code/skills/design/data/elevation/polaris-elevation-inset-bevel.md +21 -0
  116. package/data/harnesses/code/skills/design/data/elevation/radix-themes-alpha-ring-scale.md +19 -0
  117. package/data/harnesses/code/skills/design/data/elevation/shadcn-neutral-derived-radius.md +19 -0
  118. package/data/harnesses/code/skills/design/data/elevation/stripe-brand-tinted-dual-shadow.md +18 -0
  119. package/data/harnesses/code/skills/design/data/elevation/tailwind-default-utility-scale.md +19 -0
  120. package/data/harnesses/code/skills/design/data/elevation/vercel-geist-shadow-as-border.md +20 -0
  121. package/data/harnesses/code/skills/design/data/iconography.md +199 -0
  122. package/data/harnesses/code/skills/design/data/motion/accordion-expand.md +18 -0
  123. package/data/harnesses/code/skills/design/data/motion/destructive-hold-confirm.md +18 -0
  124. package/data/harnesses/code/skills/design/data/motion/drag-dismiss-momentum.md +18 -0
  125. package/data/harnesses/code/skills/design/data/motion/empty-state-arrive.md +18 -0
  126. package/data/harnesses/code/skills/design/data/motion/hover-lift.md +18 -0
  127. package/data/harnesses/code/skills/design/data/motion/modal-center-arrive.md +18 -0
  128. package/data/harnesses/code/skills/design/data/motion/number-ticker-roll.md +18 -0
  129. package/data/harnesses/code/skills/design/data/motion/onboarding-bounce.md +18 -0
  130. package/data/harnesses/code/skills/design/data/motion/panel-slide.md +18 -0
  131. package/data/harnesses/code/skills/design/data/motion/press-feedback.md +18 -0
  132. package/data/harnesses/code/skills/design/data/motion/progress-linear-loop.md +18 -0
  133. package/data/harnesses/code/skills/design/data/motion/route-crossfade.md +18 -0
  134. package/data/harnesses/code/skills/design/data/motion/rubber-band-overscroll.md +18 -0
  135. package/data/harnesses/code/skills/design/data/motion/skeleton-shimmer.md +18 -0
  136. package/data/harnesses/code/skills/design/data/motion/stagger-arrive.md +18 -0
  137. package/data/harnesses/code/skills/design/data/motion/toast-enter-stack.md +18 -0
  138. package/data/harnesses/code/skills/design/data/motion/tooltip-chain-instant.md +18 -0
  139. package/data/harnesses/code/skills/design/data/motion/trigger-anchored-reveal.md +18 -0
  140. package/data/harnesses/code/skills/design/data/tells.csv +34 -0
  141. package/data/harnesses/code/skills/design/data/voices/bright-collaborator.md +29 -0
  142. package/data/harnesses/code/skills/design/data/voices/direct-operator.md +29 -0
  143. package/data/harnesses/code/skills/design/data/voices/earnest-helper.md +29 -0
  144. package/data/harnesses/code/skills/design/data/voices/editorial-composed.md +29 -0
  145. package/data/harnesses/code/skills/design/data/voices/quiet-concierge.md +29 -0
  146. package/data/harnesses/code/skills/design/data/voices/warm-guide.md +29 -0
  147. package/data/harnesses/code/skills/design/references/compose.md +3 -7
  148. package/data/harnesses/code/skills/design/references/content.md +4 -4
  149. package/data/harnesses/code/skills/design/references/existing-apps.md +1 -1
  150. package/data/harnesses/code/skills/design/references/foundations.md +57 -0
  151. package/data/harnesses/code/skills/design/references/intake.md +11 -11
  152. package/data/harnesses/code/skills/design/references/object-pass.md +1 -1
  153. package/data/harnesses/code/skills/design/references/ship-gate.md +1 -1
  154. package/data/harnesses/code/skills/design/scripts/select-chart.mjs +14 -8
  155. package/data/harnesses/code/skills/design/scripts/validate-design-md.mjs +1 -1
  156. package/package.json +2 -2
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: number-ticker-roll
3
+ class: a6
4
+ sourced: 2026-07-12
5
+ source: "emilkowalski.skills/skills/animation-vocabulary/SKILL.md (Number ticker; Tabular numbers) + review-animations/STANDARDS.md (sub-300ms rule; interruptibility)"
6
+ license: open
7
+ feel: "digits rolling to the new value at ~250ms read like a live counter; an instant jump-cut reads like the number just glitched"
8
+ aliases: { glitched: "value changes with no roll/interpolation at all", "tabular-drift": "digits set without tabular figures, so the number visibly shifts width as it rolls", janky: "keyframe roll restarting from zero on each rapid update instead of retargeting" }
9
+ ---
10
+ Live counters, stat tiles, KPI cards, running totals — system-driven value changes, so the sub-300ms UI rule applies. Requires tabular figures so surrounding layout doesn't shift while digits roll. Rapid successive updates retarget the roll (transition, not keyframes), never restart from zero.
11
+
12
+ ```yaml values
13
+ duration: 250ms
14
+ easing: cubic-bezier(0.23, 1, 0.32, 1)
15
+ element-class: control
16
+ interruptible: required
17
+ budget: { control: 200-300ms }
18
+ ```
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: onboarding-bounce
3
+ class: a6
4
+ sourced: 2026-07-12
5
+ source: "emilkowalski.skills/skills/review-animations/STANDARDS.md (springs — bounce 0.1-0.3, reserved for playful moments) + improve-animations/AUDIT.md §1 (rare/first-time → delight)"
6
+ license: open
7
+ feel: "a springy overshoot on a first-run welcome card reads warm and considered; the same bounce on anything seen daily reads gimmicky"
8
+ aliases: { gimmicky: "spring bounce applied outside a rare/first-time identity moment — the same overshoot on a daily-use control", overdone: "bounce pushed above the 0.1-0.3 range into cartoonish territory" }
9
+ ---
10
+ Onboarding welcome screens, first-run tours — rare, high-emotion, seen once or a handful of times ever. The scoped exception where springy/physical vocabulary is admissible; it does not license bounce anywhere else.
11
+
12
+ ```yaml values
13
+ duration: 500ms (spring; no fixed duration)
14
+ easing: spring(bounce 0.3)
15
+ element-class: identity-moment
16
+ interruptible: n/a
17
+ budget: { identity-moment: 400-600ms }
18
+ ```
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: panel-slide
3
+ class: a6
4
+ sourced: 2026-07-12
5
+ source: "emilkowalski.skills/skills/review-animations/STANDARDS.md (--ease-drawer curve; duration table, modal/drawer row) + apple-design/SKILL.md §3 (interruption; velocity continuity)"
6
+ license: open
7
+ feel: "a 260ms slide on the iOS drawer curve reads native and grabbable; a keyframe slide that restarts on repeated taps reads broken"
8
+ aliases: { broken: "keyframes restarting from zero instead of a transition/spring retargeting mid-slide", floaty: "duration pushed past the panel budget" }
9
+ ---
10
+ Side panels, drawers, bottom sheets. Must be interruptible and carry velocity on a gesture-driven close — grabbing a closing panel should follow the pointer, not fight it.
11
+
12
+ ```yaml values
13
+ duration: 260ms
14
+ easing: cubic-bezier(0.32, 0.72, 0, 1)
15
+ element-class: panel
16
+ interruptible: required
17
+ budget: { panel: 200-500ms }
18
+ ```
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: press-feedback
3
+ class: a6
4
+ sourced: 2026-07-12
5
+ source: "emilkowalski.skills/skills/review-animations/STANDARDS.md (physicality — press feedback; duration table) + improve-animations/AUDIT.md §2-3"
6
+ license: open
7
+ feel: "160ms scale-to-0.97 on pointer-down reads tactile and instant; slower or absent reads dead under the finger"
8
+ aliases: { dead: "no press feedback at all, or duration pushed above the 160ms control budget", mushy: "an easing softer than ease-out, delaying the visible response" }
9
+ ---
10
+ Any pressable control — buttons, icon buttons, tap-target rows. The canon prescribes this on every pressable element while forbidding animation on keyboard-initiated actions: it fires on pointer-down only (a tap affordance, not a state transition), and keyboard activation (Enter/Space) never replays it.
11
+
12
+ ```yaml values
13
+ duration: 160ms
14
+ easing: cubic-bezier(0.23, 1, 0.32, 1)
15
+ element-class: control
16
+ interruptible: n/a
17
+ budget: { control: 100-160ms }
18
+ ```
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: progress-linear-loop
3
+ class: a6
4
+ sourced: 2026-07-12
5
+ source: "emilkowalski.skills/skills/review-animations/STANDARDS.md (easing decision order — constant motion → linear) + animation-vocabulary/SKILL.md (Loop; Marquee); Material's linear token agrees as secondary"
6
+ license: open
7
+ feel: "a constant linear sweep reads honest about an unknown wait; any easing that speeds up and slows down reads like a fake promise"
8
+ aliases: { "fake-promise": "eased (non-linear) motion on an indeterminate progress indicator, implying a completion point that doesn't exist", twitchy: "loop cycle faster than ~1s, reading anxious rather than calm" }
9
+ ---
10
+ Indeterminate progress bars, loading spinners, marquees. Constant-speed motion only — the one place `linear` is correct and `ease` curves are wrong.
11
+
12
+ ```yaml values
13
+ duration: 1200ms (loop)
14
+ easing: linear
15
+ element-class: control
16
+ interruptible: n/a
17
+ budget: { control: 1000-1500ms }
18
+ ```
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: route-crossfade
3
+ class: a6
4
+ sourced: 2026-07-12
5
+ source: "emilkowalski.skills/skills/animation-vocabulary/SKILL.md (Crossfade; Page transition) + review-animations/STANDARDS.md (sub-300ms rule; masking imperfect crossfades; easing decision order — opacity/color → ease)"
6
+ license: open
7
+ feel: "a single ~250ms crossfade between views reads like one continuous product; a staggered reveal of each panel on arrival reads like a slideshow"
8
+ aliases: { slideshow: "child elements staggering in individually on route arrival instead of one crossfade", "double-exposed": "old and new view both fully visible mid-transition — mask with a subtle blur (~2px, never above 20px)" }
9
+ ---
10
+ Navigating between routes or top-level views — a same-place opacity morph, not a spatial entrance, so `ease` rather than the entrance curve. One crossfade only; never an orchestrated sequence of the destination's own elements arriving one by one. A product loads into a task, not a reveal.
11
+
12
+ ```yaml values
13
+ duration: 250ms
14
+ easing: ease
15
+ element-class: page
16
+ interruptible: n/a
17
+ budget: { page: 200-300ms }
18
+ ```
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: rubber-band-overscroll
3
+ class: a6
4
+ sourced: 2026-07-12
5
+ source: "emilkowalski.skills/skills/animation-vocabulary/SKILL.md (Rubber-banding) + apple-design/SKILL.md §8 (boundary resistance) and spring cheat-sheet (critically-damped default)"
6
+ license: open
7
+ feel: "resistance that grows the further you pull, then a quick snap-back, reads alive and physical; a hard stop at the edge reads frozen"
8
+ aliases: { frozen: "a hard stop at the scroll boundary instead of progressive resistance", overshoot: "snap-back overshoots past the origin instead of settling cleanly" }
9
+ ---
10
+ Scrollable containers and pull-to-refresh regions at their boundary. Resistance increases continuously with drag distance past the edge; release animates back with a critically-damped spring, never a linear tween.
11
+
12
+ ```yaml values
13
+ duration: 300ms (snap-back)
14
+ easing: spring(damping increases near boundary)
15
+ element-class: page
16
+ interruptible: required
17
+ budget: { page: 200-400ms }
18
+ ```
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: skeleton-shimmer
3
+ class: a6
4
+ sourced: 2026-07-12
5
+ source: "emilkowalski.skills/skills/animation-vocabulary/SKILL.md (Skeleton/Shimmer) + review-animations/STANDARDS.md (easing decision order — constant motion → linear)"
6
+ license: open
7
+ feel: "a slow, continuous sheen reads like content is genuinely on its way; a fast or jittery shimmer reads anxious"
8
+ aliases: { anxious: "shimmer cycle faster than ~1s, reading twitchy instead of calm", stuck: "a static placeholder with no shimmer at all, giving no sense of progress" }
9
+ ---
10
+ Loading placeholders for cards, rows, and detail panes before content resolves. Runs as a continuous ambient loop, exempt from the sub-300ms UI budget (constant-motion class); swap to real content with a quick crossfade, not a hard cut.
11
+
12
+ ```yaml values
13
+ duration: 1400ms (loop)
14
+ easing: linear
15
+ element-class: list-item
16
+ interruptible: n/a
17
+ budget: { list-item: 1200-1600ms }
18
+ ```
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: stagger-arrive
3
+ class: a6
4
+ sourced: 2026-07-12
5
+ source: "emilkowalski.skills/skills/review-animations/STANDARDS.md (stagger — 30-80ms, decorative, never blocks interaction)"
6
+ license: open
7
+ feel: "a ~50ms cascade with a small upward drift reads considered; everything landing at once reads dumped, and gaps above 80ms read slow"
8
+ aliases: { dumped: "no stagger at all on a multi-item entrance", draggy: "per-item stagger delay above the 80ms budget" }
9
+ ---
10
+ List and grid entrances for freshly-loaded content within a task (search results, new rows) — never on initial page load or route arrival (no orchestrated load sequences). Purely decorative — must never delay the list becoming interactive; keep the per-item delay inside 30-80ms so a ten-row list finishes well under half a second.
11
+
12
+ ```yaml values
13
+ duration: 300ms
14
+ easing: cubic-bezier(0.23, 1, 0.32, 1)
15
+ element-class: list-item
16
+ interruptible: n/a
17
+ budget: { list-item: 250-350ms }
18
+ ```
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: toast-enter-stack
3
+ class: a6
4
+ sourced: 2026-07-12
5
+ source: "emilkowalski.skills/skills/review-animations/STANDARDS.md (interruptibility — toast transition example; cohesion — the Sonner register)"
6
+ license: open
7
+ feel: "a 400ms transition-based stack reads calm even when toasts pile up fast; a keyframe stack reads jumpy every time a new one lands"
8
+ aliases: { jumpy: "@keyframes restarting already-stacked toasts instead of one continuous transition retargeting them", jarring: "no @starting-style/mount fallback, so the first toast snaps in with no entrance" }
9
+ ---
10
+ Toast/notification stacks. A new arrival must not restart the position transition of toasts already stacked — everything reflows on one continuous transition, never per-toast keyframes.
11
+
12
+ ```yaml values
13
+ duration: 400ms
14
+ easing: ease
15
+ element-class: overlay
16
+ interruptible: required
17
+ budget: { overlay: 300-450ms }
18
+ ```
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: tooltip-chain-instant
3
+ class: a6
4
+ sourced: 2026-07-12
5
+ source: "emilkowalski.skills/skills/emil-design-eng/SKILL.md (tooltip-chaining example) + review-animations/STANDARDS.md (duration table, tooltip row; perceived performance)"
6
+ license: open
7
+ feel: "the first tooltip's 125ms fade-and-lift reads considered; every later tooltip in the same toolbar should read instant, with zero animation"
8
+ aliases: { "laggy-toolbar": "every tooltip in a group replaying the full delay+animation instead of chaining to instant after the first", floaty: "duration above the small-popover budget" }
9
+ ---
10
+ Tooltips, especially adjacent ones in a toolbar. First open: full delay + animation. While the pointer stays within the tooltip group, later tooltips switch to 0ms — this is the frequency law being satisfied, not an exception to it.
11
+
12
+ ```yaml values
13
+ duration: 125ms
14
+ easing: cubic-bezier(0.23, 1, 0.32, 1)
15
+ element-class: control
16
+ interruptible: n/a
17
+ budget: { control: 0-200ms }
18
+ ```
@@ -0,0 +1,18 @@
1
+ ---
2
+ id: trigger-anchored-reveal
3
+ class: a6
4
+ sourced: 2026-07-12
5
+ source: "emilkowalski.skills/skills/review-animations/STANDARDS.md (physicality — origin-aware popovers; duration table, dropdown row) + improve-animations/AUDIT.md §3"
6
+ license: open
7
+ feel: "growing out of the trigger at ~200ms reads anchored and native; center-scale or scale(0) reads like a random popup"
8
+ aliases: { disconnected: "transform-origin left at center instead of the trigger element", glitchy: "scale(0) start instead of scale(0.9-0.97) + opacity" }
9
+ ---
10
+ Popovers, dropdowns, select menus, tooltips. `transform-origin` follows the trigger (Radix/Base UI expose it as a CSS var); never centers. Rapid open/close/open must retarget, not restart.
11
+
12
+ ```yaml values
13
+ duration: 200ms
14
+ easing: cubic-bezier(0.23, 1, 0.32, 1)
15
+ element-class: overlay
16
+ interruptible: required
17
+ budget: { overlay: 150-250ms }
18
+ ```
@@ -0,0 +1,34 @@
1
+ id,tell,category,provenance,sourced,status
2
+ tell-001,"every shadow set to zero and every border the same 1px gray — structure without a single elevation decision",wireframe-smell,"design-skill 01 §E5; impeccable detector registry",2026-07-12,active
3
+ tell-002,"rounded-square icon tile stacked above the heading on every card — the universal generated feature-card template",template,"impeccable detector registry (icon-tile-stack)",2026-07-12,active
4
+ tell-003,"cards nested inside cards — double borders and stacked radii standing in for hierarchy",card-abuse,"impeccable detector registry (nested-cards); design-skill 01 §E5",2026-07-12,active
5
+ tell-004,"thick colored stripe down one edge of a card as the accent device",accent-abuse,"impeccable detector registry (side-tab); design-skill 01 §E5",2026-07-12,active
6
+ tell-005,"accent border wrapped around a rounded card — the stripe fighting the corner radius",accent-abuse,"impeccable detector registry (border-accent-on-rounded)",2026-07-12,active
7
+ tell-006,"hero-metric template — a row of identical stat tiles each icon + label + big number, with no comparison, trend, state, or door",template,"design-skill 01 §E5; b2b-ux-patterns dashboards chapter",2026-07-12,active
8
+ tell-007,"cream or warm-beige page surface reached by reflex as the tasteful default",palette,"impeccable detector registry (cream-palette); taste-skill §9.A; design-skill 01 §A2 anti-cream guardband",2026-07-12,active
9
+ tell-008,"ghost cards — bordered or shadowed containers wrapping a single short text run or nothing at all",card-abuse,"design-skill 01 §E5",2026-07-12,active
10
+ tell-009,"purple-violet gradients and cyan-on-dark as the default accent scheme",palette,"impeccable detector registry (ai-color-palette)",2026-07-12,active
11
+ tell-010,"dark theme expressed as colored box-shadow glows instead of a surface-lightness ladder",palette,"impeccable detector registry (dark-glow); design-skill 01 §A3 dark ladder",2026-07-12,active
12
+ tell-011,"gradient fills on heading or metric text",typography,"impeccable detector registry (gradient-text)",2026-07-12,active
13
+ tell-012,"flat type ramp — adjacent sizes too close together to carry hierarchy anywhere on the surface",typography,"impeccable detector registry (flat-type-hierarchy)",2026-07-12,active
14
+ tell-013,"one spacing value everywhere — no tight grouping of related controls, no generous seams between sections",layout,"impeccable detector registry (monotonous-spacing)",2026-07-12,active
15
+ tell-014,"hairline border and a wide diffuse shadow on the same container — two elevation systems at once",elevation,"impeccable detector registry (generated-UI signature set)",2026-07-12,active
16
+ tell-015,"decorative two-axis hairline grid background behind a surface that is not a canvas, map, or measurement view",template,"impeccable detector registry (generated-UI signature set)",2026-07-12,active
17
+ tell-016,"numbered section markers (01 / 02 / 03) as structural scaffolding",template,"impeccable detector registry (numbered-section-markers); taste-skill §9.F",2026-07-12,active
18
+ tell-017,"tiny uppercase letter-spaced kicker label repeated above every section heading",template,"impeccable detector registry (repeated-section-kickers)",2026-07-12,active
19
+ tell-018,"colored status dots decorating every nav item, row, or badge with no real state behind them",chrome,"taste-skill §9.F production-observed tells",2026-07-12,active
20
+ tell-019,"middle-dot chains as the default separator for every metadata strip",chrome,"taste-skill §9.F production-observed tells",2026-07-12,active
21
+ tell-020,"top and bottom hairline borders on every row of a long table or spec list",wireframe-smell,"taste-skill §9.F production-observed tells",2026-07-12,active
22
+ tell-021,"fake build or version strings as decoration where no real build data exists",demo-content,"taste-skill §9.F production-observed tells",2026-07-12,active
23
+ tell-022,"placeholder-generic person names in demo data (the John Doe class)",demo-content,"taste-skill §9.D (Jane Doe effect); design-skill 01 §E5",2026-07-12,active
24
+ tell-023,"the same gray egg or user-icon avatar on every person row",demo-content,"taste-skill §9.D production-observed tells",2026-07-12,active
25
+ tell-024,"fake-perfect numbers — round percentages, sequential IDs, totals that reconcile too neatly",demo-content,"taste-skill §9.D; design-skill 01 §E5",2026-07-12,active
26
+ tell-025,"startup-slop company names in demo data (the Acme / Nexus / Cloudly class)",demo-content,"taste-skill §9.D production-observed tells",2026-07-12,active
27
+ tell-026,"marketing buzzwords in interface copy (streamline, empower, supercharge, enterprise-grade)",copy,"impeccable detector registry (marketing-buzzword); taste-skill §9.D",2026-07-12,active
28
+ tell-027,"em-dash-heavy microcopy — the character recurring across labels, empty states, and tooltips",copy,"taste-skill §9.G; impeccable detector registry (em-dash-overuse)",2026-07-12,active
29
+ tell-028,"transition: all on interactive elements",motion,"design-skill 02 ship-gate Tier-2 motion tells",2026-07-12,active
30
+ tell-029,"ease-in easing on an entrance",motion,"design-skill 02 ship-gate Tier-2 motion tells; emilkowalski motion canon",2026-07-12,active
31
+ tell-030,"animation attached to a keyboard-triggered action",motion,"design-skill 02 ship-gate Tier-2 motion tells; emilkowalski frequency law",2026-07-12,active
32
+ tell-031,"bounce or elastic easing on product chrome",motion,"impeccable detector registry (bounce-easing)",2026-07-12,active
33
+ tell-032,"width, height, padding, or margin animated instead of transform and opacity",motion,"impeccable detector registry (layout-transition)",2026-07-12,active
34
+ tell-033,"orchestrated staggered entrance choreography on a work surface — a product loads into a task",motion,"design-skill 01 §A6 admission criteria; emilkowalski motion canon",2026-07-12,active
@@ -0,0 +1,29 @@
1
+ ---
2
+ id: bright-collaborator
3
+ class: c2
4
+ sourced: 2026-07-12
5
+ source: "Distilled from Slack's voice & tone guidance (api.slack.com/best-practices/voice-and-tone) — confident not cocky, witty not silly, clear-concise-human, tone as seasoning not the dish."
6
+ license: open
7
+ ---
8
+ # Voice: bright-collaborator
9
+
10
+ **Feel:** Confident and a little playful, but the point always lands first.
11
+
12
+ Conversational rhythm — short sentences mixed with one longer one for cadence, contractions standard, second person throughout. Personality is seasoning: light wit is reserved for confirmations and empty states, never for errors. Actions open with a verb. Numbers are digits. One idea per sentence — never two clauses competing for attention.
13
+
14
+ ## Tone map
15
+
16
+ Voice is constant; tone dials by situation.
17
+
18
+ - **routine action:** verb-first with a light conversational lift
19
+ - **error:** personality drops out entirely — plain statement, then the fix
20
+ - **success:** wit is allowed, one line, never stacked
21
+ - **destructive confirmation:** playfulness fully off, states the stakes plainly
22
+
23
+ ## Examples
24
+
25
+ - **button:** "Invite teammate"
26
+ - **empty state (heading + motivation):** "Quiet in here" / "Invite a teammate and this space starts filling up."
27
+ - **error:** "That invite didn't go through. Check the email and send it again."
28
+ - **tooltip:** "Only workspace admins can see this."
29
+ - **confirmation:** "Teammate invited — welcome aboard."
@@ -0,0 +1,29 @@
1
+ ---
2
+ id: direct-operator
3
+ class: c2
4
+ sourced: 2026-07-12
5
+ source: "Distilled from Atlassian's 'bold, optimistic, practical' brevity mandate (atlassian.design/content/voice-and-tone-principles) and Material Design's clarity-to-anyone standard (m3.material.io/foundations/content-design)."
6
+ license: open
7
+ ---
8
+ # Voice: direct-operator
9
+
10
+ **Feel:** Brisk and task-first — reads like a command line, not a conversation.
11
+
12
+ Imperative mood by default; sentence fragments are acceptable where a full sentence adds nothing ("Upload failed. Retry."). No adjectives unless load-bearing. Numerals are always digits, units abbreviated once established. No exclamation points, no rhetorical questions, no throat-clearing openers ("Please note that…"). Density over politeness — every word has to justify its presence.
13
+
14
+ ## Tone map
15
+
16
+ Voice is constant; tone dials by situation.
17
+
18
+ - **routine action:** imperative, fragments allowed
19
+ - **error:** states failure plus count or reason, no softening
20
+ - **success:** single clipped phrase, no embellishment
21
+ - **destructive confirmation:** same flat register as everything else — no added urgency language, the plainness is the safeguard
22
+
23
+ ## Examples
24
+
25
+ - **button:** "Create workspace"
26
+ - **empty state (heading + motivation):** "No records" / "Import a file or add one manually to begin."
27
+ - **error:** "Save failed. 3 fields are invalid."
28
+ - **tooltip:** "Locks the row for editing by others."
29
+ - **confirmation:** "Workspace created."
@@ -0,0 +1,29 @@
1
+ ---
2
+ id: earnest-helper
3
+ class: c2
4
+ sourced: 2026-07-12
5
+ source: "Distilled from Intercom's PREACH framework (intercom.com/blog/preach-framework-for-customer-support-tone) — Proud, Responsible, Empathetic, Articulate, Concise, Human."
6
+ license: open
7
+ ---
8
+ # Voice: earnest-helper
9
+
10
+ **Feel:** Owns the failure, states the fix, never grovels.
11
+
12
+ First-person-plural ownership when the product is at fault ("we couldn't…"), second person when guiding the user's next step. Sentences are short and declarative; empathy is shown through precision and a clear next step rather than apology words ("sorry," "oops" are avoided). No exclamation points, even on success — confidence doesn't need punctuation. Numbers are digits throughout.
13
+
14
+ ## Tone map
15
+
16
+ Voice is constant; tone dials by situation.
17
+
18
+ - **routine action:** second person, concise, no flourish
19
+ - **error:** first-person-plural ownership ("we couldn't…"), immediate next step
20
+ - **success:** short, no exclamation, confidence without decoration
21
+ - **destructive confirmation:** states irreversibility explicitly, still no apology language
22
+
23
+ ## Examples
24
+
25
+ - **button:** "Submit request"
26
+ - **empty state (heading + motivation):** "No requests yet" / "Submit one and track its progress here."
27
+ - **error:** "We couldn't submit that request. Reconnect and try again."
28
+ - **tooltip:** "Requests are visible to your whole team once submitted."
29
+ - **confirmation:** "Request submitted."
@@ -0,0 +1,29 @@
1
+ ---
2
+ id: editorial-composed
3
+ class: c2
4
+ sourced: 2026-07-12
5
+ source: "Distilled from Material Design's AP-style clarity standard (m3.material.io/foundations/content-design/style-guide/ux-writing-best-practices) and Atlassian's 'practical, with a wink' brand register (atlassian.design/content/writing-style), slowed to an editorial cadence."
6
+ license: open
7
+ ---
8
+ # Voice: editorial-composed
9
+
10
+ **Feel:** Measured and literate — composed sentences, unhurried but exact.
11
+
12
+ Longer, fully-formed sentences that favor a subordinate clause over a fragment; still one idea per sentence, but the idea is given room. Verbs remain the engine of the sentence rather than being buried under nominalizations. Numbers under ten are spelled out even in most UI text; digits are reserved for data-dense contexts (tables, counters, timestamps). Restraint reads as taste, not coldness — warmth comes from word choice, never from exclamation.
13
+
14
+ ## Tone map
15
+
16
+ Voice is constant; tone dials by situation.
17
+
18
+ - **routine action:** a fuller sentence, still verb-led
19
+ - **error:** composed, no blame, the fix named in a complete sentence
20
+ - **success:** a complete, satisfying sentence rather than a clipped label
21
+ - **destructive confirmation:** the most fully-formed of the four — consequence and reversibility spelled out in full
22
+
23
+ ## Examples
24
+
25
+ - **button:** "Add collection"
26
+ - **empty state (heading + motivation):** "Nothing archived yet" / "Items you archive will be kept here, in order, for as long as you need them."
27
+ - **error:** "The collection couldn't be saved. Review the highlighted fields and try again."
28
+ - **tooltip:** "Determines the order collections appear in for every viewer."
29
+ - **confirmation:** "Collection added and ready to share."
@@ -0,0 +1,29 @@
1
+ ---
2
+ id: quiet-concierge
3
+ class: c2
4
+ sourced: 2026-07-12
5
+ source: "Distilled from Shopify Polaris content fundamentals (polaris-react.shopify.com — verb-first directness, plain language, 'remove until it breaks') and Atlassian voice & tone (atlassian.design — say it once, then get out of the way)."
6
+ license: open
7
+ ---
8
+ # Voice: quiet-concierge
9
+
10
+ **Feel:** Understated and precise — says the necessary thing once, then steps back.
11
+
12
+ Short-to-medium declarative sentences, verb-first for any instruction ("Add," "Move," "Archive"). Warmth comes from precision, not adjectives — no exclamation points, no stacked modifiers, no filler words ("just," "simply," "easily"). Numbers render as digits even under ten, to keep the eye moving. Contractions are allowed ("it's," "can't") to keep the register human. If a sentence can be cut without losing meaning, cut it.
13
+
14
+ ## Tone map
15
+
16
+ Voice is constant; tone dials by situation.
17
+
18
+ - **routine action:** plain, verb-first, no ornament
19
+ - **error:** flat statement of what happened, then the fix — no apology
20
+ - **success:** states the fact and stops there
21
+ - **destructive confirmation:** names exactly what's lost, in the same even register — precision is the only warning
22
+
23
+ ## Examples
24
+
25
+ - **button:** "Add customer"
26
+ - **empty state (heading + motivation):** "No reports yet" / "Reports appear here once your first one is generated."
27
+ - **error:** "The file didn't upload. Check your connection and try again."
28
+ - **tooltip:** "Archives the record without deleting its history."
29
+ - **confirmation:** "Customer added."
@@ -0,0 +1,29 @@
1
+ ---
2
+ id: warm-guide
3
+ class: c2
4
+ sourced: 2026-07-12
5
+ source: "Distilled from the Mailchimp Content Style Guide (styleguide.mailchimp.com) — voice & tone, writing principles, web elements, and grammar & mechanics pages: plainspoken warmth, dry humor, active voice, treats users as capable partners. Mailchimp's style guide content is published under a Creative Commons Attribution-NonCommercial 4.0 International License (CC BY-NC 4.0); reworded and distilled throughout, no verbatim reuse."
6
+ license: licensed
7
+ ---
8
+ # Voice: warm-guide
9
+
10
+ **Feel:** Plainspoken and warm — talks to you like a colleague who respects your time.
11
+
12
+ Medium sentences in active voice, contractions throughout. One dry aside is permitted per surface, never forced. Numbers under ten are spelled out in body copy, digits in dense UI (tables, counters). Confidence over cheerleading — no "Great job!"; encouragement is implied by clarity, not stated outright. The register never talks down to the reader.
13
+
14
+ ## Tone map
15
+
16
+ Voice is constant; tone dials by situation.
17
+
18
+ - **routine action:** relaxed, active voice, one idea per sentence
19
+ - **error:** takes ownership ("we couldn't…"), calm next step, no exclamation
20
+ - **success:** quietly confident, still no exclamation
21
+ - **destructive confirmation:** slows down a beat, spells out what's being removed and that it can't be undone
22
+
23
+ ## Examples
24
+
25
+ - **button:** "Send invoice"
26
+ - **empty state (heading + motivation):** "Nothing here yet" / "Once you add a project, it'll show up in this list."
27
+ - **error:** "We couldn't send that invoice. Check the email address and try again."
28
+ - **tooltip:** "Sends a copy to your own inbox too."
29
+ - **confirmation:** "Invoice sent."
@@ -6,20 +6,16 @@ Build the app — all surfaces in one continuous context, the chosen package's d
6
6
 
7
7
  Per the primitives switch recorded in the project's `design.md`:
8
8
 
9
- - **`nurix`** — compose chrome from `@nurix/components`. The chrome recipes (`get_entry`, kind `chrome` — fetch only the recipes for surfaces in the structure doc) carry composition, states, and when-to-use; the component reference folder (`components/`) carries props, imports, and usage — consult the index for what exists, and open the touched category's API reference on need.
9
+ - **`nurix`** — compose chrome from `@nurix/components`. The chrome recipes (`data/chrome/` — read only the recipes for surfaces in the structure doc) carry composition, states, and when-to-use; the component dictionary (`components/`) carries props, imports, and usage across both provenances — consult the index for what exists, and open the touched category's API reference on need.
10
10
  - **`native`** — the recipes are *specifications*: anatomy, the eight states, keyboard behavior, token reach — implement them with the incumbent stack's own components. The index's shadcn/fallback columns carry the composition; category API references never load.
11
11
 
12
12
  Recipes are starting points, not jails: restyle or extend them in place when the package demands it.
13
13
 
14
- ## The consult, at your discretion
15
-
16
- The composition consult is available here — a whole-app paragraph in, candidate shapes + a component list + rulings out. It is advisory, never binding: you compose. The judgment rule for *when* lives in the router (SKILL.md § The coupled server); the short form: consult on a real knowledge gap or a rework signal, stay local when the canvas is the answer, and `record` every consult and every deviation from its advice. Unavailable is normal — compose locally, record it, continue.
17
-
18
14
  ## Composition rules
19
15
 
20
- - **Every surface starts from a chosen layout blueprint** — `get_entry` the chosen archetype's blueprint (kind `blueprint`); pick the shape reading the brief, record it in one line. Structural variety, not visual variety, is what reads as designed.
16
+ - **Every surface starts from a chosen layout blueprint** (`data/blueprints/<archetype>.md`) — pick the shape reading the brief, record it in one line. Structural variety, not visual variety, is what reads as designed.
21
17
  - **Values come from the token artifact** — components consume the emitted custom properties and never invent raw values ([emission.md](emission.md) has the pipe rules). Switching packages must re-skin the whole app.
22
- - **Positive obligations apply** — `get_entry` the surface's archetype checklist (kind `checklist`); the checklists are ceilings: a sidebar ships with brand block, icons, and user context; a dashboard tile ships with number + comparison + trend + state + door; every surface ships its state matrix.
18
+ - **Positive obligations apply** — load the surface's archetype checklist (`data/checklists/<archetype>.md`); the checklists are ceilings: a sidebar ships with brand block, icons, and user context; a dashboard tile ships with number + comparison + trend + state + door; every surface ships its state matrix.
23
19
  - **The register scope holds**: the display face never touches cells, buttons, labels, or form chrome; data numerals run the mono face with `tabular-nums`.
24
20
  - **Motion follows the package's §7** and the frequency law: actions performed 100+ times a day, and any keyboard-initiated action, get no animation, ever; panel/drawer motion is interruptible; entrances never `ease-in`.
25
21
  - **No ownership jails.** Any file may be edited at any time, including generated ones and library compositions.
@@ -4,7 +4,7 @@ Author the demo data **before composing surfaces**. Data credibility is the sing
4
4
 
5
5
  ## From the corpus
6
6
 
7
- Fetch the chosen domain's corpus — `search_catalog` (kind `corpus`) to find it, `get_entry` to load it: the body (vocabulary, number-shape recipes, the invariants block) arrives with its `people` and `companies` rosters in one payload.
7
+ Fetch the chosen domain's corpus — `search_catalog` (family `corpus`) to find it, `get_entry` to load it: the body (vocabulary, number-shape recipes, the invariants block) arrives with its `people` and `companies` rosters in one payload.
8
8
 
9
9
  - Names come from the corpus roster; emails derive from names; roles are domain-correct.
10
10
  - Activity strings use the corpus vocabulary — a CRM logs "Intro call with Elena — pricing discussion", never webhook noise.
@@ -14,13 +14,13 @@ Fetch the chosen domain's corpus — `search_catalog` (kind `corpus`) to find it
14
14
 
15
15
  ## Voice
16
16
 
17
- Fetch the package-bound voice pack — `get_entry` the voice the package's §9 names. All authored strings — buttons, empty states, errors, tooltips, confirmations — speak in that voice, with tone varying by situation per the pack's tone map.
17
+ Load the package-bound voice pack (`data/voices/<id>.md` — the package's §9 names it). All authored strings — buttons, empty states, errors, tooltips, confirmations — speak in that voice, with tone varying by situation per the pack's tone map.
18
18
 
19
19
  ## Chart choice
20
20
 
21
- Every data-bearing surface consults the chart-selection engine — **one graph question per consult**. The census rows the engine evaluates are fetched **once per session** via `get_entry("chart-census")`:
21
+ Every data-bearing surface consults the chart-selection engine — **one graph question per consult**. The census ships beside the engine; nothing is fetched:
22
22
 
23
- 1. Author the data signature (the judgment half): the question, measures, dimensions, semantic flags (temporal, parts-form-whole, target-exists, …), constraints — plus the session's `census` rows. Decompose multi-question asks first.
23
+ 1. Author the data signature (the judgment half): the question, measures, dimensions, semantic flags (temporal, parts-form-whole, target-exists, …), constraints. Decompose multi-question asks first.
24
24
  2. Run `node scripts/select-chart.mjs <signature.json>` and read the typed output: admissible set, eliminations with reason codes, ranking, recommendation, or a refusal code.
25
25
  3. **Honor refusals** — a refusal means the question isn't chartable as posed (often: it's a table). Never invent a measure to force a chart.
26
26
  4. `record` the pick in one line. Taking a non-recommended admissible option needs a reason on that line; taking an eliminated option is out of contract.
@@ -4,7 +4,7 @@ The same machinery runs on existing UIs, under a preservation contract.
4
4
 
5
5
  ## Judge — a user-invoked service
6
6
 
7
- A critique of an existing UI against the brief, the project's `design.md`, the archetype checklists, and the project's taste profile (`get_project`), producing a **severity-ranked (never scored) report**. Judge is a service the user asks for — never a self-check the skill runs on its own output. Read the actual rendered state (screenshots the user provides, or captures the user asks for); refuse to critique from source alone when the ask is "does it look right", and never imagine what unrendered code looks like. Each finding: severity, the on-screen element, what's wrong, the exact fix.
7
+ A critique of an existing UI against the brief, the project's `design.md`, the archetype checklists, and the workspace's taste profile (`get_preferences`), producing a **severity-ranked (never scored) report**. Judge is a service the user asks for — never a self-check the skill runs on its own output. Read the actual rendered state (screenshots the user provides, or captures the user asks for); refuse to critique from source alone when the ask is "does it look right", and never imagine what unrendered code looks like. Each finding: severity, the on-screen element, what's wrong, the exact fix.
8
8
 
9
9
  ## Improve — judge + the fix pass
10
10
 
@@ -0,0 +1,57 @@
1
+ # Foundations — the brief fixed doctrine
2
+
3
+ Cross-cutting decisions every build makes once, stated at the length they deserve and no longer (the obviousness rule: what competent intelligence already knows gets nothing). Load the touched entry at the step that decides it, never the file whole.
4
+
5
+ ## The five status palettes
6
+
7
+ Pick **one** per project at intake and hold it everywhere — status colors are semantics, not decoration, and deltas color by *meaning* (down is green when down is good):
8
+
9
+ | Palette | success | warning | danger | info | neutral | Feel |
10
+ | --- | --- | --- | --- | --- | --- | --- |
11
+ | `signal` | `oklch(0.64 0.15 150)` | `oklch(0.75 0.15 80)` | `oklch(0.58 0.20 25)` | `oklch(0.60 0.14 250)` | `oklch(0.65 0.02 260)` | the default — clear, saturated, unmistakable |
12
+ | `muted-pro` | `oklch(0.60 0.09 155)` | `oklch(0.68 0.10 75)` | `oklch(0.55 0.13 25)` | `oklch(0.58 0.08 250)` | `oklch(0.62 0.015 260)` | desaturated for dense dashboards — readable without shouting |
13
+ | `warm-ledger` | `oklch(0.62 0.11 140)` | `oklch(0.70 0.13 60)` | `oklch(0.56 0.17 30)` | `oklch(0.60 0.10 230)` | `oklch(0.64 0.02 80)` | warm-neutral products (finance, ops review) |
14
+ | `cool-console` | `oklch(0.66 0.12 165)` | `oklch(0.74 0.12 85)` | `oklch(0.60 0.18 15)` | `oklch(0.62 0.12 265)` | `oklch(0.66 0.02 250)` | cool/dark consoles — holds up on deep backgrounds |
15
+ | `high-contrast` | `oklch(0.55 0.17 150)` | `oklch(0.60 0.16 70)` | `oklch(0.50 0.21 27)` | `oklch(0.50 0.16 255)` | `oklch(0.50 0.02 260)` | accessibility-first; every value ≥4.5:1 on white |
16
+
17
+ Each value is the light-theme anchor; derive the dark-theme sibling by raising lightness ~0.08 and trimming chroma ~0.02. Severity ladders (P0–P3 and kin) map onto danger → warning → info → neutral, never onto new hues.
18
+
19
+ ## Data-viz palettes
20
+
21
+ No database — three constraints, values yours: **categorical** series need distinguishable hues that survive colorblind simulation (rotate hue ≥40° apart, vary lightness too, ≤8 series then facet); **sequential** ramps run light→dark in one hue for magnitude; **diverging** ramps put two hues around a *meaningful* zero, neutral at the middle. Validate every ramp in both themes; charts consume package tokens, never raw hex.
22
+
23
+ ## Number, date, unit formatting
24
+
25
+ Tabular figures in tables and KPIs; thousands separators; unit or currency attached to the number; consistent decimals per column; large values truncate meaningfully (`1.2M`, never `1,200,000` in a tile); timestamps show relative when recent and absolute on hover; timezones explicit anywhere ambiguity costs money.
26
+
27
+ ## Spacing & density
28
+
29
+ The 2/4/6/8 scale, period. Operator surfaces default **compact** (data rows 32–36px) with a comfortable mode only when `product.md` says reading, not scanning. Density is a per-project decision made once, not a per-surface mood.
30
+
31
+ ## Radius & stroke
32
+
33
+ Radius is identity — sharp (0–2px), soft (4–6px), or round (10px+) — chosen by the package and applied consistently; mixing radii on one surface reads as templated. One border weight per surface; elevation *or* borders separate layers, never both at full strength.
34
+
35
+ ## Loading, skeleton, progress
36
+
37
+ Skeletons for layout-known loads, spinners only for unknowable ones, optimistic updates for high-frequency mutations with undo. Skeletons mirror the real layout's bones (no generic gray blocks). Nothing pulses faster than 1.2s.
38
+
39
+ ## Empty states
40
+
41
+ The three empties (first-use, no-results, cleared-filter) each say what happened and what to do next, in the project voice. Art direction follows the package's restraint: an icon or nothing for dense tools; illustration only where the package's feel says warm. Never a bare "No data".
42
+
43
+ ## Keyboard
44
+
45
+ The operator vocabulary: `⌘K` command palette, `j/k` traversal where lists dominate, `esc` closes the topmost layer only, `enter` commits, focus visible always. Declare shortcuts in a discoverable surface (palette footer or `?` overlay).
46
+
47
+ ## Dark mode physics
48
+
49
+ Elevation becomes lightness (surfaces lighten as they rise — shadows barely read); desaturate fills ~15%; never pure black (`oklch(0.13–0.18 …)` floors); borders drop to low-alpha white; charts re-derive from dark-theme tokens, never inherit light values.
50
+
51
+ ## Code, log, terminal surfaces
52
+
53
+ Mono face with `tabular-nums`; a shiki theme paired to the package (dark identity → dark code surface even in light theme is legitimate); log levels use the status palette; wrap off by default with horizontal scroll.
54
+
55
+ ## Polish
56
+
57
+ Focus rings on-brand (2px, offset, the accent — never browser default blue on a styled app); selection color derived from the accent at low alpha; scrollbars styled thin on dense panes; cursor changes only where affordance is real.