How the Hallmark Theme-Diversification Rule Works: Paper-Band, Display-Style, and Accent-Hue

The Hallmark theme-diversification rule guarantees that consecutive page generations use perceptually distinct themes by requiring each new selection to differ from the previous theme on at least one of three orthogonal axes: paper-band lightness, display-style typeface category, or accent-hue angle.

The Nutlope/hallmark repository implements this diversification system to prevent "same-theme-again" slop across consecutive builds. By evaluating candidate themes against three independent aesthetic dimensions defined in site/css/tokens.css, the algorithm ensures that each new page feels visually fresh while respecting the catalog’s structured design language. The rule operates by comparing potential selections against the most recent entry stored in .hallmark/log.json.

The Three Orthogonal Axes

The theme-diversification rule measures perceptual difference across three independent properties. Each theme in the 20-theme catalog declares specific values for these axes in site/css/tokens.css.

Paper-Band Lightness

The paper-band axis categorizes the lightness of the --color-paper token using OKLch percentages. Values fall into three bands:

  • Dark: Less than 30% lightness
  • Mid: Between 30% and 85% lightness
  • Light: Greater than 85% lightness

For example, the Specimen theme declares oklch(96% …) for its paper color according to the comment in site/css/tokens.css (line 16), placing it in the light band.

Display-Style Typography

The display-style axis identifies the typeface family of the --font-display token. The system recognizes ten distinct categories:

  • High-contrast-serif
  • Roman-serif
  • Classical-serif
  • Geometric-sans
  • Grotesk-sans
  • Rounded-sans
  • Mono
  • Condensed-display
  • Heavy-display
  • Risograph-bold

As defined in site/css/tokens.css (line 34), the Midnight theme uses a geometric-sans stack, while other themes may declare heavy-display or roman-serif variants.

Accent-Hue Classification

The accent-hue axis measures the hue angle of the --color-accent token, grouped into four perceptual categories:

  • Warm: 10° to 60° (reds, oranges, yellows)
  • Cool: 200° to 300° (blues, purples)
  • Neutral: Achromatic or near-zero chroma
  • Chromatic-other: Distinct hues like greens (used for the Studio theme)

In site/css/tokens.css (line 69), the Brutal theme defines --color-accent: #E63946, which maps to a warm hue angle, satisfying the warm classification.

The Theme Selection Algorithm

When Hallmark generates a new page, it executes a five-step decision flow to enforce diversification. According to skills/hallmark/SKILL.md (lines 74-82), the process works as follows:

  1. Read the previous state. The algorithm inspects the last entry in .hallmark/log.json to retrieve the previous theme’s axis values. If the file does not exist, this indicates the first run and any theme may be selected. The logging schema is documented in skills/hallmark/SKILL.md (lines 99-110).

  2. Enumerate candidates. The system loads all 20 named themes from the catalog and extracts their three axis values from site/css/tokens.css.

  3. Compare axes. For each candidate, the algorithm checks against the previous theme:

    • If all three axes match, the candidate is rejected.
    • If any one axis differs, the candidate is acceptable.
  4. Select and announce. The first acceptable candidate is chosen (or the one matching additional user signals). Hallmark announces the selection before generation, for example: "Theme: Bloom. Differs from the last on: accent-hue."

  5. Log the result. The chosen theme’s axis values are recorded in .hallmark/log.json for the next run’s diversification check.

This permissive rule allows themes to share two axes as long as the third differs, creating a rich rotation of visual styles.

Implementation Examples

The diversification logic can be implemented in code by comparing axis values directly:

// Function that decides if a candidate theme satisfies diversification
function passesDiversification(prev, candidate) {
  const diffPaper = prev.paperBand !== candidate.paperBand;
  const diffDisplay = prev.displayStyle !== candidate.displayStyle;
  const diffAccent = prev.accentHue !== candidate.accentHue;
  return diffPaper || diffDisplay || diffAccent;
}

To inspect the last logged theme manually:


# View the previous theme name from the log

cat .hallmark/log.json | jq '.[0].theme'

# → "specimen"

# Show its axis values from the CSS tokens

grep -A3 "\[data-theme=\"specimen\"\]" site/css/tokens.css

The CSS tokens for the Brutal theme demonstrate how the three axes manifest in code:

[data-theme="brutal"] {
  --color-paper:    oklch(98% 0.001 0);  /* light band */
  --font-display:   "Albert Sans", "GT America", ui-sans-serif, sans-serif; /* heavy-condensed style */
  --color-accent:   #E63946;            /* warm hue */
}

Summary

  • The theme-diversification rule operates on three independent axes: paper-band lightness, display-style typography, and accent-hue angle.
  • Candidate themes must differ from the previous selection in .hallmark/log.json on at least one axis to be acceptable.
  • Axis values are defined in site/css/tokens.css within each theme’s CSS custom properties.
  • The algorithm prevents visual repetition while allowing themes to share two axes if the third differs.
  • Selections are persisted to .hallmark/log.json to inform future diversification checks.

Frequently Asked Questions

What happens if there is no previous theme in the log?

If .hallmark/log.json does not exist or contains no entries, Hallmark treats this as the initial run. Any theme from the 20-theme catalog may be selected without diversification restrictions, as there is no prior state to compare against.

Can two themes share two axes but still be selected consecutively?

Yes. The rule is deliberately permissive: a theme only needs to differ on one of the three axes to be acceptable. For example, a new theme may share the same paper-band (light) and display-style (geometric-sans) as the previous theme, provided the accent-hue changes from warm to cool.

Where are the axis values defined for each theme?

Each theme’s axis values are derived from three CSS custom properties in site/css/tokens.css: --color-paper defines the paper-band, --font-display defines the display-style, and --color-accent defines the accent-hue. The human-readable testing documentation in site/_tests/README.md (line 69) also describes these classifications.

How does the rule prevent "same-theme-again" slop?

By requiring at least one axis change from the previous entry in .hallmark/log.json, the system guarantees that consecutive outputs cannot be visually identical. Because the three axes are orthogonal, Hallmark can rotate through many theme combinations before any single axis repeats, ensuring each generated page maintains perceptual distinctiveness.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →