docs: strip AI prose, add STYLE.md and validateProse (#134)

Site copy was being called out as AI slop (specifically the word
"load-bearing"). Five-pass cleanup with a build validator to keep it
from creeping back.

Pass 1 — mechanical purge:
- Remove "load-bearing" from impeccable.md, brand.md, live.md,
  iterate-live.md
- Remove "highest-leverage" from critique.md, typeset.md, designing
- Remove em dashes from all 9 slop-page rule cards
- Replace "leverage" verb in personas.md

Pass 2 — rewrite the worst offenders:
- Changelog v2.0 "Data-driven skill rewrite" entry: drop "data-driven",
  "frontier models", "collapses into monoculture", "biggest unlock",
  "reflex defaults"; name the actual mechanism
- README opener: drop "deeper expertise and more control"; replace with
  three concrete differentiators (7 reference files, 23 commands, 27
  detection rules)
- Neo Mirai case study opener: action-first, name the image model used

Pass 3 — editorials:
- Fix negation pivot in distill.md ("simplicity is not about ... It is
  about ...")

Pass 4 — homepage why-panels:
- Foundation lead: name the 7 reference files specifically
- Language lead: show the discipline mapping with real command names
- Production-codebases panel: drop "Impeccable isn't a sketchpad"
  negation pivot
- Ships-code panel: replace "is native to that world" with "runs there"

Pass 5 — STYLE.md and validator:
- New STYLE.md at root: editorial brief with 12 principles and the
  enforced denylist (each rule with a rationale and a suggested
  replacement)
- scripts/build.js: validateNoEmDashes becomes validateProse. Adds 21
  phrase rules with rationales, catches the \`--\` em-dash substitute,
  expands target list to site/pages, site/content, README.md,
  README.npm.md
- CLAUDE.md: replace the em-dash section with a STYLE.md pointer and
  document the two-content-tree footgun (content/site/ vs site/content/
  must be edited in lockstep until they're unified)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-05-02 23:40:32 -07:00
committed by GitHub
co-authored by Claude
parent eecdfa128e
commit 122a82f715
72 changed files with 279 additions and 110 deletions
+1 -1
View File
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
+1 -1
View File
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
+1 -1
View File
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
+1 -1
View File
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
+1 -1
View File
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
+1 -1
View File
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
+1 -1
View File
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
+1 -1
View File
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
+1 -1
View File
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
+1 -1
View File
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
+1 -1
View File
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
+1 -1
View File
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
+1 -1
View File
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
+16 -2
View File
@@ -51,9 +51,23 @@ Edit any of these directly and reload. No rebuild needed for CSS changes.
- **`--color-ash`** (55%) is for secondary labels, captions, relationship meta lines.
- **Never use pure black or pure white.** Use the tinted tokens.
## No em dashes, no `--` either
## Prose: read STYLE.md before writing user-facing copy
CLAUDE.md feedback from multiple sessions: "no em dashes in project copy" does NOT mean "replace with `--`". It means **use actual punctuation**: commas, colons, semicolons, periods, parentheses. The `--` substitution makes the problem worse. The build validator (`validateNoEmDashes` in `scripts/build.js`) catches real em dashes but not the `--` double-hyphen habit, so you have to catch yourself.
Editorial brief is at `STYLE.md` (root). Read it before editing the homepage, sub-pages, command editorials, tutorials, or READMEs. The site has been called out for AI prose; the rules there exist to keep that from creeping back.
The build's `validateProse` step (in `scripts/build.js`) enforces a denylist: em dashes (`—` and HTML entities), the `--` em-dash substitute, `load-bearing`, `highest-leverage`, `biggest unlock`, `seamless`, `robust`, `delve`, `elevate`, `empower`, `underscore`, `pivotal`, `tapestry`, `data-driven`, `reflex defaults`, `collapses into monoculture`, `in today's`, `gone are the days`, `whether you're`, `let's dive in`, `in summary`, `in conclusion`, `moreover`, `furthermore`. Each rule prints a rationale and a suggested replacement when it fires. **Do not silently work around the regex.** If a banned word has earned a real meaning here, raise it as a STYLE.md amendment.
The validator scans `content/site/`, `site/pages/`, `site/content/`, `site/components/`, `site/layouts/`, `README.md`, `README.npm.md`. It deliberately skips `source/skills/impeccable/` because LLM-facing reference instructions sometimes need technical phrasings the marketing copy can't.
The deeper structural issues (negation pivot, triadic auto-pilot, uniform paragraph rhythm, hollow confidence) require human judgment. STYLE.md lists them. Use them on every editorial pass.
## Two content trees: keep them in sync
After the Astro migration, editorials and tutorials live in TWO places that are both real:
- `content/site/skills/<id>.md` and `content/site/tutorials/<id>.md` — read by `scripts/build.js` for taglines and as source of truth for downstream tooling.
- `site/content/skills/<id>.md` and `site/content/tutorials/<id>.md` — read by Astro's content collection; this is what actually renders on the site.
There is no automated sync. **Edit both** when changing any editorial or tutorial body. `diff -rq content/site/ site/content/` should always be clean except for `anti-patterns-catalog.js`. Unifying these is on the cleanup list.
## Development Server
+6 -6
View File
@@ -6,14 +6,14 @@ The vocabulary you didn't know you needed. 1 skill, 23 commands, and curated ant
## Why Impeccable?
Anthropic created [frontend-design](https://github.com/anthropics/skills/tree/main/skills/frontend-design), a skill that guides Claude toward better UI design. Impeccable builds on that foundation with deeper expertise and more control.
Anthropic's [frontend-design](https://github.com/anthropics/skills/tree/main/skills/frontend-design) was the first widely-used design skill for Claude. Impeccable started from there.
Every LLM learned from the same generic templates. Without guidance, you get the same predictable mistakes: Inter font, purple gradients, cards nested in cards, gray text on colored backgrounds.
Every model trained on the same SaaS templates. Skip the guidance and you get the same handful of tells on every project: Inter for everything, purple-to-blue gradients, cards nested in cards, gray text on colored backgrounds, the rounded-square icon tile above every heading.
Impeccable fights that bias with:
- **An expanded skill** with 7 domain-specific reference files ([view source](source/skills/impeccable/))
- **23 commands** to audit, review, polish, distill, animate, and more
- **Curated anti-patterns** that explicitly tell the AI what NOT to do
Impeccable adds:
- **7 domain reference files** ([view source](source/skills/impeccable/)). Typography, color, motion, spatial, interaction, responsive, UX writing. Load on every command, alongside a brand-vs-product register that adjusts the defaults.
- **23 commands.** A shared design vocabulary with your AI: `polish`, `audit`, `critique`, `distill`, `animate`, `bolder`, `quieter`, and more.
- **27 deterministic anti-pattern rules** plus a 12-rule LLM critique pass. CLI and browser extension run the deterministic ones with no LLM and no API key. Each is tied to specific design guidance the skill teaches against.
## What's Included
+103
View File
@@ -0,0 +1,103 @@
# STYLE.md
Editorial brief for impeccable.design. Read this before writing or editing user-facing copy: the homepage, sub-pages, command editorials, tutorials, and READMEs.
The bar: **for every paragraph, point to the sentence that makes it specifically yours.** If you can't, the paragraph is AI by default, even if a human typed it.
## Principles
1. **Open with the reader's wrong belief, your strongest claim, or the example.** No "in this guide", no "let's dive in".
2. **Take a position someone could disagree with.** If the paragraph could be inverted without changing meaning, it has no position. Sign your stance.
3. **Name names. Use numbers.** Real competitors, real customer names, real version numbers, real file paths, real benchmarks. Cut "lightweight"; write "54 KB".
4. **Verbs lead. Nouns follow.** Imperative is fine. Active voice. Cut nominalizations ("the implementation of" → "implementing").
5. **Vary sentence length on purpose.** Long, long, short. Smooth uniform rhythm is the deepest AI tell.
6. **Prose carries the load; structure supports it.** Bullets are for parallel options. Paragraphs are for argument. Don't bullet what would be tighter as a sentence.
7. **Plain words. Technical terms only when something specifically rests on them.** Mixing levels lets the technical terms hit harder.
8. **Allow ungrammatical fragments for rhythm.** Five words. Confidence signal.
9. **Respect the reader's competence.** No "developers should consider"; just "you might not need an effect".
10. **Read it aloud. Fix anything you stumble over.**
11. **Concrete over comprehensive.** Coverage is an AI obsession. Trade coverage for momentum. Leave things out.
12. **Close by handing off the next move.** Don't summarize. End on the strongest sentence, give a directive ("Now do this"), or just stop.
## Denylist
The build's `validateProse` step (in `scripts/build.js`) fails the build on these. The list is the editorial brief, enforced. Add a rule here when you ban a new pattern; remove a rule when the term has earned a real meaning here. **Do not silently allowlist** by working around the regex.
### Stolen-engineer diction
Engineering words that became AI flavor once they leaked into training data around late 2024.
| Banned | Why | Use instead |
|---|---|---|
| `load-bearing` | Almost always vague. The literal sense is rare. | Name the specific thing it does. "The decision that shapes the rest", "carries the brand", "matters specifically". |
| `highest-leverage` | Vague claim of impact. | Say what specifically pays off. "The change that moves the design most". |
| `biggest unlock` | Marketing-speak. | Describe the actual change. |
### Internal jargon leaking out
Words that work in a research notebook and fail in user copy.
| Banned | Why | Use instead |
|---|---|---|
| `reflex defaults` | Eval-team jargon. | "Instincts", "first guesses", "default reaches". |
| `collapses into monoculture` | Eval-paper voice. | Describe what specifically went wrong (e.g. "every model picked the same three fonts"). |
| `data-driven` | Empty marketing adjective. | Cite the data. "Validated against 15 briefs across two models". |
### Marketing voice
Adjectives and verbs that gesture at quality without doing the work.
| Banned | Why | Use instead |
|---|---|---|
| `seamless`, `seamlessly` | Hollow positive. | Say what specifically works without friction. |
| `robust`, `robustness` | Hollow positive. | Cite the failure mode handled. |
| `elevate`, `elevates` | Marketing verb. | Use the specific verb (improve, raise, sharpen). |
| `empower`, `empowers` | Marketing verb. | "Let you", "make possible". |
| `underscore`, `underscores` | AI tell. | "Show", "make clear". |
| `pivotal` | Hollow positive. | "Central", "key", or describe the role. |
| `tapestry` | AI scenery noun. | Cut. |
### Verbs
| Banned | Why | Use instead |
|---|---|---|
| `delve`, `delves`, `delved`, `delving` | The most-flagged AI tell of all. | "Look at", "explore", or just delete the throat-clearing verb. |
### Throat-clearing
Sentences that delay the point. Cut them; almost nothing of value is lost.
| Banned | Why | Use instead |
|---|---|---|
| `in today's …` | Generic opener. | Start at the actual point. |
| `gone are the days` | Cliché opener. | Make the point directly. |
| `whether you're …` | Audience-pandering; addresses no one. | Pick one reader. Write to them. |
| `let's dive in` | Throat-clearing. | Just start. |
### Closers
| Banned | Why | Use instead |
|---|---|---|
| `in summary`, `in conclusion` | Restates what was just said. | End on the strongest sentence. Trust the reader. |
### Transitions
| Banned | Why | Use instead |
|---|---|---|
| `moreover`, `furthermore` | Metronome transition crutch. | Drop, or use "also", or restructure. |
### Punctuation
| Banned | Why | Use instead |
|---|---|---|
| Em dash `—` (and HTML entities `&mdash;`, `&#8212;`, `&#x2014;`) | Decision-avoidance: writer didn't pick a relationship between the clauses. | Comma, colon, semicolon, period, parentheses. Pick the relationship. |
| ` -- ` (double hyphen as em-dash substitute) | Worse than the em dash. Signals failed cleanup. | Real punctuation. |
## Patterns the validator can't catch
The above are the easy wins. The deeper issues require human judgment on every paragraph.
- **Negation pivot.** "It's not just X, it's Y." "Less about X, more about Y." This is now a stronger AI tell than any vocabulary item. Use sparingly. Most instances should be replaced with a direct positive claim.
- **Triadic everything.** Every list exactly three items. Every adjective in groups of three ("fast, simple, and powerful"). Vary count: use 2 or 4. Use 1.
- **The five-paragraph essay shape.** Intro → 3 sections → conclusion, on every page. Mix it up. Lead with the example. Skip the conclusion. Let some sections be one sentence.
- **Uniform paragraph length.** Insert a 4-word sentence. Insert a one-line paragraph.
- **Synthetic balance.** Pros and cons of equal length when one is clearly right. Write the recommendation; note real exceptions briefly.
- **Hollow confidence.** "Powerful" without numbers. Replace with a concrete fact.
- **Hedging stacks.** "It might potentially be useful to consider..." Each hedge is fine; stacked, they sound trained.
- **Interchangeable copy.** Swap "Impeccable" for a competitor name. If nothing becomes false, the copy is generic.
## When in doubt
Read the paragraph aloud. If you stumble, rewrite. If a sentence describes nothing specific to this product, cut it.
+1 -1
View File
@@ -105,5 +105,5 @@ From there, pair with `/impeccable polish` or `/impeccable distill` to act on th
## Pitfalls
- **Running it on incomplete work.** Critique is for finished pages. An empty state with three TODOs will score badly because it is not done, not because it is bad.
- **Ignoring the questions at the end.** They are usually the highest-leverage fixes.
- **Ignoring the questions at the end.** They are usually the fixes that change the design most.
- **Treating the heuristic scores as a grade.** They are diagnostic, not evaluative. A 3/4 on a heuristic that matters less for your context is fine.
+1 -1
View File
@@ -17,7 +17,7 @@ It works in two passes:
1. **Assess the complexity sources**. Too many elements, excessive variation, information overload, visual noise, confusing hierarchy, feature creep. Name each one.
2. **Edit ruthlessly**. Remove what is not essential. Combine what can be combined. Hide what can wait. Consolidate variation into a single treatment. Commit to a single visual language.
The principle: simplicity is not about fewer features. It is about fewer obstacles between users and their goals. Every element on the page has to justify its existence.
The principle: every element on the page has to justify its existence. Fewer obstacles, not fewer features.
## Try it
+1 -1
View File
@@ -23,7 +23,7 @@ Two files at your project root shape everything the skill does:
- **`PRODUCT.md`** carries register (brand vs product), target users, brand personality, anti-references, design principles. Answers "who, what, why".
- **`DESIGN.md`** carries colors, typography, elevation, components, do's and don'ts, in the six-section Google Stitch format. Answers "how it looks".
Every command reads both files before generating. **Register** is the load-bearing switch. Brand (marketing, landing, portfolio, where design IS the product) and product (app UI, dashboards, tools, where design SERVES the product) have different defaults for type, motion, color, and density. Specifying it once in PRODUCT.md means `/impeccable typeset` will not push editorial-magazine fonts on a dashboard, and will not push product-fluent defaults on a campaign page. See the [brand vs product tutorial](/tutorials/brand-vs-product) for how the two diverge.
Every command reads both files before generating. **Register** decides which defaults load. Brand (marketing, landing, portfolio, where design IS the product) and product (app UI, dashboards, tools, where design SERVES the product) have different defaults for type, motion, color, and density. Specifying it once in PRODUCT.md means `/impeccable typeset` will not push editorial-magazine fonts on a dashboard, and will not push product-fluent defaults on a campaign page. See the [brand vs product tutorial](/tutorials/brand-vs-product) for how the two diverge.
On first use in a project, the skill runs the `teach` flow automatically: a short interview that writes PRODUCT.md and then delegates to `/impeccable document` for DESIGN.md. Future commands read the files without asking again.
+1 -1
View File
@@ -47,7 +47,7 @@ A few things you can do before pressing Go:
- **Click the command chip** (default is `impeccable`, the freeform action). Pick a specific action like `bolder`, `delight`, `layout`, or `typeset` to constrain the variants along one dimension.
- **Type in the freeform field.** "More playful." "Less SaaS." "Feel like a newsletter from a magazine."
- **Drop a comment pin** by clicking anywhere on the picked element. The pin's position is load-bearing: a comment near the title is about the title, not the whole element.
- **Drop a comment pin** by clicking anywhere on the picked element. The pin's position matters: a comment near the title is about the title, not the whole element.
- **Draw a stroke** by dragging across the element. Closed loop = "this part matters." Arrow = direction. Cross = "delete this." The skill reads strokes by shape, not by pixel content.
When the brief feels clear, hit **Go**.
+1 -1
View File
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params
+72 -20
View File
@@ -129,22 +129,83 @@ function validateSkillFrontmatter(skills) {
}
/**
* Scan user-facing copy for em dashes ( or &mdash;).
* Em dashes in project copy are a known anti-pattern here; flag them loudly.
* Only scans files where we author copy, not vendored or generated output.
* Scan user-facing copy for AI-prose anti-patterns:
* - em dashes ( or &mdash;)
* - double-hyphen substitutes (` -- `)
* - denylisted phrases that read as AI tells in marketing copy
*
* Returns the number of occurrences found.
* The denylist is the editorial brief in STYLE.md, enforced. Each rule has a
* rationale that prints with the failure so the next author understands why.
*
* Scope: every surface a reader sees. Not source/skills/impeccable/, where
* LLM-facing reference instructions can use technical phrasings the marketing
* copy can't.
*
* Returns the number of occurrences found. Build fails if > 0.
*/
function validateNoEmDashes(rootDir) {
function validateProse(rootDir) {
const targets = [
'content/site',
'site/components',
'site/content',
'site/layouts',
'site/pages',
'README.md',
'README.npm.md',
];
const extensions = new Set(['.html', '.md', '.js', '.mjs', '.css', '.astro']);
const emDashPatterns = [/—/g, /&mdash;/gi, /&#8212;/gi, /&#x2014;/gi];
// Phrase rules: { re, rationale }. Add to STYLE.md when adding here.
const phraseRules = [
{ re: /\bload-bearing\b/i, rationale: 'AI tell. Stolen-engineer diction; almost always vague. Name what the thing actually does.' },
{ re: /\bhighest-leverage\b/i, rationale: 'AI tell. Vague claim of impact. Say what specifically pays off.' },
{ re: /\bbiggest unlock\b/i, rationale: 'AI tell. Marketing-speak. Describe the actual change.' },
{ re: /\breflex defaults?\b/i, rationale: 'Internal jargon leaking into user-facing copy. Say "instincts" or "first guesses".' },
{ re: /\bcollapses? into monoculture\b/i, rationale: 'Internal eval-speak. Describe what actually went wrong.' },
{ re: /\bdata-driven\b/i, rationale: 'Empty marketing adjective. Cite the data instead.' },
{ re: /\bseamless(?:ly)?\b/i, rationale: 'Hollow positive. Say what specifically works without friction.' },
{ re: /\brobust(?:ness)?\b/i, rationale: 'Hollow positive. Cite the failure mode it handles.' },
{ re: /\bdelves?\b|\bdelved\b|\bdelving\b/i, rationale: 'Top AI tell. Use "explore", "look at", or just delete.' },
{ re: /\belevate(?:s|d)?\b/i, rationale: 'Marketing verb. Use the specific verb (improve, raise, sharpen).' },
{ re: /\bempower(?:s|ed|ing)?\b/i, rationale: 'Marketing verb. Use "let you" or "make possible".' },
{ re: /\bunderscore(?:s|d)?\b/i, rationale: 'AI tell. Use "show" or "make clear".' },
{ re: /\bpivotal\b/i, rationale: 'Hollow positive. Use "central", "key", or describe the role.' },
{ re: /\bin today's\b/i, rationale: 'Throat-clearing opener. Cut the clause; start at the point.' },
{ re: /\bgone are the days\b/i, rationale: 'Throat-clearing. Make the point directly.' },
{ re: /\bwhether you're\b/i, rationale: 'Audience-pandering. Pick one reader; write to them.' },
{ re: /\blet's dive in\b/i, rationale: 'Throat-clearing. Just start.' },
{ re: /\bin summary\b|\bin conclusion\b/i, rationale: 'Summarizing closer. End on the strongest sentence; trust the reader.' },
{ re: /\bmoreover\b|\bfurthermore\b/i, rationale: 'Transition crutch on a metronome. Drop, or use "also".' },
{ re: /\btapestry\b/i, rationale: 'AI scenery noun. Cut.' },
];
let errors = 0;
const checkLine = (line, rel, lineNum) => {
for (const re of emDashPatterns) {
if (re.test(line)) {
console.error(`${rel}:${lineNum}: em dash → ${line.trim().slice(0, 120)}`);
console.error(` Use commas, colons, semicolons, periods, or parentheses.`);
errors++;
re.lastIndex = 0;
break;
}
re.lastIndex = 0;
}
if (/ -- /.test(line)) {
console.error(`${rel}:${lineNum}: \` -- \` em-dash substitute → ${line.trim().slice(0, 120)}`);
console.error(` Worse than the em dash. Pick real punctuation.`);
errors++;
}
for (const rule of phraseRules) {
if (rule.re.test(line)) {
const matched = line.match(rule.re)?.[0] ?? '';
console.error(`${rel}:${lineNum}: "${matched}" → ${line.trim().slice(0, 120)}`);
console.error(` ${rule.rationale}`);
errors++;
}
}
};
const scan = (absPath, rel) => {
const stat = fs.statSync(absPath);
if (stat.isDirectory()) {
@@ -156,16 +217,7 @@ function validateNoEmDashes(rootDir) {
if (!extensions.has(path.extname(absPath))) return;
const src = fs.readFileSync(absPath, 'utf-8');
const lines = src.split('\n');
lines.forEach((line, i) => {
for (const re of emDashPatterns) {
if (re.test(line)) {
console.error(`${rel}:${i + 1}: em dash in copy → ${line.trim().slice(0, 120)}`);
errors++;
break;
}
re.lastIndex = 0;
}
});
lines.forEach((line, i) => checkLine(line, rel, i + 1));
};
for (const target of targets) {
@@ -174,9 +226,9 @@ function validateNoEmDashes(rootDir) {
}
if (errors === 0) {
console.log(`No em dashes in project copy`);
console.log(`Prose validator: no AI tells in user-facing copy`);
} else {
console.error(`\n${errors} em dash(es) in project copy. Use commas, colons, or parentheses.`);
console.error(`\n${errors} prose issue(s) in user-facing copy. See STYLE.md for the rules.`);
}
return errors;
}
@@ -672,10 +724,10 @@ async function build() {
// Verify every hand-authored HTML page carries the shared site header
const headerErrors = validateSiteHeader(ROOT_DIR);
// Scan user-facing copy for em dashes
const emDashErrors = validateNoEmDashes(ROOT_DIR);
// Scan user-facing copy for AI tells (em dashes, marketing fluff, denylisted phrases)
const proseErrors = validateProse(ROOT_DIR);
if (countErrors > 0 || headerErrors > 0 || emDashErrors > 0) {
if (countErrors > 0 || headerErrors > 0 || proseErrors > 0) {
process.exit(1);
}
+1 -1
View File
@@ -105,5 +105,5 @@ From there, pair with `/impeccable polish` or `/impeccable distill` to act on th
## Pitfalls
- **Running it on incomplete work.** Critique is for finished pages. An empty state with three TODOs will score badly because it is not done, not because it is bad.
- **Ignoring the questions at the end.** They are usually the highest-leverage fixes.
- **Ignoring the questions at the end.** They are usually the fixes that change the design most.
- **Treating the heuristic scores as a grade.** They are diagnostic, not evaluative. A 3/4 on a heuristic that matters less for your context is fine.
+1 -1
View File
@@ -17,7 +17,7 @@ It works in two passes:
1. **Assess the complexity sources**. Too many elements, excessive variation, information overload, visual noise, confusing hierarchy, feature creep. Name each one.
2. **Edit ruthlessly**. Remove what is not essential. Combine what can be combined. Hide what can wait. Consolidate variation into a single treatment. Commit to a single visual language.
The principle: simplicity is not about fewer features. It is about fewer obstacles between users and their goals. Every element on the page has to justify its existence.
The principle: every element on the page has to justify its existence. Fewer obstacles, not fewer features.
## Try it
+1 -1
View File
@@ -23,7 +23,7 @@ Two files at your project root shape everything the skill does:
- **`PRODUCT.md`** carries register (brand vs product), target users, brand personality, anti-references, design principles. Answers "who, what, why".
- **`DESIGN.md`** carries colors, typography, elevation, components, do's and don'ts, in the six-section Google Stitch format. Answers "how it looks".
Every command reads both files before generating. **Register** is the load-bearing switch. Brand (marketing, landing, portfolio, where design IS the product) and product (app UI, dashboards, tools, where design SERVES the product) have different defaults for type, motion, color, and density. Specifying it once in PRODUCT.md means `/impeccable typeset` will not push editorial-magazine fonts on a dashboard, and will not push product-fluent defaults on a campaign page. See the [brand vs product tutorial](/tutorials/brand-vs-product) for how the two diverge.
Every command reads both files before generating. **Register** decides which defaults load. Brand (marketing, landing, portfolio, where design IS the product) and product (app UI, dashboards, tools, where design SERVES the product) have different defaults for type, motion, color, and density. Specifying it once in PRODUCT.md means `/impeccable typeset` will not push editorial-magazine fonts on a dashboard, and will not push product-fluent defaults on a campaign page. See the [brand vs product tutorial](/tutorials/brand-vs-product) for how the two diverge.
On first use in a project, the skill runs the `teach` flow automatically: a short interview that writes PRODUCT.md and then delegates to `/impeccable document` for DESIGN.md. Future commands read the files without asking again.
+1 -1
View File
@@ -47,7 +47,7 @@ A few things you can do before pressing Go:
- **Click the command chip** (default is `impeccable`, the freeform action). Pick a specific action like `bolder`, `delight`, `layout`, or `typeset` to constrain the variants along one dimension.
- **Type in the freeform field.** "More playful." "Less SaaS." "Feel like a newsletter from a magazine."
- **Drop a comment pin** by clicking anywhere on the picked element. The pin's position is load-bearing: a comment near the title is about the title, not the whole element.
- **Drop a comment pin** by clicking anywhere on the picked element. The pin's position matters: a comment near the title is about the title, not the whole element.
- **Draw a stroke** by dragging across the element. Closed loop = "this part matters." Arrow = direction. Cross = "delete this." The skill reads strokes by shape, not by pixel content.
When the brief feels clear, hit **Go**.
+2 -2
View File
@@ -15,7 +15,7 @@ import '../../styles/sub-pages.css';
<a class="neon-case-back" href="/designing#start">Designing with Impeccable</a>
<span class="neon-case-eyebrow">Case study</span>
<h1>Neo Mirai: generated mock to shipped page.</h1>
<p>A retro-futurist AI design conference became a real static site through the full Impeccable loop: visual reference, brand direction, implementation, asset regeneration, responsive fixes, animation polish, and browser verification.</p>
<p>Neo Mirai started as a single hi-fi mock from OpenAI GPT Image 2 and a generated brand toolkit. <code>/impeccable craft</code> turned it into the live conference site: brand interpretation, semantic implementation, regenerated assets, responsive fixes, and browser iteration in one run.</p>
<div class="neon-case-actions">
<a class="neon-case-primary" href="/neo-mirai/">Open the live build</a>
<a class="neon-case-secondary" href="/docs/craft">Read the craft docs</a>
@@ -49,7 +49,7 @@ import '../../styles/sub-pages.css';
<section class="neon-case-body">
<div class="neon-case-column">
<span class="neon-case-section-label">What changed</span>
<h2>The mock did not become a screenshot. It became a system.</h2>
<h2>The mock did not become a screenshot. It became HTML, CSS, regenerated assets, and the responsive behavior a static image only suggests.</h2>
</div>
<div class="neon-case-notes">
<article>
+1 -1
View File
@@ -416,7 +416,7 @@ import '../../styles/sub-pages.css';
<a class="designing-cta-card" href="/tutorials">
<span class="designing-cta-card-kind">Walk a scenario</span>
<h2 class="designing-cta-card-title">Open a <em>tutorial</em></h2>
<p class="designing-cta-card-desc">Four short walkthroughs of the highest-leverage flows: getting started, Live Mode, critique with the overlay, brand vs product.</p>
<p class="designing-cta-card-desc">Four short walkthroughs: getting started, Live Mode, critique with the overlay, brand vs product.</p>
</a>
</nav>
</div>
+6 -6
View File
@@ -180,7 +180,7 @@ import '../styles/sub-pages.css';
<h2 class="section-title">The Foundation</h2>
</div>
<div class="foundation-content">
<p class="section-lead" data-reveal>Before commands, before detection, Impeccable teaches your AI real design. Deep reference knowledge across 7 dimensions, loaded every time your AI writes code.</p>
<p class="section-lead" data-reveal>Before any command runs, Impeccable teaches your AI how design works. Seven reference files load on every prompt: typography, color, motion, spatial, interaction, responsive, UX writing.</p>
<div class="foundation-grid" data-reveal>
<!-- 7 dimension cards, rendered by JS -->
@@ -201,7 +201,7 @@ import '../styles/sub-pages.css';
</div>
<div class="language-content">
<div class="language-intro-row" data-reveal>
<p class="section-lead">23 commands form a shared vocabulary between you and your AI. Each one encodes a specific design discipline, so you can steer with precision. Pick any to see it in action, or <a href="/docs" class="cheatsheet-link">browse the full reference &rarr;</a></p>
<p class="section-lead">23 commands give you a shared design vocabulary with your AI. Each maps to one discipline (<code>/typeset</code> for type, <code>/colorize</code> for color, <code>/animate</code> for motion), so you can ask for the exact thing without explaining it. Pick any to see it in action, or <a href="/docs" class="cheatsheet-link">browse the full reference &rarr;</a></p>
<div class="language-view-toggle" role="tablist" aria-label="Commands view">
<button type="button" role="tab" class="language-view-tab is-active" data-view="palette" aria-selected="true">Palette</button>
<button type="button" role="tab" class="language-view-tab" data-view="periodic" aria-selected="false">Periodic</button>
@@ -358,7 +358,7 @@ import '../styles/sub-pages.css';
<article class="why-panel" id="why-panel-2" role="tabpanel" data-index="2" hidden>
<h3 class="why-panel-title">Built to live in your production codebase.</h3>
<p class="why-panel-body">Impeccable isn't a sketchpad. It reads your existing tokens, components, and rendered output; polishes what's there; flags regressions; iterates with your design system rather than around it. Daily-driver for real work on real apps, not a one-shot mock factory.</p>
<p class="why-panel-body">Impeccable reads your existing tokens, components, and rendered output. It polishes what's there, flags regressions, and stays inside your design system instead of inventing a new one each run.</p>
<div class="why-visual why-visual--terminal">
<div class="why-terminal">
<div class="why-terminal-header">
@@ -408,7 +408,7 @@ import '../styles/sub-pages.css';
<article class="why-panel" id="why-panel-4" role="tabpanel" data-index="4" hidden>
<h3 class="why-panel-title">Design where the work actually happens.</h3>
<p class="why-panel-body">The waterfall era (designer in canvas, throws a mock over the wall) is over. Most product work now starts directly in Claude Code, Cursor, Codex, Gemini, or Copilot, on the real codebase, in the browser. Impeccable is native to that world. No canvas. No handoff. Open your AI harness, type a command, ship the change.</p>
<p class="why-panel-body">The waterfall era (designer in canvas, throws a mock over the wall) is over. Most product work now starts directly in Claude Code, Cursor, Codex, Gemini, or Copilot, on the real codebase, in the browser. Impeccable runs there. No canvas. No handoff. Open your AI harness, type a command, ship the change.</p>
<div class="why-visual why-visual--v2">
<div class="v2-side v2-side--old">
<span class="v2-label">The old way</span>
@@ -963,7 +963,7 @@ import '../styles/sub-pages.css';
</div>
<ul class="changelog-items">
<li><strong>Live mode lands valid TSX through the wrap → preview → accept → carbonize loop on Vite/Next React/TSX projects.</strong> The wrapper now keeps a single JSX-slot child instead of three adjacent siblings, so it round-trips cleanly inside <code>return (...)</code>, array <code>.map(...)</code>, and <code>asChild</code> parents like Radix's <code>&lt;DialogPrimitive.Title&gt;</code>. Carbonize stopped double-wrapping CSS in nested template literals on TSX targets, accept and discard restore the picked element at its original indent (with relative depth between lines preserved), and the screenshot overlay no longer flashes solid black on default-background pages. Closes <a href="https://github.com/pbakaus/impeccable/issues/114" target="_blank" rel="noopener">#114</a>, with thanks again to <a href="https://github.com/dergachoff" target="_blank" rel="noopener">@dergachoff</a> for the detailed bug report.</li>
<li><strong>Wrap correctly disambiguates repeated identical-class siblings.</strong> A list of <code>&lt;Card className="card"&gt;</code> rendered three times with the same classes used to land on the first one regardless of which the user picked. <code>live-wrap.mjs</code> now accepts <code>--text TEXT</code> (the picked element's <code>textContent</code>) and narrows candidates accordingly, falling back to first-match when the text is too short or doesn't appear literally in source (data-driven children like <code>&#123;title&#125;</code>), and erroring with <code>element_ambiguous</code> when multiple branches still match equally.</li>
<li><strong>Wrap correctly disambiguates repeated identical-class siblings.</strong> A list of <code>&lt;Card className="card"&gt;</code> rendered three times with the same classes used to land on the first one regardless of which the user picked. <code>live-wrap.mjs</code> now accepts <code>--text TEXT</code> (the picked element's <code>textContent</code>) and narrows candidates accordingly, falling back to first-match when the text is too short or doesn't appear literally in source (children with interpolated values like <code>&#123;title&#125;</code>), and erroring with <code>element_ambiguous</code> when multiple branches still match equally.</li>
<li><strong><code>live-inject</code> CSP-meta unwrap now byte-for-byte preserves self-closing tag whitespace.</strong> The patch+revert cycle on a <code>&lt;meta http-equiv="Content-Security-Policy" ... /&gt;</code> tag was eating the space before <code>/&gt;</code> via a double-space artifact in the marker insertion path; common Vite shapes that ship a CSP meta now round-trip cleanly.</li>
<li><strong><code>live.md</code> spec gained explicit guidance for three real authoring traps.</strong> Variant CSS must use a descendant combinator (<code>:scope &gt; .card</code>, not bare <code>:scope</code>) or it lands on the wrapper instead of the picked element. JSX <code>&lt;style&gt;</code> bodies need <code>&#123;`...`&#125;</code> template-literal wrapping. Aborting an in-flight session uses <code>live-poll --reply EVENT_ID error "msg"</code>, not <code>live-accept --discard</code>; the latter only mutates source while the bar stays stuck on GENERATING dots forever.</li>
</ul>
@@ -1046,7 +1046,7 @@ import '../styles/sub-pages.css';
</div>
<ul class="changelog-items">
<li><strong>Renamed <code>frontend-design</code> to <code>impeccable</code>.</strong> The core skill now shares its name with the project, and the teach subcommand moved from <code>/teach-impeccable</code> to <code>/impeccable teach</code>. One skill, one namespace.</li>
<li><strong>Data-driven skill rewrite.</strong> The core skill was rebuilt against an internal eval framework that runs the same brief through frontier models with and without the skill loaded, then measures how much the output collapses into monoculture. The result: dramatically more font and color diversity, sharper overall design quality, and much stronger Codex support. The biggest unlock was an anti-attractor procedure that forces the model to enumerate and reject its reflex defaults before picking. Validated on gpt-5.4 and Qwen 3.6 Plus across 15 niches.</li>
<li><strong>Skill rewritten against evals.</strong> Fifteen briefs ran through gpt-5.4 and Qwen 3.6 Plus, with and without the skill loaded, then graded side by side. More font and color variety, fewer purple gradients, much better Codex output. The single change that moved the numbers most: before the model commits to a font or palette, it has to name its first three instincts and reject them.</li>
<li><strong>Anti-pattern detection engine.</strong> 27 deterministic rules across typography, color, layout, motion, and quality. Handles oklch, oklab, lch, and lab color formats, CSS variables inside border shorthands, gradient-backed text, and emoji-only nodes.</li>
<li><strong>CLI: <code>npx impeccable detect</code>.</strong> Scans HTML, CSS, JSX/TSX, Vue, Svelte, and CSS-in-JS. Framework detection, multi-file import tracking, Puppeteer-backed live URL scanning, CI-ready JSON output, and a <code>--fast</code> regex mode for huge codebases.</li>
<li><strong>Chrome DevTools extension.</strong> One-click detection on any page: yours, staging, production, or someone else's. Reads live computed styles, surfaces findings in an interactive panel, and highlights elements on the page. In Chrome Web Store review.</li>
+9 -9
View File
@@ -230,7 +230,7 @@ import '../../styles/sub-pages.css';
<span class="rule-card-layer" data-layer="cli" title="Deterministic. Runs from `npx impeccable detect` on files, no browser required.">CLI</span>
</div>
<h3 class="rule-card-name">Border accent on rounded element</h3>
<p class="rule-card-desc">Thick accent border on a rounded card — the border clashes with the rounded corners. Remove the border or the border-radius.</p>
<p class="rule-card-desc">Thick accent border on a rounded card. The border clashes with the rounded corners. Remove the border or the border-radius.</p>
<a class="rule-card-skill-link" href="/docs/impeccable#visual-details">See in /impeccable</a>
</div>
</article>
@@ -282,7 +282,7 @@ import '../../styles/sub-pages.css';
<span class="rule-card-layer" data-layer="cli" title="Deterministic. Runs from `npx impeccable detect` on files, no browser required.">CLI</span>
</div>
<h3 class="rule-card-name">Side-tab accent border</h3>
<p class="rule-card-desc">Thick colored border on one side of a card — the most recognizable tell of AI-generated UIs. Use a subtler accent or remove it entirely.</p>
<p class="rule-card-desc">Thick colored border on one side of a card. The most recognizable tell of AI-generated UIs. Use a subtler accent or remove it entirely.</p>
<a class="rule-card-skill-link" href="/docs/impeccable#visual-details">See in /impeccable</a>
</div>
</article>
@@ -316,7 +316,7 @@ import '../../styles/sub-pages.css';
<span class="rule-card-layer" data-layer="cli" title="Deterministic. Runs from `npx impeccable detect` on files, no browser required.">CLI</span>
</div>
<h3 class="rule-card-name">Flat type hierarchy</h3>
<p class="rule-card-desc">Font sizes are too close together — no clear visual hierarchy. Use fewer sizes with more contrast (aim for at least a 1.25 ratio between steps).</p>
<p class="rule-card-desc">Font sizes are too close together. No clear visual hierarchy. Use fewer sizes with more contrast (aim for at least a 1.25 ratio between steps).</p>
<a class="rule-card-skill-link" href="/docs/impeccable#typography">See in /impeccable</a>
</div>
</article>
@@ -329,7 +329,7 @@ import '../../styles/sub-pages.css';
<span class="rule-card-layer" data-layer="cli" title="Deterministic. Runs from `npx impeccable detect` on files, no browser required.">CLI</span>
</div>
<h3 class="rule-card-name">Icon tile stacked above heading</h3>
<p class="rule-card-desc">A small rounded-square icon container above a heading is the universal AI feature-card template — every generator outputs this exact shape. Try a side-by-side icon and heading, or let the icon sit in flow without its own container.</p>
<p class="rule-card-desc">A small rounded-square icon container above a heading is the universal AI feature-card template. Every generator outputs this exact shape. Try a side-by-side icon and heading, or let the icon sit in flow without its own container.</p>
<a class="rule-card-skill-link" href="/docs/impeccable#typography">See in /impeccable</a>
</div>
</article>
@@ -415,7 +415,7 @@ import '../../styles/sub-pages.css';
<span class="rule-card-layer" data-layer="cli" title="Deterministic. Runs from `npx impeccable detect` on files, no browser required.">CLI</span>
</div>
<h3 class="rule-card-name">Dark mode with glowing accents</h3>
<p class="rule-card-desc">Dark backgrounds with colored box-shadow glows are the default &quot;cool&quot; look of AI-generated UIs. Use subtle, purposeful lighting instead or skip the dark theme entirely.</p>
<p class="rule-card-desc">Dark backgrounds with colored box-shadow glows are the default &quot;cool&quot; look of AI-generated UIs. Use subtle, purposeful lighting instead, or skip the dark theme entirely.</p>
<a class="rule-card-skill-link" href="/docs/impeccable#color-contrast">See in /impeccable</a>
</div>
</article>
@@ -441,7 +441,7 @@ import '../../styles/sub-pages.css';
<span class="rule-card-layer" data-layer="cli" title="Deterministic. Runs from `npx impeccable detect` on files, no browser required.">CLI</span>
</div>
<h3 class="rule-card-name">Gradient text</h3>
<p class="rule-card-desc">Gradient text is decorative rather than meaningful — a common AI tell, especially on headings and metrics. Use solid colors for text.</p>
<p class="rule-card-desc">Gradient text is decorative rather than meaningful. A common AI tell, especially on headings and metrics. Use solid colors for text.</p>
<a class="rule-card-skill-link" href="/docs/impeccable#color-contrast">See in /impeccable</a>
</div>
</article>
@@ -527,7 +527,7 @@ import '../../styles/sub-pages.css';
<span class="rule-card-layer" data-layer="cli" title="Deterministic. Runs from `npx impeccable detect` on files, no browser required.">CLI</span>
</div>
<h3 class="rule-card-name">Monotonous spacing</h3>
<p class="rule-card-desc">The same spacing value used everywhere — no rhythm, no variation. Use tight groupings for related items and generous separations between sections.</p>
<p class="rule-card-desc">The same spacing value used everywhere. No rhythm, no variation. Use tight groupings for related items and generous separations between sections.</p>
<a class="rule-card-skill-link" href="/docs/impeccable#layout-space">See in /impeccable</a>
</div>
</article>
@@ -540,7 +540,7 @@ import '../../styles/sub-pages.css';
<span class="rule-card-layer" data-layer="cli" title="Deterministic. Runs from `npx impeccable detect` on files, no browser required.">CLI</span>
</div>
<h3 class="rule-card-name">Nested cards</h3>
<p class="rule-card-desc">Cards inside cards create visual noise and excessive depth. Flatten the hierarchy use spacing, typography, and dividers instead of nesting containers.</p>
<p class="rule-card-desc">Cards inside cards create visual noise and excessive depth. Flatten the hierarchy: use spacing, typography, and dividers instead of nesting containers.</p>
<a class="rule-card-skill-link" href="/docs/impeccable#layout-space">See in /impeccable</a>
</div>
</article>
@@ -587,7 +587,7 @@ import '../../styles/sub-pages.css';
<span class="rule-card-layer" data-layer="cli" title="Deterministic. Runs from `npx impeccable detect` on files, no browser required.">CLI</span>
</div>
<h3 class="rule-card-name">Bounce or elastic easing</h3>
<p class="rule-card-desc">Bounce and elastic easing feel dated and tacky. Real objects decelerate smoothly — use exponential easing (ease-out-quart/quint/expo) instead.</p>
<p class="rule-card-desc">Bounce and elastic easing feel dated and tacky. Real objects decelerate smoothly. Use exponential easing (ease-out-quart/quint/expo) instead.</p>
<a class="rule-card-skill-link" href="/docs/impeccable#motion">See in /impeccable</a>
</div>
</article>
+1 -1
View File
@@ -64,7 +64,7 @@ Brand surfaces have permission for Committed, Full palette, and Drenched strateg
- Name a real reference before picking a strategy. "Klim Type Foundry #ff4500 orange drench", "Stripe purple-on-white restraint", "Liquid Death acid-green full palette", "Mailchimp yellow full palette", "Condé Nast Traveler muted navy restraint", "Vercel pure black monochrome". Unnamed ambition becomes beige.
- Palette IS voice. A calm brand and a restless brand should not share palette mechanics.
- When the strategy is Committed or Drenched, the color is load-bearing. Don't hedge with neutrals around the edges — commit.
- When the strategy is Committed or Drenched, color carries the brand. Don't hedge with neutrals around the edges. Commit.
- Don't converge across projects. If the last brand surface was restrained-on-cream, this one is not.
## Layout
+1 -1
View File
@@ -66,7 +66,7 @@ When `screenshotPath` is absent, don't ask for one and don't go looking for the
Reading annotations precisely:
- **Comment position is load-bearing.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comment position carries meaning.** Its `{x, y}` is element-local CSS px (same coord space as `element.boundingRect`). Find the child under that point and apply the comment text LOCALLY to that sub-element. A comment near the title is about the title, not a global description.
- **Comments and strokes are independent annotations** unless clearly paired by overlap or tight proximity. Don't let the visual weight of a prominent stroke override the precise location of a textually-specific comment elsewhere.
- **Strokes are gestures — read them by shape.** Closed loop = "this thing" (emphasis / focus); arrow = direction (move / point to); cross or slash = delete; free scribble = emphasis or delete depending on context. A loop around region X means "pay attention to X," not "only change pixels inside X."
- **When a stroke's intent is ambiguous** (circle or arrow? emphasis or move?), state your reading in one sentence of rationale rather than silently guessing. If the uncertainty materially changes the brief, ask one short clarifying question before generating.
@@ -130,7 +130,7 @@ Test the interface through the eyes of 5 distinct user archetypes. Each persona
- Are primary actions in the thumb zone (bottom half of screen)?
- Is state preserved if the user leaves and returns?
- Does it work on slow connections (3G)?
- Can forms leverage autocomplete and smart defaults?
- Can forms use autocomplete and smart defaults?
- Are touch targets at least 44×44pt?
**Red Flags** (report these specifically):
@@ -109,7 +109,7 @@ Build a clear type scale:
- **Performance**: Are web fonts loading efficiently without layout shift?
- **Accessibility**: Does text meet WCAG contrast ratios? Is it zoomable to 200%?
Remember: Typography is the foundation of interface design — it carries the majority of information. Getting it right is the highest-leverage improvement you can make.
Remember: Typography is the foundation of interface design. It carries most of the information on the page. Getting it right changes the design more than any other single move.
## Live-mode signature params