howone 0.1.29 → 0.1.30

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 (219) hide show
  1. package/package.json +1 -1
  2. package/templates/vite/.howone/skills/hallmark/SKILL.md +48 -42
  3. package/templates/vite/.howone/skills/hallmark/references/anti-patterns.md +12 -6
  4. package/templates/vite/.howone/skills/hallmark/references/assets.md +7 -0
  5. package/templates/vite/.howone/skills/hallmark/references/component-cookbook.md +19 -10
  6. package/templates/vite/.howone/skills/hallmark/references/components/f2-sticky-scroll-stack.md +1 -1
  7. package/templates/vite/.howone/skills/hallmark/references/components/ft6-letter-close.md +1 -1
  8. package/templates/vite/.howone/skills/hallmark/references/components/h7-demo-video-clipped-by-viewport-edge.md +1 -1
  9. package/templates/vite/.howone/skills/hallmark/references/components/h9-custom-illustration-centerpiece.md +1 -1
  10. package/templates/vite/.howone/skills/hallmark/references/components/n10-floating-on-scroll-morph.md +1 -1
  11. package/templates/vite/.howone/skills/hallmark/references/components/n11-mega-menu.md +40 -0
  12. package/templates/vite/.howone/skills/hallmark/references/components/n12-banner-retract.md +34 -0
  13. package/templates/vite/.howone/skills/hallmark/references/components/n13-inline-cmdk-pill.md +39 -0
  14. package/templates/vite/.howone/skills/hallmark/references/components/n1b-saas-three-section.md +35 -0
  15. package/templates/vite/.howone/skills/hallmark/references/components/n9-edge-aligned-minimal.md +1 -1
  16. package/templates/vite/.howone/skills/hallmark/references/components/s3-sticky-pinned.md +2 -2
  17. package/templates/vite/.howone/skills/hallmark/references/copy.md +8 -8
  18. package/templates/vite/.howone/skills/hallmark/references/custom-craft.md +2 -2
  19. package/templates/vite/.howone/skills/hallmark/references/custom-theme.md +50 -12
  20. package/templates/vite/.howone/skills/hallmark/references/export-formats.md +1 -1
  21. package/templates/vite/.howone/skills/hallmark/references/genres/atmospheric.md +11 -7
  22. package/templates/vite/.howone/skills/hallmark/references/genres/editorial.md +6 -4
  23. package/templates/vite/.howone/skills/hallmark/references/genres/modern-minimal.md +10 -6
  24. package/templates/vite/.howone/skills/hallmark/references/genres/playful.md +15 -10
  25. package/templates/vite/.howone/skills/hallmark/references/hero-enrichment.md +13 -12
  26. package/templates/vite/.howone/skills/hallmark/references/interaction-and-states.md +2 -1
  27. package/templates/vite/.howone/skills/hallmark/references/layout-and-space.md +4 -3
  28. package/templates/vite/.howone/skills/hallmark/references/macrostructures/04-stat-led.md +3 -1
  29. package/templates/vite/.howone/skills/hallmark/references/macrostructures/12-letter.md +1 -1
  30. package/templates/vite/.howone/skills/hallmark/references/macrostructures.md +1 -1
  31. package/templates/vite/.howone/skills/hallmark/references/microinteractions.md +1 -3
  32. package/templates/vite/.howone/skills/hallmark/references/preview-examples.md +12 -12
  33. package/templates/vite/.howone/skills/hallmark/references/responsive.md +8 -8
  34. package/templates/vite/.howone/skills/hallmark/references/slop-test.md +72 -85
  35. package/templates/vite/.howone/skills/hallmark/references/structure.md +9 -13
  36. package/templates/vite/.howone/skills/hallmark/references/study.md +40 -17
  37. package/templates/vite/.howone/skills/hallmark/references/themes/carnival.md +301 -0
  38. package/templates/vite/.howone/skills/hallmark/references/themes/cobalt.md +146 -0
  39. package/templates/vite/.howone/skills/hallmark/references/themes/hum.md +403 -0
  40. package/templates/vite/.howone/skills/hallmark/references/themes/lumen.md +478 -0
  41. package/templates/vite/.howone/skills/hallmark/references/typography.md +3 -3
  42. package/templates/vite/.howone/skills/hallmark/references/verbs/redesign.md +1 -1
  43. package/templates/vite/.howone/skills/hallmark/LICENSE +0 -21
  44. package/templates/vite/.howone/skills/hallmark/README.md +0 -147
  45. package/templates/vite/.howone/skills/hallmark/ROADMAP.md +0 -201
  46. package/templates/vite/.howone/skills/hallmark/docs/recipes.md +0 -186
  47. package/templates/vite/.howone/skills/hallmark/docs/screenshots/hero-anya.jpg +0 -0
  48. package/templates/vite/.howone/skills/hallmark/docs/screenshots/hero-bananastudio.jpg +0 -0
  49. package/templates/vite/.howone/skills/hallmark/docs/screenshots/hero-hyperlane.jpg +0 -0
  50. package/templates/vite/.howone/skills/hallmark/docs/screenshots/hero-najm.jpg +0 -0
  51. package/templates/vite/.howone/skills/hallmark/docs/screenshots/hero-slow-pour.jpg +0 -0
  52. package/templates/vite/.howone/skills/hallmark/docs/screenshots/hero-soroe.jpg +0 -0
  53. package/templates/vite/.howone/skills/hallmark/docs/screenshots/hero-tally.jpg +0 -0
  54. package/templates/vite/.howone/skills/hallmark/docs/screenshots/hero-wayfare.jpg +0 -0
  55. package/templates/vite/.howone/skills/hallmark/docs/study-examples.md +0 -176
  56. package/templates/vite/.howone/skills/hallmark/docs/talk-slides.md +0 -364
  57. package/templates/vite/.howone/skills/hallmark/package.json +0 -36
  58. package/templates/vite/.howone/skills/hallmark/site/OG-hallmark.png +0 -0
  59. package/templates/vite/.howone/skills/hallmark/site/_tests/01-tide-podcast/brief.md +0 -71
  60. package/templates/vite/.howone/skills/hallmark/site/_tests/01-tide-podcast/index.html +0 -64
  61. package/templates/vite/.howone/skills/hallmark/site/_tests/01-tide-podcast/style.css +0 -240
  62. package/templates/vite/.howone/skills/hallmark/site/_tests/02-streampipe-cli/brief.md +0 -65
  63. package/templates/vite/.howone/skills/hallmark/site/_tests/02-streampipe-cli/index.html +0 -105
  64. package/templates/vite/.howone/skills/hallmark/site/_tests/02-streampipe-cli/style.css +0 -250
  65. package/templates/vite/.howone/skills/hallmark/site/_tests/03-maple-bakery/brief.md +0 -64
  66. package/templates/vite/.howone/skills/hallmark/site/_tests/03-maple-bakery/index.html +0 -131
  67. package/templates/vite/.howone/skills/hallmark/site/_tests/03-maple-bakery/style.css +0 -240
  68. package/templates/vite/.howone/skills/hallmark/site/_tests/04-meridian-manifesto/brief.md +0 -67
  69. package/templates/vite/.howone/skills/hallmark/site/_tests/04-meridian-manifesto/index.html +0 -86
  70. package/templates/vite/.howone/skills/hallmark/site/_tests/04-meridian-manifesto/style.css +0 -262
  71. package/templates/vite/.howone/skills/hallmark/site/_tests/05-tracejam-saas/brief.md +0 -63
  72. package/templates/vite/.howone/skills/hallmark/site/_tests/05-tracejam-saas/index.html +0 -167
  73. package/templates/vite/.howone/skills/hallmark/site/_tests/05-tracejam-saas/style.css +0 -457
  74. package/templates/vite/.howone/skills/hallmark/site/_tests/06-anya-portfolio/brief.md +0 -65
  75. package/templates/vite/.howone/skills/hallmark/site/_tests/06-anya-portfolio/index.html +0 -159
  76. package/templates/vite/.howone/skills/hallmark/site/_tests/06-anya-portfolio/style.css +0 -288
  77. package/templates/vite/.howone/skills/hallmark/site/_tests/07-foundry-compliance/brief.md +0 -64
  78. package/templates/vite/.howone/skills/hallmark/site/_tests/07-foundry-compliance/index.html +0 -146
  79. package/templates/vite/.howone/skills/hallmark/site/_tests/07-foundry-compliance/style.css +0 -484
  80. package/templates/vite/.howone/skills/hallmark/site/_tests/08-cohort-courses/brief.md +0 -64
  81. package/templates/vite/.howone/skills/hallmark/site/_tests/08-cohort-courses/index.html +0 -116
  82. package/templates/vite/.howone/skills/hallmark/site/_tests/08-cohort-courses/style.css +0 -354
  83. package/templates/vite/.howone/skills/hallmark/site/_tests/09-slow-pour/index.html +0 -638
  84. package/templates/vite/.howone/skills/hallmark/site/_tests/10-owl-hours/index.html +0 -515
  85. package/templates/vite/.howone/skills/hallmark/site/_tests/11-soroe-ceramics/index.html +0 -515
  86. package/templates/vite/.howone/skills/hallmark/site/_tests/12-loafer/index.html +0 -608
  87. package/templates/vite/.howone/skills/hallmark/site/_tests/13-alma/index.html +0 -587
  88. package/templates/vite/.howone/skills/hallmark/site/_tests/README.md +0 -157
  89. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/BananaStudio-loop.mp4 +0 -0
  90. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/BananaStudio-still.jpg +0 -0
  91. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/Hyperlane-example.mp4 +0 -0
  92. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/Hyperlane-still.jpg +0 -0
  93. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/Najm-loop.mp4 +0 -0
  94. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/Najm-still.jpg +0 -0
  95. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/Podcast-loop.mp4 +0 -0
  96. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/SaaS-loop.mp4 +0 -0
  97. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/SaaS-still.jpg +0 -0
  98. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/Soroe-loop.mp4 +0 -0
  99. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/Soroe-still.jpg +0 -0
  100. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/after-quiet-hour.png +0 -0
  101. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/anya-loop.mp4 +0 -0
  102. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/anya-still.jpg +0 -0
  103. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/audit-example.png +0 -0
  104. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/before-quiet-hour.png +0 -0
  105. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/example-redesign-uractivation.png +0 -0
  106. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/slow-pour-loop.mp4 +0 -0
  107. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/slow-pour-still.jpg +0 -0
  108. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/study-example.png +0 -0
  109. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/uractivation-after-loop.mp4 +0 -0
  110. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/wayfare-loop.mp4 +0 -0
  111. package/templates/vite/.howone/skills/hallmark/site/_tests/_thumbs/wayfare-still.jpg +0 -0
  112. package/templates/vite/.howone/skills/hallmark/site/_tests/custom/01-coffeebox/index.html +0 -77
  113. package/templates/vite/.howone/skills/hallmark/site/_tests/custom/01-coffeebox/style.css +0 -238
  114. package/templates/vite/.howone/skills/hallmark/site/_tests/custom/02-loop/index.html +0 -110
  115. package/templates/vite/.howone/skills/hallmark/site/_tests/custom/02-loop/style.css +0 -326
  116. package/templates/vite/.howone/skills/hallmark/site/_tests/custom/03-mossroot/index.html +0 -134
  117. package/templates/vite/.howone/skills/hallmark/site/_tests/custom/03-mossroot/style.css +0 -262
  118. package/templates/vite/.howone/skills/hallmark/site/_tests/custom/README.md +0 -30
  119. package/templates/vite/.howone/skills/hallmark/site/_tests/verbs/README.md +0 -17
  120. package/templates/vite/.howone/skills/hallmark/site/_tests/verbs/audit/audit-report.md +0 -56
  121. package/templates/vite/.howone/skills/hallmark/site/_tests/verbs/audit/input.html +0 -160
  122. package/templates/vite/.howone/skills/hallmark/site/_tests/verbs/audit/notes.md +0 -29
  123. package/templates/vite/.howone/skills/hallmark/site/_tests/verbs/redesign/input.html +0 -63
  124. package/templates/vite/.howone/skills/hallmark/site/_tests/verbs/redesign/notes.md +0 -72
  125. package/templates/vite/.howone/skills/hallmark/site/_tests/verbs/redesign/output.html +0 -374
  126. package/templates/vite/.howone/skills/hallmark/site/_tests/verbs/study/diagnosis.md +0 -52
  127. package/templates/vite/.howone/skills/hallmark/site/_tests/verbs/study/input-description.md +0 -29
  128. package/templates/vite/.howone/skills/hallmark/site/_tests/verbs/study/notes.md +0 -61
  129. package/templates/vite/.howone/skills/hallmark/site/_tests/verbs/study/output.css +0 -193
  130. package/templates/vite/.howone/skills/hallmark/site/_tests/verbs/study/output.html +0 -66
  131. package/templates/vite/.howone/skills/hallmark/site/css/base.css +0 -194
  132. package/templates/vite/.howone/skills/hallmark/site/css/components.css +0 -4886
  133. package/templates/vite/.howone/skills/hallmark/site/css/sections.css +0 -2072
  134. package/templates/vite/.howone/skills/hallmark/site/css/tokens.css +0 -1129
  135. package/templates/vite/.howone/skills/hallmark/site/examples/bananastudio/index.html +0 -475
  136. package/templates/vite/.howone/skills/hallmark/site/examples/bananastudio/styles.css +0 -1584
  137. package/templates/vite/.howone/skills/hallmark/site/examples/bananastudio/tokens.css +0 -96
  138. package/templates/vite/.howone/skills/hallmark/site/examples/hyperlane/index.html +0 -344
  139. package/templates/vite/.howone/skills/hallmark/site/examples/hyperlane/script.js +0 -103
  140. package/templates/vite/.howone/skills/hallmark/site/examples/hyperlane/styles.css +0 -1103
  141. package/templates/vite/.howone/skills/hallmark/site/examples/hyperlane/tokens.css +0 -83
  142. package/templates/vite/.howone/skills/hallmark/site/examples/najm/index.html +0 -368
  143. package/templates/vite/.howone/skills/hallmark/site/examples/najm/script.js +0 -133
  144. package/templates/vite/.howone/skills/hallmark/site/examples/najm/styles.css +0 -1062
  145. package/templates/vite/.howone/skills/hallmark/site/examples/najm/tokens.css +0 -97
  146. package/templates/vite/.howone/skills/hallmark/site/examples/tally/app.js +0 -84
  147. package/templates/vite/.howone/skills/hallmark/site/examples/tally/index.html +0 -446
  148. package/templates/vite/.howone/skills/hallmark/site/examples/tally/styles.css +0 -1087
  149. package/templates/vite/.howone/skills/hallmark/site/examples/tally/tokens.css +0 -101
  150. package/templates/vite/.howone/skills/hallmark/site/examples/wayfare/index.html +0 -359
  151. package/templates/vite/.howone/skills/hallmark/site/examples/wayfare/style.css +0 -1168
  152. package/templates/vite/.howone/skills/hallmark/site/examples/wayfare/tokens.css +0 -81
  153. package/templates/vite/.howone/skills/hallmark/site/favicon-dark.svg +0 -5
  154. package/templates/vite/.howone/skills/hallmark/site/favicon-light.svg +0 -5
  155. package/templates/vite/.howone/skills/hallmark/site/index.html +0 -1043
  156. package/templates/vite/.howone/skills/hallmark/site/js/main.js +0 -1175
  157. package/templates/vite/.howone/skills/hallmark/vercel.json +0 -6
  158. package/templates/vite/.howone/skills/impeccable/SKILL.md +0 -168
  159. package/templates/vite/.howone/skills/impeccable/agents/impeccable-asset-producer.md +0 -101
  160. package/templates/vite/.howone/skills/impeccable/reference/adapt.md +0 -190
  161. package/templates/vite/.howone/skills/impeccable/reference/animate.md +0 -175
  162. package/templates/vite/.howone/skills/impeccable/reference/audit.md +0 -133
  163. package/templates/vite/.howone/skills/impeccable/reference/bolder.md +0 -113
  164. package/templates/vite/.howone/skills/impeccable/reference/brand.md +0 -118
  165. package/templates/vite/.howone/skills/impeccable/reference/clarify.md +0 -174
  166. package/templates/vite/.howone/skills/impeccable/reference/codex.md +0 -105
  167. package/templates/vite/.howone/skills/impeccable/reference/cognitive-load.md +0 -106
  168. package/templates/vite/.howone/skills/impeccable/reference/color-and-contrast.md +0 -105
  169. package/templates/vite/.howone/skills/impeccable/reference/colorize.md +0 -154
  170. package/templates/vite/.howone/skills/impeccable/reference/craft.md +0 -123
  171. package/templates/vite/.howone/skills/impeccable/reference/critique.md +0 -273
  172. package/templates/vite/.howone/skills/impeccable/reference/delight.md +0 -302
  173. package/templates/vite/.howone/skills/impeccable/reference/distill.md +0 -111
  174. package/templates/vite/.howone/skills/impeccable/reference/document.md +0 -427
  175. package/templates/vite/.howone/skills/impeccable/reference/extract.md +0 -69
  176. package/templates/vite/.howone/skills/impeccable/reference/harden.md +0 -347
  177. package/templates/vite/.howone/skills/impeccable/reference/heuristics-scoring.md +0 -234
  178. package/templates/vite/.howone/skills/impeccable/reference/interaction-design.md +0 -195
  179. package/templates/vite/.howone/skills/impeccable/reference/layout.md +0 -141
  180. package/templates/vite/.howone/skills/impeccable/reference/live.md +0 -622
  181. package/templates/vite/.howone/skills/impeccable/reference/motion-design.md +0 -109
  182. package/templates/vite/.howone/skills/impeccable/reference/onboard.md +0 -234
  183. package/templates/vite/.howone/skills/impeccable/reference/optimize.md +0 -258
  184. package/templates/vite/.howone/skills/impeccable/reference/overdrive.md +0 -130
  185. package/templates/vite/.howone/skills/impeccable/reference/personas.md +0 -179
  186. package/templates/vite/.howone/skills/impeccable/reference/polish.md +0 -242
  187. package/templates/vite/.howone/skills/impeccable/reference/product.md +0 -62
  188. package/templates/vite/.howone/skills/impeccable/reference/quieter.md +0 -99
  189. package/templates/vite/.howone/skills/impeccable/reference/responsive-design.md +0 -114
  190. package/templates/vite/.howone/skills/impeccable/reference/shape.md +0 -165
  191. package/templates/vite/.howone/skills/impeccable/reference/spatial-design.md +0 -100
  192. package/templates/vite/.howone/skills/impeccable/reference/teach.md +0 -156
  193. package/templates/vite/.howone/skills/impeccable/reference/typeset.md +0 -124
  194. package/templates/vite/.howone/skills/impeccable/reference/typography.md +0 -159
  195. package/templates/vite/.howone/skills/impeccable/reference/ux-writing.md +0 -107
  196. package/templates/vite/.howone/skills/impeccable/scripts/cleanup-deprecated.mjs +0 -284
  197. package/templates/vite/.howone/skills/impeccable/scripts/command-metadata.json +0 -94
  198. package/templates/vite/.howone/skills/impeccable/scripts/critique-storage.mjs +0 -242
  199. package/templates/vite/.howone/skills/impeccable/scripts/design-parser.mjs +0 -820
  200. package/templates/vite/.howone/skills/impeccable/scripts/detect-csp.mjs +0 -198
  201. package/templates/vite/.howone/skills/impeccable/scripts/detect.mjs +0 -21
  202. package/templates/vite/.howone/skills/impeccable/scripts/impeccable-paths.mjs +0 -110
  203. package/templates/vite/.howone/skills/impeccable/scripts/is-generated.mjs +0 -69
  204. package/templates/vite/.howone/skills/impeccable/scripts/live-accept.mjs +0 -595
  205. package/templates/vite/.howone/skills/impeccable/scripts/live-browser-session.js +0 -123
  206. package/templates/vite/.howone/skills/impeccable/scripts/live-browser.js +0 -4860
  207. package/templates/vite/.howone/skills/impeccable/scripts/live-complete.mjs +0 -75
  208. package/templates/vite/.howone/skills/impeccable/scripts/live-completion.mjs +0 -18
  209. package/templates/vite/.howone/skills/impeccable/scripts/live-inject.mjs +0 -446
  210. package/templates/vite/.howone/skills/impeccable/scripts/live-poll.mjs +0 -200
  211. package/templates/vite/.howone/skills/impeccable/scripts/live-resume.mjs +0 -48
  212. package/templates/vite/.howone/skills/impeccable/scripts/live-server.mjs +0 -838
  213. package/templates/vite/.howone/skills/impeccable/scripts/live-session-store.mjs +0 -254
  214. package/templates/vite/.howone/skills/impeccable/scripts/live-status.mjs +0 -47
  215. package/templates/vite/.howone/skills/impeccable/scripts/live-wrap.mjs +0 -632
  216. package/templates/vite/.howone/skills/impeccable/scripts/live.mjs +0 -247
  217. package/templates/vite/.howone/skills/impeccable/scripts/load-context.mjs +0 -141
  218. package/templates/vite/.howone/skills/impeccable/scripts/modern-screenshot.umd.js +0 -14
  219. package/templates/vite/.howone/skills/impeccable/scripts/pin.mjs +0 -214
