@nurix/etna 0.18.20 → 0.18.22
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.
- package/README.md +1 -1
- package/data/harness-index.json +1 -1
- package/data/harnesses/code/CLAUDE.md +3 -3
- package/data/harnesses/code/agents/brainstorm.md +1 -1
- package/data/harnesses/code/agents/maintenance.md +8 -7
- package/data/harnesses/code/harness.json +2 -2
- package/data/harnesses/code/rules/database.md +38 -0
- package/data/harnesses/code/rules/express.md +28 -0
- package/data/harnesses/code/rules/frontend.md +14 -0
- package/data/harnesses/code/rules/general.md +2 -40
- package/data/harnesses/code/rules/nomenclature.md +1 -8
- package/data/harnesses/code/rules/nustack.md +150 -0
- package/data/harnesses/code/skills/brainstorm/README.md +4 -4
- package/data/harnesses/code/skills/brainstorm/SKILL.md +5 -3
- package/data/harnesses/code/skills/brainstorm/exit-artifacts.md +15 -11
- package/data/harnesses/code/skills/brainstorm/templates/source-of-truth.md +5 -5
- package/data/harnesses/code/skills/design/SKILL.md +14 -11
- package/data/harnesses/code/skills/design/data/catalog/rules.csv +4 -4
- package/data/harnesses/code/skills/design/data/combinations/Readme.md +29 -0
- package/data/harnesses/code/skills/design/data/combinations/charts.csv +33 -0
- package/data/harnesses/code/skills/design/data/combinations/fonts-known.json +437 -0
- package/data/harnesses/code/skills/design/data/combinations/icons.csv +157 -0
- package/data/harnesses/code/skills/design/data/combinations/landing.csv +38 -0
- package/data/harnesses/code/skills/design/data/combinations/lucide-names.json +2001 -0
- package/data/harnesses/code/skills/design/data/combinations/manifest.json +283 -0
- package/data/harnesses/code/skills/design/data/combinations/palettes.csv +49 -0
- package/data/harnesses/code/skills/design/data/combinations/product-router.csv +80 -0
- package/data/harnesses/code/skills/design/data/combinations/styles.csv +54 -0
- package/data/harnesses/code/skills/design/data/combinations/typography.csv +61 -0
- package/data/harnesses/code/skills/design/data/design-md/SCHEMA.md +27 -238
- package/data/harnesses/code/skills/design/data/design-md/library/airbnb.md +7 -88
- package/data/harnesses/code/skills/design/data/design-md/library/airtable.md +1 -82
- package/data/harnesses/code/skills/design/data/design-md/library/anthropic-claude.md +4 -85
- package/data/harnesses/code/skills/design/data/design-md/library/apple.md +5 -86
- package/data/harnesses/code/skills/design/data/design-md/library/binance.md +4 -87
- package/data/harnesses/code/skills/design/data/design-md/library/bmw.md +7 -86
- package/data/harnesses/code/skills/design/data/design-md/library/cal.md +4 -84
- package/data/harnesses/code/skills/design/data/design-md/library/clay.md +5 -86
- package/data/harnesses/code/skills/design/data/design-md/library/clickhouse.md +3 -84
- package/data/harnesses/code/skills/design/data/design-md/library/cohere.md +2 -82
- package/data/harnesses/code/skills/design/data/design-md/library/coinbase.md +10 -91
- package/data/harnesses/code/skills/design/data/design-md/library/composio.md +2 -84
- package/data/harnesses/code/skills/design/data/design-md/library/cursor.md +3 -85
- package/data/harnesses/code/skills/design/data/design-md/library/elevenlabs.md +7 -90
- package/data/harnesses/code/skills/design/data/design-md/library/expo.md +0 -80
- package/data/harnesses/code/skills/design/data/design-md/library/figma.md +0 -80
- package/data/harnesses/code/skills/design/data/design-md/library/framer.md +5 -85
- package/data/harnesses/code/skills/design/data/design-md/library/hashicorp.md +2 -82
- package/data/harnesses/code/skills/design/data/design-md/library/ibm.md +5 -86
- package/data/harnesses/code/skills/design/data/design-md/library/intercom.md +9 -91
- package/data/harnesses/code/skills/design/data/design-md/library/kraken.md +9 -89
- package/data/harnesses/code/skills/design/data/design-md/library/linear-app.md +0 -115
- package/data/harnesses/code/skills/design/data/design-md/library/lovable.md +5 -85
- package/data/harnesses/code/skills/design/data/design-md/library/meta.md +7 -88
- package/data/harnesses/code/skills/design/data/design-md/library/minimax.md +3 -84
- package/data/harnesses/code/skills/design/data/design-md/library/mintlify.md +4 -85
- package/data/harnesses/code/skills/design/data/design-md/library/miro.md +8 -88
- package/data/harnesses/code/skills/design/data/design-md/library/mistral-ai.md +8 -88
- package/data/harnesses/code/skills/design/data/design-md/library/mongodb.md +4 -85
- package/data/harnesses/code/skills/design/data/design-md/library/notion.md +4 -84
- package/data/harnesses/code/skills/design/data/design-md/library/nvidia.md +7 -88
- package/data/harnesses/code/skills/design/data/design-md/library/ollama.md +5 -86
- package/data/harnesses/code/skills/design/data/design-md/library/opencode-ai.md +6 -87
- package/data/harnesses/code/skills/design/data/design-md/library/posthog.md +9 -91
- package/data/harnesses/code/skills/design/data/design-md/library/raycast.md +5 -88
- package/data/harnesses/code/skills/design/data/design-md/library/replicate.md +9 -89
- package/data/harnesses/code/skills/design/data/design-md/library/resend.md +4 -119
- package/data/harnesses/code/skills/design/data/design-md/library/revolut.md +4 -84
- package/data/harnesses/code/skills/design/data/design-md/library/runwayml.md +0 -82
- package/data/harnesses/code/skills/design/data/design-md/library/sanity.md +3 -86
- package/data/harnesses/code/skills/design/data/design-md/library/sentry.md +13 -94
- package/data/harnesses/code/skills/design/data/design-md/library/shopify.md +2 -82
- package/data/harnesses/code/skills/design/data/design-md/library/slack.md +6 -88
- package/data/harnesses/code/skills/design/data/design-md/library/spacex.md +13 -94
- package/data/harnesses/code/skills/design/data/design-md/library/spotify.md +4 -86
- package/data/harnesses/code/skills/design/data/design-md/library/stripe.md +7 -88
- package/data/harnesses/code/skills/design/data/design-md/library/supabase.md +6 -88
- package/data/harnesses/code/skills/design/data/design-md/library/superhuman.md +5 -86
- package/data/harnesses/code/skills/design/data/design-md/library/tesla.md +6 -86
- package/data/harnesses/code/skills/design/data/design-md/library/theverge.md +12 -93
- package/data/harnesses/code/skills/design/data/design-md/library/together-ai.md +11 -91
- package/data/harnesses/code/skills/design/data/design-md/library/uber.md +8 -88
- package/data/harnesses/code/skills/design/data/design-md/library/vercel.md +2 -82
- package/data/harnesses/code/skills/design/data/design-md/library/voltagent.md +11 -126
- package/data/harnesses/code/skills/design/data/design-md/library/warp.md +8 -88
- package/data/harnesses/code/skills/design/data/design-md/library/webflow.md +3 -83
- package/data/harnesses/code/skills/design/data/design-md/library/wired.md +10 -91
- package/data/harnesses/code/skills/design/data/design-md/library/wise.md +7 -90
- package/data/harnesses/code/skills/design/data/design-md/library/x-ai.md +6 -88
- package/data/harnesses/code/skills/design/data/design-md/library/zapier.md +9 -89
- package/data/harnesses/code/skills/design/data/design-md/nurix.md +4 -87
- package/data/harnesses/code/skills/design/data/design-tokens/SCHEMA.md +580 -0
- package/data/harnesses/code/skills/design/data/design-tokens/airbnb/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/airbnb/design.tokens.json +964 -0
- package/data/harnesses/code/skills/design/data/design-tokens/airtable/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/airtable/design.tokens.json +960 -0
- package/data/harnesses/code/skills/design/data/design-tokens/anthropic-claude/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/anthropic-claude/design.tokens.json +965 -0
- package/data/harnesses/code/skills/design/data/design-tokens/apple/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/apple/design.tokens.json +954 -0
- package/data/harnesses/code/skills/design/data/design-tokens/binance/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/binance/design.tokens.json +949 -0
- package/data/harnesses/code/skills/design/data/design-tokens/bmw/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/bmw/design.tokens.json +962 -0
- package/data/harnesses/code/skills/design/data/design-tokens/cal/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/cal/design.tokens.json +958 -0
- package/data/harnesses/code/skills/design/data/design-tokens/clay/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/clay/design.tokens.json +953 -0
- package/data/harnesses/code/skills/design/data/design-tokens/clickhouse/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/clickhouse/design.tokens.json +960 -0
- package/data/harnesses/code/skills/design/data/design-tokens/cohere/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/cohere/design.tokens.json +973 -0
- package/data/harnesses/code/skills/design/data/design-tokens/coinbase/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/coinbase/design.tokens.json +954 -0
- package/data/harnesses/code/skills/design/data/design-tokens/composio/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/composio/design.tokens.json +963 -0
- package/data/harnesses/code/skills/design/data/design-tokens/cursor/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/cursor/design.tokens.json +968 -0
- package/data/harnesses/code/skills/design/data/design-tokens/elevenlabs/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/elevenlabs/design.tokens.json +981 -0
- package/data/harnesses/code/skills/design/data/design-tokens/expo/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/expo/design.tokens.json +962 -0
- package/data/harnesses/code/skills/design/data/design-tokens/figma/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/figma/design.tokens.json +964 -0
- package/data/harnesses/code/skills/design/data/design-tokens/framer/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/framer/design.tokens.json +959 -0
- package/data/harnesses/code/skills/design/data/design-tokens/goldens.json +251 -0
- package/data/harnesses/code/skills/design/data/design-tokens/hashicorp/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/hashicorp/design.tokens.json +965 -0
- package/data/harnesses/code/skills/design/data/design-tokens/ibm/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/ibm/design.tokens.json +978 -0
- package/data/harnesses/code/skills/design/data/design-tokens/intercom/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/intercom/design.tokens.json +982 -0
- package/data/harnesses/code/skills/design/data/design-tokens/kraken/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/kraken/design.tokens.json +958 -0
- package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.resolver.json +23 -0
- package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.tokens.dark.json +589 -0
- package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.tokens.json +964 -0
- package/data/harnesses/code/skills/design/data/design-tokens/lovable/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/lovable/design.tokens.json +955 -0
- package/data/harnesses/code/skills/design/data/design-tokens/meta/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/meta/design.tokens.json +977 -0
- package/data/harnesses/code/skills/design/data/design-tokens/minimax/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/minimax/design.tokens.json +950 -0
- package/data/harnesses/code/skills/design/data/design-tokens/mintlify/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/mintlify/design.tokens.json +976 -0
- package/data/harnesses/code/skills/design/data/design-tokens/miro/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/miro/design.tokens.json +979 -0
- package/data/harnesses/code/skills/design/data/design-tokens/mistral-ai/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/mistral-ai/design.tokens.json +955 -0
- package/data/harnesses/code/skills/design/data/design-tokens/mongodb/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/mongodb/design.tokens.json +958 -0
- package/data/harnesses/code/skills/design/data/design-tokens/notion/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/notion/design.tokens.json +953 -0
- package/data/harnesses/code/skills/design/data/design-tokens/nurix/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/nurix/design.tokens.json +904 -0
- package/data/harnesses/code/skills/design/data/design-tokens/nvidia/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/nvidia/design.tokens.json +957 -0
- package/data/harnesses/code/skills/design/data/design-tokens/ollama/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/ollama/design.tokens.json +945 -0
- package/data/harnesses/code/skills/design/data/design-tokens/opencode-ai/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/opencode-ai/design.tokens.json +960 -0
- package/data/harnesses/code/skills/design/data/design-tokens/posthog/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/posthog/design.tokens.json +953 -0
- package/data/harnesses/code/skills/design/data/design-tokens/raycast/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/raycast/design.tokens.json +955 -0
- package/data/harnesses/code/skills/design/data/design-tokens/replicate/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/replicate/design.tokens.json +958 -0
- package/data/harnesses/code/skills/design/data/design-tokens/resend/design.resolver.json +23 -0
- package/data/harnesses/code/skills/design/data/design-tokens/resend/design.tokens.dark.json +613 -0
- package/data/harnesses/code/skills/design/data/design-tokens/resend/design.tokens.json +968 -0
- package/data/harnesses/code/skills/design/data/design-tokens/revolut/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/revolut/design.tokens.json +956 -0
- package/data/harnesses/code/skills/design/data/design-tokens/runwayml/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/runwayml/design.tokens.json +960 -0
- package/data/harnesses/code/skills/design/data/design-tokens/sanity/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/sanity/design.tokens.json +958 -0
- package/data/harnesses/code/skills/design/data/design-tokens/sentry/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/sentry/design.tokens.json +980 -0
- package/data/harnesses/code/skills/design/data/design-tokens/shopify/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/shopify/design.tokens.json +964 -0
- package/data/harnesses/code/skills/design/data/design-tokens/slack/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/slack/design.tokens.json +957 -0
- package/data/harnesses/code/skills/design/data/design-tokens/spacex/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/spacex/design.tokens.json +979 -0
- package/data/harnesses/code/skills/design/data/design-tokens/spotify/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/spotify/design.tokens.json +974 -0
- package/data/harnesses/code/skills/design/data/design-tokens/stripe/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/stripe/design.tokens.json +973 -0
- package/data/harnesses/code/skills/design/data/design-tokens/supabase/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/supabase/design.tokens.json +979 -0
- package/data/harnesses/code/skills/design/data/design-tokens/superhuman/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/superhuman/design.tokens.json +966 -0
- package/data/harnesses/code/skills/design/data/design-tokens/tesla/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/tesla/design.tokens.json +961 -0
- package/data/harnesses/code/skills/design/data/design-tokens/theverge/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/theverge/design.tokens.json +977 -0
- package/data/harnesses/code/skills/design/data/design-tokens/together-ai/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/together-ai/design.tokens.json +991 -0
- package/data/harnesses/code/skills/design/data/design-tokens/uber/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/uber/design.tokens.json +966 -0
- package/data/harnesses/code/skills/design/data/design-tokens/vercel/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/vercel/design.tokens.json +988 -0
- package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.resolver.json +23 -0
- package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.tokens.dark.json +602 -0
- package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.tokens.json +974 -0
- package/data/harnesses/code/skills/design/data/design-tokens/warp/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/warp/design.tokens.json +979 -0
- package/data/harnesses/code/skills/design/data/design-tokens/webflow/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/webflow/design.tokens.json +960 -0
- package/data/harnesses/code/skills/design/data/design-tokens/wired/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/wired/design.tokens.json +968 -0
- package/data/harnesses/code/skills/design/data/design-tokens/wise/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/wise/design.tokens.json +965 -0
- package/data/harnesses/code/skills/design/data/design-tokens/x-ai/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/x-ai/design.tokens.json +988 -0
- package/data/harnesses/code/skills/design/data/design-tokens/zapier/design.resolver.json +20 -0
- package/data/harnesses/code/skills/design/data/design-tokens/zapier/design.tokens.json +978 -0
- package/data/harnesses/code/skills/design/data/operator-pack/surface-catalog.md +1 -1
- package/data/harnesses/code/skills/design/references/create.md +14 -9
- package/data/harnesses/code/skills/design/references/diagnosis.md +1 -1
- package/data/harnesses/code/skills/design/references/hard-rules.md +4 -4
- package/data/harnesses/code/skills/design/references/improve.md +11 -9
- package/data/harnesses/code/skills/design/references/introspect.md +1 -1
- package/data/harnesses/code/skills/design/references/personality.md +337 -413
- package/data/harnesses/code/skills/design/scripts/convert-design-md.mjs +1032 -0
- package/data/harnesses/code/skills/design/scripts/derive-personality.mjs +596 -296
- package/data/harnesses/code/skills/design/scripts/{detector.mjs → lib/checks.mjs} +145 -140
- package/data/harnesses/code/skills/design/scripts/lib/golden.mjs +26 -0
- package/data/harnesses/code/skills/design/scripts/phase-gate.mjs +105 -37
- package/data/harnesses/code/skills/design/scripts/preship-sweep.mjs +60 -73
- package/data/harnesses/code/skills/design/scripts/render-rung.mjs +1 -1
- package/data/harnesses/code/skills/design/scripts/scaffold.mjs +1 -1
- package/data/harnesses/code/skills/design/scripts/self-integrity.mjs +205 -37
- package/data/harnesses/code/skills/design/scripts/snapshot-goldens.mjs +68 -0
- package/data/harnesses/code/skills/design/scripts/validate-combinations.mjs +314 -0
- package/data/harnesses/code/skills/documentation/SKILL.md +61 -17
- package/data/harnesses/code/skills/documentation/references/examples.md +41 -0
- package/data/harnesses/code/skills/documentation/references/style-guide.md +14 -9
- package/data/harnesses/code/skills/documentation/references/templates.md +306 -52
- package/data/harnesses/etna/CLAUDE.md +3 -3
- package/data/harnesses/etna/agents/brainstorm.md +1 -1
- package/data/harnesses/etna/agents/maintenance.md +8 -7
- package/data/harnesses/etna/harness.json +2 -2
- package/data/harnesses/etna/rules/general.md +2 -40
- package/data/harnesses/etna/rules/nomenclature.md +1 -8
- package/data/harnesses/etna/skills/brainstorm/README.md +4 -4
- package/data/harnesses/etna/skills/brainstorm/SKILL.md +5 -3
- package/data/harnesses/etna/skills/brainstorm/exit-artifacts.md +15 -11
- package/data/harnesses/etna/skills/brainstorm/templates/source-of-truth.md +5 -5
- package/data/harnesses/etna/skills/documentation/SKILL.md +61 -17
- package/data/harnesses/etna/skills/documentation/references/examples.md +41 -0
- package/data/harnesses/etna/skills/documentation/references/style-guide.md +14 -9
- package/data/harnesses/etna/skills/documentation/references/templates.md +306 -52
- package/data/harnesses/mobile/CLAUDE.md +3 -3
- package/data/harnesses/mobile/agents/brainstorm.md +1 -1
- package/data/harnesses/mobile/agents/maintenance.md +8 -7
- package/data/harnesses/mobile/harness.json +2 -2
- package/data/harnesses/mobile/rules/database.md +38 -0
- package/data/harnesses/mobile/rules/general.md +2 -40
- package/data/harnesses/mobile/rules/nomenclature.md +1 -8
- package/data/harnesses/mobile/rules/nustack.md +150 -0
- package/data/harnesses/mobile/skills/brainstorm/README.md +4 -4
- package/data/harnesses/mobile/skills/brainstorm/SKILL.md +5 -3
- package/data/harnesses/mobile/skills/brainstorm/exit-artifacts.md +15 -11
- package/data/harnesses/mobile/skills/brainstorm/templates/source-of-truth.md +5 -5
- package/data/harnesses/mobile/skills/documentation/SKILL.md +61 -17
- package/data/harnesses/mobile/skills/documentation/references/examples.md +41 -0
- package/data/harnesses/mobile/skills/documentation/references/style-guide.md +14 -9
- package/data/harnesses/mobile/skills/documentation/references/templates.md +306 -52
- package/package.json +1 -1
- package/data/harnesses/code/skills/design/scripts/hook-config.json +0 -11
|
@@ -1,214 +1,159 @@
|
|
|
1
1
|
# Personality — the look pipeline
|
|
2
2
|
|
|
3
|
-
`design
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
`design-tokens artifact → --check → --emit`. A look travels as a **design-tokens artifact** — three
|
|
4
|
+
DTCG JSON files whose grammar, payload, and resolution rules are the frozen transport schema,
|
|
5
|
+
[SCHEMA.md](../data/design-tokens/SCHEMA.md). [`derive-personality.mjs`](../scripts/derive-personality.mjs)
|
|
6
|
+
is the reference consumer: `--check` is the coverage gate that must pass before `--emit` writes
|
|
7
|
+
`personality.css`, `globals.css`, and the `<html>` attributes. The emitted files *are* the state —
|
|
8
|
+
no sidecar cache, no intermediate document. (The design.md format exists only as the library's
|
|
9
|
+
curated documentation corpus, `data/design-md/library/`; the machine path reads token files.)
|
|
7
10
|
|
|
8
11
|
The look comes entirely from the cascade. A surface composes in semantic tokens (`bg-card`,
|
|
9
|
-
`text-foreground`) and reads its personality from the CSS variables
|
|
10
|
-
|
|
12
|
+
`text-foreground`) and reads its personality from the CSS variables emission writes. Swap the
|
|
13
|
+
artifact, re-emit, and every surface re-skins with zero JSX edits — the invariant the exemplars are
|
|
11
14
|
validated against.
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
Every CSS and comment excerpt in this document is pasted from a real emission of the shipped Nurix
|
|
17
|
+
default (`data/design-tokens/nurix/`); gate transcripts are from real runs, with scratch paths
|
|
18
|
+
shown as `<artifact-dir>`.
|
|
19
|
+
|
|
20
|
+
## 1. The pipeline — artifact in, CSS out
|
|
14
21
|
|
|
15
22
|
```
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
design-tokens artifact ──▶ derive-personality.mjs --check ──▶ (green) ──▶ --emit <outdir>
|
|
24
|
+
design.tokens.json the coverage gate (rules 1–12): src/styles/personality.css
|
|
25
|
+
design.tokens.dark.json? 26 primitives + 2 dials + density tier src/styles/globals.css
|
|
26
|
+
design.resolver.json + 34 color roles + typography 3+6, index-html-attributes.txt
|
|
27
|
+
each assigned or hinted, or exit 1
|
|
20
28
|
```
|
|
21
29
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
30
|
+
```
|
|
31
|
+
derive-personality.mjs <artifact-dir> [--check | --emit <outdir>] [--theme light|dark]
|
|
32
|
+
```
|
|
25
33
|
|
|
26
|
-
|
|
34
|
+
**The artifact.** Three files in one directory: `design.tokens.json` (the base set — primitives,
|
|
35
|
+
color roles, typography, and the file-level `$extensions["com.nurix.design"]` payload carrying
|
|
36
|
+
`product`, `provenance`, the dials, and the lever manifest), `design.tokens.dark.json` (only when
|
|
37
|
+
the look has dark values), and `design.resolver.json`. The script resolves them in the resolver's
|
|
38
|
+
deterministic order — concatenate the set files, overlay the selected theme context, resolve aliases
|
|
39
|
+
after overlay — then validates or emits. File shapes, `$type` grammar, and payload spec live in
|
|
40
|
+
[SCHEMA.md](../data/design-tokens/SCHEMA.md); this document covers what emission does with a
|
|
41
|
+
resolved artifact.
|
|
27
42
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
the
|
|
43
|
+
**`--check` never best-efforts.** It runs the schema's rules 1–12 and exits non-zero naming every
|
|
44
|
+
offending path, so the fix is mechanical; the `tokens` phase gate (and the verify/pre-ship sweeps)
|
|
45
|
+
stay shut until it is green. Over the shipped default, from the skill root,
|
|
46
|
+
`node scripts/derive-personality.mjs data/design-tokens/nurix --check` prints:
|
|
31
47
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
gated):
|
|
45
|
-
- `--ease-exit: var(--ease-default)` — departure mirrors the neutral curve.
|
|
46
|
-
- `--ease-enter` → the emphasized-decelerate arrival curve `cubic-bezier(0.16, 1, 0.3, 1)` (fast in,
|
|
47
|
-
settles clean); reuse `ease-default` verbatim if it is already a decelerate curve.
|
|
48
|
-
- `--stagger-delay` → `duration-unit × 0.15`, clamped `0–40ms`, emitted as a concrete ms; a snappier
|
|
49
|
-
tempo staggers less. (`50ms → 8ms`.)
|
|
48
|
+
```
|
|
49
|
+
check PASSED (data/design-tokens/nurix): rules 1–11 OK — 26 primitives, 34 color roles, typography 3+6, payload/manifest/parse-back OK — provenance=default, style=nurix, theme=light
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Rule 12 (the emission precondition) is enforced at emit time; `--check` surfaces it as the
|
|
53
|
+
outstanding-hint count (§3). A failing artifact names its gaps — this run is against a scratch copy
|
|
54
|
+
of the default with one color token deleted:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
check FAILED (<artifact-dir>): 1 issue(s)
|
|
58
|
+
- rule 4 — color.warning: missing
|
|
59
|
+
```
|
|
50
60
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
silent — the full convention is [SCHEMA.md](../data/design-md/SCHEMA.md) §"hint convention". After
|
|
56
|
-
resolution no bare `hint:` remains.
|
|
61
|
+
**`--emit <outdir>`** runs only over a passing artifact and refuses while any token carries a hint
|
|
62
|
+
(§3). It writes three files: `<outdir>/src/styles/personality.css`, `<outdir>/src/styles/globals.css`,
|
|
63
|
+
and `<outdir>/index-html-attributes.txt` — the attribute set the project's `index.html` `<html>` tag
|
|
64
|
+
must carry. In real use `<outdir>` is the project root.
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
### The emitted header is the cache record
|
|
59
67
|
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
There is no sidecar state file. The header comment of the emitted `personality.css` carries the
|
|
69
|
+
active personality — dials, theme, and the artifact citation with its provenance — and the `<html>`
|
|
70
|
+
attributes carry the same state in markup:
|
|
62
71
|
|
|
63
72
|
```css
|
|
64
73
|
/* src/styles/personality.css — operator-UI personality tokens (emitted; do not hand-edit).
|
|
65
74
|
*
|
|
66
|
-
* Active personality — code is the cache.
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* style:
|
|
70
|
-
* density:
|
|
71
|
-
* verbosity: default
|
|
72
|
-
* feedback: subtle
|
|
73
|
-
* theme: light
|
|
75
|
+
* Active personality — code is the cache. These values and the <html data-*>
|
|
76
|
+
* attributes in index.html are emitted from the design-tokens artifact. To change
|
|
77
|
+
* the look, edit design.tokens.json and re-run derive-personality.mjs --emit.
|
|
78
|
+
* style: nurix (<html data-style="nurix">) — the project's own personality (rosterless)
|
|
79
|
+
* density: standard (<html data-density="standard">)
|
|
80
|
+
* verbosity: default (<html data-verbosity="default">)
|
|
81
|
+
* feedback: subtle (<html data-feedback="subtle">)
|
|
82
|
+
* theme: light (<html data-theme="light">) — light is the default; dark is opt-in
|
|
83
|
+
* artifact: design.tokens.json (resolved via design.resolver.json) — provenance: default, sourced 2026-07-04
|
|
74
84
|
*
|
|
75
85
|
* Semantic-token doctrine: components name purpose (bg-card, text-foreground, border-border);
|
|
76
86
|
* this file resolves those names to values. Components never use dark: prefixes or literal colors.
|
|
77
87
|
*/
|
|
88
|
+
```
|
|
78
89
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
* values live in the single [data-style="meridian"] block below, which
|
|
82
|
-
* overrides these. Improve/extract rewrites that block, never this baseline. */
|
|
83
|
-
:root {
|
|
84
|
-
/* geometric */
|
|
85
|
-
--radius: 6px;
|
|
86
|
-
--shadow-intensity: 1;
|
|
87
|
-
--border-weight: 1px;
|
|
88
|
-
--density-base-gap: 1; /* the density tier writes this; see the density mechanism */
|
|
89
|
-
--density-base-inset: 1;
|
|
90
|
-
--density-gap: var(--density-base-gap);
|
|
91
|
-
--density-inset: var(--density-base-inset);
|
|
92
|
-
/* typographic */
|
|
93
|
-
--font-sans: "Inter", system-ui, sans-serif;
|
|
94
|
-
--font-mono: "JetBrains Mono", ui-monospace, monospace;
|
|
95
|
-
--font-weight-normal: 400;
|
|
96
|
-
--font-weight-strong: 600;
|
|
97
|
-
--heading-tracking: -0.01em;
|
|
98
|
-
/* temporal (+ derived) */
|
|
99
|
-
--duration-unit: 200ms;
|
|
100
|
-
--duration-fast: calc(var(--duration-unit) * 0.5);
|
|
101
|
-
--duration-normal: var(--duration-unit);
|
|
102
|
-
--duration-slow: calc(var(--duration-unit) * 2);
|
|
103
|
-
--ease-default: cubic-bezier(0.4, 0, 0.2, 1);
|
|
104
|
-
--ease-enter: cubic-bezier(0.16, 1, 0.3, 1);
|
|
105
|
-
--ease-exit: var(--ease-default);
|
|
106
|
-
--stagger-delay: 30ms;
|
|
107
|
-
/* surface */
|
|
108
|
-
--contrast-boost: 1;
|
|
109
|
-
/* iconography */
|
|
110
|
-
--icon-stroke: 1.75;
|
|
111
|
-
--icon-size-base: 16px;
|
|
112
|
-
/* operator layout */
|
|
113
|
-
--sidebar-width-expanded: 240px;
|
|
114
|
-
--sidebar-width-collapsed: 56px;
|
|
115
|
-
--topbar-height: 52px;
|
|
116
|
-
--side-panel-width: 480px;
|
|
117
|
-
--side-panel-width-rich: 640px;
|
|
118
|
-
--modal-width-max: 480px;
|
|
119
|
-
--form-max-width: 720px;
|
|
120
|
-
--table-row-height: 40px;
|
|
121
|
-
/* behavioral fallbacks (match verbosity=default + feedback=subtle) */
|
|
122
|
-
--label-display: inline-flex;
|
|
123
|
-
--helper-text-display: block;
|
|
124
|
-
--tooltip-delay: 500ms;
|
|
125
|
-
--feedback-press-scale: 0.99;
|
|
126
|
-
--focus-ring-width: 2px;
|
|
127
|
-
--focus-ring-offset: 1px;
|
|
128
|
-
}
|
|
90
|
+
Recovery therefore reads two things: the token artifact (the source) and the emitted attributes
|
|
91
|
+
(the active state). `index-html-attributes.txt` from the same run:
|
|
129
92
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
[data-style
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
--
|
|
184
|
-
--density-gap: var(--density-base-gap);
|
|
185
|
-
--density-inset: var(--density-base-inset);
|
|
186
|
-
--font-sans: "Inter", system-ui, sans-serif;
|
|
187
|
-
--font-mono: "JetBrains Mono", ui-monospace, monospace;
|
|
188
|
-
--font-weight-normal: 400;
|
|
189
|
-
--font-weight-strong: 600;
|
|
190
|
-
--heading-tracking: -0.01em;
|
|
191
|
-
--duration-unit: 50ms;
|
|
192
|
-
--duration-fast: 100ms;
|
|
193
|
-
--duration-normal: 150ms;
|
|
194
|
-
--duration-slow: 250ms;
|
|
195
|
-
--ease-default: cubic-bezier(0.4, 0, 0.2, 1);
|
|
93
|
+
```html
|
|
94
|
+
<!-- Personality state lives in these <html data-*> attributes — code is the cache.
|
|
95
|
+
The design-tokens artifact is the source. To change the look, edit design.tokens.json
|
|
96
|
+
and re-run derive-personality.mjs --emit; to nudge one axis, edit an attribute here. -->
|
|
97
|
+
<html
|
|
98
|
+
lang="en"
|
|
99
|
+
data-style="nurix"
|
|
100
|
+
data-density="standard"
|
|
101
|
+
data-verbosity="default"
|
|
102
|
+
data-feedback="subtle"
|
|
103
|
+
data-theme="light"
|
|
104
|
+
>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## 2. Derivation — token paths to emitted CSS variables
|
|
108
|
+
|
|
109
|
+
Leaf names are law: a `primitive.*` or `color.*` token maps 1:1 to the CSS variable of the same
|
|
110
|
+
name, without the leading `--`.
|
|
111
|
+
|
|
112
|
+
| Artifact source | Emitted target | Rule |
|
|
113
|
+
| --- | --- | --- |
|
|
114
|
+
| `primitive.<name>` (24 static) | `[data-style="<slug>"] { --<name>: … }` | 1:1 by leaf name |
|
|
115
|
+
| `primitive.density-gap` / `density-inset` | governed refs `var(--density-base-gap/inset)` in `[data-style]` | the density tier writes the base (§4) |
|
|
116
|
+
| `color.<name>` (34) | `:root, :root[data-theme="light"] { --<name>: … }` | 1:1 by leaf name |
|
|
117
|
+
| dark set `color.<name>` | `[data-theme="dark"] { --<name>: … }` | only when the dark file ships (§5) |
|
|
118
|
+
| payload `product` | `<html data-style="<slug>">` | slugified (lowercase, non-alphanumeric runs → `-`) |
|
|
119
|
+
| payload `verbosity` / `feedback` / `density-tier` | `<html data-verbosity / data-feedback / data-density>` | dial → attribute |
|
|
120
|
+
| payload `product-traits` | read by the front gate; **not** emitted to CSS | — |
|
|
121
|
+
| `primitive.font-sans` / `font-mono`, `font-weight-normal` | `[data-style]` **and** literals in `@theme inline` | §4, two-weight discipline / no self-reference |
|
|
122
|
+
| `typography.family.*` / `typography.ramp.*` | data for emitters and exemplars | reaches CSS only through the primitives it aliases |
|
|
123
|
+
| — (derived at emit) | `--ease-enter`, `--ease-exit`, `--stagger-delay` | computed from `ease-default` + `duration-unit` |
|
|
124
|
+
|
|
125
|
+
**The preserved-css rule.** For every emitted value the emitters prefer the token's
|
|
126
|
+
`$extensions["com.nurix.design"].css` — the exact source string — so output is byte-stable across
|
|
127
|
+
convert/emit round trips (an aliased token takes its target's `.css`). Absent `.css`, the schema's
|
|
128
|
+
deterministic serialization applies: `dimension`/`duration` as `<value><unit>`; `number`/`fontWeight`
|
|
129
|
+
as the plain number; `cubicBezier` as `cubic-bezier(x1, y1, x2, y2)`; `fontFamily` as the families
|
|
130
|
+
joined with `", "`, multi-word names double-quoted; `color` as the `hex` field when srgb, else
|
|
131
|
+
`oklch(…)`. The parse-back check (rule 9) guarantees the two forms agree before anything is emitted.
|
|
132
|
+
|
|
133
|
+
**Derived, never stored.** Three temporal variables are computed at emit from `ease-default` and
|
|
134
|
+
`duration-unit` — they are not tokens, not authored, and not gated (do not add them to an artifact):
|
|
135
|
+
|
|
136
|
+
- `--ease-exit: var(--ease-default)` — departure mirrors the neutral curve.
|
|
137
|
+
- `--ease-enter` — the emphasized-decelerate arrival curve `cubic-bezier(0.16, 1, 0.3, 1)` (fast
|
|
138
|
+
in, settles clean); `ease-default` is reused verbatim when it is already a decelerate curve
|
|
139
|
+
(y1 ≥ 0.9).
|
|
140
|
+
- `--stagger-delay` — `duration-unit × 0.15`, rounded, clamped 0–40ms; a snappier tempo staggers
|
|
141
|
+
less.
|
|
142
|
+
|
|
143
|
+
Emitted into the `[data-style]` block, directly after `ease-default`:
|
|
144
|
+
|
|
145
|
+
```css
|
|
146
|
+
--ease-default: cubic-bezier(0.4,0,0.2,1);
|
|
196
147
|
--ease-enter: cubic-bezier(0.16, 1, 0.3, 1); /* derived from ease-default */
|
|
197
148
|
--ease-exit: var(--ease-default); /* derived: departure mirrors the neutral curve */
|
|
198
149
|
--stagger-delay: 8ms; /* derived: duration-unit × 0.15, clamped 0–40ms */
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
--topbar-height: 52px;
|
|
205
|
-
--side-panel-width: 420px;
|
|
206
|
-
--side-panel-width-rich: 640px;
|
|
207
|
-
--modal-width-max: 560px;
|
|
208
|
-
--form-max-width: 640px;
|
|
209
|
-
--table-row-height: 40px;
|
|
210
|
-
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Dial semantics.** The payload's two behavioral dials become `<html>` attributes, and
|
|
153
|
+
`personality.css` carries one block per dial value setting the behavioral variables the lifecycle
|
|
154
|
+
and interaction layers read:
|
|
211
155
|
|
|
156
|
+
```css
|
|
212
157
|
/* ── Behavioral dials (D4) — orthogonal to the visual primitives. ── */
|
|
213
158
|
[data-verbosity="full"] { --label-display: inline-flex; --helper-text-display: block; --tooltip-delay: 800ms; }
|
|
214
159
|
[data-verbosity="default"] { --label-display: inline-flex; --helper-text-display: block; --tooltip-delay: 500ms; }
|
|
@@ -217,82 +162,166 @@ record. Values below are one project's (`meridian`, the SCHEMA worked example);
|
|
|
217
162
|
|
|
218
163
|
[data-feedback="subtle"] { --feedback-press-scale: 0.99; --focus-ring-width: 2px; --focus-ring-offset: 1px; }
|
|
219
164
|
[data-feedback="minimal"] { --feedback-press-scale: 1; --focus-ring-width: 1px; --focus-ring-offset: 0px; }
|
|
165
|
+
```
|
|
220
166
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
[data-density="spacious"] { --density-base-gap: 1.15; --density-base-inset: 1.15; }
|
|
167
|
+
- `--label-display` / `--helper-text-display` — `compact`/`expert` verbosity collapse form labels
|
|
168
|
+
and helper text; `full`/`default` keep them. Field chrome reads these, not a JS branch.
|
|
169
|
+
- `--tooltip-delay` — tightens with verbosity (`800ms → 0ms`).
|
|
170
|
+
- `--feedback-press-scale`, `--focus-ring-width`, `--focus-ring-offset` — `minimal` feedback
|
|
171
|
+
flattens the press and thins the focus ring; `subtle` keeps the operator-default ring.
|
|
227
172
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
* library's p-*/gap-* through the @theme --spacing remap (§4). */
|
|
234
|
-
[data-density-step="tighter"] { --density-gap: calc(var(--density-base-gap) * 0.85); --density-inset: calc(var(--density-base-inset) * 0.85); }
|
|
235
|
-
[data-density-step="looser"] { --density-gap: calc(var(--density-base-gap) * 1.15); --density-inset: calc(var(--density-base-inset) * 1.15); }
|
|
173
|
+
The lifecycle pattern ([lifecycle.md](./lifecycle.md)) consumes the dials directly — empty-state
|
|
174
|
+
richness scales with verbosity, confirmation depth rides feedback; focus and overlay discipline read
|
|
175
|
+
the ring variables ([interaction.md](./interaction.md)). A component that must branch structurally
|
|
176
|
+
on a dial reads the `<html>` attribute — it never duplicates the state. Density (`data-density`) is
|
|
177
|
+
spatial chrome, not behavior — it composes with the dials, never replaces them (§4).
|
|
236
178
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
[
|
|
241
|
-
|
|
242
|
-
|
|
179
|
+
## 3. Hints — provisional values that pass the gate but block emission
|
|
180
|
+
|
|
181
|
+
Where a value needs judgment, the token carries a **valid provisional `$value`** plus
|
|
182
|
+
`$extensions["com.nurix.design"].hint` — the intent in plain words (the full convention, with the
|
|
183
|
+
JSON shape, is SCHEMA.md's hint section; payload fields are always concrete — hints exist only on
|
|
184
|
+
tokens). Every gated token is in exactly one state:
|
|
185
|
+
|
|
186
|
+
| State | Marker | `--check` | `--emit` |
|
|
187
|
+
| --- | --- | --- | --- |
|
|
188
|
+
| **assigned** | real value, no `hint` key | passes | emits |
|
|
189
|
+
| **hinted** | `hint` key present | passes | **refuses**, naming every hinted path |
|
|
190
|
+
| **missing** | token absent | fails, naming the key | — |
|
|
243
191
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
192
|
+
A hinted artifact is checkable — the pass line counts the outstanding hints (this run: a scratch
|
|
193
|
+
copy of the default with a hint added to `primitive.contrast-boost`):
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
check PASSED (<artifact-dir>): rules 1–11 OK — 26 primitives, 34 color roles, typography 3+6, payload/manifest/parse-back OK — provenance=default, style=nurix, theme=light, 1 hint(s) outstanding (emit will refuse)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
— but not emittable. `--emit` over the same artifact:
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
emit REFUSED (<artifact-dir>): 1 unresolved hint(s) — rule 12: every gated token must be concrete before emission.
|
|
203
|
+
- primitive.contrast-boost: hint: nudge borders up a step so the dense table grid reads as a grid
|
|
204
|
+
Resolve each with judgment: set the real $value, delete the hint key, record the rationale in $description — then re-run --emit.
|
|
257
205
|
```
|
|
258
206
|
|
|
259
|
-
|
|
207
|
+
Resolving a hint is exactly that three-step: set the real `$value`, delete the `hint` key, record
|
|
208
|
+
the rationale in the token's `$description` — so the resolved artifact stays self-explaining and
|
|
209
|
+
re-derivable. Judgment is recorded, never silent.
|
|
260
210
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
211
|
+
## 4. The substrate contracts — living with `@nurix/components`
|
|
212
|
+
|
|
213
|
+
`@nurix/components/dist/styles.css` ships its own bare-`:root` token defaults and its own `@theme`
|
|
214
|
+
radius scale. Two cascade contracts keep the personality in charge; both are hardened with the
|
|
215
|
+
emitted in-CSS comments below and enforced by the code-and-token rules (`cod-*`) in
|
|
216
|
+
[hard-rules.md](./hard-rules.md). The library's actual consumption is enumerated in
|
|
217
|
+
[the substrate audit](../../../docs/history/brainstorms/design/u1-audit-report.md).
|
|
218
|
+
|
|
219
|
+
**CASCADE CONTRACT 1 — the specificity/attribute pair.** The color tokens are emitted under a
|
|
220
|
+
doubled selector, and `<html>` must carry `data-theme="light"`:
|
|
221
|
+
|
|
222
|
+
```css
|
|
223
|
+
/* ── Semantic + substrate color tokens — light theme. ──
|
|
224
|
+
* CASCADE CONTRACT 1: the doubled selector out-specifies the library's bare
|
|
225
|
+
* :root defaults in @nurix/components/styles.css — but ONLY because <html> carries
|
|
226
|
+
* data-theme="light". A bare :root here loses to the later library import. All 34
|
|
227
|
+
* tokens are set (D6): no consumed token falls back to a shadcn-gray default. */
|
|
228
|
+
:root,
|
|
229
|
+
:root[data-theme="light"] {
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
*Failure mode:* a bare `:root { --background: … }` is specificity `(0,1,0)` — the library's own
|
|
233
|
+
`:root { --background: … }` is also `(0,1,0)` and imported *later*, so it wins and every surface
|
|
234
|
+
silently reverts to shadcn gray. The `:root[data-theme="light"]` arm is `(0,2,0)` and out-wins — but
|
|
235
|
+
only if `data-theme="light"` is actually on `<html>`; drop the attribute and the arm never matches,
|
|
236
|
+
leaving only the losing bare `:root`. Both halves are load-bearing together.
|
|
237
|
+
|
|
238
|
+
**CASCADE CONTRACT 2 — the four-step import order.** The emitted `globals.css` opens:
|
|
264
239
|
|
|
265
240
|
```css
|
|
266
241
|
/* src/styles/globals.css — Tailwind v4 glue + @theme inline mappings (emitted). */
|
|
267
242
|
|
|
268
|
-
/* CASCADE CONTRACT 2
|
|
243
|
+
/* CASCADE CONTRACT 2: this four-step order is LOAD-BEARING. The library's
|
|
269
244
|
* styles.css ships its own :root token defaults and its own @theme radius scale;
|
|
270
245
|
* our @theme MUST come AFTER the import to win the radius scale and own every
|
|
271
|
-
* mapping. rules/
|
|
246
|
+
* mapping. rules/frontend.md states the same order — co-authority. */
|
|
272
247
|
@import "./personality.css"; /* 1. token source (must be first) */
|
|
273
248
|
@import "tailwindcss"; /* 2. framework */
|
|
274
249
|
@import "@nurix/components/styles.css"; /* 3. library (before our @theme) */
|
|
275
250
|
|
|
276
251
|
@theme inline { /* 4. consumer theme — AFTER the library, so it wins */
|
|
277
|
-
|
|
278
|
-
* A flat personality sets --radius: 0 → every step collapses to 0. */
|
|
279
|
-
--radius-sm: calc(var(--radius) - 4px);
|
|
280
|
-
--radius-md: calc(var(--radius) - 2px);
|
|
281
|
-
--radius-lg: var(--radius);
|
|
282
|
-
--radius-xl: calc(var(--radius) + 4px);
|
|
252
|
+
```
|
|
283
253
|
|
|
254
|
+
*Failure mode:* put `@theme inline` (or the whole consumer theme) *before* the library import and
|
|
255
|
+
the library's own `@theme` radius scale (`--radius-lg: var(--radius)`, its own offsets) comes later
|
|
256
|
+
and wins — the personality `--radius` stops driving the scale and archetype radius switching breaks.
|
|
257
|
+
`rules/frontend.md` states this same order — co-authority, not a restatement to
|
|
258
|
+
drift from. `@theme inline` inlines each value into the generated utilities (so `bg-card` compiles
|
|
259
|
+
to `background-color: var(--card)`).
|
|
260
|
+
|
|
261
|
+
**The gray-fallback trap — all 34 roles, always.** Beyond the 15 semantic color tokens it maps
|
|
262
|
+
(888 semantic-token class uses), the library consumes **16 more shadcn tokens** — `--popover(-foreground)`,
|
|
263
|
+
`--secondary(-foreground)`, `--chart-1..5`, and the `--sidebar` family — that silently fall back to
|
|
264
|
+
the shadcn-gray defaults inside `dist/styles.css` when unset: popovers, menus, secondary buttons,
|
|
265
|
+
sidebars, and charts render visibly off-palette next to personality surfaces. The artifact's
|
|
266
|
+
substrate group carries 17 roles covering them, and emission sets all 34 color roles every time.
|
|
267
|
+
`--color-destructive-foreground` is mapped explicitly in `@theme` because the library leaves it
|
|
268
|
+
unmapped.
|
|
269
|
+
|
|
270
|
+
**Coverage — every token the library consumes is emitted.**
|
|
271
|
+
|
|
272
|
+
| Library consumes | How | Emitted at |
|
|
273
|
+
| --- | --- | --- |
|
|
274
|
+
| `--radius` (283 `rounded-*`) | direct primitive + `@theme` radius scale | `[data-style]` · `@theme` |
|
|
275
|
+
| shadow (`shadow-xs/sm/md/lg`, 58) | `--shadow-*` alpha rides `--shadow-intensity` | `@theme` |
|
|
276
|
+
| font weight (`font-medium/semibold/bold/normal`, 139) | two-weight map to `--font-weight-strong` | `@theme` |
|
|
277
|
+
| tracking (`tracking-*`, 13) | `--tracking-tight/tighter → --heading-tracking` | `@theme` |
|
|
278
|
+
| spacing (all `p-*`/`gap-*`) | `--spacing` density remap | `@theme` |
|
|
279
|
+
| `font-mono` (9) / `font-sans` | literal font stacks | `@theme` |
|
|
280
|
+
| 15 semantic colors (888 uses) | direct token values | `:root[data-theme=light]` |
|
|
281
|
+
| `--success`, `--warning` | direct token values (library ignores today — upstream gaps) | `:root[data-theme=light]` |
|
|
282
|
+
| `--destructive-foreground` (unmapped by library) | explicit `--color-destructive-foreground` map | `@theme` |
|
|
283
|
+
| 17 substrate (`popover`/`secondary`/`chart-1..5`/`sidebar` family) | direct token values | `:root[data-theme=light]` |
|
|
284
|
+
| `--sidebar-width` / `--sidebar-width-icon` | SidebarProvider `style` prop | shell (below) |
|
|
285
|
+
|
|
286
|
+
**Density — global tier composed with a per-surface relative step.** Two composed levels, pure
|
|
287
|
+
cascade, no JS. The payload's `density-tier` becomes `data-density` on `<html>`, and the emitted
|
|
288
|
+
blocks write only the **base** multipliers; a surface carries `data-density-step` (from its
|
|
289
|
+
surface-catalog `density-modifier`, [surface-catalog.md](../data/operator-pack/surface-catalog.md),
|
|
290
|
+
emitted by `scaffold.mjs`) and re-derives one relative step off whatever tier the app runs:
|
|
291
|
+
|
|
292
|
+
```css
|
|
293
|
+
/* ── Density: global tier → base multipliers (D31). ──
|
|
294
|
+
* The tier writes ONLY the base; --density-gap/inset resolve from it (above),
|
|
295
|
+
* so a per-surface step can re-derive relative to the tier. */
|
|
296
|
+
[data-density="dense"] { --density-base-gap: 0.85; --density-base-inset: 0.85; }
|
|
297
|
+
[data-density="standard"] { --density-base-gap: 1; --density-base-inset: 1; }
|
|
298
|
+
[data-density="spacious"] { --density-base-gap: 1.15; --density-base-inset: 1.15; }
|
|
299
|
+
|
|
300
|
+
/* ── Per-archetype density modifier (D31) — relative step on the tier, pure cascade, no JS. ──
|
|
301
|
+
* A surface element carries data-density-step; it re-derives one step off the
|
|
302
|
+
* inherited base. Reads --density-base-* (never itself) so it composes with the
|
|
303
|
+
* tier and never absolutely overrides it. The recomputed --density-gap flows into
|
|
304
|
+
* the library's p-*/gap-* through the @theme --spacing remap. */
|
|
305
|
+
[data-density-step="tighter"] { --density-gap: calc(var(--density-base-gap) * 0.85); --density-inset: calc(var(--density-base-inset) * 0.85); }
|
|
306
|
+
[data-density-step="looser"] { --density-gap: calc(var(--density-base-gap) * 1.15); --density-inset: calc(var(--density-base-inset) * 1.15); }
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
A log-stream inside a `standard` app resolves one step denser without pinning an absolute value.
|
|
310
|
+
Both levels reach the library's internals through one `@theme` line — every library `p-*`/`gap-*`
|
|
311
|
+
is `calc(var(--spacing) × N)`, and `--density-gap` resolves per element (respecting a
|
|
312
|
+
`data-density-step` ancestor):
|
|
313
|
+
|
|
314
|
+
```css
|
|
284
315
|
/* density remap — the single line that scales ALL library spacing. Every p-*/gap-*
|
|
285
316
|
* is calc(var(--spacing) × N); driving --spacing off --density-gap flows the tier
|
|
286
|
-
* AND the per-surface density step
|
|
317
|
+
* AND the per-surface density step into the library's internals. */
|
|
287
318
|
--spacing: calc(0.25rem * var(--density-gap));
|
|
319
|
+
```
|
|
288
320
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
--shadow-xs: 0 1px 2px 0 rgb(15 23 42 / calc(0.06 * var(--shadow-intensity)));
|
|
292
|
-
--shadow-sm: 0 1px 3px 0 rgb(15 23 42 / calc(0.10 * var(--shadow-intensity))), 0 1px 2px -1px rgb(15 23 42 / calc(0.10 * var(--shadow-intensity)));
|
|
293
|
-
--shadow-md: 0 4px 6px -1px rgb(15 23 42 / calc(0.10 * var(--shadow-intensity))), 0 2px 4px -2px rgb(15 23 42 / calc(0.10 * var(--shadow-intensity)));
|
|
294
|
-
--shadow-lg: 0 10px 15px -3px rgb(15 23 42 / calc(0.10 * var(--shadow-intensity))), 0 4px 6px -4px rgb(15 23 42 / calc(0.10 * var(--shadow-intensity)));
|
|
321
|
+
**The two-weight discipline.** Operator UI carries exactly two font weights; the `@theme` map folds
|
|
322
|
+
the library's whole weight vocabulary onto them:
|
|
295
323
|
|
|
324
|
+
```css
|
|
296
325
|
/* font weight — two-weight discipline: medium/semibold/bold all resolve to the
|
|
297
326
|
* single emphasis weight; operator UI carries no third weight. normal is emitted
|
|
298
327
|
* as a literal because its theme key and the primitive share a name (no self-ref). */
|
|
@@ -300,205 +329,100 @@ each value into the generated utilities (so `bg-card` compiles to `background-co
|
|
|
300
329
|
--font-weight-medium: var(--font-weight-strong);
|
|
301
330
|
--font-weight-semibold: var(--font-weight-strong);
|
|
302
331
|
--font-weight-bold: var(--font-weight-strong);
|
|
303
|
-
|
|
304
|
-
/* tracking — heading tightness reaches the library's tracking-* utilities */
|
|
305
|
-
--tracking-tighter: var(--heading-tracking);
|
|
306
|
-
--tracking-tight: var(--heading-tracking);
|
|
307
|
-
|
|
308
|
-
/* fonts — emitted as the literal stack: a font is not a runtime-toggled token, and
|
|
309
|
-
* the theme key shares a name with the personality primitive (no self-reference).
|
|
310
|
-
* personality.css carries the same --font-sans/--font-mono for direct var() use. */
|
|
311
|
-
--font-sans: "Inter", system-ui, sans-serif;
|
|
312
|
-
--font-mono: "JetBrains Mono", ui-monospace, monospace;
|
|
313
|
-
|
|
314
|
-
/* transitions */
|
|
315
|
-
--transition-fast: var(--duration-fast) var(--ease-default);
|
|
316
|
-
--transition-normal: var(--duration-normal) var(--ease-default);
|
|
317
|
-
--transition-slow: var(--duration-slow) var(--ease-default);
|
|
318
|
-
--transition-enter: var(--duration-normal) var(--ease-enter);
|
|
319
|
-
--transition-exit: var(--duration-fast) var(--ease-exit);
|
|
320
|
-
|
|
321
|
-
/* semantic + substrate color maps — all 34, so bg-popover / bg-chart-1 / bg-sidebar resolve.
|
|
322
|
-
* --color-destructive-foreground is mapped explicitly (D6): the library leaves it unmapped. */
|
|
323
|
-
--color-background: var(--background);
|
|
324
|
-
--color-foreground: var(--foreground);
|
|
325
|
-
--color-card: var(--card);
|
|
326
|
-
--color-card-foreground: var(--card-foreground);
|
|
327
|
-
--color-muted: var(--muted);
|
|
328
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
329
|
-
--color-border: var(--border);
|
|
330
|
-
--color-input: var(--input);
|
|
331
|
-
--color-ring: var(--ring);
|
|
332
|
-
--color-primary: var(--primary);
|
|
333
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
334
|
-
--color-accent: var(--accent);
|
|
335
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
336
|
-
--color-destructive: var(--destructive);
|
|
337
|
-
--color-destructive-foreground: var(--destructive-foreground);
|
|
338
|
-
--color-success: var(--success);
|
|
339
|
-
--color-warning: var(--warning);
|
|
340
|
-
--color-popover: var(--popover);
|
|
341
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
342
|
-
--color-secondary: var(--secondary);
|
|
343
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
344
|
-
--color-chart-1: var(--chart-1);
|
|
345
|
-
--color-chart-2: var(--chart-2);
|
|
346
|
-
--color-chart-3: var(--chart-3);
|
|
347
|
-
--color-chart-4: var(--chart-4);
|
|
348
|
-
--color-chart-5: var(--chart-5);
|
|
349
|
-
--color-sidebar: var(--sidebar);
|
|
350
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
351
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
352
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
353
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
354
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
355
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
356
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/* dark variant — emitted ONLY when the project ships dark; redefines the library's
|
|
360
|
-
* class-based dark to follow data-theme so the library's dark: utilities honor our
|
|
361
|
-
* convention. Absent for a light-only project.
|
|
362
|
-
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *)); */
|
|
363
332
|
```
|
|
364
333
|
|
|
365
|
-
|
|
334
|
+
Fonts follow the same no-self-reference rule: `--font-sans`/`--font-mono` are emitted into `@theme`
|
|
335
|
+
as literal stacks (a font is not a runtime-toggled token, and the theme key shares the primitive's
|
|
336
|
+
name), while `personality.css` carries the same variables for direct `var()` use.
|
|
366
337
|
|
|
367
|
-
|
|
368
|
-
the
|
|
338
|
+
**Sidebar width — the style-prop seam.** The library hardcodes `--sidebar-width` /
|
|
339
|
+
`--sidebar-width-icon` as inline styles, overridable only via the provider's `style` prop — the one
|
|
340
|
+
layout primitive that cannot reach the library through `@theme`. The shell wires the personality
|
|
341
|
+
primitives in:
|
|
369
342
|
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
data-style="meridian"
|
|
377
|
-
data-density="dense"
|
|
378
|
-
data-verbosity="default"
|
|
379
|
-
data-feedback="subtle"
|
|
380
|
-
data-theme="light"
|
|
343
|
+
```tsx
|
|
344
|
+
<SidebarProvider
|
|
345
|
+
style={{
|
|
346
|
+
"--sidebar-width": "var(--sidebar-width-expanded)",
|
|
347
|
+
"--sidebar-width-icon": "var(--sidebar-width-collapsed)",
|
|
348
|
+
} as React.CSSProperties}
|
|
381
349
|
>
|
|
382
|
-
<head>
|
|
383
|
-
<meta charset="UTF-8" />
|
|
384
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
385
|
-
<title>Meridian</title>
|
|
386
|
-
</head>
|
|
387
|
-
<body>
|
|
388
|
-
<div id="root"></div>
|
|
389
|
-
<script type="module" src="/src/main.tsx"></script>
|
|
390
|
-
</body>
|
|
391
|
-
</html>
|
|
392
350
|
```
|
|
393
351
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
[hard-rules.md](./hard-rules.md); the `scaffold` and `tokens` phase gates check them.
|
|
398
|
-
|
|
399
|
-
**Contract 1 — the specificity/attribute pair.** Semantic + substrate tokens sit under
|
|
400
|
-
`:root, :root[data-theme="light"]` **and** `<html>` carries `data-theme="light"`.
|
|
401
|
-
*Failure mode:* a bare `:root { --background: … }` is specificity `(0,1,0)` — the library's own
|
|
402
|
-
`:root { --background: … }` in `styles.css` is also `(0,1,0)` and imported *later*, so it wins and every
|
|
403
|
-
surface silently reverts to shadcn gray. The `:root[data-theme="light"]` arm is `(0,2,0)` and out-wins —
|
|
404
|
-
but only if `data-theme="light"` is actually on `<html>`; drop the attribute and the arm never matches,
|
|
405
|
-
leaving only the losing bare `:root`. Both halves are load-bearing together.
|
|
406
|
-
|
|
407
|
-
**Contract 2 — the import order.** `personality.css → tailwindcss → @nurix/components/styles.css →
|
|
408
|
-
@theme inline`. *Failure mode:* put `@theme inline` (or the whole consumer theme) *before* the library
|
|
409
|
-
import and the library's own `@theme` radius scale (`--radius-lg: var(--radius)`, its own offsets) comes
|
|
410
|
-
later and wins — the personality `--radius` stops driving the scale and archetype radius switching breaks.
|
|
411
|
-
The consumer `@theme` must come last. `rules/general.md` (frontend section) states this same order — it is
|
|
412
|
-
co-authority, not a restatement to drift from.
|
|
352
|
+
**Upstream gaps — expected, never worked around.** Some values live in `@nurix/components` JS, not
|
|
353
|
+
CSS, so they do not follow tokens until the library adopts them. This is user-owned upstream work —
|
|
354
|
+
never patched with brittle per-instance overrides:
|
|
413
355
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
surface-catalog `density-modifier`, [surface-catalog.md](../data/operator-pack/surface-catalog.md)),
|
|
424
|
-
emitted by `scaffold.mjs` onto the surface root. It re-derives `--density-gap/inset` as
|
|
425
|
-
`calc(base × 0.85|1.15)` — a **relative** step off whatever tier the app runs, reading
|
|
426
|
-
`--density-base-*` (never itself, so no circular reference and never an absolute override). A
|
|
427
|
-
log-stream inside a `standard` app resolves one step denser without pinning an absolute value.
|
|
428
|
-
|
|
429
|
-
Both feed the library through `--spacing: calc(0.25rem * var(--density-gap))` in `@theme`: every library
|
|
430
|
-
`p-*`/`gap-*` is `calc(var(--spacing) × N)`, and `--density-gap` resolves per element (respecting a
|
|
431
|
-
`data-density-step` ancestor), so the tier and the step both reach the library's internal spacing. This
|
|
432
|
-
composes *with*, never replaces, the behavioral dials (D4) — density is spatial chrome; verbosity/feedback
|
|
433
|
-
are behavior.
|
|
434
|
-
|
|
435
|
-
## 8. Dial wiring and the lifecycle
|
|
356
|
+
- **Chart palettes** — the d3 family hardcodes oklch/hex and ignores `--chart-1..5`; color props are
|
|
357
|
+
per-instance overridable, but the defaults are upstream. Emit `--chart-1..5` regardless, so
|
|
358
|
+
adoption is a drop-in.
|
|
359
|
+
- **Status literals** — `changes-list` and `statistics` hardcode emerald/amber/sky rather than
|
|
360
|
+
`--success`/`--warning`.
|
|
361
|
+
- **Motion & icon stroke** — `duration: .2/.3` and `strokeWidth: 2/1.75` are JS numbers;
|
|
362
|
+
`--duration-*` and `--icon-stroke` reach consumer-emitted markup but not library internals.
|
|
363
|
+
- **Filled-control foreground** — `text-white` pinned on filled primary/destructive; the mapped
|
|
364
|
+
`--destructive-foreground` waits on the library reading it.
|
|
436
365
|
|
|
437
|
-
|
|
366
|
+
The stance: emit the complete token surface so the library "just works" the moment it adopts each
|
|
367
|
+
token; do not build an override layer that fights the library and rots.
|
|
438
368
|
|
|
439
|
-
|
|
440
|
-
helper text; `full`/`default` keep them. Field chrome reads these, not a JS branch.
|
|
441
|
-
- `--tooltip-delay` — tightens with verbosity (`800ms → 0ms`).
|
|
442
|
-
- `--feedback-press-scale`, `--focus-ring-width`, `--focus-ring-offset` — `minimal` feedback flattens the
|
|
443
|
-
press and thins the focus ring; `subtle` keeps the operator-default ring.
|
|
369
|
+
## 5. Dark and themes — the base set is light
|
|
444
370
|
|
|
445
|
-
The
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
371
|
+
The base token set **is** the light rendering — light is never omitted, and the resolver's `light`
|
|
372
|
+
context is always the empty overlay. A look with dark values ships `design.tokens.dark.json` —
|
|
373
|
+
exactly the `color` group, all 34 roles, nothing else — named by the resolver's `dark` context and
|
|
374
|
+
overlaid per the resolution order. When it ships, emission adds a `[data-theme="dark"]` block
|
|
375
|
+
remapping all 34 roles:
|
|
450
376
|
|
|
451
|
-
|
|
377
|
+
```css
|
|
378
|
+
/* ── Dark theme — OPT-IN ONLY (this look ships a dark overlay). ──
|
|
379
|
+
* design.tokens.dark.json remaps all 34 color tokens; <html data-theme="dark">
|
|
380
|
+
* opts in. Light stays the default. */
|
|
381
|
+
[data-theme="dark"] {
|
|
382
|
+
```
|
|
452
383
|
|
|
453
|
-
|
|
454
|
-
|
|
384
|
+
For a light-only artifact (the shipped default is one), the emitted file carries a placeholder
|
|
385
|
+
comment instead:
|
|
455
386
|
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
387
|
+
```css
|
|
388
|
+
/* ── Dark theme — OPT-IN ONLY. ──
|
|
389
|
+
* Emitted only when the artifact ships a design.tokens.dark.json dark overlay.
|
|
390
|
+
* Light stays the default; this block never appears for a light-only project.
|
|
391
|
+
[data-theme="dark"] {
|
|
392
|
+
--background: ...; --foreground: ...; ... all 34 tokens remapped ...
|
|
393
|
+
} */
|
|
463
394
|
```
|
|
464
395
|
|
|
465
|
-
|
|
466
|
-
|
|
396
|
+
`--theme dark` selects the dark context and sets `<html data-theme="dark">` in the emitted
|
|
397
|
+
attributes (the header's `theme:` line follows). The default is `light`; requesting dark from a
|
|
398
|
+
light-only artifact fails cleanly —
|
|
399
|
+
`node scripts/derive-personality.mjs data/design-tokens/nurix --check --theme dark` prints:
|
|
467
400
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
401
|
+
```
|
|
402
|
+
check FAILED (data/design-tokens/nurix): 1 issue(s)
|
|
403
|
+
- rule 1 — resolver: --theme dark requested but the resolver carries no dark context
|
|
404
|
+
```
|
|
472
405
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
| shadow (`shadow-xs/sm/md/lg`, 58) | `--shadow-*` alpha rides `--shadow-intensity` | `@theme` |
|
|
477
|
-
| font weight (`font-medium/semibold/bold/normal`, 139) | two-weight map to `--font-weight-strong` | `@theme` |
|
|
478
|
-
| tracking (`tracking-*`, 13) | `--tracking-tight/tighter → --heading-tracking` | `@theme` |
|
|
479
|
-
| spacing (all `p-*`/`gap-*`) | `--spacing` density remap | `@theme` |
|
|
480
|
-
| `font-mono` (9) / `font-sans` | inlined font keys | `@theme` |
|
|
481
|
-
| 15 semantic colors (888 uses) | direct token values | `:root[data-theme=light]` |
|
|
482
|
-
| `--success`, `--warning` | direct token values (library ignores today — §11) | `:root[data-theme=light]` |
|
|
483
|
-
| `--destructive-foreground` (unmapped by library) | explicit `--color-destructive-foreground` map | `@theme` |
|
|
484
|
-
| 17 substrate (`popover`/`secondary`/`chart-1..5`/`sidebar` family) | direct token values | `:root[data-theme=light]` |
|
|
485
|
-
| `--sidebar-width` / `--sidebar-width-icon` | SidebarProvider `style` prop | shell (§9) |
|
|
406
|
+
The library's `dark:` utilities are class-based; a dark-shipping project redefines the variant to
|
|
407
|
+
follow the attribute. `globals.css` carries the instruction as a comment, enabled only when dark
|
|
408
|
+
ships:
|
|
486
409
|
|
|
487
|
-
|
|
410
|
+
```css
|
|
411
|
+
/* dark variant — emitted ONLY when the project ships dark; redefines the library's
|
|
412
|
+
* class-based dark to follow data-theme so the library's dark: utilities honor our
|
|
413
|
+
* convention. Absent for a light-only project.
|
|
414
|
+
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *)); */
|
|
415
|
+
```
|
|
488
416
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
overrides:
|
|
417
|
+
Components never use `dark:` prefixes or literal colors regardless — the semantic tokens remap and
|
|
418
|
+
every surface follows (the semantic-token doctrine in the emitted header).
|
|
492
419
|
|
|
493
|
-
|
|
494
|
-
oklch/hex and ignores `--chart-1..5`. Color props are per-instance overridable, but the defaults are
|
|
495
|
-
upstream. Emit `--chart-1..5` regardless, so adoption is a drop-in.
|
|
496
|
-
- **Status literals** — `changes-list` and `statistics` hardcode emerald/amber/sky rather than
|
|
497
|
-
`--success`/`--warning`. Upstream token adoption is the fix.
|
|
498
|
-
- **Motion & icon stroke** — `duration: .2/.3` and `strokeWidth: 2/1.75` are JS numbers; `--duration-*`
|
|
499
|
-
and `--icon-stroke` reach consumer-emitted markup but not library internals.
|
|
500
|
-
- **Filled-control foreground** — `text-white` pinned on filled primary/destructive; the mapped
|
|
501
|
-
`--destructive-foreground` waits on the library reading it.
|
|
420
|
+
## 6. Precedence and provenance — which artifact gets emitted
|
|
502
421
|
|
|
503
|
-
|
|
504
|
-
|
|
422
|
+
Look resolution is project-first: a `project` or `extracted` artifact wins outright; a `library`
|
|
423
|
+
entry serves only when the brief names or resembles the product and the user confirms; the Nurix
|
|
424
|
+
default (`data/design-tokens/nurix/`) is worn when nothing else speaks. The origin is the payload's
|
|
425
|
+
`provenance` field, and the emitted header's `artifact:` line records it alongside the `sourced`
|
|
426
|
+
date — so the emitted CSS always says where its look came from. The full precedence table, payload
|
|
427
|
+
spec, and per-value provenance convention (`$description`) are
|
|
428
|
+
[SCHEMA.md](../data/design-tokens/SCHEMA.md).
|