arkaos 4.29.0 → 4.31.0

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 (131) hide show
  1. package/THE-ARKAOS-GUIDE.md +1 -1
  2. package/VERSION +1 -1
  3. package/config/claude-agents/conversion-strategist.md +1 -1
  4. package/config/claude-agents/extraction-script-writer.md +1 -1
  5. package/config/claude-agents/frontend-dev.md +1 -1
  6. package/config/claude-agents/landing-cro-specialist.md +1 -1
  7. package/config/claude-agents/visual-designer.md +1 -1
  8. package/config/skills-provenance.yaml +17 -3
  9. package/core/governance/evidence_checks.py +185 -1
  10. package/departments/brand/agents/design-ops/extraction-script-writer.yaml +1 -0
  11. package/departments/brand/agents/visual-designer.yaml +1 -0
  12. package/departments/brand/references/uiux-knowledge-and-tools.md +13 -1
  13. package/departments/brand/skills/colors/SKILL.md +9 -1
  14. package/departments/brand/skills/colors/references/hallmark.LICENSE +21 -0
  15. package/departments/brand/skills/colors/references/impeccable.LICENSE +191 -0
  16. package/departments/brand/skills/colors/references/oklch-theme.md +563 -0
  17. package/departments/brand/skills/design-review/SKILL.md +6 -0
  18. package/departments/brand/skills/design-system/SKILL.md +34 -0
  19. package/departments/brand/skills/design-system/references/design-dna-study.md +512 -0
  20. package/departments/brand/skills/design-system/references/design-md-spec.md +454 -0
  21. package/departments/brand/skills/design-system/references/hallmark.LICENSE +21 -0
  22. package/departments/brand/skills/design-system/references/impeccable.LICENSE +191 -0
  23. package/departments/brand/skills/design-system/references/interaction-states.md +306 -0
  24. package/departments/brand/skills/design-system/references/themes/carnival.md +303 -0
  25. package/departments/brand/skills/design-system/references/themes/cobalt.md +148 -0
  26. package/departments/brand/skills/design-system/references/themes/hum.md +405 -0
  27. package/departments/brand/skills/design-system/references/themes/lumen.md +480 -0
  28. package/departments/brand/skills/design-system/references/typography-craft.md +319 -0
  29. package/departments/brand/skills/mockup-generate/SKILL.md +4 -1
  30. package/departments/brand/skills/ux-audit/SKILL.md +4 -1
  31. package/departments/brand/skills/wireframe/SKILL.md +5 -0
  32. package/departments/dev/agents/frontend-dev.yaml +1 -0
  33. package/departments/dev/skills/animated-website/SKILL.md +10 -0
  34. package/departments/dev/skills/animated-website/references/hallmark.LICENSE +21 -0
  35. package/departments/dev/skills/animated-website/references/impeccable.LICENSE +191 -0
  36. package/departments/dev/skills/animated-website/references/motion-recipes.md +546 -0
  37. package/departments/dev/skills/evaluator-build-loop/SKILL.md +5 -0
  38. package/departments/landing/agents/conversion-strategist.yaml +1 -0
  39. package/departments/landing/agents/cro-specialist.yaml +1 -0
  40. package/departments/landing/skills/landing-gen/SKILL.md +16 -5
  41. package/departments/landing/skills/page-architect/SKILL.md +25 -1
  42. package/departments/landing/skills/page-architect/references/component-cookbook.md +265 -0
  43. package/departments/landing/skills/page-architect/references/components/c1-outlined-chip.md +14 -0
  44. package/departments/landing/skills/page-architect/references/components/c2-inline-form-as-cta.md +19 -0
  45. package/departments/landing/skills/page-architect/references/components/c3-typographic-link.md +11 -0
  46. package/departments/landing/skills/page-architect/references/components/c4-sticky-bottom-bar.md +17 -0
  47. package/departments/landing/skills/page-architect/references/components/f1-bento-grid.md +22 -0
  48. package/departments/landing/skills/page-architect/references/components/f2-sticky-scroll-stack.md +23 -0
  49. package/departments/landing/skills/page-architect/references/components/f3-tabular-spec-sheet.md +14 -0
  50. package/departments/landing/skills/page-architect/references/components/f4-step-sequence.md +14 -0
  51. package/departments/landing/skills/page-architect/references/components/f5-annotated-screenshot.md +14 -0
  52. package/departments/landing/skills/page-architect/references/components/f6-product-card-grid.md +42 -0
  53. package/departments/landing/skills/page-architect/references/components/ft1-mast-headed.md +15 -0
  54. package/departments/landing/skills/page-architect/references/components/ft2-inline-rule-single-line.md +13 -0
  55. package/departments/landing/skills/page-architect/references/components/ft3-index-style-category-list.md +15 -0
  56. package/departments/landing/skills/page-architect/references/components/ft4-dense-typographic.md +13 -0
  57. package/departments/landing/skills/page-architect/references/components/ft5-statement.md +24 -0
  58. package/departments/landing/skills/page-architect/references/components/ft6-letter-close.md +22 -0
  59. package/departments/landing/skills/page-architect/references/components/ft7-newsletter-first.md +30 -0
  60. package/departments/landing/skills/page-architect/references/components/ft8-marquee-scroll.md +26 -0
  61. package/departments/landing/skills/page-architect/references/components/h1-marquee.md +17 -0
  62. package/departments/landing/skills/page-architect/references/components/h2-split-diptych.md +18 -0
  63. package/departments/landing/skills/page-architect/references/components/h3-quote-led.md +14 -0
  64. package/departments/landing/skills/page-architect/references/components/h4-stat-led.md +17 -0
  65. package/departments/landing/skills/page-architect/references/components/h5-letter-hero.md +14 -0
  66. package/departments/landing/skills/page-architect/references/components/h6-photographic-fold.md +19 -0
  67. package/departments/landing/skills/page-architect/references/components/h7-demo-video-clipped-by-viewport-edge.md +30 -0
  68. package/departments/landing/skills/page-architect/references/components/h8-mockup-split-browser-framed.md +26 -0
  69. package/departments/landing/skills/page-architect/references/components/h9-custom-illustration-centerpiece.md +28 -0
  70. package/departments/landing/skills/page-architect/references/components/n1-wordmark-2-links.md +14 -0
  71. package/departments/landing/skills/page-architect/references/components/n10-floating-on-scroll-morph.md +20 -0
  72. package/departments/landing/skills/page-architect/references/components/n11-mega-menu.md +43 -0
  73. package/departments/landing/skills/page-architect/references/components/n12-banner-retract.md +37 -0
  74. package/departments/landing/skills/page-architect/references/components/n13-inline-cmdk-pill.md +42 -0
  75. package/departments/landing/skills/page-architect/references/components/n1b-saas-three-section.md +38 -0
  76. package/departments/landing/skills/page-architect/references/components/n2-floating-chip.md +17 -0
  77. package/departments/landing/skills/page-architect/references/components/n3-side-rail.md +17 -0
  78. package/departments/landing/skills/page-architect/references/components/n4-hidden-behind-k.md +12 -0
  79. package/departments/landing/skills/page-architect/references/components/n5-floating-pill.md +31 -0
  80. package/departments/landing/skills/page-architect/references/components/n6-newspaper-masthead.md +27 -0
  81. package/departments/landing/skills/page-architect/references/components/n7-brutal-slab.md +25 -0
  82. package/departments/landing/skills/page-architect/references/components/n8-terminal-command.md +24 -0
  83. package/departments/landing/skills/page-architect/references/components/n9-edge-aligned-minimal.md +20 -0
  84. package/departments/landing/skills/page-architect/references/components/s1-left-margin-numbered.md +17 -0
  85. package/departments/landing/skills/page-architect/references/components/s2-hanging.md +16 -0
  86. package/departments/landing/skills/page-architect/references/components/s3-sticky-pinned.md +22 -0
  87. package/departments/landing/skills/page-architect/references/components/s4-inline-no-break.md +14 -0
  88. package/departments/landing/skills/page-architect/references/components/s5-bottom-anchored.md +14 -0
  89. package/departments/landing/skills/page-architect/references/components/t1-pull-quote-with-marginalia.md +14 -0
  90. package/departments/landing/skills/page-architect/references/components/t2-logo-wall-hairline.md +22 -0
  91. package/departments/landing/skills/page-architect/references/components/t3-single-huge-quote.md +14 -0
  92. package/departments/landing/skills/page-architect/references/components/t4-numbered-stat-strip.md +15 -0
  93. package/departments/landing/skills/page-architect/references/floating-nav.md +91 -0
  94. package/departments/landing/skills/page-architect/references/hallmark.LICENSE +21 -0
  95. package/departments/landing/skills/page-architect/references/hero-enrichment.md +477 -0
  96. package/departments/landing/skills/page-architect/references/impeccable.LICENSE +191 -0
  97. package/departments/landing/skills/page-architect/references/layout-craft.md +236 -0
  98. package/departments/landing/skills/page-architect/references/macrostructures/01-bento-grid.md +37 -0
  99. package/departments/landing/skills/page-architect/references/macrostructures/02-long-document.md +36 -0
  100. package/departments/landing/skills/page-architect/references/macrostructures/03-marquee-hero.md +33 -0
  101. package/departments/landing/skills/page-architect/references/macrostructures/04-stat-led.md +36 -0
  102. package/departments/landing/skills/page-architect/references/macrostructures/05-workbench.md +34 -0
  103. package/departments/landing/skills/page-architect/references/macrostructures/06-conversational-faq.md +35 -0
  104. package/departments/landing/skills/page-architect/references/macrostructures/07-manifesto.md +34 -0
  105. package/departments/landing/skills/page-architect/references/macrostructures/08-photographic.md +36 -0
  106. package/departments/landing/skills/page-architect/references/macrostructures/09-quote-led.md +34 -0
  107. package/departments/landing/skills/page-architect/references/macrostructures/10-specimen.md +34 -0
  108. package/departments/landing/skills/page-architect/references/macrostructures/11-catalogue.md +25 -0
  109. package/departments/landing/skills/page-architect/references/macrostructures/12-letter.md +25 -0
  110. package/departments/landing/skills/page-architect/references/macrostructures/13-index-first.md +25 -0
  111. package/departments/landing/skills/page-architect/references/macrostructures/14-narrative-workflow.md +25 -0
  112. package/departments/landing/skills/page-architect/references/macrostructures/15-split-studio.md +25 -0
  113. package/departments/landing/skills/page-architect/references/macrostructures/16-feature-stack.md +25 -0
  114. package/departments/landing/skills/page-architect/references/macrostructures/17-type-specimen.md +25 -0
  115. package/departments/landing/skills/page-architect/references/macrostructures/18-portfolio-grid.md +25 -0
  116. package/departments/landing/skills/page-architect/references/macrostructures/19-map-diagram.md +25 -0
  117. package/departments/landing/skills/page-architect/references/macrostructures/20-ecosystem-index.md +25 -0
  118. package/departments/landing/skills/page-architect/references/macrostructures/21-component-playground.md +25 -0
  119. package/departments/landing/skills/page-architect/references/macrostructures.md +91 -0
  120. package/departments/landing/skills/page-architect/references/ui-copy.md +75 -0
  121. package/harness/codex/AGENTS.md +1 -1
  122. package/harness/copilot/copilot-instructions.md +1 -1
  123. package/harness/cursor/rules/arkaos.mdc +2 -2
  124. package/harness/gemini/GEMINI.md +1 -1
  125. package/harness/opencode/AGENTS.md +1 -1
  126. package/harness/zed/.rules +1 -1
  127. package/installer/frontend-tooling.js +36 -0
  128. package/knowledge/agents-registry-v2.json +9 -4
  129. package/knowledge/skills-manifest.json +10 -4
  130. package/package.json +1 -1
  131. package/pyproject.toml +1 -1