@@ -130,6 +130,7 @@ The outline starts transparent at 2 px so when the focus ring appears, the box g
130
130
  ## Modals and overlays
131
131
 
132
132
  - Use the native `<dialog>` element. It handles focus trap, escape to close, and `::backdrop` styling for free.
133
+ - **Centre it explicitly.** A `<dialog>` opened with `showModal()` centres on its own — but the moment you add custom positioning (a `margin-top`, a `top`, a stray `transform`) it can snap to the viewport's top-left corner. Pin it: `position: fixed; inset: 0; margin: auto; height: fit-content; max-height: min(80vh, 40rem);`. A non-`<dialog>` overlay centres via its container instead: `position: fixed; inset: 0; display: grid; place-items: center;`. Never ship a modal or command palette stuck in the corner.
133
134
  - Set `inert` on the page content behind a modal so tab order doesn't leak.
134
135
  - Close on: escape key, backdrop click, explicit close button.
135
136
  - First focus goes to the first interactive element, not the close button.
@@ -169,7 +170,7 @@ The outline starts transparent at 2 px so when the focus ring appears, the box g
169
170
 
170
171
  ## Contrast discipline
171
172
 
172
- Hallmark output must pass slop-test gates 4650 before shipping. Compute contrast for every `(color, background-color)` pair on the page. The common failures Hallmark output trips on:
173
+ Hallmark output must pass slop-test gates 4041 before shipping. Compute contrast for every `(color, background-color)` pair on the page. The common failures Hallmark output trips on:
173
174
 
174
175
  1. **Text on a flipped surface.** `.section--ink { background: var(--color-ink); }` flips the surface dark; nested text still inherits `color: var(--color-ink)` → ink-on-ink. Fix: any rule that sets a dark `background` must *also* set `color: var(--color-paper)` in the same rule.
175
176
  2. **Button text on accent fill.** `background: var(--color-accent); color: white;` — but white is 4.5:1 against this accent only if `--color-accent` is dark enough. Use `var(--color-accent-ink)` instead, which the theme guarantees passes ≥ APCA Lc 60.
@@ -41,11 +41,12 @@ Layout is where "AI-generated" gets caught. Equal columns, everything centred, e
41
41
 
42
42
  ## Asymmetry techniques
43
43
 
