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

> Discover how the Hallmark theme-diversification rule ensures unique page themes using paper-band lightness, display-style typeface, and accent-hue angle. Learn more!

- Repository: [Hassan El Mghari/hallmark](https://github.com/Nutlope/hallmark)
- Tags: deep-dive
- Published: 2026-07-19

---

**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`](https://github.com/Nutlope/hallmark/blob/main/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`](https://github.com/Nutlope/hallmark/blob/main/.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`](https://github.com/Nutlope/hallmark/blob/main/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`](https://github.com/Nutlope/hallmark/blob/main/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`](https://github.com/Nutlope/hallmark/blob/main/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`](https://github.com/Nutlope/hallmark/blob/main/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`](https://github.com/Nutlope/hallmark/blob/main/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`](https://github.com/Nutlope/hallmark/blob/main/.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`](https://github.com/Nutlope/hallmark/blob/main/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`](https://github.com/Nutlope/hallmark/blob/main/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`](https://github.com/Nutlope/hallmark/blob/main/.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:

```javascript
// 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:

```bash

# 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:

```css
[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`](https://github.com/Nutlope/hallmark/blob/main/.hallmark/log.json) on **at least one axis** to be acceptable.
- Axis values are defined in [`site/css/tokens.css`](https://github.com/Nutlope/hallmark/blob/main/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`](https://github.com/Nutlope/hallmark/blob/main/.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`](https://github.com/Nutlope/hallmark/blob/main/.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`](https://github.com/Nutlope/hallmark/blob/main/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`](https://github.com/Nutlope/hallmark/blob/main/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`](https://github.com/Nutlope/hallmark/blob/main/.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.