@@ -0,0 +1,563 @@
1
+ # OKLCH Theme Construction
2
+
3
+ > Derived from [hallmark](https://github.com/nutlope/hallmark) (MIT —
4
+ > Copyright (c) 2026 Hallmark contributors) `references/custom-theme.md`
5
+ > and [impeccable](https://github.com/pbakaus/impeccable) (Apache-2.0 —
6
+ > Copyright Paul Bakaus) `skill/reference/colorize.md`. License texts at
7
+ > `departments/brand/skills/design-review/references/` (`hallmark.LICENSE`,
8
+ > `impeccable.LICENSE`, `impeccable.NOTICE`). Upstream stamps renamed to
9
+ > `[arka:design-dna]`; project memory relocated to `.arka/design/log.json`.
10
+
11
+ A custom theme is **made-to-measure for one brief**, written inline into the
12
+ page's `:root`, never a permanent catalog entry. It spans a spectrum of
13
+ depth: at its lightest, a complete OKLCH palette + free-font pairing tuned
14
+ to the brief while keeping the project's existing structures (the
15
+ *combination* is per-brief); at its fullest — **bespoke** — the page's
16
+ structure and composition are designed from first principles too. One
17
+ route, chosen depth. Every palette below is built in OKLCH, never HSL
18
+ (rationale in § Why OKLCH). <!-- rule:theme-oklch-only -->
19
+
20
+ **The freedom is the combination — never the floor.** Every contrast,
21
+ ban-list, and slop-test constraint still applies at every depth — the
22
+ gates are the floor that never moves (gates:
23
+ `departments/brand/skills/design-review/references/slop-test.md`; ban-list:
24
+ hub §11, `departments/brand/references/uiux-knowledge-and-tools.md`). The
25
+ palette + pairing surface in plain text *before* any code is emitted (the
26
+ token-plan-then-critique loop, hub §8), so the user can redirect early.
27
+ <!-- rule:theme-preview-before-code -->
28
+
29
+ **Register split** (see
30
+ `departments/brand/skills/design-review/references/design-registers.md`):
31
+ on **brand** surfaces the palette IS voice — pick a color strategy first
32
+ (Restrained / Committed / Full palette / Drenched, hub §12) and follow its
33
+ dosage; Committed, Full palette, and Drenched deliberately exceed the ≤10%
34
+ accent rule, and a dominant color can own the page when the strategy calls
35
+ for it. On **product** surfaces color is semantic-first and almost always
36
+ Restrained: accent is reserved for primary action, current selection, and
37
+ state indicators — not decoration — and every color keeps one consistent
38
+ meaning across every screen. More color ≠ better; strategic color beats
39
+ rainbow vomit. <!-- rule:theme-register-split -->
40
+
41
+ ---
42
+
43
+ ## When to construct a custom theme — trigger signals
44
+
45
+ Do not offer custom-vs-existing on every prompt; that's friction, not
46
+ discipline. The default route is the project's design system or a curated
47
+ aesthetic direction (hub §10). Construct a custom OKLCH theme only when
48
+ one of these signals fires:
49
+
50
+ 1. **Explicit ask** — "custom theme", "tailored to our brand", "make it
51
+ ours", "something unique", "I want my own palette".
52
+ 2. **Named brand colour** — a specific anchor as hex / OKLCH / name
53
+ ("use our terracotta", "the brand red is #c0392b", "anchor on sea-blue").
54
+ 3. **Multi-attribute aesthetic no existing direction carries** — three or
55
+ more vibe words pointing at a specific, off-catalog feel ("moss, lichen,
56
+ soft pink, herbal" · "sun-drenched, market-day, carbon-black"). One
57
+ adjective ("warm", "technical", "playful") is not a signal — that's a
58
+ tone any direction already carries.
59
+ 4. **Brand-mood reference attached** — a colour swatch, moodboard, or
60
+ Pantone chip. (A *page* screenshot is a design-DNA study ask — route to
61
+ design-review/refine; custom is for brand colour and mood.)
62
+ 5. **A singular structural vision** — the brief names a structure or
63
+ composition, not just a palette/mood ("from scratch", "ignore the
64
+ catalog", a scroll-assembling poem, a ticket-shaped page). Routes to
65
+ the **bespoke depth** (§ Bespoke depth below).
66
+
67
+ If a signal fires, confirm the route in one short question and wait.
68
+ Silence routes to the default, not to custom. If no signal fires, do not
69
+ mention the fork at all.
70
+
71
+ ## The one follow-up question
72
+
73
+ Once custom is confirmed, ask **one** thing in **one** message:
74
+
75
+ > *"Custom needs one input — describe the brand's vibe in 4–8 words.
76
+ > Examples: 'archival warmth, hand-set, no varnish' · 'industrial
77
+ > precision, cool, technical' · 'moss, lichen, soft pink, herbal'.
78
+ > Optional second input: an anchor colour — hex, OKLCH, or a name like
79
+ > 'terracotta', 'sea-blue'. If you skip it, I'll pick one from the vibe."*
80
+
81
+ **Do not ask anything else.** Audience / use / tone plus the brand vibe is
82
+ already enough signal. The model has no business asking the user to
83
+ nominate paper lightness or font weights — that's the model's job. If the
84
+ user gives a paragraph, accept it but compress to 4–8 words for the stamp.
85
+
86
+ ---
87
+
88
+ ## Palette construction — the algorithm
89
+
90
+ Build the palette in this order. Each step cites the rule it obeys — do
91
+ not restate the rule, just apply it.
92
+
93
+ ### 1 · Anchor accent first
94
+
95
+ - Convert the user's named or hex anchor into OKLCH.
96
+ - Clamp chroma to **0.12–0.20**. <!-- rule:theme-anchor-chroma-clamp -->
97
+ - If the user skipped the anchor: derive hue from the vibe — *warmth* →
98
+ 30–60° · *technical/industrial* → 220–250° · *botanical/moss* → 130–160° ·
99
+ *late-night/neon* → 280–320° · *sun-drenched/market* → 60–80° amber. Keep
100
+ chroma 0.12–0.16 (mid-saturation; saturation comes from contrast against
101
+ neutral, not from chroma).
102
+ - **One accent, strictly.** When the vibe names two hues, one becomes the
103
+ accent and the other becomes the paper/neutral tint (see the Mossroot
104
+ worked example). <!-- rule:theme-single-accent -->
105
+
106
+ ### 2 · Paper
107
+
108
+ - Derive paper L from the vibe: <!-- rule:theme-paper-bands -->
109
+ - bright/airy/breakfast/hand-set → **L 95–98%** (warm-tinted)
110
+ - archival/editorial/restrained → **L 92–95%** (warm-tinted)
111
+ - technical/clinical/spec-sheet → **L 98–100% near-white** (cool-tinted;
112
+ can equal #fff but tinted neutrals downstream)
113
+ - dark/restless/late-night/manifesto → **L 12–18%** (anchor-tinted)
114
+ - **Always tint paper toward the anchor hue with chroma 0.005–0.020.**
115
+ Pure-white #fff is allowed only when ink + accent + greys carry the
116
+ chroma; the paper itself never carries chroma 0 in *both* directions.
117
+ Watch the warm-neutral tell: the generic cream/sand band is the
118
+ saturated AI default (law: hub §12) — tint toward *this brand's* anchor,
119
+ not toward "warm" by reflex. <!-- rule:theme-paper-tint -->
120
+ - Paper-2 (one elevation step): step ±2–4% L from paper.
121
+ - Paper-3 (optional second step): step ±5–7% L from paper. Skip on
122
+ minimal palettes.
123
+
124
+ ### 3 · Ink
125
+
126
+ - If paper L < 50: ink L **88–96%**. <!-- rule:theme-ink-bands -->
127
+ - If paper L ≥ 50: ink L **16–24%**.
128
+ - Tint ink chroma **0.005–0.014** toward anchor (a shade darker / lighter,
129
+ never neutral).
130
+ - Ink-2 (secondary text): step 4–8% L away from ink toward paper. Same
131
+ hue family.
132
+
133
+ ### 4 · Supporting greys
134
+
135
+ Step by ~6–10% L between paper and ink, all tinted toward anchor with
136
+ chroma 0.005–0.018: <!-- rule:theme-grey-ladder -->
137
+
138
+ - `--color-rule` — dividers · L ~70–82% (light paper) or ~26–34% (dark paper).
139
+ - `--color-rule-2` — secondary dividers · 4–6% L closer to paper than rule.
140
+ - `--color-muted` — de-emphasised text · L ~38–56%.
141
+ - `--color-neutral` — mid-grey equivalent · L ~30–56%.
142
+
143
+ These are not arbitrary. The L-step gives the palette **typographic
144
+ depth** without leaning on accent. Muted text must still clear body
145
+ contrast (law: hub §12 — muted-gray-on-tinted-near-white is the single
146
+ biggest readability failure).
147
+
148
+ ### 5 · Focus
149
+
150
+ - Same hue as accent, slightly higher chroma (0.18–0.22) for visibility.
151
+ - Same L as accent ±5%.
152
+ - Used only on `:focus-visible` — the ring must show instantly, never
153
+ animate in (see
154
+ `departments/dev/skills/animated-website/references/motion-recipes.md`).
155
+ <!-- rule:theme-focus-token -->
156
+
157
+ ### 6 · Accent-ink (overlay text colour on accent)
158
+
159
+ - If accent L > 50: use ink (text reads dark on accent fill).
160
+ - If accent L ≤ 50: use paper (text reads light on accent fill).
161
+ - Verify contrast ≥ 7:1 for body-size text on accent, ≥ 3:1 for large
162
+ text. Text and fill must also differ by > 5% lightness or > 0.05 chroma
163
+ in OKLCH — the check that catches the black-on-black button bug
164
+ (law: hub §12). <!-- rule:theme-accent-ink-contrast -->
165
+
166
+ ### 7 · Verification
167
+
168
+ Named checks — the full gate battery lives in
169
+ `departments/brand/skills/design-review/references/slop-test.md`:
170
+
171
+ - **No pure #000/#fff base**: paper and ink both have chroma > 0.
172
+ <!-- rule:theme-verify-no-pure-extremes -->
173
+ - **No zero-chroma neutrals**: every grey has chroma ≥ 0.005.
174
+ <!-- rule:theme-verify-tinted-greys -->
175
+ - **Accent stays a signal**: plan the accent's role on the page (active
176
+ state, one wordmark dot, one CTA fill) — don't carpet a section in
177
+ accent. This is the Restrained-strategy default; when the brief picks
178
+ Committed / Full palette / Drenched (hub §12), the chosen strategy
179
+ governs dosage instead — the footprint cap is Restrained-only.
180
+ <!-- rule:theme-accent-footprint -->
181
+
182
+ ---
183
+
184
+ ## Cross-tone font pairing
185
+
186
+ The palette carries the temperature; the pairing carries the voice.
187
+ Tone-pairing tables group faces by tone (Editorial, Technical, Brutalist,
188
+ Soft, Luxury, Playful, Austere, Workshop), each with a free baseline and a
189
+ paid upgrade. Catalog pairings match Display-from-tone-X with
190
+ Body-from-tone-X. **Custom can mix tones — that's the whole point:**
191
+ <!-- rule:theme-cross-tone-pairing -->
192
+
193
+ - Editorial display + Technical body (italic Fraunces wordmark + Geist
194
+ body) — an academic-tone SaaS.
195
+ - Brutalist display + Editorial body (Anton + Newsreader italic) — a
196
+ left-leaning manifesto magazine.
197
+ - Playful display + Austere body (Bricolage Grotesque + Inter Tight) — a
198
+ creator-tool brand.
199
+ - Luxury display + Technical body (Cormorant Garamond + JetBrains Mono) —
200
+ a hand-crafted dev-tool.
201
+
202
+ Pick **one display face** and **one body face** from any tone's columns.
203
+ Optional mono if the page has code or tabular data.
204
+
205
+ The discipline:
206
+
207
+ - **Free baseline only** unless the user has confirmed paid licences.
208
+ Never name a paid font in code without confirming the licence.
209
+ <!-- rule:theme-free-fonts-only -->
210
+ - **The reflex-reject list still applies** — the canonical font ban-list
211
+ is hub §11 (`departments/brand/references/uiux-knowledge-and-tools.md`).
212
+ Several faces named in this file's examples sit on that list (Fraunces,
213
+ Newsreader, Cormorant Garamond…): using one is legal only as a
214
+ *deliberate pick with a stated reason* — §11's carve-out. Reflex is the
215
+ crime, not the font.
216
+ - **Variable fonts are preferred** when available — they support
217
+ optical-size and weight axes for tighter typographic control.
218
+ - **The pair must read.** Before committing, mentally render the page:
219
+ does the display face have enough weight contrast (200/400 next to
220
+ 700/900)? Does the body face read at ≥ 1rem across a 45–75ch measure?
221
+ Mono display + mono body is allowed only when the single font IS the
222
+ design (terminal aesthetic, true specimen). If any answer is no,
223
+ redirect — pick a different body face or shift the display weight.
224
+
225
+ Pairing depth — tone tables, free-vs-paid columns, sizes, tracking, and
226
+ weight systems — lives in
227
+ `departments/brand/skills/design-system/references/typography-craft.md`.
228
+
229
+ ---
230
+
231
+ ## Theme axes — declare them for diversification
232
+
233
+ A custom theme must declare its three diversification axes explicitly so
234
+ the structural-diversification rule (hub §9: consecutive outputs must
235
+ differ on at least one axis) fires the same way it does on named themes.
236
+ <!-- rule:theme-axes-declared -->
237
+
238
+ **Paper band** — `dark` (paper L < 30%) · `mid` (L 30–85%) · `light`
239
+ (L > 85%).
240
+
241
+ **Display style** — pick one for the chosen display face:
242
+ `italic-serif` (Fraunces italic, Newsreader italic, EB Garamond italic) ·
243
+ `roman-serif` (Source Serif 4, Crimson Pro, Bitter, Cardo) ·
244
+ `geometric-sans` (Geist, Bricolage Grotesque, Manrope, Sora) ·
245
+ `mono` (Geist Mono, JetBrains Mono) ·
246
+ `display-condensed-italic` (Migra italic, Tobias italic) ·
247
+ `display-condensed-bold` (Anton, Bebas Neue, Oswald) ·
248
+ `display-heavy` (Inter Tight 900, Bricolage 800, Druk-class) ·
249
+ `slab-serif` (Roboto Slab, Bitter heavy, Zilla Slab) ·
250
+ `system-native` (austere) · `risograph-bold` · `handwritten` (rare; only
251
+ when the brand demands).
252
+
253
+ **Accent hue band** — `warm` (hue 10–60°) · `cool` (hue 200–300°) ·
254
+ `neutral` (no chromatic accent; chroma < 0.05) · `chromatic-other`
255
+ (anything else — sub-tag the anchor: `chromatic-green ~145°` ·
256
+ `chromatic-terracotta ~30°` · `chromatic-dusty-pink ~350°` ·
257
+ `chromatic-moss ~140°` · `chromatic-amber ~75°`).
258
+
259
+ Write all three into the `[arka:design-dna]` stamp and the
260
+ `.arka/design/log.json` entry (below). They are the durable record; the
261
+ next run reads them. A custom run that follows another custom run must
262
+ differ on at least one axis; a custom run that follows a catalog run must
263
+ differ from the catalog theme's axes. The diversification rule is
264
+ theme-route-blind. <!-- rule:theme-diversification -->
265
+
266
+ ---
267
+
268
+ ## Bespoke depth — custom that designs the whole page
269
+
270
+ Most custom runs are *tuned* (a palette + pairing on existing structures).
271
+ **Bespoke** is the deep end, fired by trigger signal 5: the brief's
272
+ *structure itself* is the ask and no catalog shape fits. At this depth
273
+ custom designs the page from first principles — palette, type, **and**
274
+ composition — and the only thing it inherits is the floor.
275
+
276
+ Confirm the route once (default to the catalog on silence), then take
277
+ **one** input: *"the direction in a sentence or two — what should this
278
+ page feel like and do that an off-the-shelf theme wouldn't?"*
279
+
280
+ **It drops** (only at this depth): the named-theme tokens (write the
281
+ palette inline for this page only — the algorithm above still governs
282
+ *how*); the genre-cluster routing; the fixed macrostructure catalog
283
+ (compose the page's structure for the brief — a novel hero, nav, or
284
+ section is *encouraged* when it serves the idea); the diversification
285
+ rotation (bespoke is a one-off, though it shouldn't clone a recent
286
+ bespoke run).
287
+
288
+ **It keeps** — the non-negotiable floor, identical to tuned custom: every
289
+ slop-test gate (`design-review/references/slop-test.md`); accessibility &
290
+ contrast (WCAG), a visible `:focus-visible`, `prefers-reduced-motion`,
291
+ semantic landmarks, alt text; the font ban-list (hub §11) and
292
+ free-baseline discipline; the OKLCH palette discipline above (tinted
293
+ neutrals, no pure #000/#fff, accent kept to a signal unless the strategy
294
+ earns more); one orchestrated motion; the preview before code; the stamp
295
+ + log.
296
+
297
+ **Process:** read the brief + the one-line direction → design the *system
298
+ and the one central move* (the idea that makes it not-a-template) → run
299
+ the gates *as you compose* → surface the preview (palette, type,
300
+ structure, central idea) → build, stamp, log. Bespoke is **more** design
301
+ judgment, not less — a bespoke page that reads generic, or trips a gate,
302
+ has failed; re-design.
303
+
304
+ **Bespoke is rare.** Most briefs use the project system or a curated
305
+ direction; some are tuned custom; few are bespoke. Reaching for bespoke
306
+ on a vanilla brief is over-reach.
307
+
308
+ ---
309
+
310
+ ## Stamp and log — the durable record
311
+
312
+ The produced stylesheet opens with the `[arka:design-dna]` companion
313
+ stamp (hub §9 — key=value, single line, greppable; the six pre-emit
314
+ critique scores are appended when the §8 critique runs). Custom runs add
315
+ `theme=custom`, `vibe`, `paper`, and `axes` keys:
316
+
317
+ ```css
318
+ /* [arka:design-dna] macrostructure=<name> theme=custom vibe="<4–8 words>" paper=oklch(<L> <C> <H>) anchor=oklch(<L> <C> <H>) display=<font> body=<font> axes=<paper-band>/<display-style>/<accent-hue> critique=P#H#E#S#R#V# */
319
+ ```
320
+
321
+ Bespoke runs record the structure and the central idea instead of a
322
+ catalog macrostructure:
323
+
324
+ ```css
325
+ /* [arka:design-dna] macrostructure=bespoke structure="<one-line shape>" idea="<central move>" theme=custom paper=oklch(...) anchor=oklch(...) display=<font> body=<font> axes=<paper-band>/<display-style>/<accent-hue> critique=P#H#E#S#R#V# */
326
+ ```
327
+
328
+ Custom runs extend the `.arka/design/log.json` schema with a `theme_axes`
329
+ field and an optional `vibe` field:
330
+
331
+ ```json
332
+ { "date": "2026-05-01",
333
+ "macrostructure": "Stat-Led",
334
+ "theme": "custom",
335
+ "theme_axes": "light / italic-serif / chromatic-terracotta",
336
+ "vibe": "archival warmth, hand-set, no varnish",
337
+ "enrichment": "none",
338
+ "brief": "Coffeebox · subscription" }
339
+ ```
340
+
341
+ Catalog entries continue to record `theme: <name>` and skip `theme_axes`.
342
+ The diversification check reads axes from the entry for custom runs and
343
+ from the theme definition for catalog runs.
344
+
345
+ ---
346
+
347
+ ## Three worked examples
348
+
349
+ Concrete generations to seed imitation. Each shows the brief, the vibe
350
+ answer, the constructed palette, the chosen pair, and the stamp.
351
+
352
+ ### Archival café — "Coffeebox"
353
+
354
+ **Brief:** *"Build me a landing page for Coffeebox — a small-batch coffee
355
+ subscription. Roast on Sunday, ship on Monday, drink Tuesday. Audience:
356
+ people who already buy good coffee and want fewer trips to the shop.
357
+ Tone: warm, hand-set, editorial — like a small café's chalkboard. Theme
358
+ route: custom."*
359
+
360
+ **Vibe answer:** *"archival warmth, hand-set, no varnish."*
361
+ **Anchor:** *"terracotta."*
362
+
363
+ **Palette:**
364
+ - paper `oklch(94% 0.020 65)` — warm-cream, hue 65 (amber-warm)
365
+ - paper-2 `oklch(91% 0.022 65)` — one elevation step
366
+ - ink `oklch(22% 0.014 60)` — warm dark brown-black
367
+ - ink-2 `oklch(40% 0.014 60)` — warm secondary
368
+ - rule `oklch(78% 0.018 65)` — warm hairline
369
+ - muted `oklch(54% 0.014 60)` — warm grey
370
+ - accent `oklch(58% 0.16 35)` — terracotta (hue 35, chroma 0.16)
371
+ - accent-ink `oklch(96% 0.014 65)` — paper for text on accent
372
+ - focus `oklch(56% 0.20 35)` — accent at higher chroma
373
+
374
+ **Pair:** display **Fraunces italic** (Editorial, free) · body **Source
375
+ Serif 4** (Editorial, free) · mono **JetBrains Mono** (Technical, free).
376
+ Fraunces is on the hub §11 reflex-reject list — this is a deliberate pick
377
+ for a stated hand-set editorial brief, i.e. the §11 carve-out. Note also
378
+ that warm-cream + serif + terracotta brushes the hub §8 default look:
379
+ legal here because the brief *pins* it ("warm, hand-set, editorial");
380
+ never spend a free axis on it.
381
+
382
+ **Axes:** **light / italic-serif / chromatic-terracotta**.
383
+
384
+ **Stamp:**
385
+ ```css
386
+ /* [arka:design-dna] macrostructure=Long-Document theme=custom vibe="archival warmth, hand-set, no varnish" paper=oklch(94% 0.020 65) anchor=oklch(58% 0.16 35) display=Fraunces-italic body=Source-Serif-4 axes=light/italic-serif/chromatic-terracotta */
387
+ ```
388
+
389
+ ### Industrial fintech — "Loop"
390
+
391
+ **Brief:** *"Loop is a real-time payment-rail observability platform for
392
+ fintechs. Audience: platform engineers. Use case: try it / contact sales.
393
+ Tone: industrial, cool, technical. Theme route: custom."*
394
+
395
+ **Vibe answer:** *"industrial precision, cool, technical."*
396
+ **Anchor:** *"sea-blue."*
397
+
398
+ **Palette:**
399
+ - paper `oklch(13% 0.012 220)` — dark cool
400
+ - paper-2 `oklch(17% 0.014 220)` — one step up
401
+ - paper-3 `oklch(22% 0.014 220)` — two steps up (panels)
402
+ - ink `oklch(94% 0.010 220)` — cool light
403
+ - ink-2 `oklch(72% 0.010 220)`
404
+ - rule `oklch(30% 0.012 220)`
405
+ - muted `oklch(58% 0.012 220)`
406
+ - accent `oklch(72% 0.16 220)` — sea-blue (cool)
407
+ - focus `oklch(78% 0.20 220)`
408
+
409
+ **Pair:** display **Geist Mono 500** (Technical, free) · body **Geist**
410
+ (Technical, free) · mono **Geist Mono** (Technical, free).
411
+
412
+ Note: this *is* a single-family page (Geist + Geist Mono are the same
413
+ family at different widths). Single-font pages are allowed only when the
414
+ single font IS the design choice — for an industrial-precision fintech,
415
+ it is.
416
+
417
+ **Axes:** **dark / mono / cool**.
418
+
419
+ **Stamp:**
420
+ ```css
421
+ /* [arka:design-dna] macrostructure=Workbench theme=custom vibe="industrial precision, cool, technical" paper=oklch(13% 0.012 220) anchor=oklch(72% 0.16 220) display=Geist-Mono-500 body=Geist axes=dark/mono/cool */
422
+ ```
423
+
424
+ ### Botanical apothecary — "Mossroot"
425
+
426
+ **Brief:** *"Mossroot is a small herbal apothecary in Porto. We make
427
+ tinctures, salves, and tea blends. Audience: locals + visitors. Use: see
428
+ what we make + visit. Tone: quiet, herbal, hand-poured. Theme route:
429
+ custom."*
430
+
431
+ **Vibe answer:** *"moss, lichen, soft pink, herbal."*
432
+ **Anchor:** *(skipped — pick from vibe)*.
433
+
434
+ The vibe names two hues: *moss* (greenish, ~140°) and *soft pink* (warm,
435
+ ~350°). Pick **soft pink as the accent** (single anchor — custom is
436
+ one-accent strict) and use the moss-green as the *paper tint* (chroma
437
+ 0.018 toward 145°). This carries the dual-vibe without splitting accent.
438
+
439
+ **Palette:**
440
+ - paper `oklch(96% 0.018 145)` — moss-tinted near-white
441
+ - paper-2 `oklch(93% 0.020 145)`
442
+ - ink `oklch(22% 0.014 140)` — moss-tinted dark
443
+ - ink-2 `oklch(42% 0.014 140)`
444
+ - rule `oklch(82% 0.018 145)`
445
+ - muted `oklch(56% 0.014 140)`
446
+ - accent `oklch(72% 0.13 350)` — dusty-pink (chromatic-other)
447
+ - focus `oklch(70% 0.18 350)`
448
+
449
+ **Pair:** display **Cormorant Garamond** (Luxury, free) · body **EB
450
+ Garamond** (Luxury, free) · mono **Geist Mono** (rare on this page; only
451
+ for ingredient lists). Cormorant Garamond is §11-listed — deliberate pick
452
+ for a quiet, hand-poured luxury register; state the reason in the plan.
453
+
454
+ **Axes:** **light / roman-serif / chromatic-other (dusty-pink)**.
455
+
456
+ **Stamp:**
457
+ ```css
458
+ /* [arka:design-dna] macrostructure=Catalogue theme=custom vibe="moss, lichen, soft pink, herbal" paper=oklch(96% 0.018 145) anchor=oklch(72% 0.13 350) display=Cormorant-Garamond body=EB-Garamond axes=light/roman-serif/chromatic-other-dusty-pink */
459
+ ```
460
+
461
+ ---
462
+
463
+ ## Why OKLCH — stop using HSL
464
+
465
+ **Stop using HSL.** Use OKLCH (or LCH) instead. It's perceptually
466
+ uniform: equal steps in lightness *look* equal, unlike HSL where 50%
467
+ lightness in yellow looks bright while 50% in blue looks dark.
468
+
469
+ `oklch(lightness chroma hue)` — lightness 0–100%, chroma roughly 0–0.4,
470
+ hue 0–360. To build a colour and its lighter/darker variants, hold
471
+ chroma + hue roughly constant and vary the lightness, but **reduce chroma
472
+ as you approach white or black** — high chroma at extreme lightness looks
473
+ garish.
474
+
475
+ The hue you pick is a brand decision and should not come from a default.
476
+ Do not reach for blue (hue 250) or warm orange (hue 60) by reflex; those
477
+ are the dominant AI-design defaults, not the right answer for any
478
+ specific brand.
479
+
480
+ ## Tinted neutrals — why the algorithm tints everything
481
+
482
+ **Pure gray is dead.** A neutral with zero chroma feels lifeless next to
483
+ a coloured brand. That is why every step of the algorithm above tints
484
+ toward the anchor: add a tiny chroma value (0.005–0.015; paper may reach
485
+ 0.020 on warm atmospheric briefs) to all neutrals, hued toward the brand
486
+ colour (law: hub §12). The chroma is small enough not to read as "tinted"
487
+ consciously, but it creates subconscious cohesion between brand colour
488
+ and UI surfaces. <!-- rule:theme-tinted-neutrals-rationale -->
489
+
490
+ The hue you tint toward comes from THIS project's brand, not from a
491
+ "warm = friendly, cool = tech" formula. If the brand colour is teal, the
492
+ neutrals lean teal; if amber, they lean amber. **Avoid** the trap of
493
+ always tinting warm-orange or always cool-blue — those are the two
494
+ laziest defaults and they create their own monoculture across projects.
495
+ The generic warm tint (`oklch(97% 0.01 60)` and neighbours) is now the AI
496
+ cream/sand giveaway: be specific to the brand or stay neutral.
497
+
498
+ ## Gray on colour
499
+
500
+ Never put gray text on coloured backgrounds — it looks washed out (law:
501
+ hub §12). Use a darker shade of the background's own hue, or a
502
+ transparency of the text colour, so the "muted" step stays inside the
503
+ fill's colour family. This is why the algorithm derives accent-ink from
504
+ paper or ink (same hue family) rather than from a neutral.
505
+ <!-- rule:theme-gray-on-color -->
506
+
507
+ ## Alpha is a design smell
508
+
509
+ Heavy use of transparency (`rgba`, `hsla`, low-alpha `oklch`) usually
510
+ means an incomplete palette. Alpha creates unpredictable contrast,
511
+ performance overhead, and inconsistency. The grey ladder above exists so
512
+ you never need it: define explicit overlay colours for each context
513
+ instead. Exception: focus rings and interactive states where see-through
514
+ is genuinely needed (law: hub §12). <!-- rule:theme-alpha-smell -->
515
+
516
+ ## Dark mode is not inverted light mode
517
+
518
+ You can't just swap colours. Dark mode requires different design
519
+ decisions: <!-- rule:theme-dark-mode-surfaces -->
520
+
521
+ | Light mode | Dark mode |
522
+ |------------|-----------|
523
+ | Shadows for depth | Lighter surfaces for depth (no shadows) |
524
+ | Dark text on light | Light text on dark (reduce font weight) |
525
+ | Vibrant accents | Desaturate accents slightly |
526
+ | White backgrounds | Either pure black or a deep surface that fits the brand (a brand-tinted near-black at oklch 12–18% — the algorithm's dark paper band) |
527
+
528
+ In dark mode, depth comes from surface lightness, not shadow. Build a
529
+ 3-step surface scale where higher elevations are lighter (the paper /
530
+ paper-2 / paper-3 ladder — e.g. 15% / 20% / 25% L). Use the SAME hue and
531
+ chroma as the brand anchor (whatever it is for THIS project; do not reach
532
+ for blue) and only vary the lightness. Reduce body text weight slightly
533
+ (e.g. 350 instead of 400): light text on dark reads heavier than dark
534
+ text on light. <!-- rule:theme-dark-mode-body-weight -->
535
+
536
+ **Token hierarchy:** use two layers — primitive tokens (`--blue-500`) and
537
+ semantic tokens (`--color-primary: var(--blue-500)`). For dark mode,
538
+ redefine only the semantic layer; primitives stay the same.
539
+
540
+ ---
541
+
542
+ ## What custom does **not** do (worth restating)
543
+
544
+ 1. **Does not invent themes that ignore the rules.** Every paper L band,
545
+ accent chroma cap, neutral-tinting requirement, font ban (hub §11), and
546
+ slop-test gate carries forward. The freedom is the *combination* — not
547
+ the rules.
548
+ 2. **Does not save themes for reuse.** A custom run is per-output; the
549
+ skill does not write back to any shared token file. If the user wants a
550
+ permanent theme, they promote the palette into the project's design
551
+ system themselves and name it. <!-- rule:theme-no-permanent-themes -->
552
+ 3. **Does not ask multiple follow-up questions.** One vibe answer
553
+ (+ optional anchor) is enough — the brief plus the structure pick
554
+ already give 80% of the signal.
555
+ 4. **Does not relax the diversification rule.** Custom entries declare
556
+ their three axes the same way catalog entries do; the rotation fires on
557
+ both, theme-route-blind.
558
+ 5. **Does not bypass the preview.** The palette + pairing surface in
559
+ plain text *before* any code is emitted (hub §8 loop), so the user can
560
+ redirect early.
561
+
562
+ If any of those five lines is bent, the custom output is over-invented.
563
+ Audit it; redirect.
@@ -112,6 +112,12 @@ For every captured surface, annotate deviations with exact values
112
112
  - **Benchmark contrast** — for each major finding, one line on what the
113
113
  named benchmark does instead.
114
114
 
115
+ > The deterministic half of this review also runs mechanically as the
116
+ > QG evidence check `design-slop` (`core.governance.evidence_checks` —
117
+ > the external `impeccable` detector over changed UI files, fail-open);
118
+ > cite its finding `antipattern` ids in verdicts when the report
119
+ > carries them.
120
+
115
121
  ## Slop gates (pre-verdict — MANDATORY)
116
122
 
117
123
  Before issuing any verdict, run the reviewed surfaces through
@@ -11,6 +11,10 @@ description: >
11
11
  specifies the system, it does not build the app); reviewing an existing UI
12
12
  against brand guidelines -> brand/design-review.
13
13
  allowed-tools: [Read, Write, Edit, Bash, Grep, Glob, Agent, WebFetch, WebSearch]
14
+ metadata:
15
+ origin: community
16
+ source: https://github.com/nutlope/hallmark
17
+ license: MIT
14
18
  ---
15
19
 
16
20
  <!-- arka:kb-first-prefix begin -->
@@ -66,6 +70,36 @@ A production design system in 5 deliverables:
66
70
  4. **Storybook story stubs** — one story per component, ready to drop into Storybook
67
71
  5. **Integration guide** — how to wire the system into a Vue/React/Vanilla project
68
72
 
73
+ ## Study mode (design DNA extraction)
74
+
75
+ When the operator brings a **reference** — a screenshot or a live URL —
76
+ instead of a brief, run the study protocol in
77
+ `references/design-dna-study.md`: it extracts structural DNA
78
+ (macrostructure, archetypes, type roles, colour anchor, rhythm) into a
79
+ JSON schema + human diagnosis, *structure not pixels*. The protocol's
80
+ refusal layer (template marketplaces, signature designer work), SSRF
81
+ safety rules and attestation gate are mandatory and not negotiable.
82
+ A completed study suspends the theme catalog: the studied DNA IS the
83
+ system (`theme=studied-DNA` in the `[arka:design-dna]` stamp).
84
+
85
+ ## design.md lock (portable output)
86
+
87
+ The system can emit a portable `design.md` at the project root per
88
+ `references/design-md-spec.md` — tokens, components, motion and identity
89
+ rules any compatible agent can consume — with exports to `tokens.css`,
90
+ Tailwind v4 `@theme`, DTCG `tokens.json` and shadcn CSS vars. When the
91
+ project declares `design-system.yaml` (rule `design-system-locked`),
92
+ mirror the emitted tokens into the token source named by the
93
+ `[arka:design] tokens=` marker field.
94
+
95
+ ## Craft references (load per need, not wholesale)
96
+
97
+ - `references/typography-craft.md` — 2+1 rule, rem-vs-clamp doctrine,
98
+ pairing tables, font-loading mechanics (ban lists live in hub §11).
99
+ - `references/interaction-states.md` — the 8-state model + input rules.
100
+ - `references/themes/` — 4 opt-in theme specs (carnival, cobalt, hum,
101
+ lumen); themes are seeds, never the final system (hub §10).
102
+
69
103
  ## Token JSON schema
70
104
 
71
105
  The token system has a **two-layer architecture**: raw primitives + semantic aliases. Semantic tokens reference primitives; surfaces reference semantic tokens. Never reference primitives directly in components.