44
- - **Wide left margin.** Treat the left as a permanent negative space — narrow column of labels, wide column of content. **Labels must NOT be section eyebrows / numbers paired with the heading** — that's gate-66-banned. Reserve this technique for body-level micro-labels (caption, footnote, date) alongside body copy.
45
- - **Hanging headers.** ⚠️ **Opt-in only.** Section labels sit in the left margin; content flows to the right. Permitted only when the user explicitly asks for an editorial / hanging-header layout AND no eyebrow / number / chapter tag sits in the left margin. The eyebrow-left / heading-right pattern is banned by slop-test gate 66 — it's the most reliable templated-editorial AI tell. Default to a stacked single-column section head.
44
+ - **Wide left margin.** Treat the left as a permanent negative space — narrow column of labels, wide column of content. **Labels must NOT be section eyebrows / numbers paired with the heading** — that's gate-54-banned. Reserve this technique for body-level micro-labels (caption, footnote, date) alongside body copy.
45
+ - **Hanging headers.** ⚠️ **Opt-in only.** Section labels sit in the left margin; content flows to the right. Permitted only when the user explicitly asks for an editorial / hanging-header layout AND no eyebrow / number / chapter tag sits in the left margin. The eyebrow-left / heading-right pattern is banned by slop-test gate 54 — it's the most reliable templated-editorial AI tell. Default to a stacked single-column section head.
46
46
  - **Offset grids.** Odd columns wider than even. Or the other way.
47
47
  - **Grid-breaks.** One element that deliberately extends past a column boundary: a pull-quote, a photograph, a rule, a number.
48
48
  - **Generous top, tight bottom** (or vice-versa). Sections don't need to be evenly padded.
49
+ - **Alignment coherence.** A section head's horizontal alignment should be a deliberate choice that *coheres* with the body it introduces — match it (left head over left-flush body; centred head over symmetric / centred body) or break from it on purpose (a head that escapes an asymmetric grid). What reads as an AI mistake is the *accidental* mismatch: a narrow head block auto-centred (`margin-inline: auto` plus a `max-width` / `ch` cap) left floating over full-width, left-flush content beneath it. Centred, hanging, bottom-aligned, and asymmetric heads all stay on the table — the guard is intentionality, not uniformity.
49
50
 
50
51
  ## Depth
51
52
 
@@ -82,7 +83,7 @@ Layout is where "AI-generated" gets caught. Equal columns, everything centred, e
82
83
 
83
84
  The clipped-edge enrichment archetype (E1) — and any other deliberately overflowing element (full-bleed marquee, oversized headline that exceeds the viewport on small screens, a tilted figure that pushes past a column) — needs a parent that *visually* shows the overflow without letting the document scroll horizontally.
84
85
 
85
- The default is unsafe: a `width: calc(100% + 12vw)` figure inside a section with `overflow: visible` makes the document scroll horizontally on every viewport. The page feels broken on touch devices. Slop-test gate 36 fails on this.
86
+ The default is unsafe: a `width: calc(100% + 12vw)` figure inside a section with `overflow: visible` makes the document scroll horizontally on every viewport. The page feels broken on touch devices. Slop-test gate 34 fails on this.
86
87
 
87
88
  **Always pair clipped-edge with a global clip.** At the top of the stylesheet:
88
89
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  The hero is a giant number — a metric, a count, a percentage. Everything that follows supports or qualifies it. Data is the narrative.
4
4
 
5
- - **Heading:** numeric display (8–12 rem), tabular figures, small qualifier line below.
5
+ - **Heading:** a large numeric display (8–12 rem, tabular figures) **paired with a worded headline** — the figure is the biggest element, but it is *never the hero's only words*. State what the number means right beside or beneath it as a real headline, not a tiny label. Read the figure and its words together (*"4 seconds. From the alert link to the slow span."*).
6
6
  - **Body:** sections each anchored by a supporting stat or chart.
7
7
  - **Divider:** hairline rules between stat blocks; tabular-nums everywhere.
8
8
  - **Button:** outlined chip aligned beneath the qualifier.
@@ -13,6 +13,8 @@ Reach for it when the brief is "we have proof in numbers" — enterprise/B2B, fu
13
13
 
14
14
  Avoid for products without a defensible single metric. A fake big number is worse than no number.
15
15
 
16
+ **The hero header always contains words.** The lead figure never stands alone as the headline — pair it with a worded line that completes it. A bare number as the dominant hero text fails slop-test gate 46.
17
+
16
18
  Reference: Ahrefs, Stripe Sessions stat blocks, climate-impact dashboards, venture firm portfolio pages.
17
19
 
18
20
  **Sample opening lines** (imitate the *specificity*, not the wording — the number does the work):
@@ -18,6 +18,6 @@ Reference: Frank Chimero's site, founder farewell posts, indie newsletter front
18
18
  **Sample opening lines** (imitate the *specificity* — Letter openings are first-person greetings, dated, with a place if relevant):
19
19
  > *"Hello, I'm Anya."* — Anya (test 06) — single line, name, full stop
20
20
  > *"Saturday, 6:14 a.m. The dough went in at midnight."* — opens on a moment, then explains it
21
- > *"Hey there. This page is soft because the surface should be soft."* — Hallmark Plume — colloquial open + a principle
21
+ > *"Hey there. This page is soft because the surface should be soft."* — Hallmark Hum — colloquial open + a principle
22
22
 
23
23
  ---
