diff --git a/README.md b/README.md index 07a5250..52cf9b2 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Made by Together AI. Hallmark — A design skill that refuses to look AI-generated

-Hallmark picks a macrostructure for the brief, dresses it in one of twenty themes, runs seventy slop-test gates plus a pre-emit self-critique, and refuses the on-distribution defaults every LLM was trained into. Two pages by Hallmark for two different briefs feel like different sites, not colour-swaps of the same template. +Hallmark picks a macrostructure for the brief, dresses it in one of twenty themes, runs fifty-seven slop-test gates plus a pre-emit self-critique, and refuses the on-distribution defaults every LLM was trained into. Two pages by Hallmark for two different briefs feel like different sites, not colour-swaps of the same template. --- @@ -62,7 +62,7 @@ Each page is self-contained HTML + CSS, stamped with its macrostructure in the C ## Custom NEW -Most briefs route to the catalog. But when a brief carries real creative intent — a named brand colour, a vibe the catalog can't carry, or a layout that *is* the point — Hallmark switches to **Custom** and designs the whole page from first principles: a made-to-measure OKLCH palette, a free-font pairing, and a structure no catalog theme would produce. Same seventy slop-test gates. No template underneath. +Most briefs route to the catalog. But when a brief carries real creative intent — a named brand colour, a vibe the catalog can't carry, or a layout that *is* the point — Hallmark switches to **Custom** and designs the whole page from first principles: a made-to-measure OKLCH palette, a free-font pairing, and a structure no catalog theme would produce. Same fifty-seven slop-test gates. No template underneath. Four one-line briefs, four pages that share nothing: diff --git a/site/css/components.css b/site/css/components.css index 41b94f7..d4d5949 100644 --- a/site/css/components.css +++ b/site/css/components.css @@ -3542,7 +3542,7 @@ html[data-theme="bloom"] body { /* Bloom — left-aligned section heads (hero stays centered above). The atmospheric glow does the centering work — re-centering section heads reads as a templated AI fingerprint. Tag stays above the title in the - same column (matches slop-test gate 66). */ + same column (matches slop-test gate 54). */ [data-theme="bloom"] .section__head { grid-template-columns: 1fr; text-align: left; diff --git a/site/examples/custom-01/styles.css b/site/examples/custom-01/styles.css index a50280e..a22d02c 100644 --- a/site/examples/custom-01/styles.css +++ b/site/examples/custom-01/styles.css @@ -149,7 +149,7 @@ p { margin: 0; } /* no forced nowrap — let the line break on narrow sheets */ .broadside__title-2 { display: block; - font-weight: 500; /* roman — emphasis via weight, never italic (gate 40a) */ + font-weight: 500; /* roman — emphasis via weight, never italic (gate 38a) */ color: var(--ink-soft); } /* the drop-figure: an oversized initial in the printer's red */ diff --git a/site/examples/custom-02/styles.css b/site/examples/custom-02/styles.css index a0885da..708bac8 100644 --- a/site/examples/custom-02/styles.css +++ b/site/examples/custom-02/styles.css @@ -153,7 +153,7 @@ body { letter-spacing: var(--track-tight); color: var(--ink); /* keep words whole at comfortable widths; the narrow breakpoint switches to - break-word as a last resort so long names can't overflow (gate 63) */ + break-word as a last resort so long names can't overflow (gate 51) */ overflow-wrap: normal; min-width: 0; } @@ -613,7 +613,7 @@ body { never under it; the puck is var(--stamp-size-s) + its inset offset */ .nameplate { padding-right: var(--stamp-clear); } /* narrow widths: allow last-resort intra-word breaks so a long station/line - name can never overflow the slimmer column (gate 63) */ + name can never overflow the slimmer column (gate 51) */ .nameplate__line { font-size: var(--text-xl); overflow-wrap: break-word; } .perforation__rule { letter-spacing: 0.08em; } diff --git a/site/examples/custom-03/styles.css b/site/examples/custom-03/styles.css index 8efcdab..1d93bbe 100644 --- a/site/examples/custom-03/styles.css +++ b/site/examples/custom-03/styles.css @@ -159,7 +159,7 @@ button { font: inherit; color: inherit; } Intro / central explainer =================================================================== */ .intro { - /* hero pads heavier at the bottom (gate 54): it sits INTO the table + /* hero pads heavier at the bottom (gate 44): it sits INTO the table below rather than floating. block-end ≈ 2× block-start. */ max-width: var(--maxw-page); margin-inline: auto; diff --git a/site/examples/custom-04/styles.css b/site/examples/custom-04/styles.css index edb449c..45dc5ed 100644 --- a/site/examples/custom-04/styles.css +++ b/site/examples/custom-04/styles.css @@ -284,7 +284,7 @@ body::after { /* directional grain — fine diagonal hatch */ padding-top: clamp(var(--space-xl), 5vw, var(--space-3xl)); } .spine__head { - display: block; /* gate 66 — eyebrow + heading single column */ + display: block; /* gate 54 — eyebrow + heading single column */ margin-bottom: clamp(var(--space-xl), 6vw, var(--space-3xl)); } .spine__eyebrow { diff --git a/site/examples/custom-05/styles.css b/site/examples/custom-05/styles.css index 3ab3fb7..963e752 100644 --- a/site/examples/custom-05/styles.css +++ b/site/examples/custom-05/styles.css @@ -53,7 +53,7 @@ ul, ol { list-style: none; } padding-inline: var(--gutter); } -/* timecode + name stamp that opens every section (vertical stack — gate 66) */ +/* timecode + name stamp that opens every section (vertical stack — gate 54) */ .stamp { display: flex; align-items: baseline; @@ -343,7 +343,7 @@ section[tabindex]:focus { outline: none; } .track--b .track__copy { grid-column: 1; grid-row: 1 / 3; align-self: center; } .track--b .minwave { grid-column: 1 / -1; } -.track__head { grid-column: 1; } /* eyebrow + heading stacked (gate 66) */ +.track__head { grid-column: 1; } /* eyebrow + heading stacked (gate 54) */ .track__title { font-family: var(--font-display); font-weight: 460; diff --git a/site/index.html b/site/index.html index c285336..452f6e1 100644 --- a/site/index.html +++ b/site/index.html @@ -56,10 +56,10 @@ - - - - + + + + + \ No newline at end of file diff --git a/site/js/main.js b/site/js/main.js index 11eed4a..1e9437c 100644 --- a/site/js/main.js +++ b/site/js/main.js @@ -141,7 +141,7 @@ const COPY = { proofLabel: "Proof", proofA: "21 macrostructures · 50 archetypes", proofB: "14 navs · 8 footers · 4 hero polish", - proofC: "70-gate slop test", + proofC: "57-gate slop test", cta: "Read the rules", stat: "21", qualifier: "macrostructures", @@ -156,14 +156,14 @@ const COPY = { newsprint: { eyebrow: "Volume I · Issue 02 · 28 April 2026", title: HERO_TITLE, - lede: "Twenty themes. Twenty-one named page shapes. Fifty component archetypes — fourteen navs, eight footers, four hero polish patterns. A 70-gate slop test that gates every output before it ships. Hallmark is the rulebook the LLM never read.", + lede: "Twenty themes. Twenty-one named page shapes. Fifty component archetypes — fourteen navs, eight footers, four hero polish patterns. A 57-gate slop test that gates every output before it ships. Hallmark is the rulebook the LLM never read.", ctaLabel: "Distribution", proofLabel: "From the rule sheet", proofA: "Multi-column body, justified", proofB: "Hairline rules, not boxes", proofC: "Outlined CTAs, never pills", cta: "Read in full", - stat: "70", + stat: "57", qualifier: "gates", quote: "We compose the page like a broadsheet. Hairlines, columns, restraint.", attrib: "From the Hallmark rule sheet", @@ -221,14 +221,14 @@ const COPY = { proofLabel: "Catalogued", proofA: "21 macrostructures · 50 archetypes", proofB: "14 navs · 8 footers · 4 polish patterns", - proofC: "70 slop-test gates", + proofC: "57 slop-test gates", cta: "Open the index", stat: "420", qualifier: "theme × shape combinations", quote: "An almanac is a book that knows where to look.", attrib: "Almanac, frontispiece", salutation: "Reference note,", - letterBody: "This page is a reference, not an argument. The numbers are the point: 21 macrostructures, 50 archetypes, 20 themes, 70 slop-test gates. Cross-referenced so the next page Hallmark builds is genuinely different from the last.", + letterBody: "This page is a reference, not an argument. The numbers are the point: 21 macrostructures, 50 archetypes, 20 themes, 57 slop-test gates. Cross-referenced so the next page Hallmark builds is genuinely different from the last.", signoff: "— editor", captionA: "Vol. III", captionB: "Plate 12", @@ -465,7 +465,7 @@ const COPY = { proofLabel: "ON THE BILL", proofA: "21 page-shapes, 50 archetypes", proofB: "Duo-tone drops, hard-offset shadows", - proofC: "70-gate slop test, every build", + proofC: "57-gate slop test, every build", cta: "See the lineup", stat: "20", qualifier: "THEMES. ZERO TEMPLATES.", @@ -485,7 +485,7 @@ const COPY = { proofLabel: "00 · SPEC", proofA: "21 page-shapes · 50 archetypes", proofB: "lowercase serif · mono labels · no orb", - proofC: "70-gate slop test, every emit", + proofC: "57-gate slop test, every emit", cta: "read the docs", stat: "20", qualifier: "themes, instrument-grade.", @@ -500,12 +500,12 @@ const COPY = { hum: { eyebrow: "A design skill", title: "Make your AI agent a designer.", - lede: "The anti-slop design skill for Claude Code, Cursor, and Codex. Twenty themes with real structural variety, and a 70-gate check before anything ships.", + lede: "The anti-slop design skill for Claude Code, Cursor, and Codex. Twenty themes with real structural variety, and a 57-gate check before anything ships.", ctaLabel: "Install", proofLabel: "What's inside", proofA: "21 page-shapes · 50 archetypes", proofB: "9 heroes · 14 navs · 8 footers", - proofC: "70-gate slop test, every build", + proofC: "57-gate slop test, every build", cta: "See examples", stat: "20", qualifier: "themes, all alive.", diff --git a/skills/hallmark/SKILL.md b/skills/hallmark/SKILL.md index 5250012..14a0645 100644 --- a/skills/hallmark/SKILL.md +++ b/skills/hallmark/SKILL.md @@ -45,15 +45,15 @@ These six disciplines are **not** verb-specific. They apply to default Design, ` 1. **Pre-emit self-critique.** Before handing back any output, score it 1–5 on six axes — Philosophy, Hierarchy, Execution, Specificity, Restraint, Variety. Anything **< 3** triggers a revision pass. Stamp the six scores at the top of the artifact (`/* Hallmark · pre-emit critique: P5 H4 E5 S4 R5 V5 */`). See [`references/slop-test.md`](references/slop-test.md) § Pre-emit self-critique. -2. **Honest copy — no fabricated content.** If the user did not supply a metric, do not invent one. Stat-led layouts, comparison rows, and proof bars must use real numbers, a placeholder (`—` plus a labelled grey block, "metric to confirm"), or a different macrostructure. *"+47 % conversion"*, *"trusted by 50,000+ teams"*, and *"10× faster"* are slop the moment they're invented. Same rule for testimonials, logos, and case-study counts. See [`references/anti-patterns.md` § Invented metrics](references/anti-patterns.md) and slop-test gate **56**. +2. **Honest copy — no fabricated content.** If the user did not supply a metric, do not invent one. Stat-led layouts, comparison rows, and proof bars must use real numbers, a placeholder (`—` plus a labelled grey block, "metric to confirm"), or a different macrostructure. *"+47 % conversion"*, *"trusted by 50,000+ teams"*, and *"10× faster"* are slop the moment they're invented. Same rule for testimonials, logos, and case-study counts. See [`references/anti-patterns.md` § Invented metrics](references/anti-patterns.md) and slop-test gate **46**. -3. **Locked tokens — no mid-render improvisation.** Once a theme is selected at Step 2.6, every colour and every `font-family` declaration in the artifact must reference a named token (`var(--color-accent)`, `font-family: var(--font-display)`). Inline OKLCH / hex / `rgb()` values, or a `font-family: "Some Font"` declaration that bypasses the token block, are not allowed. If a value is needed that doesn't exist as a token, lift it into the token block as a new named variable, then reference it. See [`references/anti-patterns.md` § Mid-render token improvisation](references/anti-patterns.md) and slop-test gate **58**. +3. **Locked tokens — no mid-render improvisation.** Once a theme is selected at Step 2.6, every colour and every `font-family` declaration in the artifact must reference a named token (`var(--color-accent)`, `font-family: var(--font-display)`). Inline OKLCH / hex / `rgb()` values, or a `font-family: "Some Font"` declaration that bypasses the token block, are not allowed. If a value is needed that doesn't exist as a token, lift it into the token block as a new named variable, then reference it. See [`references/anti-patterns.md` § Mid-render token improvisation](references/anti-patterns.md) and slop-test gate **48**. -4. **Re-drawn chrome forbidden.** Hallmark must not hand-build fake browser bars (URL pill + traffic-light dots), fake phone frames, fake code-block windows (mock title bar + dots wrapping a `
`), or fake IDE chrome — the user's environment already supplies real chrome. Use real screenshots wrapped in a `
` (with at most a hairline border), or omit the chrome and let the content stand on its own. See [`references/anti-patterns.md` § Re-drawn UI chrome](references/anti-patterns.md) and slop-test gate **57**. +4. **Re-drawn chrome forbidden.** Hallmark must not hand-build fake browser bars (URL pill + traffic-light dots), fake phone frames, fake code-block windows (mock title bar + dots wrapping a `
`), or fake IDE chrome — the user's environment already supplies real chrome. Use real screenshots wrapped in a `
` (with at most a hairline border), or omit the chrome and let the content stand on its own. See [`references/anti-patterns.md` § Re-drawn UI chrome](references/anti-patterns.md) and slop-test gate **47**. -5. **Mobile responsiveness — every emit verified at 320 / 375 / 414 / 768 px.** Hallmark's output must render flawlessly at all four widths. The non-negotiables: no horizontal scroll (gate 36), no two-line clickable text — buttons, primary nav links, footer links, breadcrumbs, CTAs (gate 59); image-bearing grid tracks use `minmax(0, 1fr)`, never bare `1fr` (gate 61); root has `overflow-x: clip` on both `html` and `body` — never `hidden` (gate 62); display headers wrap inside long words via `overflow-wrap: anywhere; min-width: 0` (gate 63); section heads collapse to one column on mobile across every theme variant (gate 64); radio-tab patterns don't scroll-jump (gate 65). See [`references/responsive.md` § Mobile — non-negotiable](references/responsive.md). This is a hard floor, not a wish list. +5. **Mobile responsiveness — every emit verified at 320 / 375 / 414 / 768 px.** Hallmark's output must render flawlessly at all four widths. The non-negotiables: no horizontal scroll + root `overflow-x: clip` on both `html` and `body`, never `hidden` (gate 34); no two-line clickable text — buttons, primary nav links, footer links, breadcrumbs, CTAs (gate 49); image-bearing grid tracks use `minmax(0, 1fr)`, never bare `1fr` (gate 50); display headers wrap inside long words via `overflow-wrap: anywhere; min-width: 0` (gate 51); section heads collapse to one column on mobile across every theme variant (gate 52); radio-tab patterns don't scroll-jump (gate 53). See [`references/responsive.md` § Mobile — non-negotiable](references/responsive.md). This is a hard floor, not a wish list. -6. **Typography purity — no italic headers.** Headings and display type are always roman (`font-style: normal`). An italicised emphasis word inside an otherwise-upright heading (`Built to think`) is one of the most reliable AI tells; so is an all-italic display face on headings. Carry emphasis with weight, accent colour, or a drawn underline. Italic survives only as *body-copy* emphasis inside running paragraphs. See [`references/anti-patterns.md` § Italic headers](references/anti-patterns.md) and slop-test gate **40a**. +6. **Typography purity — no italic headers.** Headings and display type are always roman (`font-style: normal`). An italicised emphasis word inside an otherwise-upright heading (`Built to think`) is one of the most reliable AI tells; so is an all-italic display face on headings. Carry emphasis with weight, accent colour, or a drawn underline. Italic survives only as *body-copy* emphasis inside running paragraphs. See [`references/anti-patterns.md` § Italic headers](references/anti-patterns.md) and slop-test gate **38a**. --- @@ -77,7 +77,7 @@ If two signals fire, route component. If only the page flow fires (multi-section - **Step 2.6 · Theme route** — same. If a `tokens.css` or `design.md` exists, the component uses those tokens. Otherwise it asks "is there a system to follow, or should I pick one?" — defaulting to *catalog* if the user is silent. - **2+1 font discipline** — same. - **State discipline — STRICTER.** Every interactive component MUST ship code for **all 8 states**: default · hover · `:focus-visible` · `:active` · disabled · loading · error · success. The 8-state checklist in [`interaction-and-states.md`](references/interaction-and-states.md) is mandatory, not advisory. -- **Slop test — universal-only subset.** Run the visual / microinteraction / contrast (gates 46–50) / a11y / typography gates. Skip the diversification gates (no `.hallmark/log.json` entry — components don't rotate) and skip the layout-safety gates that assume a full page. +- **Slop test — universal-only subset.** Run the visual / microinteraction / contrast (gates 40–41) / a11y / typography gates. Skip the diversification gates (no `.hallmark/log.json` entry — components don't rotate) and skip the layout-safety gates that assume a full page. ### What Component-scope skips @@ -341,7 +341,7 @@ By the time you reach this step, one of four things is true: **Custom is a quiet branch, not a default question.** Most briefs route to catalog and the user never sees the words "catalog" or "custom." The 20 named themes plus the rotation rule already deliver structural variety; the fork is reserved for when the brief specifically asks for a tuned look the catalog can't carry. -A custom theme is a **complete** OKLCH palette + font pairing tuned to the brief — not a one-off colour swap, not an excuse to bypass the rules. Every constraint in [`color.md`](references/color.md), [`typography.md`](references/typography.md), and [`anti-patterns.md`](references/anti-patterns.md) still applies. The 70 slop-test gates fire unchanged. The Step 5 preview block surfaces the palette + pairing in plain text **before** any code is emitted, so the user can redirect. +A custom theme is a **complete** OKLCH palette + font pairing tuned to the brief — not a one-off colour swap, not an excuse to bypass the rules. Every constraint in [`color.md`](references/color.md), [`typography.md`](references/typography.md), and [`anti-patterns.md`](references/anti-patterns.md) still applies. The 57 slop-test gates fire unchanged. The Step 5 preview block surfaces the palette + pairing in plain text **before** any code is emitted, so the user can redirect. The diversification rule is theme-route-blind: a custom run that follows another custom (or a catalog) must differ on at least one of the three axes from the previous entry, same as catalog-vs-catalog. Custom entries record their three axes explicitly into `.hallmark/log.json` (see [`custom-theme.md`](references/custom-theme.md) § F). @@ -378,7 +378,7 @@ The non-negotiables live in [`references/`](references/). **Be precise about wha - [`preview-examples.md`](references/preview-examples.md) — load only if you need a worked example of the Step 5 preview block format. The bullet list in Step 5 itself is normally enough; reach for the file only when picking unusual macrostructures / custom themes. **Load-at-the-end (Step 7 only):** -- [`slop-test.md`](references/slop-test.md) — **strictly Step 7, after Build.** The 70 gates are a post-emit check, not a pre-emit reference. Pre-loading slop-test.md costs ~7K tokens for nothing — the gates inform fixes, not generation. If a gate fails at Step 7, fix and re-test; do not consult the file earlier "to know what to avoid" — that's what `anti-patterns.md` is for. +- [`slop-test.md`](references/slop-test.md) — **strictly Step 7, after Build.** The 57 gates are a post-emit check, not a pre-emit reference. Pre-loading slop-test.md costs ~7K tokens for nothing — the gates inform fixes, not generation. If a gate fails at Step 7, fix and re-test; do not consult the file earlier "to know what to avoid" — that's what `anti-patterns.md` is for. - [`contract.md`](references/contract.md) — load at handoff time for output-contract + scope rules. - [`export-formats.md`](references/export-formats.md) — load at Step 6 only when the project warrants multi-format exports (i.e. has a `design.md`). Single-page builds emit `tokens.css` from the in-memory token state and don't need this file. @@ -416,7 +416,7 @@ Before emitting any code, output a tight summary of what you're about to ship. T - **Enrichment** · none (typography only) - **Sections** · Hero · Logos · Stats · Features · Testimonials · Pricing · FAQ · CTA · Footer - **Motion** · counter · pricing-lift · pulse-once -- **Slop test** · 70 / 70 ✓ (run after Build) +- **Slop test** · 57 / 57 ✓ (run after Build) - **Diversification** · differs from Newsprint on display style + accent hue ``` @@ -427,7 +427,7 @@ Before emitting any code, output a tight summary of what you're about to ship. T 3. **Enrichment** — the chosen archetype + tier, or *none (typography only)*. 4. **Sections** — section names separated by ` · `, in DOM order. 5. **Motion** — microinteraction primitives separated by ` · `, or *none — typography only*. Always under three primitives per the [`microinteractions.md`](references/microinteractions.md) hard rules. -6. **Slop test** — `70 / 70 ✓` if all gates pass, or `N / 70 — fails: ` if any are open. Run the slop test BEFORE writing this row; the slop test is Step 7. +6. **Slop test** — `57 / 57 ✓` if all gates pass, or `N / 57 — fails: ` if any are open. Run the slop test BEFORE writing this row; the slop test is Step 7. 7. **Diversification** *(optional, only when `.hallmark/log.json` has prior entries)* — what axes differ vs the previous run. **Then one quiet CTA line, italicised, after the bullets:** @@ -447,7 +447,7 @@ Emit code that satisfies the tone and structural fingerprint. Match the complexi Always: - **Hero headline — match font-size to copy length.** When you write the headline yourself (no user-supplied copy), aim for **≤ 7 words and ≤ 50 chars** from the start. For longer headlines, apply the size-by-length brackets in [`typography.md § Hero headline sizing`](references/typography.md): 21–50 chars use `--text-display`; 51–90 chars cap at `--text-display-s`; > 90 chars rewrite shorter or cap at `--text-4xl`. Aggressive-display themes (Brutal, Riso, Manifesto) auto-step down one rung past 50 chars — their 6.5–9rem ceiling is for short statements only. -- **Section tags / eyebrows — default OFF.** Do NOT emit `01 · THE TOUR`, `02 / FEATURES`, `Chapter Three`, or any uppercase mono-cap section number / kicker / label unless either (a) the user explicitly asked for chapter / step / section numbering, OR (b) the macrostructure is Long Document, Manifesto, or Catalogue numbered AND the content is genuinely ordinal. Cap at 1–2 per page even then. **When a tag IS used, always stack vertical — tag above, heading directly underneath in the same column.** The tag-left / heading-right two-column pattern (a.k.a. hanging header, left-margin label) is banned outright — it is the single most reliable templated-editorial tell, and slop-test gate **66** auto-fails it. +- **Section tags / eyebrows — default OFF.** Do NOT emit `01 · THE TOUR`, `02 / FEATURES`, `Chapter Three`, or any uppercase mono-cap section number / kicker / label unless either (a) the user explicitly asked for chapter / step / section numbering, OR (b) the macrostructure is Long Document, Manifesto, or Catalogue numbered AND the content is genuinely ordinal. Cap at 1–2 per page even then. **When a tag IS used, always stack vertical — tag above, heading directly underneath in the same column.** The tag-left / heading-right two-column pattern (a.k.a. hanging header, left-margin label) is banned outright — it is the single most reliable templated-editorial tell, and slop-test gate **54** auto-fails it. - Use OKLCH for every colour. Declare tokens as CSS custom properties at `:root`. - Use a 4pt spacing scale with semantic names (`--space-sm`, `--space-md`, …). - Pick a distinctive display face and a refined body face. Pairings, not single-font pages — *unless* the single-font choice IS the design (a true terminal-aesthetic page is monospace-only on purpose; that's allowed). @@ -466,7 +466,7 @@ Always: ### 7. The slop test -Before handing back, run the output through the 70-gate slop test in [`references/slop-test.md`](references/slop-test.md). Every answer must be **no**. Load that file at this step (not earlier — it isn't needed until handoff). The active genre matters: some gates are universal, some are genre-scoped (atmospheric loosens the radial-bloom gate; modern-minimal loosens the zero-chroma neutral gate; etc.). The full per-genre overrides are listed inline in `slop-test.md`. +Before handing back, run the output through the 57-gate slop test in [`references/slop-test.md`](references/slop-test.md). Every answer must be **no**. Load that file at this step (not earlier — it isn't needed until handoff). The active genre matters: some gates are universal, some are genre-scoped (atmospheric loosens the radial-bloom gate; modern-minimal loosens the zero-chroma neutral gate; etc.). The full per-genre overrides are listed inline in `slop-test.md`. Run the slop test BEFORE writing the Slop test row in the Step 5 preview block — that row reflects the actual outcome of this step. diff --git a/skills/hallmark/references/anti-patterns.md b/skills/hallmark/references/anti-patterns.md index 3356de8..e643cfb 100644 --- a/skills/hallmark/references/anti-patterns.md +++ b/skills/hallmark/references/anti-patterns.md @@ -150,7 +150,7 @@ Eyebrows are **default OFF**. They are not a stylistic flourish you reach for to **Fix.** Ship the page with **zero eyebrows** unless either (a) the user explicitly asked for chapter / step / section numbering, OR (b) the macrostructure is **Long Document, Manifesto, or Catalogue numbered** AND the content is genuinely ordinal (steps you must do in order, chapters that build, items in a deliberate sequence). Even then: cap at 1–2 per page. -**Hard ban: tag-left / header-right two-column section heads.** Patterns like `01 · THE TOUR` in a narrow left column with the section title to its right (a.k.a. *hanging header*, *left-margin label*) are the single most reliable AI-templated tell for editorial-style SaaS pages. When an eyebrow IS used, **the heading goes directly underneath it, in the same column** — vertical stack only. Never a two-column section-head grid. Gate 66 enforces this. +**Hard ban: tag-left / header-right two-column section heads.** Patterns like `01 · THE TOUR` in a narrow left column with the section title to its right (a.k.a. *hanging header*, *left-margin label*) are the single most reliable AI-templated tell for editorial-style SaaS pages. When an eyebrow IS used, **the heading goes directly underneath it, in the same column** — vertical stack only. Never a two-column section-head grid. Gate 54 enforces this. **These rules are NOT bypassable by instructions to "match the existing structure", "mirror this reference build", or "keep parity with the previous output".** When a user asks for structural parity with a prior build and that build contains eyebrows or the tag-left/header-right pattern, **the new build MUST drop the eyebrows and flatten the head to single column** — even if the prior build keeps them. Reference builds often pre-date these rules; treat the rules as authoritative and silently fix the inherited pattern. Don't perpetuate a banned pattern to honour a parity instruction. @@ -212,7 +212,7 @@ A stat-led layout, comparison row, or proof bar carrying numbers the user never **Why it fails.** Audiences read invented stats as fast as they read invented testimonials. A page that lies on its proof bar can't be trusted on its claims either, and the AI tell is unmistakable: every fabricated number reads "this was generated, not written". -**Fix.** Three options, in order of preference: (1) replace the number with `—` and a labelled grey block ("metric to confirm" or "stat pending"); (2) ask the user for the real number and pause the run; (3) rebuild the section without the proof slot — a stat-led macrostructure with no real stats is the wrong macrostructure. The number-shaped hole is honest; the fabricated number is slop. *(Slop-test gate 56.)* +**Fix.** Three options, in order of preference: (1) replace the number with `—` and a labelled grey block ("metric to confirm" or "stat pending"); (2) ask the user for the real number and pause the run; (3) rebuild the section without the proof slot — a stat-led macrostructure with no real stats is the wrong macrostructure. The number-shaped hole is honest; the fabricated number is slop. *(Slop-test gate 46.)* ### Generic emoji as feature icon @@ -220,7 +220,7 @@ A feature card, value prop, step number, or pricing tier with `✨` `🚀` `⚡` **Why it fails.** Emoji are typography of a sort, but they are not part of the page's typographic system — they're rendered by the OS and look different on every device, they break the icon's stroke voice (you've now mixed a Phosphor-style line icon with a Twemoji blob), and the choice is recognisably the AI default. Sparkle-emoji-as-AI-shortcut is the cliché of the 2024–2025 era. -**Fix.** Pick a single icon library and ship it ([assets.md](assets.md) names the canon). Or build a custom SVG mark. Or omit the icon entirely and lead with typography — most feature lists don't need icons. *(Slop-test gate 60.)* +**Fix.** Pick a single icon library and ship it ([assets.md](assets.md) names the canon). Or build a custom SVG mark. Or omit the icon entirely and lead with typography — most feature lists don't need icons. *(Slop-test gate 30.)* ### Re-drawn UI chrome @@ -228,7 +228,7 @@ A fake browser bar (URL pill + traffic-light dots) wrapping a screenshot. A fake **Why it fails.** The user already has the chrome — their browser, their phone, their IDE all *are* chrome. Redrawing it in a page is like printing a photograph of a picture frame inside a real picture frame. The fakery is also bad: the URL is wrong, the dots aren't macOS dots, the notch is the wrong shape. Audiences pattern-match re-drawn chrome as "AI invented a UI that already exists" within a glance. -**Fix.** Use a real screenshot wrapped in `
` (with a hairline border at most). For phone mockups, use a transparent-PNG device frame from a vendor or a real product photograph — never a CSS-drawn one. For code blocks, use the system `
` with a typographic frame (top rule + label + bottom rule), not a faked window-chrome. The page's job is to show content, not to imitate the OS. *(Slop-test gate 57.)*
+**Fix.** Use a real screenshot wrapped in `
` (with a hairline border at most). For phone mockups, use a transparent-PNG device frame from a vendor or a real product photograph — never a CSS-drawn one. For code blocks, use the system `
` with a typographic frame (top rule + label + bottom rule), not a faked window-chrome. The page's job is to show content, not to imitate the OS. *(Slop-test gate 47.)*
 
 ### Mid-render token improvisation
 
@@ -236,7 +236,7 @@ A theme is selected at the top of the run, but the artifact contains inline colo
 
 **Why it fails.** Token discipline is the difference between a system and a freestyle. Once a theme is locked, every colour and every font in the file must reference a named token (`var(--color-accent)`, `font-family: var(--font-display)`). Inline values are how cohesion erodes — by the third edit pass, the page has eight colours instead of three, and the editorial restraint that made the theme work is gone. Audiences don't see the inline value, but they feel the looseness.
 
-**Fix.** Every colour and every font in the artifact must come through `var(--token-name)`. If you need a value that doesn't exist as a token, add it to the token block first (`--color-accent-warm: oklch(...)`) and then reference it. Inline OKLCH or one-off hex values mid-render are not allowed. *(Slop-test gate 58. See also [SKILL.md § Locked tokens](../SKILL.md).)*
+**Fix.** Every colour and every font in the artifact must come through `var(--token-name)`. If you need a value that doesn't exist as a token, add it to the token block first (`--color-accent-warm: oklch(...)`) and then reference it. Inline OKLCH or one-off hex values mid-render are not allowed. *(Slop-test gate 48. See also [SKILL.md § Locked tokens](../SKILL.md).)*
 
 ### Wrap-to-two-lines clickable text
 
@@ -244,7 +244,7 @@ A button label, nav link, footer link, breadcrumb, or CTA reads on two lines bec
 
 **Why it fails.** Clickable affordances are one-line objects. The reader scans the label, decides whether to click, moves on. A two-line label slows the scan, breaks the row's vertical rhythm (button height grows, sibling buttons stay the same), and signals "this page wasn't tested at this width". It's a responsive-discipline tell.
 
-**Fix.** In order of preference: (1) shorten the label — *"Get started free" → "Start free"*; *"Read the documentation" → "Read docs"*. Most CTA labels are too long. (2) Set `white-space: nowrap` on the affordance and let the parent flex container reflow. (3) Drop a non-essential nav item at narrow widths via `hidden=until-found` or `display: none`. (4) Collapse the nav into a sheet/menu under a threshold. *Never* let a primary CTA or nav link wrap. *(Slop-test gate 59. See [responsive.md § Clickable text — never wraps](responsive.md).)*
+**Fix.** In order of preference: (1) shorten the label — *"Get started free" → "Start free"*; *"Read the documentation" → "Read docs"*. Most CTA labels are too long. (2) Set `white-space: nowrap` on the affordance and let the parent flex container reflow. (3) Drop a non-essential nav item at narrow widths via `hidden=until-found` or `display: none`. (4) Collapse the nav into a sheet/menu under a threshold. *Never* let a primary CTA or nav link wrap. *(Slop-test gate 49. See [responsive.md § Clickable text — never wraps](responsive.md).)*
 
 ### Lottie shortcut
 
diff --git a/skills/hallmark/references/components/f2-sticky-scroll-stack.md b/skills/hallmark/references/components/f2-sticky-scroll-stack.md
index 321653b..7675d52 100644
--- a/skills/hallmark/references/components/f2-sticky-scroll-stack.md
+++ b/skills/hallmark/references/components/f2-sticky-scroll-stack.md
@@ -15,6 +15,6 @@ Sticky left pane, scrolling right pane that cycles through related screenshots.
 .sticky-stack { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2xl); }
 /* `calc(--banner-height + --space-xl)` so the sticky pane docks below the
    nav with breathing room. Falls back to --space-xl alone when no sticky
-   nav is on the page (slop-test gate 68). */
+   nav is on the page (slop-test gate 56). */
 .pane-sticky { position: sticky; top: calc(var(--banner-height, 0px) + var(--space-xl)); align-self: start; z-index: var(--z-sticky); }
 ```
diff --git a/skills/hallmark/references/components/s3-sticky-pinned.md b/skills/hallmark/references/components/s3-sticky-pinned.md
index faf02a7..dbdd0f3 100644
--- a/skills/hallmark/references/components/s3-sticky-pinned.md
+++ b/skills/hallmark/references/components/s3-sticky-pinned.md
@@ -11,9 +11,9 @@ Heading remains in viewport while content scrolls beneath. Orientation aid.
 ```
 ```css
 /* If the page has a sticky top nav, offset by its height so the sticky
-   head docks BENEATH it instead of bleeding over (slop-test gate 68).
+   head docks BENEATH it instead of bleeding over (slop-test gate 56).
    Use --z-sticky (in-page) so the nav's --z-sticky-nav out-paints it. */
 .head-sticky { position: sticky; top: var(--banner-height, 0px); background: var(--color-paper); padding-block: var(--space-sm); border-bottom: 1px solid var(--color-ink); z-index: var(--z-sticky); }
 ```
 
-**Sticky pairing rule:** if the page emits a sticky `
` / `