mirror of
https://github.com/Nutlope/hallmark.git
synced 2026-08-14 12:35:33 +02:00
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:
co-authored by
Claude Opus 4.7
parent
0f9be195e5
commit
0ad29fa6e0
@@ -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) · twenty-three themes · five verbs · press `T` to cycle.
|
||||
[Live demo →](https://hallmark-murex.vercel.app) · twenty-three themes · four verbs · 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 |
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 <screenshot></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
@@ -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
@@ -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 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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user