@@ -68,7 +68,7 @@ Each section transition uses theme-appropriate vertical spacing — `--space-3xl
68
68
  **Voice rules for SaaS sections:**
69
69
 
70
70
  - **Pricing:** show the actual price. Sales-led pricing on every tier ("Contact us") signals the brand doesn't trust the buyer.
71
- - **Testimonials:** include the quoted person's role *and* company. Abstract "Engineering Manager" testimonials are slop. If the brief is a real product, use real names. If the brief is a placeholder, use plausible names — never "Jane Doe" / "John Smith" (gate 20).
71
+ - **Testimonials:** include the quoted person's role *and* company. Abstract "Engineering Manager" testimonials are slop. If the brief is a real product, use real names. If the brief is a placeholder, use plausible names — never "Jane Doe" / "John Smith" (gate 19).
72
72
  - **FAQ:** answer like a person, not a sales doc. "Yes — Stripe and Adyen are both supported out of the box" beats "Our platform integrates with leading payment providers."
73
73
  - **CTA strip:** one button. Not two. The repetition is the call to action.
74
74
 
@@ -193,7 +193,7 @@ Trigger: ⌘K or `/`. Open: instant, no animation. Arrow-keys move selection —
193
193
 
194
194
  ### Page-load reveals
195
195
 
196
- One orchestrated entrance. Stagger by DOM index, capped at ~500ms total. Use `IntersectionObserver`, never scroll listeners. After first reveal, no more on-scroll animations — let the page just *be there*. Theme-specific themes (Atelier, Salon, Newsprint) skip reveals entirely; that is correct, not a bug.
196
+ One orchestrated entrance. Stagger by DOM index, capped at ~500ms total. Use `IntersectionObserver`, never scroll listeners. After first reveal, no more on-scroll animations — let the page just *be there*. Theme-specific themes (Atelier, Newsprint) skip reveals entirely; that is correct, not a bug.
197
197
 
198
198
  ## The named tells (what AI defaults produce)
199
199
 
@@ -234,8 +234,6 @@ Microinteractions adapt to the theme. The same button press is louder in Brutal
234
234
  | Newsprint | 0× | none | Static. Print metaphor. |
235
235
  | Terminal | 0× | none, except caret blink *inside* a typed command (N8 nav, install code) | Print + monospace metaphor. **No standalone blinking cursor** — see the Caret blink row above. The caret only blinks where the user would type. |
236
236
  | Manifesto | 0.7× | `--ease-out` (sharp) | Snap into place. |
237
- | Salon | 1.4× | `--ease-out` (very gentle) | Softest. |
238
- | Linen | 1.2× | `--ease-out` | Calm. |
239
237
  | Almanac | 0.85× | `--ease-out` | Functional, like a reference book. |
240
238
  | Sport | 0.7× | `--ease-out` (sharp) | Quick, italic-energy. |
241
239
 
@@ -5,45 +5,45 @@ Four sample Step 5 preview blocks for the model to imitate, varied across macros
5
5
  ---
6
6
 
7
7
  *Long Document (editorial, motion-cut):*
8
- > **Hallmark · v1.0.0**
8
+ > **Hallmark · v1.1.0**
9
9
  >
10
10
  > - **Macrostructure** · Long Document
11
- > - **Theme** · Linen (cool slate paper · steel-blue accent · geometric sans)
11
+ > - **Theme** · Newsprint (cool slate paper · steel-blue accent · geometric sans)
12
12
  > - **Enrichment** · Tier-B hand-built SVG (a 60-line coffee bean with `@property --rise` 6 s breathing-loop)
13
13
  > - **Sections** · Masthead · Letter · Three Notes · Visit · Colophon
14
14
  > - **Motion** · breathing-loop on bean only (respects `prefers-reduced-motion`)
15
- > - **Slop test** · 69 / 69
15
+ > - **Slop test** · 57 / 57
16
16
  > - **Diversification** · first run for this project
17
17
 
18
18
  *Bento Grid (SaaS, motion-on):*
19
- > **Hallmark · v1.0.0**
19
+ > **Hallmark · v1.1.0**
20
20
  >
21
21
  > - **Macrostructure** · Bento Grid
22
- > - **Theme** · Linen (cool slate paper · steel-blue accent · geometric sans)
22
+ > - **Theme** · Newsprint (cool slate paper · steel-blue accent · geometric sans)
23
23
  > - **Enrichment** · E1 Clipped-Edge Demo Video, Tier-A CSS-art trace waterfall
24
24
  > - **Sections** · Hero · 6-tile Bento (stat · sparkline · quote · code · integrations · spotlight) · Index Footer
25
25
  > - **Motion** · counter · pricing-lift · CSS marquee on integrations strip
26
- > - **Slop test** · 69 / 69
26
+ > - **Slop test** · 57 / 57
27
27
  > - **Diversification** · differs from Plain on paper hue (light-cool vs pure-white) + accent (indigo vs ink-blue)
28
28
 
29
29
  *Manifesto (declarative, no enrichment):*
30
- > **Hallmark · v1.0.0**
30
+ > **Hallmark · v1.1.0**
31
31
  >
32
32
  > - **Macrostructure** · Manifesto
33
33
  > - **Theme** · Manifesto (dark · Inter Tight 900 · single red bleed)
34
34
  > - **Enrichment** · none (typography only — voice carries the brand)
35
35
  > - **Sections** · Masthead · Title · Five Declarations · Bleed Band · What We Refuse · Working Rules · Practice · Reading · Colophon
36
36
  > - **Motion** · none — typography only
37
- > - **Slop test** · 69 / 69
38
- > - **Diversification** · differs from Linen on paper band (dark vs light) + display style (display-heavy vs geometric-sans)
37
+ > - **Slop test** · 57 / 57
38
+ > - **Diversification** · differs from Newsprint on paper band (dark vs light) + display style (display-heavy vs geometric-sans)
39
39
 
40
40
  *Custom (Coffeebox archival café):*
41
- > **Hallmark · v1.0.0**
41
+ > **Hallmark · v1.1.0**
42
42
  >
43
43
  > - **Macrostructure** · Long Document
44
44
  > - **Theme** · custom (vibe: "archival warmth, hand-set, no varnish" · paper oklch(94% 0.020 65) · accent oklch(58% 0.16 35) terracotta · Fraunces italic display + Source Serif 4 body)
45
45
  > - **Enrichment** · Tier-A pure-CSS coffee bean (60-line SVG, breathing-loop optional)
46
46
  > - **Sections** · Masthead · Letter · Three Notes · Visit · Colophon
47
47
  > - **Motion** · breathing-loop on bean (with reduced-motion fallback)
48
- > - **Slop test** · 69 / 69
49
- > - **Diversification** · custom axes: light / italic-serif / chromatic-terracotta — differs from previous catalog Linen on accent hue + display style
48
+ > - **Slop test** · 57 / 57
49
+ > - **Diversification** · custom axes: light / italic-serif / chromatic-terracotta — differs from previous catalog Newsprint on accent hue + display style
@@ -6,13 +6,13 @@ Mobile-first. Content-driven breakpoints. No desktop-only interactions.
6
6
 
7
7
  Every Hallmark output must render flawlessly at **320 px, 375 px, 414 px, and 768 px** CSS-pixel widths. Eyeball each viewport before marking the output complete:
8
8
 
9
- - No horizontal scroll (slop-test gate 36)
10
- - No clickable text wrapping to two lines (gate 59)
11
- - No image-bearing grid pushing the layout past viewport — use `minmax(0, 1fr)`, never bare `1fr`, on tracks containing images (gate 61)
12
- - Root carries `overflow-x: clip` on both `html` and `body` — never `hidden` (gate 62)
13
- - Display headers wrap inside long words via `overflow-wrap: anywhere; min-width: 0` (gate 63)
14
- - Section heads collapse to one column on mobile across every theme variant — per-theme overrides need a matching mobile rule (gate 64)
15
- - No scroll-jump on radio-tab clicks — radios in normal flow OR JS guard with `focus({ preventScroll: true })` (gate 65)
9
+ - No horizontal scroll (slop-test gate 34)
10
+ - No clickable text wrapping to two lines (gate 49)
11
+ - No image-bearing grid pushing the layout past viewport — use `minmax(0, 1fr)`, never bare `1fr`, on tracks containing images (gate 50)
12
+ - Root carries `overflow-x: clip` on both `html` and `body` — never `hidden` (gate 34)
13
+ - Display headers wrap inside long words via `overflow-wrap: anywhere; min-width: 0` (gate 51)
14
+ - Section heads collapse to one column on mobile across every theme variant — per-theme overrides need a matching mobile rule (gate 52)
15
+ - No scroll-jump on radio-tab clicks — radios in normal flow OR JS guard with `focus({ preventScroll: true })` (gate 53)
16
16
 
17
17
  This is a hard floor, not a wish list. A page that fails any of these on any of those four widths is not done. The slop-test gates listed run automatically — keep this checklist near the screen while building.
18
18
 
@@ -87,7 +87,7 @@ Buttons, primary nav links, footer links, tab labels, breadcrumbs, and CTAs must
87
87
 
88
88
  **Never:** let a primary CTA or top-level nav link wrap. Long footer-link labels can wrap *only* in a footer column where wrapping is part of the column's rhythm — not in the inline footer link strip (Ft2).
89
89
 
90
- This is gate **59** in [`slop-test.md`](slop-test.md). Audit any output that ships interactive affordances and confirm none wrap at the breakpoints listed above.
90
+ This is gate **49** in [`slop-test.md`](slop-test.md). Audit any output that ships interactive affordances and confirm none wrap at the breakpoints listed above.
91
91
 
92
92
  ## Viewport units
93
93
 
@@ -1,4 +1,4 @@
1
- # Slop test — 60 gates + pre-emit self-critique
1
+ # Slop test — 57 gates + pre-emit self-critique
2
2
 
3
3
  Run this list before handing back any output. Every answer must be **no**. Update the Step 5 preview block's `Slop test` row to reflect the actual outcome of this run.
4
4
 
@@ -8,7 +8,7 @@ Some gates are **universal** (apply to every genre); some are **genre-scoped** (
8
8
 
9
9
  ## Pre-emit self-critique (six axes)
10
10
 
11
- Run this **before** the gate list, not after. Score the planned output 1–5 on each axis. Anything **< 3 on any axis triggers a revision pass** before the gate sweep — don't bring known weakness into a sixty-gate review.
11
+ Run this **before** the gate list, not after. Score the planned output 1–5 on each axis. Anything **< 3 on any axis triggers a revision pass** before the gate sweep — don't bring known weakness into a fifty-seven-gate review.
12
12
 
13
13
  Two passes is normal. Three is a sign the brief is wrong, not the design — re-read the brief.
14
14
 
@@ -28,87 +28,87 @@ Record the six scores in a one-line stamp comment at the top of the file: `/* Ha
28
28
  ## Visual
29
29
 
30
30
  1. Is the display font Inter, Roboto, Open Sans, Poppins, Lato, or a system default?
31
- 2. Is there a purple-to-blue (or cyan-to-magenta) gradient anywhere? *Genre note: atmospheric allows radial gradients on background only — never on text or pill buttons.*
31
+ 2. Is there a purple-to-blue (or cyan-to-magenta) gradient anywhere — **including a `background-clip: text` gradient headline**? *Genre note: atmospheric allows radial gradients on background only — never on text or pill buttons. No genre allows gradient text.*
32
32
  3. Is there a 3-equal-column card grid with icon-above-heading tiles?
33
33
  4. Is any card nested inside another card?
34
- 5. Is there a `background-clip: text` gradient headline? (Universal no genre allows gradient text.)
35
- 6. Is any card using a thick coloured left/right side-stripe border?
36
- 7. Is the hero `min-height: 100vh` with everything centred? *Genre note: atmospheric and playful allow centred heroes when the canvas itself is the design (Suno-style).*
37
- 8. Is pure `#000` or pure `#fff` used as a base colour anywhere? *Genre note: modern-minimal allows pure `#fff` paper (the Stripe / ElevenLabs school).*
34
+ 5. Is any card using a thick coloured left/right side-stripe border?
35
+ 6. **Hero shape — centred-everything.** Is the hero `min-height: 100vh` with everything centred, OR are the eyebrow, title, lede, AND CTA all stacked on the same centred vertical axis? Auto-fail. Pick at most two centred elements and break alignment for the rest; the eyebrow or CTA should sit off-axis (margin-aligned, right-flush, numeral-anchored). *Genre note: atmospheric and playful allow a centred hero when the canvas itself is the design (Suno-style); editorial / atelier allow a centred-narrow hero, but even then the eyebrow or CTA sits off-axis.*
36
+ 7. Is pure `#000` or pure `#fff` used as a base colour anywhere? *Genre note: modern-minimal allows pure `#fff` paper (the Stripe / ElevenLabs school).*
38
37
 
39
38
  ## Structural
40
39
 
41
- 9. Does the page use the *same* structural fingerprint as the last page you built? (Hero → 3 features → CTA → footer is the AI structural template; reject it.)
42
- 10. Are sections separated only by equal whitespace, with no rule, no ornament, no colour shift — every section identical in rhythm?
40
+ 8. Does the page reuse a structure it shouldn't either the generic AI template (Hero → 3 features → CTA → footer), **or** the *same* structural fingerprint / macrostructure as a previous Hallmark output in this project? Read the file system: if a `.hallmark/log.json` entry or a CSS macrostructure stamp exists, this build's macrostructure must differ from the last.
41
+ 9. Are sections separated only by equal whitespace, with no rule, no ornament, no colour shift — every section identical in rhythm?
43
42
 
44
43
  ## Microinteractions
45
44
 
46
- 11. Is `transition-all` (or `transition: all`) used anywhere? (Specify the properties.)
47
- 12. Is `hover:scale-105` (or any uniform hover-scale) applied across multiple unrelated elements?
48
- 13. Are bouncy / overshoot easings (`cubic-bezier(0.34, 1.56, ...)`, etc.) used on UI state changes — buttons, modals, tooltips? (Reserve overshoots for physical interactions only.)
49
- 14. Does any element have *more than one* hover effect at the same time (translate + scale + shadow + colour + rotate)?
50
- 15. Are you animating `width`, `height`, `top`, `left`, `margin`, or `padding` anywhere?
51
- 16. Does the focus ring transition into existence (fade in)? (Focus rings must appear instantly — keyboard users need an immediate indicator.)
52
- 17. Is there a celebratory success toast for an action whose effect the user can already see? (Silent success is taste; toasts are for failures and invisible effects.)
53
- 18. Are tooltip hover-delay and focus-delay equal? (Hover should delay 800–1000 ms; focus should be 0 ms.)
54
- 19. Is auto-rotating content (carousel, banner, stats) lacking pause-on-hover-and-focus? (WCAG 2.2.2.)
55
- 20. Is there a placeholder name "Jane Doe / John Smith" or a startup cliché (Acme, Nexus, Seamless, Unleash)?
45
+ 10. Is `transition-all` (or `transition: all`) used anywhere? (Specify the properties.)
46
+ 11. Is `hover:scale-105` (or any uniform hover-scale) applied across multiple unrelated elements?
47
+ 12. Are bouncy / overshoot easings (`cubic-bezier(0.34, 1.56, ...)`, etc.) used on UI state changes — buttons, modals, tooltips? (Reserve overshoots for physical interactions only.)
48
+ 13. Does any element have *more than one* hover effect at the same time (translate + scale + shadow + colour + rotate)?
49
+ 14. Are you animating `width`, `height`, `top`, `left`, `margin`, or `padding` anywhere?
50
+ 15. Does the focus ring transition into existence (fade in)? (Focus rings must appear instantly — keyboard users need an immediate indicator.)
51
+ 16. Is there a celebratory success toast for an action whose effect the user can already see? (Silent success is taste; toasts are for failures and invisible effects.)
52
+ 17. Are tooltip hover-delay and focus-delay equal? (Hover should delay 800–1000 ms; focus should be 0 ms.)
53
+ 18. Is auto-rotating content (carousel, banner, stats) lacking pause-on-hover-and-focus? (WCAG 2.2.2.)
54
+ 19. Is there a placeholder name "Jane Doe / John Smith" or a startup cliché (Acme, Nexus, Seamless, Unleash)?
56
55
 
57
56
  ## Variety
58
57
 
59
- 21. Is the `/* Hallmark · macrostructure: <name> · ... */` stamp missing from the top of the CSS? (It must be present.)
60
- 22. Is the macrostructure I picked the same as a previous Hallmark output's stamp in this project? (Read the file system; if a stamp exists, mine must differ.)
61
- 23. Did I default to the **Specimen** macrostructure (numbered left-margin labels + huge serif + asymmetric spans + typographic-only CTA) when the brief did not explicitly call for editorial / foundry / specimen energy? (Specimen fall-through is banned.) *Genre note: atmospheric, modern-minimal, and playful never default to Specimen — only editorial does, and only when the brief signals it.*
58
+ 20. Is the `/* Hallmark · macrostructure: <name> · ... */` stamp missing from the top of the CSS? (It must be present.)
59
+ 21. Did I default to the **Specimen** macrostructure (numbered left-margin labels + huge serif + asymmetric spans + typographic-only CTA) when the brief did not explicitly call for editorial / foundry / specimen energy? (Specimen fall-through is banned.) *Genre note: atmospheric, modern-minimal, and playful never default to Specimen — only editorial does, and only when the brief signals it.*
62
60
 
63
61
  ## Implementation gates
64
62
 
65
- 24. Does any neutral / surface colour have `oklch(... 0 ...)` (zero chroma)? Pure greys read as flat. Tint every neutral toward the anchor hue — minimum 0.005 chroma. *Genre note: modern-minimal allows zero-chroma neutrals (the monochrome Stripe / ElevenLabs school).*
66
- 25. Does the accent colour cover more than ~5 % of any single viewport (count by area: solid fills, large headings in accent, full-bleed accent backgrounds)? If yes, retreat — accent is for emphasis, not for filling. *Genre note: atmospheric allows accent-tinted radial blooms covering up to ~20 % of the canvas, since the bloom is the design.*
67
- 26. Is any padding / gap / margin a value that isn't on the named spacing scale (`--space-3xs` … `--space-5xl`, multiples of 4 px)? Arbitrary `padding: 17px` is a tell.
68
- 27. Is any prose container's `max-width` outside the 45–75 ch range? Measure must read; under 45 ch is choppy, over 75 ch loses the eye.
69
- 28. Does any interactive element lack `:focus-visible`, `:active`, OR `:disabled` styling? (Eight states is the rule. Default + hover is two; you need at least default + hover + focus-visible + active + disabled present in code.)
70
- 29. Is there any `transform` / `animation` keyframe that is NOT covered by a `@media (prefers-reduced-motion: reduce)` fallback? Every motion gets a reduced-motion alternative.
63
+ 22. Does any neutral / surface colour have `oklch(... 0 ...)` (zero chroma)? Pure greys read as flat. Tint every neutral toward the anchor hue — minimum 0.005 chroma. *Genre note: modern-minimal allows zero-chroma neutrals (the monochrome Stripe / ElevenLabs school).*
64
+ 23. Does the accent colour cover more than ~5 % of any single viewport (count by area: solid fills, large headings in accent, full-bleed accent backgrounds)? If yes, retreat — accent is for emphasis, not for filling. *Genre note: atmospheric allows accent-tinted radial blooms covering up to ~20 % of the canvas, since the bloom is the design.*
65
+ 24. Is any padding / gap / margin a value that isn't on the named spacing scale (`--space-3xs` … `--space-5xl`, multiples of 4 px)? Arbitrary `padding: 17px` is a tell.
66
+ 25. Is any prose container's `max-width` outside the 45–75 ch range? Measure must read; under 45 ch is choppy, over 75 ch loses the eye.
67
+ 26. Does any interactive element lack `:focus-visible`, `:active`, OR `:disabled` styling? (Eight states is the rule. Default + hover is two; you need at least default + hover + focus-visible + active + disabled present in code.)
68
+ 27. Is there any `transform` / `animation` keyframe that is NOT covered by a `@media (prefers-reduced-motion: reduce)` fallback? Every motion gets a reduced-motion alternative.
71
69
 
72
70
  ## Hero enrichment gates
73
71
 
74
72
  (When the page carries enrichment — see [`hero-enrichment.md`](hero-enrichment.md).)
75
73
 
76
- 30. If the page has a demo video, does it autoplay with sound, lack a `poster`, lack `fetchpriority="high"`, or use `loading="lazy"` on the LCP element? (LCP-killers fail this gate.)
77
- 31. If the page has an abstract background, is it more than one accent colour, more than ~5 % footprint, or animating mesh-gradient on the whole page? (Aurora blobs and mesh-on-everything fail this gate.) *Genre note: atmospheric allows up to two warm-toned radial blooms covering ~20–30 % of the canvas, fixed-attached, no animation.*
78
- 32. Does the page mix two or more icon libraries? (Material + Heroicons + Lucide on the same page = the icon-set tell.)
79
- 33. If the page has illustration, did I default to a Lottie library when a hand-built SVG or pure-CSS shape would have worked? (Lottie is last resort, not the default.)
74
+ 28. If the page has a demo video, does it autoplay with sound, lack a `poster`, lack `fetchpriority="high"`, or use `loading="lazy"` on the LCP element? (LCP-killers fail this gate.)
75
+ 29. If the page has an abstract background, is it more than one accent colour, more than ~5 % footprint, or animating mesh-gradient on the whole page? (Aurora blobs and mesh-on-everything fail this gate.) *Genre note: atmospheric allows up to two warm-toned radial blooms covering ~20–30 % of the canvas, fixed-attached, no animation.*
76
+ 30. **Icon tells.** Does the page (a) mix two or more icon libraries (Material + Heroicons + Lucide on the same page), OR (b) use an emoji glyph (✨ 🚀 ⚡ 🔥 🎯 ✅) as a feature-card / value-prop / step / pricing-tier icon? Either is an AI-default tell. Pick one icon library (Lucide / Phosphor / Heroicons — see [assets.md](assets.md)), build a custom SVG, or drop the icon and lead with typography.
77
+ 31. If the page has illustration, did I default to a Lottie library when a hand-built SVG or pure-CSS shape would have worked? (Lottie is last resort, not the default.)
80
78
 
81
79
  ## Diversification gates
82
80
 
83
81
  (Cross-reference `.hallmark/log.json` when present.)
84
82
 
85
- 34. If I used the same archetype as a previous Hallmark output (per `.hallmark/log.json` or the latest macrostructure stamp), did I pick at least one different *variation knob*? Two Bento Grids with `tiles=6, spans=irregular, accent=corner-only` are the same Bento — the within-archetype knobs in [`component-cookbook.md`](component-cookbook.md) exist precisely to prevent that. State the knob deltas in the stamp.
86
- 35. Does any visual-only `<svg>`, custom-art `<div>`, `<canvas>`, or decorative figure lack `aria-label` or `aria-hidden="true"`? Hand-built CSS art and SVG illustrations need an accessible name *or* an explicit hide. Skipping this is the new accessibility tell.
83
+ 32. If I used the same archetype as a previous Hallmark output (per `.hallmark/log.json` or the latest macrostructure stamp), did I pick at least one different *variation knob*? Two Bento Grids with `tiles=6, spans=irregular, accent=corner-only` are the same Bento — the within-archetype knobs in [`component-cookbook.md`](component-cookbook.md) exist precisely to prevent that. State the knob deltas in the stamp.
84
+ 33. Does any visual-only `<svg>`, custom-art `<div>`, `<canvas>`, or decorative figure lack `aria-label` or `aria-hidden="true"`? Hand-built CSS art and SVG illustrations need an accessible name *or* an explicit hide. Skipping this is the new accessibility tell.
87
85
 
88
86
  ## Layout-safety gates
89
87
 
90
88
  (The page must survive every viewport.)
91
89
 
92
- 36. Does the page horizontally scroll on any viewport between 320 px and 1920 px? Open the rendered page; drag the dev-tools width slider across that range. If a horizontal scrollbar appears at any width, fail. The fix is `html { overflow-x: clip; }` plus `body { overflow-x: clip; }` as a safety net for any clipped-edge enrichment that pushes past the viewport. Use `overflow-x: clip` (not `hidden`) `clip` preserves `position: sticky` and `position: fixed` on descendants. (Cross-reference: [`layout-and-space.md` § Page-edge clipping](layout-and-space.md).)
93
- 37. For every decorative effect on text — highlighter `<mark>` / `<em>` band / accent stroke / underline — did I visually confirm the position and size? A highlighter band must sit behind the x-height (`linear-gradient(180deg, transparent ~38%, accent ~38%, accent ~92%, transparent ~92%)`), **not** at the baseline (which reads as a fat underline). Underlines must be 1–2 px and offset 1–2 px from the baseline, never 5+ px. Decorative strokes must not exceed 5 % of the viewport (gate 25). The check is *visual*: imagine the rendered output and confirm the band lands in the right vertical zone.
94
- 38. Are interactive bars (nav, toolbar, command bar, hero CTA row, footer link strip) explicitly vertically centered? Default flex layouts inherit `align-items: stretch`, which makes a button taller than its sibling text and breaks the visual baseline. Every flex row mixing height-different elements (button + text, icon + text, mark + body) must declare `align-items: center` and `line-height: 1` on the items with intrinsic height. Inheriting `line-height: 1.55` from `html` fights the row's vertical rhythm.
90
+ 34. Does the page horizontally scroll on any viewport between 320 px and 1920 px? Open the rendered page; drag the dev-tools width slider across that range. If a horizontal scrollbar appears at any width, fail. The required fix is `overflow-x: clip` on **both** `html` and `body` use `clip`, not `hidden` (`clip` preserves `position: sticky` and `position: fixed` on descendants). This is a hard requirement on every emitted page, not only when scroll is observed. (Cross-reference: [`layout-and-space.md` § Page-edge clipping](layout-and-space.md).)
91
+ 35. For every decorative effect on text — highlighter `<mark>` / `<em>` band / accent stroke / underline — did I visually confirm the position and size? A highlighter band must sit behind the x-height (`linear-gradient(180deg, transparent ~38%, accent ~38%, accent ~92%, transparent ~92%)`), **not** at the baseline (which reads as a fat underline). Underlines must be 1–2 px and offset 1–2 px from the baseline, never 5+ px. Decorative strokes must not exceed 5 % of the viewport (gate 23). The check is *visual*: imagine the rendered output and confirm the band lands in the right vertical zone.
92
+ 36. Are interactive bars (nav, toolbar, command bar, hero CTA row, footer link strip) explicitly vertically centered? Default flex layouts inherit `align-items: stretch`, which makes a button taller than its sibling text and breaks the visual baseline. Every flex row mixing height-different elements (button + text, icon + text, mark + body) must declare `align-items: center` and `line-height: 1` on the items with intrinsic height. Inheriting `line-height: 1.55` from `html` fights the row's vertical rhythm.
95
93
 
96
94
  ## Typography discipline gates
97
95
 
98
96
  (Three faces is the ceiling. See [`typography.md` § The 2+1 rule](typography.md).)
99
97
 
100
- 39. Does the page use **more than three** distinct `font-family` families? Count: `--font-display`, `--font-body`, and at most one outlier (`--font-outlier` for wordmark / hero stat / pull quote). A fourth family on the page — e.g. body + display + mono in code blocks + a separate display for the hero — is slop. Same family at different weights counts as one family. Mono counts as a family if used in any non-code context (captions, labels, numerals). If you find four, drop one back to the body or display face.
101
- 40. Is the **outlier face used in more than two slots** on the page? The outlier is a register, not a third surface — wordmark + hero stat is the canonical pair, or wordmark + masthead, or hero stat + pull quote. Three slots = the outlier is now a third body font; collapse it back to the body face.
98
+ 37. Does the page use **more than three** distinct `font-family` families? Count: `--font-display`, `--font-body`, and at most one outlier (`--font-outlier` for wordmark / hero stat / pull quote). A fourth family on the page — e.g. body + display + mono in code blocks + a separate display for the hero — is slop. Same family at different weights counts as one family. Mono counts as a family if used in any non-code context (captions, labels, numerals). If you find four, drop one back to the body or display face.
99
+ 38. Is the **outlier face used in more than two slots** on the page? The outlier is a register, not a third surface — wordmark + hero stat is the canonical pair, or wordmark + masthead, or hero stat + pull quote. Three slots = the outlier is now a third body font; collapse it back to the body face.
100
+ 38a. Is any **heading or display type italic** (`font-style: italic` on `h1`–`h6`, a `.*__title`, `.hero__title`, a wordmark, a stat figure, a footer statement, or an `<em>`/`<i>` inside a heading)? If yes, fail. Italic headers — above all the single italicised emphasis-word inside an upright headline — are a top AI tell. Headers are roman; emphasis comes from weight, accent colour, or a drawn underline. Italic is allowed *only* as body-copy emphasis inside running paragraphs. (Applies to every theme; Studio / Garden / Sport — historically italic-display — are reworked to roman.)
102
101
 
103
- ## Input-state gates
102
+ ## Input-state gate
104
103
 
105
104
  (Inputs are where almost-right UIs lose. See [`interaction-and-states.md` § Input field states](interaction-and-states.md).)
106
105
 
107
- 41. Does any input, textarea, or select field change `border-width` between states (default → hover → focus → error)? Default is 1 px; hover, focus, and error must keep `border-width: 1px`. Border-width changes cause layout shift. State changes go to `background-color`, `outline`, `box-shadow`, or `border-color` — never `border-width`.
108
- 42. Does the input focus ring use `border` instead of `outline`? The focus ring must be `outline: 2px solid var(--color-focus)` with `outline-offset: 1px`. Reserving `outline: 2px solid transparent` in the default state prevents geometry shift on activate. A focus ring built from a `border` change is a tell.
109
- 43. Is the input height different from the height of an adjacent button on the same form? Form inputs and the form's submit button share a single base height (44 px floor). 38 px input + 44 px button is the most common form-tuning slop and reads as un-designed.
110
- 44. Is the helper-text container collapsed when no helper or error is shown? The helper slot must reserve `min-height: 1lh` even when empty so that an error appearing doesn't push the page down. Vertical jump on validation is a tell.
111
- 45. Is the disabled input state signalled by *only* `opacity: 0.5`? Disabled needs three independent signals: `opacity: 0.55` AND `cursor: not-allowed` AND `aria-disabled="true"` (or the native `disabled` attribute). One channel is missable; three are not.
106
+ 39. Do input / textarea / select fields handle every state correctly? Fail on **any** of these five:
107
+ - **Border-width shifts between states** default / hover / focus / error must all keep `border-width: 1px`. State changes go to `background-color`, `outline`, `box-shadow`, or `border-color` never `border-width` (it shifts layout).
108
+ - **Focus ring built from `border` instead of `outline`** must be `outline: 2px solid var(--color-focus)` with `outline-offset: 1px`; reserve `outline: 2px solid transparent` at rest to prevent geometry shift on activate.
109
+ - **Input height adjacent button height** on the same form share one base height (44 px floor); 38 px input + 44 px button is the most common form-tuning slop.
110
+ - **Helper-text slot collapses when empty** reserve `min-height: 1lh` even with no helper / error, so an appearing error doesn't push the page down.
111
+ - **Disabled signalled by `opacity` alone** — disabled needs three channels: `opacity: 0.55` AND `cursor: not-allowed` AND the native `disabled` attribute (or `aria-disabled="true"`).
112
112
 
113
113
  ## Contrast & readability
114
114
 
@@ -116,89 +116,76 @@ Universal — apply to every genre. These gates catch the real-world failures th
116
116
 
117
117
  Contrast computation: for every `(color, background-color)` pair on the page, run **APCA Lc** OR **WCAG 2.1 ratio**. OKLCH lightness is a fast pre-check — if `|L_text − L_bg| < 50 %`, the pair likely fails 4.5:1 — confirm with a full calculation.
118
118
 
119
- Thresholds:
120
- - Body text (under 24 px regular OR under 18 px bold): **WCAG 4.5:1 / APCA Lc ≥ 60**.
121
- - Large text / icons / focus rings: **WCAG 3:1 / APCA Lc ≥ 45**.
119
+ 40. **Contrast thresholds.** Does any text, icon, or `:focus-visible` ring fail its threshold against its *computed* background? Pair every `color` declaration with its effective `background-color` and verify. Thresholds: **body text** (under 24 px regular OR under 18 px bold) needs **WCAG 4.5:1 / APCA Lc ≥ 60**; **large text** (≥ 24 px regular / ≥ 18 px bold), **icons**, and **focus rings** need **WCAG 3:1 / APCA Lc ≥ 45**. The most-missed cases: text inside a card that inherits `color` but the card switched to `background: var(--color-paper-2)`; muted text (`var(--color-muted)`) on `var(--color-paper-3)`; a focus ring whose `--color-focus` clears 3:1 against the element but not the page surface.
122
120
 
123
- 46. Does any **body text** have a contrast ratio below **4.5:1** against its computed background? Pair every `color` declaration with its effective `background-color` and verify. The most-missed cases are: text inside cards that inherit `color` but the card switched to `background: var(--color-paper-2)` and the text is now too close in lightness; muted text (`color: var(--color-muted)`) on `background: var(--color-paper-3)` — both are mid-lightness and fail.
121
+ 41. **The contrast failures that ship most often.** Fail on **any**:
122
+ - **Button text ≈ button fill** — if the computed text colour and fill are within **5 % lightness AND 0.05 chroma** in OKLCH, fail. This catches the black-on-black bug (`color: var(--color-ink)` on `background: var(--color-ink)` — the model forgot `--color-accent-ink` / `--color-paper`).
123
+ - **`--color-accent-ink` missing or unused** — whenever `--color-accent` fills a surface that carries text, `--color-accent-ink` must be defined, verify ≥ APCA Lc 60 / WCAG 4.5:1 against `--color-accent`, and be applied as the `color` on that fill.
124
+ - **Dark-section ink-on-ink** — any section / panel whose `background-color` is OKLCH lightness < 50 % must also swap its text colour (typically to `--color-paper`) and ensure nested children inherit. A class that sets `background: <dark>` must set `color: <light>` in the same rule (or be wrapped in a parent that does). Common failure: a `.vs__col:first-child` painted with accent / ink but the inner panels still using default ink-coloured text.
124
125
 
125
- 47. Does any **large text** (≥ 24 px regular OR 18 px bold) or **icon** or **`:focus-visible` ring** have a contrast ratio below **3:1** against its background? Same calculation, looser threshold. Specifically check focus rings — `outline: 2px solid var(--color-focus)` only passes if `--color-focus` has 3:1 contrast against *both* the element and the page surface.
126
-
127
- 48. Does any **button** have `color` ≈ `background-color` on its fill? The canary check: if the computed text colour and the computed background colour are within **5 % lightness AND 0.05 chroma** in OKLCH, fail the gate. This catches the common bug where `color: var(--color-ink)` sits on `background: var(--color-ink)` (black-on-black slop) — the LLM forgot to use `--color-accent-ink` (or `--color-paper`) for text-on-fill.
128
-
129
- 49. When `--color-accent` is used as a fill anywhere on the page (button, badge, surface), is `--color-accent-ink` **also defined** (in `:root` or theme tokens) AND used as the `color` for text on that fill? If `--color-accent-ink` is missing, Hallmark output is one careless `color: white` away from a low-contrast accident. The token must exist, must verify ≥ APCA Lc 60 / WCAG 4.5:1 against `--color-accent`, and must be applied wherever accent fills a surface that carries text.
130
-
131
- 50. Does any **dark section** (a section or panel whose `background-color` has OKLCH lightness < 50 %) carry text that uses the page-default `color: var(--color-ink)` — i.e. ink-on-ink in a section that flipped its surface? Sections that swap to a dark surface MUST also swap their text colour (typically to `--color-paper`) and ensure nested children inherit. The fix is explicit: any class that sets `background: <dark>` must also set `color: <light>` in the same rule, OR be wrapped in a parent that does. The most common failure: a `.vs__col:first-child` painted with the accent or ink colour but the inner panels still using default ink-coloured text.
132
-
133
- The CSS stamp at Step 6 should record the result: `· contrast: pass (46–50)` if all five gates pass, or `· contrast: FAIL gates <list>` if any are open. Fix before shipping.
126
+ The CSS stamp at Step 6 should record the result: contrast: pass (40–41)` if both gates pass, or contrast: FAIL gates <list>` if any are open. Fix before shipping.
134
127
 
135
128
  ## Nav · footer · hero structural slop
136
129
 
137
- Universal — apply to every genre. These gates catch the most-recognised AI fingerprints in nav, footer, and hero shape. They sit alongside the structural-fingerprint gate (gate 9): gate 9 catches the *page* fingerprint; 5155 catch the *chrome* fingerprints that sit on top of it.
130
+ Universal — apply to every genre. These gates catch the most-recognised AI fingerprints in nav, footer, and hero shape. They sit alongside the structural-fingerprint gate (gate 8): gate 8 catches the *page* fingerprint; 4245 catch the *chrome* fingerprints that sit on top of it.
138
131
 
139
- 51. **Nav fingerprint.** Is the page's `<nav>` (or top-of-page `<header>` with role="banner") the AI default — wordmark-left + 4–5 inline text links centred-or-right + button-right at full viewport width + 1 px hairline border-bottom + white background? If yes, fail unless the brief explicitly justifies N1 (the page has only 2 destinations *and* the routing table for the genre allows N1). Hallmark output should rotate among N1, N3, N4, N5, N6, N7, N8, N9 from [`component-cookbook.md`](component-cookbook.md) § Navigation.
132
+ 42. **Nav fingerprint.** Is the page's `<nav>` (or top-of-page `<header>` with role="banner") the AI default — wordmark-left + 4–5 inline text links centred-or-right + button-right at full viewport width + 1 px hairline border-bottom + white background? If yes, fail unless the brief explicitly justifies N1 (the page has only 2 destinations *and* the routing table for the genre allows N1). Hallmark output should rotate among N1, N3, N4, N5, N6, N7, N8, N9 from [`component-cookbook.md`](component-cookbook.md) § Navigation.
140
133
 
141
- 52. **Footer fingerprint.** Is the `<footer>` the AI default — 4 columns of links (Product / Company / Resources / Legal) + social-icon row + tiny copyright at the very bottom + 1 px hairline top-border + neutral grey background? If yes, fail unless the page is a genuine docs root or hub. Default to Ft1, Ft2, Ft4, Ft5, Ft6, Ft7, or Ft8 from [`component-cookbook.md`](component-cookbook.md) § Footers.
134
+ 43. **Footer fingerprint.** Is the `<footer>` the AI default — 4 columns of links (Product / Company / Resources / Legal) + social-icon row + tiny copyright at the very bottom + 1 px hairline top-border + neutral grey background? If yes, fail unless the page is a genuine docs root or hub. Default to Ft1, Ft2, Ft4, Ft5, Ft6, Ft7, or Ft8 from [`component-cookbook.md`](component-cookbook.md) § Footers.
142
135
 
143
- 53. **Hero centred-everything.** Are eyebrow, title, lede, AND CTA all stacked centred on the same vertical axis? Auto-fail. Pick at most two centred elements; break alignment for the others. Centred-narrow heroes are admissible *only* on editorial / salon / atelier voice, and even then the eyebrow or CTA should sit off-axis (margin-aligned, right-flush, or numeral-anchored).
136
+ 44. **Hero fit — sits into the page and fits the fold.** Two checks, both on the rendered hero: (a) Is `padding-block-end` ≥ 1.3× `padding-block-start`? Symmetric or top-heavy padding makes the hero float off the page; heavier bottom padding pulls it into the next section's rhythm. (b) On a standard laptop viewport — test at **1280×800** (13″), not just 1440×900 — can the hero's essential content (eyebrow, headline, lede, **and the primary CTA**, plus any hero visual's focal point) all be seen **without scrolling**? This is the other half of gate 6 (which caps the hero's *shape*): this caps its *content*. A hero can satisfy `min-height` and still overflow because the content is intrinsically too tall — usual culprits are an **oversized display clamp**, **loose line-height** (display at ~1.2 instead of 1.0–1.1), a **lede that runs 3+ lines**, or **bloated `padding-block`**. Right-size to the fold: pull the display `clamp()` max down until the headline fits 2–3 lines, set display line-height 1.0–1.1, hold the lede to ~2 lines (≤ ~60 ch), trim hero padding. **Don't overcorrect:** a hero that already fits passes untouched — this never means tiny type or stripped whitespace. Long-form / art-directed statements (a poem broadside, a scroll-poster) may legitimately run taller, but even then the **first screen must read as a complete, deliberate composition** — never a headline sliced in half by the fold.
144
137
 
145
- 54. **Hero padding asymmetry.** Is `padding-block-end` 1.3× `padding-block-start` on the hero container? If hero pads symmetrically (or pads *more* on top), it floats off the page. Hero must sit *into* the page heavier bottom padding pulls it down into the next section's rhythm. Compute on the rendered output's hero element.
138
+ 45. **Decorative-without-purpose.** Does the hero contain a decorative element (cursor, scanline, gradient blob, abstract shape, ornament, badge, sticker) that has no semantic anchor in the content? Fail. Decoration must be motivated: a cursor inside a typed command (signals "you'd type next"), a numeral that names an issue / year / version / chapter, a gradient that responds to interaction (HP3 cursor-spotlight), a stamp that names an authorship or date. Random ornaments — a "42" in the corner with no edition meaning, a cursor floating beside a hero, a Pantone chip with no colour rationale — are slop.
146
139
 
147
- 55. **Decorative-without-purpose.** Does the hero contain a decorative element (cursor, scanline, gradient blob, abstract shape, ornament, badge, sticker) that has no semantic anchor in the content? Fail. Decoration must be motivated: a cursor inside a typed command (signals "you'd type next"), a numeral that names an issue / year / version / chapter, a gradient that responds to interaction (HP3 cursor-spotlight), a stamp that names an authorship or date. Random ornaments — a "42" in the corner with no edition meaning, a cursor floating beside a hero, a Pantone chip with no colour rationale — are slop.
148
-
149
- The CSS stamp at Step 6 should record the result alongside contrast: `· nav: N# · footer: Ft# · slop: pass (51–55)`. If any of 51–55 fail, fix before shipping.
140
+ The CSS stamp at Step 6 should record the result alongside contrast: nav: N# · footer: Ft# · slop: pass (42–45)`. If any of 42–45 fail, fix before shipping.
150
141
 
