Drop The Future / The Future Mono · drop refine verb · Build/Study/Examples media

Replace The Future + The Future Mono everywhere with Geist + Geist Mono — both
local fonts had a single-storey hooked "a" by design, not by faux italic. Strip
the @font-face declarations + preload links. Halo dropdown z-index leak fixed.
Editorial hero proof block strips down to just the CTA. Atelier + Salon now
left-aligned. Skill-row / hero / examples ledes unified to roman serif (italic
removed from every body / lede / intro role to kill the curly italic "a").
Refine verb removed everywhere: SKILL.md, README, landing site, references.
Ask-questions discipline strengthened — Step 1 now always asks, optional answers.
Build subsection wires Podcast loop video; Study uses Calendly screenshot with
re-written DNA fields; Worked-examples 1+2 use Banana Studio + Modern SaaS
loops in place of static thumbs. Landing-page rebrand reverted everywhere.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Youssef
2026-05-06 18:13:10 +01:00
co-authored by Claude Opus 4.7
parent 0f9be195e5
commit 0ad29fa6e0
16 changed files with 157 additions and 335 deletions
+4 -5
View File
@@ -2,7 +2,7 @@
**A design skill for Claude Code, Cursor, and Codex that refuses to look AI-generated.**
[Live demo →](https://hallmark-murex.vercel.app) &nbsp;·&nbsp; twenty-three themes &nbsp;·&nbsp; five verbs &nbsp;·&nbsp; press `T` to cycle.
[Live demo →](https://hallmark-murex.vercel.app) &nbsp;·&nbsp; twenty-three themes &nbsp;·&nbsp; four verbs &nbsp;·&nbsp; press `T` to cycle.
Powered by Together AI.
@@ -43,19 +43,18 @@ If Hallmark is wired correctly, you'll see Long Document · Linen (warm-paper ro
| **Refuses pixel-clone** | yes — DNA only, never pixels | n/a | n/a | n/a (full token export) |
| **Tactile-rebellion alignment** | warm-paper, custom-craft, slopless canon | strong | medium | none — token-only |
| **Pages by archetype** | 21 named macrostructures, picked per brief | by brief | 5 deterministic directions | n/a |
| **Verbs** | 5 (default · `audit` · `refine` · `redesign` · `study`) | 1 | 31 | 1 (CLI) |
| **Verbs** | 4 (default · `audit` · `redesign` · `study`) | 1 | 31 | 1 (CLI) |
Hallmark's edge is **`study`** — every other tool ships a preset menu or a scraper. Hallmark is the only one that takes a screenshot of a design you admire, names what it sees, refuses paid-template-marketplace listings, and rebuilds your content with the extracted DNA. Three worked study examples in [`docs/study-examples.md`](docs/study-examples.md).
---
## Five verbs
## Four verbs
| Verb | What it does |
| --- | --- |
| *(default)* | Build new UI. Asks for audience + use + tone (skippable — the skill states what it inferred). Picks a macrostructure, applies the rule-set, runs the slop test before handing back. |
| `hallmark audit <target>` | Score existing code against the named anti-patterns + structural sameness. Punch list, no edits. |
| `hallmark refine <target>` | Polish in place. Smallest possible diff. Preserves structure. |
| `hallmark redesign <target> [--mood <name>]` | Throw out the structure, keep copy + IA + brand, rebuild with a deliberately different fingerprint. |
| **`hallmark study <screenshot>`** | The differentiator. Extract the **DNA** from a design the user admires — macrostructure, archetypes, type-pairing role, colour anchor — and produce a diagnosis report. Optionally rebuild *the user's* content using the extracted DNA. **Refuses paid templates and competitor pages. Names font roles, never font IDs. Never copies pixels.** |
@@ -107,7 +106,7 @@ Each page is its own self-contained HTML + CSS — no shared theme, no shared la
## What's distinct (the long list)
- **One skill, five verbs.** Not eighteen commands.
- **One skill, four verbs.** Not eighteen commands.
- **Genres broaden the range.** Hallmark routes a brief through one of four genres before picking a theme: **editorial** (default · the canonical anti-slop voice), **modern-minimal** (Stripe / Linear / ElevenLabs school), **atmospheric** (Suno / Runway / dark-AI-tool school), **playful** (post-Linear soft school). Each genre is its own rule overlay — atmospheric allows radial blooms; modern-minimal allows pure white and pill CTAs; editorial bans both. Detection is signal-based, silent default to editorial.
- **Tone is a first-class decision.** "Clean and modern" is rejected. Pick an extreme — *editorial · brutalist · soft · technical · luxury · playful · austere*.
- **Macrostructures over axes.** Pick one of 21 named whole-page shapes wholesale; the macrostructure stamp lives in the CSS comment, so the next Hallmark run picks something different.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

-58
View File
@@ -1,63 +1,5 @@
/* Hallmark — base: fonts, reset, body */
/* — The Future (Together AI's typeface) ——————————————— */
@font-face {
font-family: "The Future";
font-style: normal;
font-weight: 300;
font-display: swap;
src: url("../fonts/the-future-light.woff2") format("woff2");
}
@font-face {
font-family: "The Future";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("../fonts/the-future-regular.woff2") format("woff2");
}
@font-face {
font-family: "The Future";
font-style: normal;
font-weight: 500;
font-display: swap;
src: url("../fonts/the-future-medium.woff2") format("woff2");
}
@font-face {
font-family: "The Future";
font-style: normal;
font-weight: 700;
font-display: swap;
src: url("../fonts/the-future-bold.woff2") format("woff2");
}
@font-face {
font-family: "The Future Mono";
font-style: normal;
font-weight: 300;
font-display: swap;
src: url("../fonts/the-future-mono-light.woff2") format("woff2");
}
@font-face {
font-family: "The Future Mono";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("../fonts/the-future-mono-regular.woff2") format("woff2");
}
@font-face {
font-family: "The Future Mono";
font-style: normal;
font-weight: 500;
font-display: swap;
src: url("../fonts/the-future-mono-medium.woff2") format("woff2");
}
@font-face {
font-family: "The Future Mono";
font-style: normal;
font-weight: 700;
font-display: swap;
src: url("../fonts/the-future-mono-bold.woff2") format("woff2");
}
/* — Google Fonts — all theme display & alt faces ——————————— */
@import url("https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300..900;1,9..144,300..900&family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Instrument+Serif:ital@0;1&family=Cormorant+Garamond:ital,wght@0,300..700;1,300..700&family=Crimson+Pro:ital,wght@0,200..900;1,200..900&family=Newsreader:ital,opsz,wght@0,6..72,200..800;1,6..72,200..800&family=DM+Serif+Display:ital@0;1&family=Anton&family=Space+Grotesk:wght@300;400;500;600;700&family=Bricolage+Grotesque:opsz,wght@12..96,200..800&family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..700&family=Hanken+Grotesk:ital,wght@0,100..900;1,100..900&family=IBM+Plex+Sans:ital,wght@0,300;0,400;0,500;0,600;1,400;1,500&family=IBM+Plex+Mono:ital,wght@0,300;0,400;0,500;0,600;1,400&family=JetBrains+Mono:ital,wght@0,400;0,500;0,700;1,400&display=swap");
+28 -82
View File
@@ -748,7 +748,6 @@
font-size: var(--text-md);
line-height: var(--lh-snug);
color: var(--color-ink-2);
font-style: italic;
max-width: 40ch;
}
@@ -899,7 +898,6 @@
.found-panel__rule {
margin: 0;
font-family: var(--font-serif);
font-style: italic;
font-size: var(--text-md);
line-height: var(--lh-normal);
color: var(--color-ink-2);
@@ -977,7 +975,6 @@
.type-spec__body {
font-family: var(--font-serif);
font-style: italic;
font-size: var(--text-md);
line-height: var(--lh-normal);
color: var(--color-ink-2);
@@ -1529,7 +1526,6 @@
.vs__panel--personal[data-variant="hallmark"] .vs__panel-bio {
margin: var(--space-md) 0 0;
font-family: var(--font-serif);
font-style: italic;
font-size: 1rem;
line-height: var(--lh-relaxed);
color: var(--color-ink-2);
@@ -1779,7 +1775,6 @@
.install-pane__next {
margin: 0;
font-family: var(--font-serif);
font-style: italic;
font-size: var(--text-md);
line-height: var(--lh-normal);
color: var(--color-ink-2);
@@ -2030,54 +2025,14 @@ body:not(.easter-open) > footer {
.easter__cursor { animation: none; opacity: 1; }
}
/* — Reveals ————————————————————————————————————————— */
.reveal {
opacity: 0;
transform: translateY(10px);
}
/* Reveals (disabled)
Scroll-in animation removed by product decision landing reads
cleaner without staggered fades. Class kept so JS + markup stay
stable; element renders in its final state with no transform/fade. */
.reveal,
.reveal.is-in {
animation: reveal var(--dur-long) var(--ease-out) forwards;
animation-delay: calc(var(--i, 0) * 60ms);
}
@keyframes reveal { to { opacity: 1; transform: none; } }
/* Theme-specific reveal patterns */
[data-theme="brutal"] .reveal,
[data-theme="manifesto"] .reveal,
[data-theme="sport"] .reveal {
transform: translateX(-16px);
}
@keyframes reveal-sweep { to { opacity: 1; transform: none; } }
[data-theme="brutal"] .reveal.is-in,
[data-theme="manifesto"] .reveal.is-in,
[data-theme="sport"] .reveal.is-in {
animation: reveal-sweep var(--dur-long) var(--ease-out) forwards;
animation-delay: calc(var(--i, 0) * 60ms);
}
[data-theme="atelier"] .reveal,
[data-theme="salon"] .reveal,
[data-theme="newsprint"] .reveal {
transform: none; /* no spatial reveal — fade only */
}
[data-theme="atelier"] .reveal.is-in,
[data-theme="salon"] .reveal.is-in,
[data-theme="newsprint"] .reveal.is-in {
animation: reveal-fade calc(var(--dur-long) * 1.4) var(--ease-out) forwards;
animation-delay: calc(var(--i, 0) * 80ms);
}
@keyframes reveal-fade { to { opacity: 1; } }
[data-theme="terminal"] .reveal,
[data-theme="terminal"] .reveal.is-in {
transform: none;
opacity: 1;
transform: none;
animation: none;
}
@@ -2144,7 +2099,6 @@ body:not(.easter-open) > footer {
}
[data-theme="studio"] .hero__photo-caption {
font-style: italic;
letter-spacing: 0;
text-transform: none;
font-feature-settings: "ss01";
@@ -2315,7 +2269,6 @@ body:not(.easter-open) > footer {
[data-theme="riso"] .tell__why,
[data-theme="riso"] .foot__tagline {
font-family: var(--font-serif);
font-style: italic;
font-weight: 400;
}
@@ -2396,7 +2349,6 @@ body:not(.easter-open) > footer {
.hero__lede {
font-family: var(--font-serif);
font-style: italic;
font-size: var(--text-md);
line-height: var(--lh-normal);
color: var(--color-ink-2);
@@ -2500,6 +2452,14 @@ body:not(.easter-open) > footer {
.hero--split .hero__proof a { margin-top: var(--space-sm); }
/* Editorial: the proof block reads cleaner with just the CTA. */
[data-theme="editorial"] .hero--split .hero__proof .label,
[data-theme="editorial"] .hero--split .hero__proof .hero__proof-line { display: none; }
[data-theme="editorial"] .hero--split .hero__proof {
padding-block-start: 0;
border-block-start: 0;
}
/* H3 — Stat-Led. Giant number + qualifier. */
.hero--stat {
padding-block: var(--space-2xl) var(--space-xl);
@@ -2614,7 +2574,6 @@ body:not(.easter-open) > footer {
margin-block: var(--space-xl) 0;
font-family: var(--font-serif);
font-size: var(--text-md);
font-style: italic;
color: var(--color-ink-2);
line-height: var(--lh-snug);
}
@@ -3182,7 +3141,6 @@ body:not(.easter-open) > footer {
.foot__tagline {
font-family: var(--font-serif);
font-style: italic;
font-size: var(--text-md);
color: var(--color-ink-2);
max-width: 50ch;
@@ -3380,7 +3338,6 @@ body:not(.easter-open) > footer {
.foot__catalog,
.foot__credit {
font-family: var(--font-serif);
font-style: italic;
font-size: 0.9375rem;
line-height: var(--lh-relaxed);
color: var(--color-ink-2);
@@ -3940,7 +3897,10 @@ html[data-theme="halo"] body::before {
opacity: 1;
}
html[data-theme="halo"] .banner,
/* Lift content above the halo body::before glow.
Banner is excluded so it keeps its sticky z-index (200) the
theme-dropdown lives inside .banner and needs that elevation
to render above the orbit + glow layers below. */
html[data-theme="halo"] main,
html[data-theme="halo"] .easter,
html[data-theme="halo"] aside {
@@ -4091,7 +4051,8 @@ html[data-theme="halo"] aside {
font-size: 0;
}
.ex-card__thumb img {
.ex-card__thumb img,
.ex-card__thumb video {
display: block;
width: 100%;
height: 100%;
@@ -4101,12 +4062,16 @@ html[data-theme="halo"] aside {
}
@media (hover: hover) and (pointer: fine) {
.ex-card:hover .ex-card__thumb img { transform: scale(1.025); }
.ex-card:hover .ex-card__thumb img,
.ex-card:hover .ex-card__thumb video { transform: scale(1.025); }
}
@media (prefers-reduced-motion: reduce) {
.ex-card__thumb img { transition: none; }
.ex-card:hover .ex-card__thumb img { transform: none; }
.ex-card__thumb video { animation-play-state: paused; }
.ex-card__thumb img,
.ex-card__thumb video { transition: none; }
.ex-card:hover .ex-card__thumb img,
.ex-card:hover .ex-card__thumb video { transform: none; }
}
.ex-card__meta {
@@ -4927,33 +4892,21 @@ html[data-theme="halo"] aside {
color: var(--color-muted);
}
/* SALON true-centred section heads + fleuron
Salon's existing grid override (in sections.css) was fine but the
eyebrow + title weren't perfectly stacked. Tighten the gap between
them, give the title a comfortable measure, and make the fleuron
read as a divider rather than a stray glyph. */
/* ───────────── SALON — left-aligned, italic title, fleuron divider ───────────── */
[data-theme="salon"] .section__head {
gap: var(--space-sm);
padding-block-end: var(--space-2xl);
}
[data-theme="salon"] .section-label {
display: inline-flex;
justify-content: center;
margin-inline: auto;
}
[data-theme="salon"] .section__title {
max-width: 32ch;
margin-inline: auto;
font-style: italic;
}
[data-theme="salon"] .section__head::after {
content: "❦";
display: block;
text-align: center;
color: var(--color-accent);
font-size: 1.1rem;
margin-block-start: var(--space-lg);
@@ -4962,13 +4915,6 @@ html[data-theme="halo"] aside {
opacity: 0.65;
}
/* Section 07 lead paragraph + outro — Salon centers all flowing prose */
[data-theme="salon"] .examples__intro,
[data-theme="salon"] .examples__outro {
text-align: center;
margin-inline: auto;
}
/* NEWSPRINT justified prose blocks
Print discipline. Long-form copy gets justified + hyphenated where
the column is wide enough to render evenly. Headlines stay
+37 -50
View File
@@ -163,7 +163,6 @@
past the max-width. The header above stays inside the gutter. */
.examples__intro {
font-family: var(--font-serif);
font-style: italic;
font-size: var(--text-md);
line-height: var(--lh-snug);
color: var(--color-ink-2);
@@ -210,8 +209,9 @@
padding-inline: var(--rail-edge);
padding-block: var(--space-md) var(--space-lg);
scroll-padding-inline: var(--rail-edge);
scrollbar-color: var(--color-rule-2) transparent;
scrollbar-width: none;
}
.examples-rail::-webkit-scrollbar { display: none; }
/* Reserve trailing whitespace inside the rail so the last card snaps
clean to the same content edge as the first. */
@@ -220,10 +220,6 @@
flex: 0 0 var(--rail-edge);
}
.examples-rail::-webkit-scrollbar { height: 6px; }
.examples-rail::-webkit-scrollbar-track { background: transparent; }
.examples-rail::-webkit-scrollbar-thumb { background: var(--color-rule-2); border-radius: 0; }
/* 03 · Without / With (parity panels, four pairs)
The section holds four W/W pairs that swap based on which toggle
radio is :checked. Pure CSS, no JS.
@@ -497,7 +493,6 @@
.study__intro {
margin: 0 0 var(--space-2xl);
font-family: var(--font-serif);
font-style: italic;
font-size: var(--text-md);
line-height: var(--lh-snug);
color: var(--color-ink-2);
@@ -544,7 +539,6 @@
.skills__intro {
margin: 0 0 var(--space-2xl);
font-family: var(--font-serif);
font-style: italic;
font-size: var(--text-md);
line-height: var(--lh-snug);
color: var(--color-ink-2);
@@ -629,7 +623,7 @@
.skill-row__title {
font-family: var(--font-display);
font-size: clamp(2rem, 3.4vw + 0.5rem, 3rem);
font-size: clamp(1.4rem, 1.6vw + 0.6rem, 2rem);
font-weight: 500;
line-height: var(--lh-tight);
letter-spacing: var(--tracking-display);
@@ -643,7 +637,6 @@
.skill-row__title-meta {
font-family: var(--font-serif);
font-style: italic;
font-weight: 400;
font-size: 0.5em;
letter-spacing: 0;
@@ -669,15 +662,42 @@
letter-spacing: var(--tracking-tight);
}
/* Skill-row lede matches the hero lede + examples intro: same role, same
typographic treatment per theme. All ledes are roman (no italic) the
curly single-storey italic "a" was unanimously bad to read. */
.skill-row__lede {
font-family: var(--font-body);
font-family: var(--font-serif);
font-size: var(--text-md);
line-height: var(--lh-relaxed);
line-height: var(--lh-normal);
color: var(--color-ink-2);
margin: 0;
max-width: 60ch;
}
[data-theme="brutal"] .skill-row__lede,
[data-theme="manifesto"] .skill-row__lede,
[data-theme="terminal"] .skill-row__lede,
[data-theme="sport"] .skill-row__lede,
[data-theme="almanac"] .skill-row__lede,
[data-theme="studio"] .skill-row__lede,
[data-theme="pastel"] .skill-row__lede,
[data-theme="quiet"] .skill-row__lede,
[data-theme="bloom"] .skill-row__lede,
[data-theme="aurora"] .skill-row__lede,
[data-theme="plume"] .skill-row__lede,
[data-theme="halo"] .skill-row__lede,
[data-theme="coral"] .skill-row__lede,
[data-theme="violet"] .skill-row__lede {
font-family: var(--font-body);
font-style: normal;
}
/* Studio: examples intro stays sans to match hero + verb ledes. */
[data-theme="studio"] .examples__intro {
font-family: var(--font-body);
font-style: normal;
}
.skill-row__lede strong {
font-weight: 600;
color: var(--color-ink);
@@ -775,7 +795,6 @@
font-family: var(--font-mono);
font-size: var(--text-xs);
color: var(--color-ink-2);
font-style: italic;
max-width: 100%;
}
@@ -804,7 +823,9 @@
border: var(--rule-card, 1px) solid var(--color-rule);
}
.brief-output img {
.brief-output img,
.brief-output video {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
@@ -1116,61 +1137,42 @@
/* · image · reveal */
/* ════════════════════════════════════════════════════════════ */
/* ── ATELIER — centered display, generous, narrow column ────── */
/* ── ATELIER — generous spacing, narrow measure, left-aligned ─── */
[data-theme="atelier"] .opening {
grid-template-columns: 1fr;
text-align: center;
align-items: center;
padding-block: var(--space-3xl) var(--space-xl);
}
[data-theme="atelier"] .opening__title {
margin-inline: auto;
max-width: 16ch;
}
[data-theme="atelier"] .opening__sub {
margin-inline: auto;
margin-top: var(--space-xl);
}
[data-theme="atelier"] .opening__eyebrow {
justify-content: center;
}
[data-theme="atelier"] .opening__aside {
display: none;
}
[data-theme="atelier"] .section__head {
grid-template-columns: 1fr;
text-align: center;
border-bottom: 0;
padding-bottom: var(--space-2xl);
}
[data-theme="atelier"] .section-label {
justify-content: center;
}
[data-theme="atelier"] .section__title {
max-width: 22ch;
margin-inline: auto;
}
[data-theme="atelier"] .foundations {
grid-template-columns: 1fr;
max-width: 38rem;
margin-inline: auto;
}
[data-theme="atelier"] .spec {
text-align: center;
border-top: 0;
border-bottom: var(--rule-hair) solid var(--color-rule);
padding: var(--space-2xl) 0;
}
[data-theme="atelier"] .spec__head {
justify-content: center;
gap: var(--space-md);
}
[data-theme="atelier"] .spec__rule {
margin-inline: auto;
}
[data-theme="atelier"] .step {
grid-template-columns: 1fr;
text-align: center;
}
[data-theme="atelier"] .vs { grid-template-columns: 1fr; border: 0; }
[data-theme="atelier"] .vs__col:first-child {
@@ -1332,17 +1334,14 @@
}
[data-theme="manifesto"] .step { border-top: 3px solid var(--color-ink); }
/* ── SALON — centered narrow, fleuron divider ───────────────── */
/* ── SALON — italic display, fleuron divider, left-aligned ───── */
[data-theme="salon"] .opening {
grid-template-columns: 1fr;
text-align: center;
align-items: center;
padding-block: var(--space-3xl) var(--space-xl);
}
[data-theme="salon"] .opening__title {
font-style: italic;
font-weight: 400;
margin-inline: auto;
max-width: 14ch;
}
[data-theme="salon"] .opening__title em {
@@ -1350,36 +1349,28 @@
font-family: var(--font-display);
}
[data-theme="salon"] .opening__sub {
margin-inline: auto;
margin-top: var(--space-xl);
font-family: var(--font-serif);
font-style: italic;
}
[data-theme="salon"] .opening__eyebrow { justify-content: center; }
[data-theme="salon"] .opening__aside { display: none; }
[data-theme="salon"] .section__head {
grid-template-columns: 1fr;
text-align: center;
border-bottom: 0;
padding-bottom: var(--space-md);
}
[data-theme="salon"] .section__head::after {
content: "❦";
display: block;
text-align: center;
color: var(--color-accent);
font-size: 1.2rem;
margin-top: var(--space-md);
font-family: var(--font-serif);
}
[data-theme="salon"] .section-label { justify-content: center; }
[data-theme="salon"] .section__title { margin-inline: auto; }
[data-theme="salon"] .foundations {
grid-template-columns: 1fr;
max-width: 36rem;
margin-inline: auto;
}
[data-theme="salon"] .spec { text-align: left; }
/* ── LINEN — hanging headings, two-column asymmetric, woven texture ─── */
[data-theme="linen"] .opening { grid-template-columns: 7fr 5fr; gap: var(--space-3xl); }
@@ -1526,7 +1517,6 @@ html[data-theme="almanac"] body {
.anti__intro {
margin: 0 0 var(--space-2xl);
font-family: var(--font-serif);
font-style: italic;
font-size: var(--text-md);
line-height: var(--lh-snug);
color: var(--color-ink-2);
@@ -1625,7 +1615,6 @@ html[data-theme="almanac"] body {
.anti-row__desc {
margin: 0;
font-family: var(--font-serif);
font-style: italic;
font-size: 0.9375rem;
line-height: var(--lh-relaxed);
color: var(--color-muted);
@@ -1670,7 +1659,6 @@ html[data-theme="almanac"] body {
.found__intro {
margin: 0 0 var(--space-2xl);
font-family: var(--font-serif);
font-style: italic;
font-size: var(--text-md);
line-height: var(--lh-snug);
color: var(--color-ink-2);
@@ -1803,7 +1791,6 @@ html[data-theme="almanac"] body {
margin-block-start: var(--space-xl);
padding-block: var(--space-sm);
font-family: var(--font-serif);
font-style: italic;
font-size: var(--text-md);
line-height: 1.2;
color: var(--color-ink-2);
+26 -26
View File
@@ -27,10 +27,10 @@
--color-focus: #FC4C02;
--font-display: "Fraunces", "Tiempos", ui-serif, Georgia, serif;
--font-body: "The Future", "Söhne", ui-sans-serif, sans-serif;
--font-body: "Geist", "Söhne", ui-sans-serif, sans-serif;
--font-serif: "Fraunces", ui-serif, Georgia, serif;
--font-label: "The Future Mono", "JetBrains Mono", ui-monospace, monospace;
--font-mono: "The Future Mono", "JetBrains Mono", ui-monospace, monospace;
--font-label: "Geist Mono", "JetBrains Mono", ui-monospace, monospace;
--font-mono: "Geist Mono", "JetBrains Mono", ui-monospace, monospace;
--display-weight: 340;
--display-optical: 144;
@@ -127,11 +127,11 @@
--color-accent-ink: oklch(72% 0.16 220);
--color-focus: oklch(72% 0.16 220);
--font-display: "The Future", "Futura", "Avenir Next", ui-sans-serif, sans-serif;
--font-body: "The Future", "Söhne", ui-sans-serif, sans-serif;
--font-display: "Geist", "Futura", "Avenir Next", ui-sans-serif, sans-serif;
--font-body: "Geist", "Söhne", ui-sans-serif, sans-serif;
--font-serif: "Instrument Serif", ui-serif, Georgia, serif;
--font-label: "The Future Mono", "JetBrains Mono", ui-monospace, monospace;
--font-mono: "The Future Mono", "JetBrains Mono", ui-monospace, monospace;
--font-label: "Geist Mono", "JetBrains Mono", ui-monospace, monospace;
--font-mono: "Geist Mono", "JetBrains Mono", ui-monospace, monospace;
--display-weight: 300;
--display-optical: 144;
@@ -166,9 +166,9 @@
--color-accent-ink: oklch(58% 0.24 25);
--color-focus: #E63946;
--font-display: "Space Grotesk", "GT America", ui-sans-serif, sans-serif;
--font-body: "Space Grotesk", "The Future", ui-sans-serif, sans-serif;
--font-serif: "Space Grotesk", ui-sans-serif, sans-serif;
--font-display: "Albert Sans", "GT America", ui-sans-serif, sans-serif;
--font-body: "Albert Sans", "Hanken Grotesk", ui-sans-serif, sans-serif;
--font-serif: "Albert Sans", ui-sans-serif, sans-serif;
--font-label: "JetBrains Mono", ui-monospace, monospace;
--font-mono: "JetBrains Mono", ui-monospace, monospace;
@@ -216,10 +216,10 @@
--color-focus: #B6485E;
--font-display: "Cormorant Garamond", "Instrument Serif", "Fraunces", ui-serif, Georgia, serif;
--font-body: "The Future", "Söhne", ui-sans-serif, sans-serif;
--font-body: "Geist", "Söhne", ui-sans-serif, sans-serif;
--font-serif: "Cormorant Garamond", "Instrument Serif", ui-serif, Georgia, serif;
--font-label: "The Future Mono", ui-monospace, monospace;
--font-mono: "The Future Mono", ui-monospace, monospace;
--font-label: "Geist Mono", ui-monospace, monospace;
--font-mono: "Geist Mono", ui-monospace, monospace;
--display-weight: 400;
--display-style: italic;
@@ -262,7 +262,7 @@
--color-focus: oklch(45% 0.13 60);
--font-display: "Playfair Display", "Cormorant Garamond", "Tiempos Headline", ui-serif, Georgia, serif;
--font-body: "Hanken Grotesk", "The Future", ui-sans-serif, sans-serif;
--font-body: "Hanken Grotesk", "Geist", ui-sans-serif, sans-serif;
--font-serif: "Playfair Display", "Cormorant Garamond", ui-serif, Georgia, serif;
--font-label: "IBM Plex Mono", ui-monospace, monospace;
--font-mono: "IBM Plex Mono", ui-monospace, monospace;
@@ -312,7 +312,7 @@
--font-display: "Playfair Display", "Crimson Pro", "Newsreader", ui-serif, Georgia, serif;
--font-body: "Crimson Pro", "Newsreader", ui-serif, Georgia, serif;
--font-serif: "Playfair Display", "Crimson Pro", ui-serif, Georgia, serif;
--font-label: "Inter", "The Future", ui-sans-serif, sans-serif;
--font-label: "Inter", "Geist", ui-sans-serif, sans-serif;
--font-mono: "IBM Plex Mono", ui-monospace, monospace;
--display-weight: 700;
@@ -358,7 +358,7 @@
--color-accent-ink: oklch(78% 0.190 138);
--color-focus: oklch(86% 0.190 138);
--font-display: "JetBrains Mono", "IBM Plex Mono", "The Future Mono", ui-monospace, monospace;
--font-display: "JetBrains Mono", "IBM Plex Mono", "Geist Mono", ui-monospace, monospace;
--font-body: "JetBrains Mono", "IBM Plex Mono", ui-monospace, monospace;
--font-serif: "JetBrains Mono", ui-monospace, monospace;
--font-label: "JetBrains Mono", ui-monospace, monospace;
@@ -404,9 +404,9 @@
--color-accent-ink: oklch(58% 0.24 28);
--color-focus: #E51A1A;
--font-display: "Anton", "Bebas Neue", "Space Grotesk", sans-serif;
--font-body: "Inter", "Public Sans", "The Future", ui-sans-serif, sans-serif;
--font-serif: "Anton", "Space Grotesk", sans-serif;
--font-display: "Anton", "Bebas Neue", "Albert Sans", sans-serif;
--font-body: "Public Sans", "Albert Sans", "Hanken Grotesk", ui-sans-serif, sans-serif;
--font-serif: "Anton", "Albert Sans", sans-serif;
--font-label: "JetBrains Mono", ui-monospace, monospace;
--font-mono: "JetBrains Mono", ui-monospace, monospace;
@@ -454,7 +454,7 @@
--color-focus: oklch(50% 0.12 50);
--font-display: "IBM Plex Mono", "JetBrains Mono", ui-monospace, monospace;
--font-body: "Plus Jakarta Sans", "Hanken Grotesk", "The Future", ui-sans-serif, sans-serif;
--font-body: "Plus Jakarta Sans", "Hanken Grotesk", "Geist", ui-sans-serif, sans-serif;
--font-serif: "Cormorant Garamond", ui-serif, Georgia, serif;
--font-label: "IBM Plex Mono", ui-monospace, monospace;
--font-mono: "IBM Plex Mono", ui-monospace, monospace;
@@ -551,7 +551,7 @@
--color-focus: oklch(38% 0.135 250);
--font-display: "Hanken Grotesk", "Inter", ui-sans-serif, sans-serif;
--font-body: "Hanken Grotesk", "Inter", "The Future", ui-sans-serif, sans-serif;
--font-body: "Hanken Grotesk", "Inter", "Geist", ui-sans-serif, sans-serif;
--font-serif: "Newsreader", ui-serif, Georgia, serif;
--font-label: "IBM Plex Mono", ui-monospace, monospace;
--font-mono: "IBM Plex Mono", "JetBrains Mono", ui-monospace, monospace;
@@ -606,8 +606,8 @@
--color-accent-ink: oklch(54% 0.20 35);
--color-focus: oklch(58% 0.190 35);
--font-display: "Inter Tight", "Space Grotesk", ui-sans-serif, sans-serif;
--font-body: "Plus Jakarta Sans", "Hanken Grotesk", "The Future", ui-sans-serif, sans-serif;
--font-display: "Inter Tight", "Albert Sans", ui-sans-serif, sans-serif;
--font-body: "Albert Sans", "Hanken Grotesk", ui-sans-serif, sans-serif;
--font-serif: "Inter Tight", ui-sans-serif, sans-serif;
--font-label: "JetBrains Mono", ui-monospace, monospace;
--font-mono: "JetBrains Mono", ui-monospace, monospace;
@@ -729,7 +729,7 @@
}
/*
RISO risograph print · Space Grotesk display, off-register
RISO risograph print · Public Sans display, off-register
Inspiration: Are.na, e-flux, Frieze, indie magazine sites.
Warm peach paper, riso cyan + yellow as accents, slight CMYK
misregistration on display via text-shadow.
@@ -750,10 +750,10 @@
--color-accent-ink: oklch(58% 0.170 220);
--color-focus: oklch(58% 0.170 220);
--font-display: "Space Grotesk", "Inter Tight", system-ui, sans-serif;
--font-display: "Public Sans", "Albert Sans", ui-sans-serif, system-ui, sans-serif;
--font-body: "Newsreader", "Tiempos", ui-serif, Georgia, serif;
--font-serif: "Newsreader", ui-serif, Georgia, serif;
--font-label: "Space Grotesk", ui-monospace, monospace;
--font-label: "Public Sans", "Albert Sans", ui-sans-serif, sans-serif;
--font-mono: "Geist Mono", "JetBrains Mono", ui-monospace, monospace;
--display-weight: 800;
+35 -69
View File
@@ -16,15 +16,11 @@
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
<link rel="preload" href="fonts/the-future-regular.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="fonts/the-future-medium.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="fonts/the-future-mono-regular.woff2" as="font" type="font/woff2" crossorigin />
<!-- Google Fonts — Fraunces, Geist, Inter Tight, Space Grotesk, Newsreader, Playfair Display, Anton. -->
<!-- Google Fonts — Anton, Albert Sans, Fraunces, Geist, Geist Mono, Hanken Grotesk, Inter, Inter Tight, Newsreader, Playfair Display, Public Sans. -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Anton&family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,500;0,9..144,600;1,9..144,400;1,9..144,500&family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500&family=Hanken+Grotesk:wght@400;500;600;700&family=Inter:wght@400;500;600;700&family=Inter+Tight:ital,wght@0,500;0,600;0,700;0,800;1,500;1,600;1,700&family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;1,6..72,400;1,6..72,500&family=Playfair+Display:ital,wght@1,400;1,500;1,600&family=Space+Grotesk:wght@400;500;600;700&display=swap" />
href="https://fonts.googleapis.com/css2?family=Albert+Sans:wght@400;500;600;700;800&family=Anton&family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,500;0,9..144,600;1,9..144,400;1,9..144,500&family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500&family=Hanken+Grotesk:wght@400;500;600;700&family=Inter:wght@400;500;600;700&family=Inter+Tight:ital,wght@0,500;0,600;0,700;0,800;1,500;1,600;1,700&family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;1,6..72,400;1,6..72,500&family=Playfair+Display:ital,wght@1,400;1,500;1,600&family=Public+Sans:wght@400;500;600;700&display=swap" />
<link rel="stylesheet" href="css/tokens.css" />
<link rel="stylesheet" href="css/base.css" />
@@ -167,40 +163,40 @@
<div class="examples-rail" role="list" aria-label="Eight example landing pages">
<a class="ex-card" href="_tests/01-tide-podcast/index.html" target="_blank" rel="noopener" role="listitem">
<picture class="ex-card__thumb" aria-hidden="true">
<img src="_tests/_thumbs/01-tide.png" alt="" loading="lazy" decoding="async" width="1024" height="640" />
</picture>
<div class="ex-card__thumb ex-card__thumb--video" aria-hidden="true">
<video src="_tests/_thumbs/BananaStudio-loop.mp4" autoplay loop muted playsinline preload="metadata" width="1784" height="1080"></video>
</div>
<div class="ex-card__meta">
<span class="ex-card__num">01</span>
<span class="ex-card__name">Tide</span>
<span class="ex-card__brief">Indie podcast · warm cream, mono masthead</span>
<span class="ex-card__name">Banana Studio</span>
<span class="ex-card__brief">Creative studio · playful motion, vivid yellow accent</span>
<span class="ex-card__open">Open ↗</span>
</div>
<div class="ex-card__trail" aria-hidden="true">
<p class="trail__row"><span class="trail__k">Brief</span><span class="trail__v">Indie podcast for solo hosts.</span></p>
<p class="trail__row"><span class="trail__k">Genre</span><span class="trail__v">editorial</span></p>
<p class="trail__row"><span class="trail__k">Macro</span><span class="trail__v">Letter</span></p>
<p class="trail__row"><span class="trail__k">Theme</span><span class="trail__v">Salon</span></p>
<p class="trail__row"><span class="trail__k">Enrich</span><span class="trail__v">none — typography only</span></p>
<p class="trail__row"><span class="trail__k">Brief</span><span class="trail__v">Independent design studio site.</span></p>
<p class="trail__row"><span class="trail__k">Genre</span><span class="trail__v">playful</span></p>
<p class="trail__row"><span class="trail__k">Macro</span><span class="trail__v">Marquee Hero</span></p>
<p class="trail__row"><span class="trail__k">Theme</span><span class="trail__v">Bloom</span></p>
<p class="trail__row"><span class="trail__k">Enrich</span><span class="trail__v">Tier-A motion-led hero loop</span></p>
</div>
</a>
<a class="ex-card" href="_tests/02-streampipe-cli/index.html" target="_blank" rel="noopener" role="listitem">
<picture class="ex-card__thumb" aria-hidden="true">
<img src="_tests/_thumbs/02-streampipe.png" alt="" loading="lazy" decoding="async" width="1024" height="640" />
</picture>
<div class="ex-card__thumb ex-card__thumb--video" aria-hidden="true">
<video src="_tests/_thumbs/SaaS-loop.mp4" autoplay loop muted playsinline preload="metadata" width="1784" height="1080"></video>
</div>
<div class="ex-card__meta">
<span class="ex-card__num">02</span>
<span class="ex-card__name">Streampipe</span>
<span class="ex-card__brief">Open-source CLI · prose-led docs, embedded terminal</span>
<span class="ex-card__name">Modern SaaS</span>
<span class="ex-card__brief">Product platform · split hero, modern-minimal register</span>
<span class="ex-card__open">Open ↗</span>
</div>
<div class="ex-card__trail" aria-hidden="true">
<p class="trail__row"><span class="trail__k">Brief</span><span class="trail__v">Open-source CLI tool docs.</span></p>
<p class="trail__row"><span class="trail__k">Genre</span><span class="trail__v">atmospheric</span></p>
<p class="trail__row"><span class="trail__k">Macro</span><span class="trail__v">Long Document</span></p>
<p class="trail__row"><span class="trail__k">Theme</span><span class="trail__v">Terminal</span></p>
<p class="trail__row"><span class="trail__k">Enrich</span><span class="trail__v">Tier-A inline CSS-art terminal</span></p>
<p class="trail__row"><span class="trail__k">Brief</span><span class="trail__v">B2B SaaS product platform.</span></p>
<p class="trail__row"><span class="trail__k">Genre</span><span class="trail__v">modern-minimal</span></p>
<p class="trail__row"><span class="trail__k">Macro</span><span class="trail__v">Split Hero</span></p>
<p class="trail__row"><span class="trail__k">Theme</span><span class="trail__v">Quiet</span></p>
<p class="trail__row"><span class="trail__k">Enrich</span><span class="trail__v">Tier-A product walkthrough loop</span></p>
</div>
</a>
@@ -338,7 +334,7 @@
</header>
<p class="skills__intro">
Hallmark has one default behaviour and four explicit verbs. Each reads a different input and returns a different shape — same opinions, different jobs.
Hallmark has one default behaviour and three explicit verbs. Each reads a different input and returns a different shape — same opinions, different jobs.
</p>
<ol class="skills-list">
@@ -359,7 +355,7 @@
<span class="brief-arrow" aria-hidden="true"></span>
<span class="fig-corners brief-output">
<span class="fig-corners__bl"></span><span class="fig-corners__br"></span>
<img src="_tests/_thumbs/hero-static-hour.jpg" alt="Static Hour — a Hallmark output for an indie-podcast brief" loading="lazy" decoding="async" width="1600" height="968" />
<video class="brief-output__media" src="_tests/_thumbs/Podcast-loop.mp4" autoplay loop muted playsinline preload="metadata" width="1600" height="1022" aria-label="Podcast platform — a Hallmark output looping through its scroll"></video>
</span>
</figure>
@@ -389,20 +385,20 @@
<span class="brief-arrow" aria-hidden="true"></span>
<span class="fig-corners brief-output">
<span class="fig-corners__bl"></span><span class="fig-corners__br"></span>
<img src="_tests/_thumbs/01-tide.png" alt="Tide — Letter macrostructure on warm cream paper" loading="lazy" decoding="async" width="1024" height="640" />
<img src="_tests/_thumbs/study-example.png" alt="A scheduling-tool landing page — used as a study reference for Hallmark's DNA extractor" loading="lazy" decoding="async" width="1680" height="1050" />
</span>
</figure>
<ol class="skill-row__list">
<li class="dna__row"><span class="dna__k">Invocation</span><span class="dna__v"><code>hallmark study &lt;screenshot&gt;</code></span></li>
<li class="dna__row"><span class="dna__k">Macrostructure</span><span class="dna__v">Letter</span></li>
<li class="dna__row"><span class="dna__k">Hero archetype</span><span class="dna__v">H5 Letter · salutation + body + signoff</span></li>
<li class="dna__row"><span class="dna__k">Display role</span><span class="dna__v">italic editorial serif</span></li>
<li class="dna__row"><span class="dna__k">Body role</span><span class="dna__v">same family, smaller weight</span></li>
<li class="dna__row"><span class="dna__k">Label role</span><span class="dna__v">small-caps grotesque</span></li>
<li class="dna__row"><span class="dna__k">Paper band</span><span class="dna__v">light · warm cream</span></li>
<li class="dna__row"><span class="dna__k">Accent hue</span><span class="dna__v">warm orange · ≤ 3% footprint</span></li>
<li class="dna__row"><span class="dna__k">Rhythm</span><span class="dna__v">left-biased · letter-format intimacy</span></li>
<li class="dna__row"><span class="dna__k">Macrostructure</span><span class="dna__v">Split Hero</span></li>
<li class="dna__row"><span class="dna__k">Hero archetype</span><span class="dna__v">H7 Clipped · copy-left + product-mock right</span></li>
<li class="dna__row"><span class="dna__k">Display role</span><span class="dna__v">heavy geometric sans</span></li>
<li class="dna__row"><span class="dna__k">Body role</span><span class="dna__v">same family · regular weight</span></li>
<li class="dna__row"><span class="dna__k">Label role</span><span class="dna__v">grotesque · sentence case</span></li>
<li class="dna__row"><span class="dna__k">Paper band</span><span class="dna__v">light · pure white</span></li>
<li class="dna__row"><span class="dna__k">Accent hue</span><span class="dna__v">cool blue + magenta · organic gradient</span></li>
<li class="dna__row"><span class="dna__k">Rhythm</span><span class="dna__v">left-copy · right product card · overlapping watercolor blobs</span></li>
<li class="dna__row"><span class="dna__k">Refuses</span><span class="dna__v">to ID fonts · to copy pixels</span></li>
</ol>
</div>
@@ -465,40 +461,10 @@
</div>
</li>
<!-- Row IV — Refine -->
<li class="skill-row" data-verb="refine">
<header class="skill-row__head">
<span class="skill-row__num num--roman" aria-hidden="true">IV</span>
<div class="skill-row__head-body">
<h3 class="skill-row__title">Refine</h3>
<p class="skill-row__lede">Layout's fine. The details aren't. Hallmark polishes in place — smallest possible diff, layout preserved, no redesign.</p>
</div>
</header>
<div class="skill-row__body skill-row__body--full">
<figure class="skill-row__demo skill-row__demo--diptych">
<figure class="diptych__half" data-state="before">
<span class="fig-corners">
<span class="fig-corners__bl"></span><span class="fig-corners__br"></span>
<img src="_tests/_thumbs/verb-audit.png" alt="Same content before refinement — centered, generic" loading="lazy" decoding="async" width="1024" height="640" />
</span>
<figcaption class="diptych__cap">Before</figcaption>
</figure>
<figure class="diptych__half" data-state="after">
<span class="fig-corners">
<span class="fig-corners__bl"></span><span class="fig-corners__br"></span>
<img src="_tests/_thumbs/verb-refine.png" alt="Same content after Hallmark refine — left-biased, italic display, real proof quote" loading="lazy" decoding="async" width="1024" height="640" />
</span>
<figcaption class="diptych__cap">After refine</figcaption>
</figure>
</figure>
</div>
</li>
<!-- Row V — Redesign -->
<!-- Row IV — Redesign -->
<li class="skill-row" data-verb="redesign">
<header class="skill-row__head">
<span class="skill-row__num num--roman" aria-hidden="true">V</span>
<span class="skill-row__num num--roman" aria-hidden="true">IV</span>
<div class="skill-row__head-body">
<h3 class="skill-row__title">Redesign</h3>
<p class="skill-row__lede">Same content. Same brand. Different bones. Hallmark throws out the structural fingerprint and rebuilds with a deliberately different one — new section rhythm, new heading placement, new component voice.</p>
+4 -19
View File
@@ -4,24 +4,9 @@
const reduced = matchMedia("(prefers-reduced-motion: reduce)").matches;
/* — Page-load reveals (one orchestrated entrance) ——————————— */
const reveals = document.querySelectorAll(".reveal");
if (reduced || !("IntersectionObserver" in window)) {
reveals.forEach((el) => el.classList.add("is-in"));
} else {
const io = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
entry.target.classList.add("is-in");
io.unobserve(entry.target);
}
}
},
{ threshold: 0.05, rootMargin: "0px 0px -2% 0px" }
);
reveals.forEach((el) => io.observe(el));
}
/* Reveal/scroll-in animations are disabled by design every .reveal
element renders in its final state on load so scrolling reads clean. */
document.querySelectorAll(".reveal").forEach((el) => el.classList.add("is-in"));
/* — Theme registry ————————————————————————————————————— */
const THEMES = {
@@ -56,7 +41,7 @@ const STORAGE_KEY = "hallmark-theme";
variety: switching themes literally rebuilds the page, not just
recolours it. See skill/references/component-cookbook.md. */
const ARCHETYPES = {
specimen: { hero: "specimen", footer: "colophon" },
specimen: { hero: "marquee", footer: "colophon" },
newsprint: { hero: "split", footer: "colophon" },
atelier: { hero: "quote-led", footer: "colophon" },
garden: { hero: "letter", footer: "colophon" },
+23 -14
View File
@@ -1,6 +1,6 @@
---
name: hallmark
description: Use this skill when the user asks to design, build, redesign, audit, refine, or study a UI, web page, landing page, dashboard, component, or interface — or when they ask to make something "feel less AI-generated." Hallmark forces intentional design decisions (typography, color, layout, motion, interaction, structure) and refuses to default to the generic AI-UI template. Trigger phrases include "design a", "build a landing page", "make a dashboard", "redesign this site", "redesign the page", "refine this UI", "audit this design", "this looks AI-generated", "fix the design", "polish this", "give this a different look", and any request that will produce HTML / CSS / JSX / Tailwind output. **Also trigger when the user attaches a screenshot of a design they admire** — that is the `hallmark study` verb (extracts design DNA, never pixel-clones).
description: Use this skill when the user asks to design, build, redesign, audit, or study a UI, web page, landing page, dashboard, component, or interface — or when they ask to make something "feel less AI-generated." Hallmark forces intentional design decisions (typography, color, layout, motion, interaction, structure) and refuses to default to the generic AI-UI template. Trigger phrases include "design a", "build a landing page", "make a dashboard", "redesign this site", "redesign the page", "audit this design", "this looks AI-generated", "fix the design", "polish this", "give this a different look", and any request that will produce HTML / CSS / JSX / Tailwind output. **Also trigger when the user attaches a screenshot of a design they admire** — that is the `hallmark study` verb (extracts design DNA, never pixel-clones).
version: 1.0.0
---
@@ -18,17 +18,16 @@ The differentiator: Hallmark insists on **structural variety**, not just visual
## How to use this skill
Hallmark has one default behaviour and four explicit verbs.
Hallmark has one default behaviour and three explicit verbs.
| Invocation | What it does |
| --- | --- |
| *(default)* | The user asked you to design or build something new. Follow the **Design flow** below. |
| `hallmark audit <target>` | Read the target, score it against the anti-pattern list, return a ranked punch list. **Do not edit.** |
| `hallmark refine <target>` | Apply the ruleset to polish the target in place. Preserve layout structure. **Smallest possible diff.** No redesign. |
| `hallmark redesign <target> [--mood <name>]` | Take the target's content and intent, throw out the structure, and **rebuild it from scratch with a deliberately different structural fingerprint.** New section rhythm, new heading placement, new component voice. Preserve copy, brand, and information architecture; replace everything else. |
| `hallmark study <screenshot>` | The user pasted or attached an image of a design they admire. Extract the **DNA** — macrostructure, archetypes, type-pairing role, colour anchor — and produce a diagnosis report, then optionally rebuild the user's content using the extracted DNA. **Never copies pixels. Never claims to identify exact fonts. Refuses obvious template-marketplace or competitor-page screenshots.** Load [`references/study.md`](references/study.md) before this verb runs. |
If the user types anything that does not clearly map to `audit`, `refine`, `redesign`, or `study`, treat it as default. If the user attaches an image without a verb prefix, ask: *"Should I `study` this (extract the DNA), or should I treat it as a reference for a fresh build?"*
If the user types anything that does not clearly map to `audit`, `redesign`, or `study`, treat it as default. If the user attaches an image without a verb prefix, ask: *"Should I `study` this (extract the DNA), or should I treat it as a reference for a fresh build?"*
The default Design flow always picks a theme. By default it picks one of the **23 named themes** — the *catalog* — and rotates among them per the diversification rule. There is also a quiet *custom* branch that constructs a one-off OKLCH palette + free-font pairing for the brief; the custom route fires **only when the brief carries a creative-intent signal** (the user names a brand colour, names a multi-attribute vibe the catalog can't carry, or explicitly asks for a custom theme). For vanilla briefs, the user never sees the words "catalog" or "custom" — the catalog runs silently. See Step 1 (signal detection) and Step 2.6 (dispatch); the protocol lives in [`references/custom-theme.md`](references/custom-theme.md).
@@ -36,7 +35,7 @@ The default Design flow always picks a theme. By default it picks one of the **2
## Disciplines that hold across every verb
These four disciplines are **not** verb-specific. They apply to default Design, `audit`, `refine`, `redesign`, `study`, and component-scope alike. They sit alongside the slop test, not inside one branch of it.
These four disciplines are **not** verb-specific. They apply to default Design, `audit`, `redesign`, `study`, and component-scope alike. They sit alongside the slop test, not inside one branch of it.
1. **Pre-emit self-critique.** Before handing back any output, score it 15 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.
@@ -200,7 +199,23 @@ Hallmark works best when you know three things before writing code:
2. **Use case.** What single job does this interface do? What is the one action the user should be able to take?
3. **Tone.** Pick an extreme — *editorial, brutalist, soft, utilitarian, luxury, playful, technical, austere*. "Clean and modern" is not a tone.
**Ask once, then commit.** If any of the three is missing, ask for all missing items in **one** short message — not one at a time, not in a follow-up. Offer the user an opt-out at the end of that message: *"or say 'go ahead' and I'll infer from the brief — I'll tell you what I picked."*
**Always ask — answering is optional.** Hallmark almost always asks before it designs. Even when the brief looks complete, post one short bundled prompt covering all three fields **plus** any open questions you'd want answered (brand colour, reference site, page sections, must-have content). Make every field skippable — the user can fill in some, all, or none.
The prompt format:
> *"Before I start, three quick fields — answer any or skip:*
> *· **Audience** — who's this for?*
> *· **Use case** — what one action should they take?*
> *· **Tone** — pick an extreme: editorial / brutalist / soft / utilitarian / luxury / playful / technical / austere.*
> *Anything else I should know — brand colour, reference site, must-have sections? Or just say 'go ahead' and I'll infer from the brief and tell you what I picked."*
Send the prompt **once**, in one message. Do not ladder follow-ups; if the user answers some fields and skips others, treat the skipped fields as opt-out and infer them. If the user says "go ahead", "you pick", "just build it", "don't ask", or doesn't engage after one prompt, the inference protocol below kicks in.
**Two narrow exceptions** where the gate is silent:
- The user already named all three (audience, use, tone) explicitly in the brief.
- The skill is invoked with `audit`, `study`, or `redesign --mood` — those verbs read context from the target, not the user.
In every other case, ask the bundled prompt. Default is to ask, not to skip.
**Genre — pick before themes.** Before the theme route, settle on a genre. Hallmark ships four: **editorial** (default · the canonical anti-slop voice), **modern-minimal** (Stripe / Linear / ElevenLabs school), **atmospheric** (Suno / Runway / dark-AI-tool school), **playful** (post-Linear soft school). The genre scopes which themes can rotate, which slop-test gates apply, and which voice fixtures the LLM picks from. Detection is signal-based — silent default to editorial unless the brief fires one of these:
@@ -223,7 +238,7 @@ If any of those fires, ask one short follow-up before picking: *"This brief read
If none of the signals fires, **proceed with catalog silently. Do not mention the fork.** Most briefs don't need a custom theme — the catalog's 23 themes plus the rotation rule already deliver structural variety. See Step 2.6 for the dispatch.
**If the user opts out** (says "go ahead", "you pick", "skip", "just build it", "don't ask", or simply doesn't engage with the question after one prompt):
**If the user opts out or skips fields** (says "go ahead", "you pick", "skip", "just build it", "don't ask", answers some fields and leaves others blank, or simply doesn't engage with the question after one prompt):
- Infer audience, use case, and tone from the brief, the domain, and any visible context (filename, framework, surrounding code is fair game *now* — only because the user delegated).
- **State the inferences in one sentence at the top of your reply** — *"Going with: audience = X · use = Y · tone = Z. If any of those is wrong, tell me and I'll redirect."*
@@ -350,7 +365,7 @@ The non-negotiables live in [`references/`](references/). **Be precise about wha
- [`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.
**Verb-specific:**
- [`verbs/audit.md`](references/verbs/audit.md), [`verbs/refine.md`](references/verbs/refine.md), [`verbs/redesign.md`](references/verbs/redesign.md) — load only when that verb runs.
- [`verbs/audit.md`](references/verbs/audit.md), [`verbs/redesign.md`](references/verbs/redesign.md) — load only when that verb runs.
- [`study.md`](references/study.md) — load only when `hallmark study` runs.
**Human-only (do NOT auto-load):**
@@ -482,12 +497,6 @@ Load [`references/verbs/audit.md`](references/verbs/audit.md) and follow it.
---
## `hallmark refine`
Load [`references/verbs/refine.md`](references/verbs/refine.md) and follow it.
---
## `hallmark redesign`
Load [`references/verbs/redesign.md`](references/verbs/redesign.md) and follow it.
-12
View File
@@ -1,12 +0,0 @@
# `hallmark refine`
The user has code they are happy with structurally but wants polished. Your job is to apply the ruleset with the smallest possible diff.
- Do not move or rename elements unless necessary.
- Do not restructure the DOM.
- Do swap fonts, rewrite colour tokens to OKLCH, tighten the type scale, correct easings, add missing states, fix any flagged anti-patterns.
- At the end, list what you changed and which reference file prompted each change.
**If the page has a Hallmark stamp** with a genre, refine within that genre's rule overlay (loaded from [`genres/<name>.md`](../genres/)). A modern-minimal page being refined keeps its pill CTAs and large display; an atmospheric page keeps its radial blooms; an editorial page keeps its hairlines and asymmetry.
**If the page has no stamp**, the genre is unknown. Refine to the universal ruleset only — do not impose editorial defaults on what may have been a deliberate atmospheric or modern-minimal choice. The smallest-possible-diff principle means *not* repainting the page in your default voice.