# Visual register — premium vs branded

The skill template ships with a default super-premium visual scheme. Two registers govern how that scheme interacts with the agent's brand pack.

## Default scheme baked into `references/template.html`

- **Type**: Cormorant Garamond (display, italics for emphasis) + Lora (humanist serif body) + Inter (tabular numerics, particulars labels)
- **Palette**: ivory paper (`#F8F4ED`), ink (`#0E1418`), bronze (`#7A6235`), antique gold (`#A4884C`), champagne (`#C9B07A`)
- **Voice**: editorial, considered, country-house tone — chapters numbered in Roman, dropcaps, pull quotes
- **Layout**: A4 landscape, 16 pages, asymmetric photo grids, full-bleed feature spreads, intermission breaks between chapters, ornamental rules between sections

## The two registers

| Register | What you change |
|---|---|
| **Branded** (default — full DESIGN.md re-skin) | Swap font names at the `--serif` / `--body-serif` / `--sans` custom properties; replace palette tokens (`--paper-25`, `--ink`, `--gold-500`, `--gold-700`, `--gold-300`, `--rule` etc.) with the DESIGN doc's values; **apply role-level type overrides from the DESIGN doc's `## Type roles` block** (see *Type-role overrides* below); substitute the brand's logo PNGs at the back-page masthead and TOC credit. The chapter structure (sixteen pages, Roman-numeral chapters, intermissions, gallery, site plan) stays — *layout, image slots, page geometry and folio chrome positions remain identical, only the styling of named type roles changes*. |
| **Premium** (opt-in only — template scheme retained) | Keep all super-premium tokens (palette, type, layout) verbatim. Swap **only** the agent's logo (back-page masthead + TOC credit) and the agent's contact details. Make subtle consistency adjustments — e.g. the accent dot in "Brand · Town" can pick up the brand's primary colour if doing so doesn't disrupt the ivory/ink/bronze relationship. **Do not apply the brand's palette or type tokens.** |

## Selecting the register — decide in this order

1. **The user explicitly said "premium" or "super-premium"** in the request → **Premium**, regardless of whether a DESIGN.md exists.
2. **Otherwise → Branded.** If no DESIGN.md exists for the brand, **run `brand-design` first** to produce one — do not fall back to Premium just because the brand pack is missing. Premium is opt-in; "missing brand pack" is a setup step, not a register decision.

The signal is the user's wording, not the property. Don't infer premium from a high guide price or a country-house name when the user has handed over a DESIGN.md without qualifying language — the agent may want their brand on every brochure regardless of property tier. Conversely, when the user says "premium" but the property is plainly mid-market (a £450k semi, a city flat), surface the mismatch in one line ("Going premium register — confirm you want the country-folio look on this listing?") before generating, so the user can correct the wording rather than discover the mismatch in the rendered output.

## Type-role overrides

The branded register's font-family and palette swap alone produces a folio painted in the brand's colours but still wearing the template's editorial conventions — italic display, small-caps decks, gold hairlines under every heading, dropcap, italic emphasis on `<em>`. For brands whose live identity does not use those conventions (Cooper Adams' upright TrajanPro, eXp UK's Montserrat, Knight-Frank-adjacent vs corporate-residential), that's a mismatch. The brochure reads as a country-house folio with brand paint, not as a brand document.

To close the gap without leaving branded territory, the brand pack's `DESIGN.md` may declare a `## Type roles` block. Each row maps a named brochure type-role to a brand styling decision. The build pipeline reads these and emits a single override CSS block — see `build.md → Type-role overlay generation` for the recipe map.

The role API is **fixed and bounded**. Only the roles below may be overridden; the build does not invent selectors. Anything else stays at template defaults.