151
142
  ## Honest copy · no fabricated content
152
143
 
153
144
  Universal — apply to every genre. The page must not invent facts about the user's product, team, or market.
154
145
 
155
- 56. **Invented metric.** Does the page contain any quantitative claim — "10× faster", "saves 5 hours per week", "trusted by 50,000+ teams", "99.9 % uptime", "+47 % conversion" — that the user did not supply, that has no source, and that the model fabricated to fill a stat-led layout, comparison row, or proof bar? If yes, fail. The fix is one of: replace the number with `—` and a labelled grey block, replace it with a question to the user ("metric to confirm"), or rebuild the section without the proof slot. Stat-led macrostructures are slop the moment their stats become decorative. *(See [anti-patterns.md § Invented metrics](anti-patterns.md).)*
146
+ 46. **Invented metric.** Does the page contain any quantitative claim — "10× faster", "saves 5 hours per week", "trusted by 50,000+ teams", "99.9 % uptime", "+47 % conversion" — that the user did not supply, that has no source, and that the model fabricated to fill a stat-led layout, comparison row, or proof bar? If yes, fail. The fix is one of: replace the number with `—` and a labelled grey block, replace it with a question to the user ("metric to confirm"), or rebuild the section without the proof slot. Stat-led macrostructures are slop the moment their stats become decorative. **A stat is also never the hero's *sole* headline** — a lead figure carries the hero only alongside a worded headline; a giant number with no words as the dominant hero text is a bare-number tell, so pair it with a line that says what it means. *(See [anti-patterns.md § Invented metrics](anti-patterns.md).)*
156
147
 
