diff --git a/DESIGN.md b/DESIGN.md index 55185a377..1bc64d375 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -139,5 +139,5 @@ Apply a subtle noise overlay to the entire page for materiality: | 2026-03-21 | Light mode amber-600 | amber-500 too bright/washed against white; amber-700 too brown/umber. amber-600 is the sweet spot. | | 2026-03-21 | Grain texture | Adds materiality to flat dark surfaces. Prevents the "generic SaaS template" sameness. | | 2026-09-08 | Open DESIGN.md format | Converted with `gstack-design-md convert`: tokens in front matter, canonical sections, Motion and Decisions Log kept as extras. DM Sans stays the body face: it sits on the overused-as-display list, and body/UI use on an Operate surface is the allowed exception under the role-scoped rule. | -| 2026-09-08 | Live-feed pulse is the one authored motion moment | The dashboard's 2s pulse on the live-feed dot is the page's single authored motion, so it stands as an intentional exception to the pulsing-dot catalog rule; every other surface keeps state changes static. | -| 2026-09-08 | JetBrains Mono labels at 11px | The mono personality font runs on labels at 11px (Nano), below the 12px UI-text floor; an intentional exception recorded here so the detector's undersized-ui-text and monospace-costume rows are read as decided, not open. | +| 2026-09-08 | Live-feed pulse is the one authored motion moment | The 2s pulse on the live-feed dot is the one authored motion moment, an intentional exception to the pulsing-dot catalog rule. The skill-bar fill and the 150ms hover transitions are functional state transitions, not authored moments. | +| 2026-09-08 | JetBrains Mono data labels at 11px | Data labels at Nano (11px) run in JetBrains Mono, below the 12px UI-text floor; UI labels stay DM Sans (the `typography.label` token). Recorded so the detector's undersized-ui-text and monospace-costume rows are read as decided, not open. | diff --git a/design-consultation/SKILL.md b/design-consultation/SKILL.md index 50342fc52..d8838fe9f 100644 --- a/design-consultation/SKILL.md +++ b/design-consultation/SKILL.md @@ -950,7 +950,7 @@ already knows. A good test: would this insight save time in a future session? If 1. **Propose, don't present menus.** You are a consultant, not a form. Make opinionated recommendations based on the product context, then let the user adjust. 2. **Every recommendation needs a rationale.** Never say "I recommend X" without "because Y." 3. **Coherence over individual choices.** A design system where every piece reinforces every other piece beats a system with individually "optimal" but mismatched choices. -4. **Never recommend blacklisted or overused fonts as primary.** If the user specifically requests one, comply but explain the tradeoff. +4. **Never a banned face in any role, never an overused face as the display voice.** Body or UI on an Operate or Read surface follows the role-scoped list in the proposal section. If the user asks for a listed face by name, comply and state the tradeoff once. 5. **The preview page must be beautiful.** It's the first visual output and sets the tone for the whole skill. 6. **Conversational tone.** This isn't a rigid workflow. If the user wants to talk through a decision, engage as a thoughtful design partner. 7. **Accept the user's final choice.** Nudge on coherence issues, but never block or refuse to write a DESIGN.md because you disagree with a choice. diff --git a/design-consultation/SKILL.md.tmpl b/design-consultation/SKILL.md.tmpl index e1b523f3a..2f79e0ae3 100644 --- a/design-consultation/SKILL.md.tmpl +++ b/design-consultation/SKILL.md.tmpl @@ -235,7 +235,7 @@ If the user said no research, skip entirely and proceed to Phase 3 using your bu 1. **Propose, don't present menus.** You are a consultant, not a form. Make opinionated recommendations based on the product context, then let the user adjust. 2. **Every recommendation needs a rationale.** Never say "I recommend X" without "because Y." 3. **Coherence over individual choices.** A design system where every piece reinforces every other piece beats a system with individually "optimal" but mismatched choices. -4. **Never recommend blacklisted or overused fonts as primary.** If the user specifically requests one, comply but explain the tradeoff. +4. **Never a banned face in any role, never an overused face as the display voice.** Body or UI on an Operate or Read surface follows the role-scoped list in the proposal section. If the user asks for a listed face by name, comply and state the tradeoff once. 5. **The preview page must be beautiful.** It's the first visual output and sets the tone for the whole skill. 6. **Conversational tone.** This isn't a rigid workflow. If the user wants to talk through a decision, engage as a thoughtful design partner. 7. **Accept the user's final choice.** Nudge on coherence issues, but never block or refuse to write a DESIGN.md because you disagree with a choice. diff --git a/design-consultation/sections/proposal-and-preview.md b/design-consultation/sections/proposal-and-preview.md index 3a0ad5f1b..686e9f281 100644 --- a/design-consultation/sections/proposal-and-preview.md +++ b/design-consultation/sections/proposal-and-preview.md @@ -62,7 +62,7 @@ The SAFE/RISK breakdown is critical. Design coherence is table stakes — every **Choosing faces: a procedure, not a menu.** Type comes from the subject's world, in the mode's register. (1) Name the world: the publication, notation, identity program, or object this audience already reads. (2) Shortlist three faces per role (display, body, label, mono) from that world. (3) Strike anything on the overused list for the role it would play. (4) Verify availability this session: WebSearch or Aside the Google Fonts / Fontshare page, or confirm the license of a self-hosted face. Unverified faces do not go in the proposal. (5) State the loading strategy with the name. -**Overused as display** (never the display voice on a Persuade or Experience surface; the detector flags several as `overused-font`): Inter, Roboto, Arial, Helvetica, Open Sans, Lato, Montserrat, Poppins, Space Grotesk, Space Mono, Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, IBM Plex Sans, IBM Plex Serif, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans, Geist. +**Overused as display** (never the display voice, on any surface; the body/UI exception below is the only one; the detector flags several as `overused-font`): Inter, Roboto, Arial, Helvetica, Open Sans, Lato, Montserrat, Poppins, Space Grotesk, Space Mono, Fraunces, Playfair Display, Cormorant, Lora, Crimson, Newsreader, Syne, IBM Plex Sans, IBM Plex Serif, DM Sans, DM Serif, Outfit, Plus Jakarta Sans, Instrument Sans, Geist. **Fine as body/UI on an Operate or Read surface when the proposal says so:** DM Sans, Instrument Sans, IBM Plex Sans. **Mono for data and code:** JetBrains Mono, IBM Plex Mono, Fira Code. diff --git a/design-html/SKILL.md b/design-html/SKILL.md index a41bd2643..625c7fff3 100644 --- a/design-html/SKILL.md +++ b/design-html/SKILL.md @@ -697,7 +697,7 @@ For framework output, save to: - `prefers-reduced-motion` for animation respect - Real content extracted from the mockup (never lorem ipsum) -**Never include (AI slop blacklist):** +**Never include by default (AI slop blacklist):** an approved mockup that carries one, a DESIGN.md blessing, or an explicit user ask overrides it; say the tradeoff once. - Purple/blue gradients as default - Cream-and-serif default palette - Gradient text @@ -759,7 +759,7 @@ If the Setup probe printed `IMPECCABLE_READY`, scan the finalized page once befo _DJ=$(mktemp); bun --no-env-file run $HOME/.claude/skills/gstack/bin/gstack-design-detect.ts scan --format gstack --host claude > "$_DJ"; echo "DETECT_EXIT_CODE=$?"; echo "DETECT_JSON=$_DJ" ``` -Exit 2 → one surgical fix pass over the non-advisory rules in the `DETECT_TOP` block, then scan once more. Whatever remains, present the page with those findings listed as accepted-with-reason: a pattern the approved mockup contains, a value DESIGN.md's tokens bless, or an inline `` the user agreed to. One pass, not a loop. Any other first line from the probe: skip, no ceremony. +Exit 2 → one surgical fix pass over the non-advisory rules in the `DETECT_TOP` block, then scan once more. Whatever remains, present the page with those findings listed as accepted-with-reason: a pattern the approved mockup contains, a value DESIGN.md's tokens bless or a pattern its Decisions Log or Do's and Don'ts records as intentional, or an inline `` the user agreed to. One pass, not a loop. Any other first line from the probe: skip, no ceremony. ### Verification Screenshots diff --git a/design-html/SKILL.md.tmpl b/design-html/SKILL.md.tmpl index b26bc94da..38cd6bc9b 100644 --- a/design-html/SKILL.md.tmpl +++ b/design-html/SKILL.md.tmpl @@ -277,7 +277,7 @@ For framework output, save to: - `prefers-reduced-motion` for animation respect - Real content extracted from the mockup (never lorem ipsum) -**Never include (AI slop blacklist):** +**Never include by default (AI slop blacklist):** an approved mockup that carries one, a DESIGN.md blessing, or an explicit user ask overrides it; say the tradeoff once. - Purple/blue gradients as default - Cream-and-serif default palette - Gradient text diff --git a/design-review/SKILL.md b/design-review/SKILL.md index 78080063e..2f9037c82 100644 --- a/design-review/SKILL.md +++ b/design-review/SKILL.md @@ -813,7 +813,7 @@ echo "REPORT_DIR: $REPORT_DIR"; echo "RUN_ID: $RUN_ID" Remember `RUN_ID` and restate it literally in later blocks (each bash block is a fresh shell). DOM dumps land in `$REPORT_DIR/dom/$RUN_ID/`; nothing from earlier runs is touched. -**Phase 0: mechanical scan** (only after `IMPECCABLE_READY`). Pick the mode once: a URL target (any URL, localhost included) is DOM mode; diff-aware with no URL is source mode. Source mode scans the changed frontend files now: +**Phase 0: mechanical scan** (only after `IMPECCABLE_READY`). Pick the mode once: a URL target (any URL, localhost included) is DOM mode; diff-aware with no URL is source mode. Source mode scans the changed frontend files now, against the base branch (`gh pr view --json baseRefName -q .baseRefName`, else `gh repo view --json defaultBranchRef -q .defaultBranchRef.name`; never assume `main`; an unknown base is refused, exit 1): ```bash _DJ=$(mktemp); bun --no-env-file run $HOME/.claude/skills/gstack/bin/gstack-design-detect.ts scan --changed --format gstack --host claude > "$_DJ"; echo "DETECT_EXIT_CODE=$?"; echo "DETECT_JSON=$_DJ" @@ -961,7 +961,7 @@ Comprehensive review: 10-15 pages, every interaction flow, exhaustive checklist. ### Diff-aware (automatic when on a feature branch with no URL) When on a feature branch, scope to pages affected by the branch changes: -1. Analyze the branch diff: `git diff main...HEAD --name-only` +1. Analyze the branch diff: `git diff ...HEAD --name-only` (the base branch: `gh pr view --json baseRefName -q .baseRefName`, else `gh repo view --json defaultBranchRef -q .defaultBranchRef.name`; never assume `main`) 2. Map changed files to affected pages/routes 3. Detect running app on common local ports (3000, 4000, 8080) 4. Audit only affected pages, compare design quality before/after @@ -1074,31 +1074,31 @@ After each script, `cp` its files out of the `ASIDE_DIR` it printed into `$REPOR ### DOM dump (DOM mode only: Setup printed `IMPECCABLE_READY` and the target is a URL) -Rule 4 forbids reading source, so the detector reads the rendered page. One shared script, `$HOME/.claude/skills/gstack/lib/dom-dump.js` (an arrow function the page runs), serves both engines: it clones the document, inlines linked stylesheets as `
x
@@ -79,7 +81,7 @@ describe.skipIf(!BROWSE || !POSIX || !OPTED_IN)('lib/dom-dump.js in a real DOM ( expect(html).toContain(`