| Role | Targets (CSS selectors) | Allowed values |
|---|---|---|
| `display-headline-style` | `.cover-title`, `.opener-title`, `.ed-headline`, `.chapter-head h3`, `.feature-page h3`, `.gallery-head h3`, `.siteplan-page h3`, `.toc-title`, `.back-headline`, `.mi-head h2`, `.mi-head h3` | `italic` (default) / `normal` |
| `display-em-style` | `<em>` inside the headline selectors above | `italic` (affirmative — preserve display family's natural italic cut; recipe emits no override) / `weight-shift` (flatten italic to bold sans-like) / `normal` (flatten italic, no weight bump). Default if omitted is the same as `italic`; setting `italic` explicitly is preferred so the choice is recorded affirmatively rather than silently. |
| `display-letterspacing` | `.cover-title`, `.opener-title` | `wide` (default, ≈0.18em — tuned for Cormorant/didone) / `medium` (≈0.10em — humanist sans) / `tight` (≈0.04em — geometric sans) |
| `deck-family` | `.ed-deck`, `.feature-deck`, `.gallery-deck`, `.siteplan-deck` | `serif` (default) / `sans` |
| `deck-case` | same as `deck-family` | `caps-tracked` (default) / `sentence` |
| `eyebrow-family` | `.ed-eyebrow`, `.toc-eyebrow`, `.chapter-eyebrow`, `.ed-eyebrow-light` | `sans` (default — documented for explicitness) |
| `subtitle-family` | `.opener-title em`, `.cover-subtitle`, `.opener-spec` | `serif-smallcaps` (default) / `sans-tracked-caps` / `sans` |
| `caption-family` | `.ed-caption`, `.caption-pill`, `.caption-text`, `.img-caption`, `.photo-caption`, `.intermission .caption-pill` | `serif` (default) / `sans` |
| `caption-em-style` | `<em>` inside any caption selector | `italic` (default) / `weight-shift` / `normal` |
| `dropcap` | `.ed-body.dropcap::first-letter` | `gold` (default — italic serif in `--gold-700`) / `ink` (italic serif in `--ink`) / `ink-bold-sans` (bold sans in `--ink`, no italic) / `hidden` (neutralised — first letter inline at body size) |
| `hairline-rules` | `.ed-rule`, `.toc-rule` | `visible` (default) / `eyebrow-only` (rules beside eyebrows only, not under chapter heads) / `hidden` |
| `body-em-style` | `.ed-body em`, `.opener-body em`, `.opener-text em`, `.gallery-cell em`, `.siteplan-panel em`, `.spec-list li em`, `.mi-row em`, `.floorplan-lead em`, `.floorplan-sub em`, `.epc-caption em` | `italic` (default) / `weight-shift` / `normal` |
| `folio-em-style` | `.folio em`, `.folio .folio-mid em` | `italic` (default) / `weight-shift` / `normal` |
| `backpage-em-style` | `.back-headline em`, `.back-tagline em`, `.back-foot em`, `.back-contact-grid em`, `.back-rule em` | `italic-gold` (default) / `weight-shift` / `normal` |

### What the role API permits

Each `value` maps to a deterministic, named CSS recipe (the full map lives in `build.md → Type-role overlay generation`). For example:

- `display-em-style: weight-shift` → emits `{ font-style: normal !important; font-weight: 500 !important; }`
- `deck-family: sans` + `deck-case: sentence` → emits `{ font-family: var(--sans) !important; font-style: normal !important; letter-spacing: 0.02em !important; text-transform: none !important; }`
- `dropcap: hidden` → emits a `::first-letter` override that neutralises the float, size, color and font-family overrides from the template

### What the role API does NOT permit

- Changing page layout, grid structure, image slot positions, page count, folio position
- Adding new CSS classes or DOM elements
- Changing colour assignments (those belong to the palette tokens, not the role API)
- Restyling the back page's QR strip or contact grid layout
- Restyling the MI three-column grid layout
- Defining new roles ad hoc — the role list above is the complete API

A branded brochure must remain layout-identical to the premium brochure; only the *styling of named type roles* may differ.

### Backward compatibility

Existing brand packs whose `DESIGN.md` files do not contain a `## Type roles` block are **unaffected**. Omitted roles inherit template defaults — which match the template's current behaviour exactly. Two agents producing brochures for the same brand on different days produce identical results because the role list is fixed and the recipe per value is fixed.


### Foundation: always-emit recipes

Two sections of the role overlay are emitted **whenever the brand pack declares any `## Type roles`**, regardless of which specific roles the operator chose. They are the foundation of any branded re-skin:

1. **Dark-surface protection.** A fixed exclusion list of selectors that sit on dark surfaces — the TOC hero caption pill, intermission caption pills, the spread-6 chapter-head overlay on its dark photo, the back-page masthead and tagline, and the back-page contact-grid name lines. The brand-token swap remaps `--gold-700` (the template's italic-emphasis colour) to the brand's accent. On a light surface that's correct. On a dark surface, a brand-accent like navy or maroon on dark photographic background is unreadable. The dark-surface protection forces text on these selectors to `var(--paper-25)` and emphasis to `var(--gold-300)` (the brand's accent / highlight). This is **not** a per-implementer concern — the exclusion list is fixed in `build.md → Always-emit recipes`.
2. **Light-surface data protection.** The template uses `--gold-700` for two semantically different things — genuine accents (em emphasis, eyebrow rules, particulars numbering) and data-value treatment in `.mi-row .v`, `.opener-meta-row .v`, `.epc-row .v`, `.spec-list li`, and `.floorplan-sub`. In Premium that's invisible because `--gold-700` is a muted bronze on cream. In Branded, where `--gold-700` is rebound to whatever the brand's primary accent is (often a saturated green, red, or navy), every data cell turns into a hyperlink-looking blob. The light-surface twin of dark-surface protection forces those data cells to `var(--ink)` and the folio strip to `var(--slate-600)` regardless of the brand token swap. The fixed selector list lives in `build.md → Always-emit recipes` as `LIGHT_SURFACE_DATA_PROTECTION`. This is structurally mandatory in Branded runs, not optional polish — the long-term cleanup is to split `--gold-700` into `--accent-strong` and `--data-text` tokens so Branded only swaps the accent.
3. **Structural clamp loosen.** The template's chapter-heading rows in `.spread-2` and `.spread-3` are sized for the Cormorant Garamond display setup (italic, weight 400, didone-tuned letter-spacing). When the role overlay changes display family, weight, or letter-spacing, headings can grow a few millimetres beyond what those fixed-height rows accommodate, and the template's `overflow: hidden` clips the descenders. The clamp-loosen recipe converts the affected rows to `minmax(<original>, max-content)` and lifts the heading-row `overflow` from `hidden` to `visible`. A heading that already fits renders identically; a heading that needs a few extra mm no longer clips. If a future template revision adds another fixed-height heading row, the entry is added in `build.md` — not handwritten per property.

A branded brochure built with the role overlay must show all three blocks in the emitted `<style id="brand-type-roles">`. Their absence is a build-time defect, not a stylistic choice.

## Forbidden template sources

**Do not** start from any of the following, even when they exist in the same brand workspace and look "more on-brand" than the skill template:

- `<brand>/properties/<other-listing>/output/brochure.html` — a sibling property's rendered brochure
- A previous brochure that was hand-edited after the last template release
- A "brand brochure" or "marketing PDF" supplied by the agency
- An older version of `template.html` cached anywhere outside `~/.claude/plugins/property-brochure/skills/property-brochure/references/`

Sibling brochures contain property-specific copy edits, hand-tuned image positions, ad-hoc CSS overrides, and drift from the canonical layout. Starting from one bakes that drift into the new brochure and silently diverges every property's structure over time. The DESIGN doc supplies design **tokens** (fonts, palette, voice) and **role declarations** — it does not authorise reaching for an existing brochure as a starting point.

If the canonical `references/template.html` looks wrong for the brand, the right action is to **patch the template** (open a discussion with the user about what to change), not to substitute a different starting point for one run.

## What neither register authorises

- Replacing the skill template with a brand's existing brochure HTML
- Restructuring the page count, page order, or chapter grid because the brand's other materials look different
- Adding new pages, removing pages, or merging spreads to "look more like" the brand's website
- Importing CSS from the brand's website into the brochure to "match the live experience"

If a branded re-skin is genuinely incompatible with the sixteen-page editorial folio (rare — most brands sit happily in this structure with token swaps plus role overrides), surface that to the user before generating anything. Don't unilaterally substitute structure. Any alternative count must still be **even** — see `a4-print-documents` → Even-page count for duplex printing.