157
148
  ## Re-drawn UI chrome
158
149
 
159
150
  Universal. Hallmark must reuse the user's existing chrome (browser, OS, IDE) instead of redrawing it.
160
151
 
161
- 57. **Re-drawn chrome.** Did Hallmark hand-build a fake browser bar (URL pill + traffic-light dots), a fake phone frame (rounded rectangle + notch + speaker slit), a fake code-block frame (mock window-chrome around a `<pre>`), a fake terminal frame, or a fake IDE chrome (file tabs + activity bar + sidebar) using HTML/CSS or SVG? If yes, fail. Re-drawn chrome is one of the strongest "looks AI-generated" tells — the model invented a UI that already exists in the user's environment. The fix: use a `<picture>` or `<figure>` containing a real screenshot, or omit the chrome and let the content stand on its own. *(See [anti-patterns.md § Re-drawn UI chrome](anti-patterns.md).)*
152
+ 47. **Re-drawn chrome.** Did Hallmark hand-build a fake browser bar (URL pill + traffic-light dots), a fake phone frame (rounded rectangle + notch + speaker slit), a fake code-block frame (mock window-chrome around a `<pre>`), a fake terminal frame, or a fake IDE chrome (file tabs + activity bar + sidebar) using HTML/CSS or SVG? If yes, fail. Re-drawn chrome is one of the strongest "looks AI-generated" tells — the model invented a UI that already exists in the user's environment. The fix: use a `<picture>` or `<figure>` containing a real screenshot, or omit the chrome and let the content stand on its own. *(See [anti-patterns.md § Re-drawn UI chrome](anti-patterns.md).)*
162
153
 
163
154
  ## Token discipline
164
155
 
165
156
  Universal. The theme picks the palette and font stack at the top of the run; the rest of the run consumes tokens, never invents them.
166
157
 
167
- 58. **Mid-render token improvisation.** Did Hallmark introduce any colour value (`#hex`, `oklch(...)`, `rgb(...)`, `hsl(...)`) or `font-family` declaration *outside* the design tokens defined in `:root` / `[data-theme="..."]`? If yes, fail. Every colour and every font in the artifact must reference a named token (`var(--color-accent)`, `font-family: var(--font-display)`). Inline OKLCH or one-off hexes are mid-render improvisation — the model picked the theme, then forgot it and freestyled. The fix: lift the value into the token block as a new named variable, or replace it with an existing token. *(See [SKILL.md § Locked tokens](../SKILL.md) and [anti-patterns.md § Mid-render token improvisation](anti-patterns.md).)*
158
+ 48. **Mid-render token improvisation.** Did Hallmark introduce any colour value (`#hex`, `oklch(...)`, `rgb(...)`, `hsl(...)`) or `font-family` declaration *outside* the design tokens defined in `:root` / `[data-theme="..."]`? If yes, fail. Every colour and every font in the artifact must reference a named token (`var(--color-accent)`, `font-family: var(--font-display)`). Inline OKLCH or one-off hexes are mid-render improvisation — the model picked the theme, then forgot it and freestyled. The fix: lift the value into the token block as a new named variable, or replace it with an existing token. *(See [SKILL.md § Locked tokens](../SKILL.md) and [anti-patterns.md § Mid-render token improvisation](anti-patterns.md).)*
168
159
 
169
160
  ## Responsive — clickable affordances
170
161
 
171
162
  Universal. Buttons, links, and nav items must remain readable as single-line affordances when the viewport shrinks.
172
163
 
173
- 59. **Two-line clickable text.** Does any button label, primary nav link, footer link, tab label, breadcrumb, or CTA text wrap to two or more lines at any viewport between 320 px and 1920 px? If yes, fail. Clickable text reading on two lines looks broken — visitors read it as a styling error, not as intentional. The fix is one of: shorten the label (the best fix; "Get started free" → "Start free"), set `white-space: nowrap` on the affordance and let the parent reflow, drop a non-essential nav item at narrow widths via `hidden=until-found`, or collapse the nav into a sheet/menu. Never let a CTA or nav link wrap. *(See [responsive.md § Clickable text — never wraps](responsive.md).)*
174
-
175
- 60. **Emoji-as-feature-icon.** Does any feature card, value prop, step number, or pricing tier carry an emoji glyph (✨ 🚀 ⚡ 🔥 🎯 ✅) as its primary icon? If yes, fail. Emoji-as-icon is one of the strongest "AI-default" tells — the model reached for a Unicode glyph instead of choosing an icon library, building a custom mark, or omitting the icon entirely. The fix: pick a single icon library (Lucide / Phosphor / Heroicons — see [assets.md](assets.md)), build a custom SVG, or drop the icon and lead with typography.
164
+ 49. **Two-line clickable text.** Does any button label, primary nav link, footer link, tab label, breadcrumb, or CTA text wrap to two or more lines at any viewport between 320 px and 1920 px? If yes, fail. Clickable text reading on two lines looks broken — visitors read it as a styling error, not as intentional. The fix is one of: shorten the label (the best fix; "Get started free" → "Start free"), set `white-space: nowrap` on the affordance and let the parent reflow, drop a non-essential nav item at narrow widths via `hidden=until-found`, or collapse the nav into a sheet/menu. Never let a CTA or nav link wrap. *(See [responsive.md § Clickable text — never wraps](responsive.md).)*
176
165
 
177
- The CSS stamp at Step 6 should record results: `· honest: pass (56) · chrome: pass (57) · tokens: pass (58) · responsive: pass (59) · icons: pass (60)`. Any failure must be fixed before shipping.
166
+ The CSS stamp at Step 6 should record results: `· honest: pass (46) · chrome: pass (47) · tokens: pass (48) · responsive: pass (49) · icons: pass (30)`. Any failure must be fixed before shipping.
178
167
 
179
168
  ## Mobile-responsiveness — the non-negotiables
180
169
 
181
- Universal. Every emitted page must render flawlessly at 320 px, 375 px, 414 px, and 768 px CSS-pixel widths. Gates 36 (no horizontal scroll) and 59 (no two-line clickable text) already cover the headline cases; 6165 below codify the patterns the marketing-site responsiveness pass uncovered. Eyeball each viewport before marking the output complete.
182
-
183
- 61. **Image-bearing grid track without `minmax(0, 1fr)`.** Does any `grid-template-columns` (or `grid-template-rows`) containing a `1fr` track render an `<img>` / `<picture>` / image-bearing element inside one of those tracks? If yes, the track must be `minmax(0, 1fr)` instead. Plain `1fr` resolves to `minmax(auto, 1fr)`, where `auto` minimum is the largest content's intrinsic width — for a 1024 + px native image, that's 1024 + px minimum, which pushes the layout past viewport on phones. The fix is one character per track: `1fr` → `minmax(0, 1fr)`.
170
+ Universal. Every emitted page must render flawlessly at 320 px, 375 px, 414 px, and 768 px CSS-pixel widths. Gates 34 (no horizontal scroll) and 49 (no two-line clickable text) already cover the headline cases; 5057 below codify the patterns the marketing-site responsiveness pass uncovered. Eyeball each viewport before marking the output complete.
184
171
 
185
- 62. **Root missing `overflow-x: clip`.** Does the artifact lack `overflow-x: clip` on both `html` and `body`? If yes, fail. `clip` (not `hidden`) prevents horizontal scroll without creating a scroll context, so `position: sticky` descendants keep working. Hard requirement on every emitted page. Add to the base reset: `html, body { overflow-x: clip; }`.
172
+ 50. **Image-bearing grid track without `minmax(0, 1fr)`.** Does any `grid-template-columns` (or `grid-template-rows`) containing a `1fr` track render an `<img>` / `<picture>` / image-bearing element inside one of those tracks? If yes, the track must be `minmax(0, 1fr)` instead. Plain `1fr` resolves to `minmax(auto, 1fr)`, where `auto` minimum is the largest content's intrinsic width — for a 1024 + px native image, that's 1024 + px minimum, which pushes the layout past viewport on phones. The fix is one character per track: `1fr` `minmax(0, 1fr)`.
186
173
 
187
- 63. **Display headers without long-word wrap.** Does any element rendering display-size text (`h1`, `.hero__display`, `.section__title`, `.skill-row__title`, hero-equivalent classes) lack `overflow-wrap: anywhere; min-width: 0`? If yes, fail. Long hyphenated words ("AI-generated", uppercase compound brand names) overflow viewport because the only break opportunity is at the hyphen — `overflow-wrap: anywhere` lets the engine break inside the word as a last resort.
174
+ 51. **Display headers without long-word wrap.** Does any element rendering display-size text (`h1`, `.hero__display`, `.section__title`, `.skill-row__title`, hero-equivalent classes) lack `overflow-wrap: anywhere; min-width: 0`? If yes, fail. Long hyphenated words ("AI-generated", uppercase compound brand names) overflow viewport because the only break opportunity is at the hyphen — `overflow-wrap: anywhere` lets the engine break inside the word as a last resort.
188
175
 
189
- 64. **Per-theme section-head override without mobile collapse.** When a theme or variant overrides `.section__head { grid-template-columns: ... }` to anything other than `1fr`, does it also include the mobile-collapse rule, OR does a global `[data-theme] .section__head { grid-template-columns: 1fr }` exist at `@media (max-width: 48rem)` with matching specificity? If neither, fail. Theme-specific 2-column heads keep their template on mobile, the title wraps onto the section label, and the page reads broken (most visible on Sport: italic Anton title overlapping "02 / EXAMPLES").
176
+ 52. **Per-theme section-head override without mobile collapse.** When a theme or variant overrides `.section__head { grid-template-columns: ... }` to anything other than `1fr`, does it also include the mobile-collapse rule, OR does a global `[data-theme] .section__head { grid-template-columns: 1fr }` exist at `@media (max-width: 48rem)` with matching specificity? If neither, fail. Theme-specific 2-column heads keep their template on mobile, the title wraps onto the section label, and the page reads broken (most visible on Sport: italic Anton title overlapping "02 / EXAMPLES").
190
177
 
191
- 65. **CSS-only radio tab pattern that scroll-jumps.** When implementing tab toggles via `<input type="radio">` siblings + `:checked` selectors, does the artifact either (a) keep the radios in normal document flow with zero size + opacity 0 (no `position: absolute; top: 0`), OR (b) ship a JS handler that intercepts label clicks, calls `e.preventDefault()`, manually sets `radio.checked = true`, dispatches `change`, and focuses with `{ preventScroll: true }`? If the radios are at `position: absolute; top: 0` with no JS guard, fail. Default-position radios cause the page to jump to the section's top on every tab click — visible on every viewport but most disruptive on mobile.
178
+ 53. **CSS-only radio tab pattern that scroll-jumps.** When implementing tab toggles via `<input type="radio">` siblings + `:checked` selectors, does the artifact either (a) keep the radios in normal document flow with zero size + opacity 0 (no `position: absolute; top: 0`), OR (b) ship a JS handler that intercepts label clicks, calls `e.preventDefault()`, manually sets `radio.checked = true`, dispatches `change`, and focuses with `{ preventScroll: true }`? If the radios are at `position: absolute; top: 0` with no JS guard, fail. Default-position radios cause the page to jump to the section's top on every tab click — visible on every viewport but most disruptive on mobile.
192
179
 
193
- 66. **Section eyebrow / tag beside the heading (tag-left, header-right).** Does any section render an eyebrow / number / mono-cap label (`01 · THE TOUR`, `02 / FEATURES`, `Chapter Three`) in a column to the left of, or to the right of, the section heading on the same horizontal row? Auto-fail. The pattern reads as a templated editorial-SaaS tell within seconds. When an eyebrow is used at all (see [`anti-patterns.md § Eyebrow on every section`](anti-patterns.md) — default OFF), the heading goes **directly underneath it in the same column**, vertical stack only. Concretely: **any `<header>`, `<div>`, or `<section>` wrapper — regardless of class name (`.section__head`, `.workbench__head`, `.pricing__head`, `.catches__head`, `.foo__intro`, anything macrostructure- or section-specific)** — that contains both an eyebrow / label / number / kicker element AND a heading element MUST resolve to single-column layout: `display: block`, `display: flex; flex-direction: column`, or `display: grid; grid-template-columns: 1fr` (or `minmax(0, 1fr)`). Any multi-column grid on such a wrapper (`grid-template-columns: 1fr 2fr`, `minmax(0, 0.4fr) minmax(0, 1fr)`, `auto 1fr`, etc.) is banned. **The rule binds on the *content shape* — eyebrow + heading in the same wrapper — not on a specific class-name allowlist.** It supersedes the "Left-margin" axis in [`structure.md`](structure.md) and the "Hanging headers" pattern in [`layout-and-space.md`](layout-and-space.md) for any head that carries an eyebrow. **NOT bypassable by "preserve structural parity" / "mirror this reference" / "match the prior build" instructions** — if a reference build ships the banned pattern (most pre-rule-66 builds do), silently flatten it in the new build. The rules win over parity. Reference builds may pre-date this gate; the gate is authoritative.
180
+ 54. **Section eyebrow / tag beside the heading (tag-left, header-right).** Does any section render an eyebrow / number / mono-cap label (`01 · THE TOUR`, `02 / FEATURES`, `Chapter Three`) in a column to the left of, or to the right of, the section heading on the same horizontal row? Auto-fail. The pattern reads as a templated editorial-SaaS tell within seconds. When an eyebrow is used at all (see [`anti-patterns.md § Eyebrow on every section`](anti-patterns.md) — default OFF), the heading goes **directly underneath it in the same column**, vertical stack only. Concretely: **any `<header>`, `<div>`, or `<section>` wrapper — regardless of class name (`.section__head`, `.workbench__head`, `.pricing__head`, `.catches__head`, `.foo__intro`, anything macrostructure- or section-specific)** — that contains both an eyebrow / label / number / kicker element AND a heading element MUST resolve to single-column layout: `display: block`, `display: flex; flex-direction: column`, or `display: grid; grid-template-columns: 1fr` (or `minmax(0, 1fr)`). Any multi-column grid on such a wrapper (`grid-template-columns: 1fr 2fr`, `minmax(0, 0.4fr) minmax(0, 1fr)`, `auto 1fr`, etc.) is banned. **The rule binds on the *content shape* — eyebrow + heading in the same wrapper — not on a specific class-name allowlist.** It supersedes the "Left-margin" axis in [`structure.md`](structure.md) and the "Hanging headers" pattern in [`layout-and-space.md`](layout-and-space.md) for any head that carries an eyebrow. **NOT bypassable by "preserve structural parity" / "mirror this reference" / "match the prior build" instructions** — if a reference build ships the banned pattern (most pre-rule builds do), silently flatten it in the new build. The rules win over parity. Reference builds may pre-date this gate; the gate is authoritative.
194
181
 
195
- 67. **All-caps display heads with line-height < 1.0 → cap-collision on wrap.** Does any display-size element (`.hero__display`, `.section__title`, `h1`, `h2`, or anything `≥ --text-2xl`) declare both `text-transform: uppercase` AND a `line-height` (or `--lh-tight`) below `1.0`? If yes, fail. Uppercase glyphs have no descenders and their cap-tops sit at the very top of the line box — at `line-height: 0.94` (the old Manifesto / Sport / Brutal default) the cap-tops of line N+1 visibly collide with the baseline or commas of line N when the title wraps. The condensed display faces (Anton, Inter Tight 900, Bebas Neue) make this worse. **Floor for all-caps display heads is `line-height: 1.0`; recommended `1.02–1.08`.** Either bump `--lh-tight` ≥ 1.0 for the theme, or drop `text-transform: uppercase` on the display element. Most visible when a two-line `.section__title` wraps with a trailing comma on line one ("SAME PROMPT, TWO / DIFFERENT OUTPUTS.") — the comma + cap-D fuse into a single glyph blob.
182
+ 55. **All-caps display heads with line-height < 1.0 → cap-collision on wrap.** Does any display-size element (`.hero__display`, `.section__title`, `h1`, `h2`, or anything `≥ --text-2xl`) declare both `text-transform: uppercase` AND a `line-height` (or `--lh-tight`) below `1.0`? If yes, fail. Uppercase glyphs have no descenders and their cap-tops sit at the very top of the line box — at `line-height: 0.94` (the old Manifesto / Sport / Brutal default) the cap-tops of line N+1 visibly collide with the baseline or commas of line N when the title wraps. The condensed display faces (Anton, Inter Tight 900, Bebas Neue) make this worse. **Floor for all-caps display heads is `line-height: 1.0`; recommended `1.02–1.08`.** Either bump `--lh-tight` ≥ 1.0 for the theme, or drop `text-transform: uppercase` on the display element. Most visible when a two-line `.section__title` wraps with a trailing comma on line one ("SAME PROMPT, TWO / DIFFERENT OUTPUTS.") — the comma + cap-D fuse into a single glyph blob.
196
183
 
197
- 68. **Sticky element at `top: 0` below a sticky page-level nav → bleed.** Does the artifact declare `position: sticky; top: 0;` on any element OTHER than the page's top-level nav / banner / header, when a sticky `<header>` / `<nav>` / `.banner` also exists at `top: 0` (i.e. there are two sticky-at-top-0 elements on the page)? Auto-fail. Both stick to the viewport top during scroll and overlap; the deeper-in-DOM element paints over the nav (visible as a "section header bleeding into the nav bar" glitch). Fix: define a `--banner-height` token (~44–64 px depending on nav design) and offset every secondary sticky to `top: var(--banner-height)`, so it docks **beneath** the nav. Also give the nav a higher z-index than in-page sticky elements — split `--z-sticky` (in-page, e.g. 200) from `--z-sticky-nav` (top nav, e.g. 300) so the nav always out-paints when sticky boxes momentarily overlap. This gate fires only when the page actually has sticky elements (S3 sticky-pinned section heads, F2 sticky-scroll feature stacks, sticky tables-of-contents); pages without sticky behaviour pass trivially.
184
+ 56. **Sticky element at `top: 0` below a sticky page-level nav → bleed.** Does the artifact declare `position: sticky; top: 0;` on any element OTHER than the page's top-level nav / banner / header, when a sticky `<header>` / `<nav>` / `.banner` also exists at `top: 0` (i.e. there are two sticky-at-top-0 elements on the page)? Auto-fail. Both stick to the viewport top during scroll and overlap; the deeper-in-DOM element paints over the nav (visible as a "section header bleeding into the nav bar" glitch). Fix: define a `--banner-height` token (~44–64 px depending on nav design) and offset every secondary sticky to `top: var(--banner-height)`, so it docks **beneath** the nav. Also give the nav a higher z-index than in-page sticky elements — split `--z-sticky` (in-page, e.g. 200) from `--z-sticky-nav` (top nav, e.g. 300) so the nav always out-paints when sticky boxes momentarily overlap. This gate fires only when the page actually has sticky elements (S3 sticky-pinned section heads, F2 sticky-scroll feature stacks, sticky tables-of-contents); pages without sticky behaviour pass trivially.
198
185
 
199
- 69. **Studied DNA discarded for a catalog theme.** Did a `study` diagnosis emit earlier in the conversation, AND does the build's CSS stamp's `theme:` field name a catalog theme (Specimen, Atelier, Brutal, Salon, Newsprint, Linen, Studio, Manifesto, Terminal, Midnight, Almanac, Garden, Quiet, Riso, Sport, Bloom, Coral, Violet, Aurora, Halo, Plume, Editorial) rather than `studied-DNA (source: ...)` — without the user having explicitly pivoted ("use Linen instead", "ignore the DNA", "rotate to a different theme")? Auto-fail. The studied DNA was meant to be the system (SKILL.md § 2.6 Condition 0); defaulting back to catalog is the attractor pull. Fix: re-emit using the studied DNA's tokens directly (paper OKLCH, accent OKLCH, named candidate fonts, macrostructure, archetypes) and update the stamp to `theme: studied-DNA (source: <URL or image>)` with the inline values. This gate is trivially passed when no recent study exists in conversation scope.
186
+ 57. **Studied DNA discarded for a catalog theme.** Did a `study` diagnosis emit earlier in the conversation, AND does the build's CSS stamp's `theme:` field name a catalog theme (Specimen, Midnight, Brutal, Garden, Atelier, Newsprint, Terminal, Manifesto, Almanac, Sport, Studio, Riso, Bloom, Coral, Cobalt, Aurora, Editorial, Carnival, Lumen, Hum) rather than `studied-DNA (source: ...)` — without the user having explicitly pivoted ("use Newsprint instead", "ignore the DNA", "rotate to a different theme")? Auto-fail. The studied DNA was meant to be the system (SKILL.md § 2.6 Condition 0); defaulting back to catalog is the attractor pull. Fix: re-emit using the studied DNA's tokens directly (paper OKLCH, accent OKLCH, named candidate fonts, macrostructure, archetypes) and update the stamp to `theme: studied-DNA (source: <URL or image>)` with the inline values. This gate is trivially passed when no recent study exists in conversation scope.
200
187
 
201
- The CSS stamp at Step 6 records mobile pass alongside contrast: `· mobile: pass (36, 59, 6169)`.
188
+ The CSS stamp at Step 6 records mobile pass alongside contrast: `· mobile: pass (34, 49, 5057)`.
202
189
 
203
190
  ---
204
191