Apply Illuminated Nocturne style to cover template

Replaces Georgia with Cormorant Garamond (display, 300 italic) + Lora
(body) across all cover text. Adds @font-face declarations pointing to
fonts/ (same as interior). Updates gold tokens to match interior palette.

Visual changes: front title in Cormorant light italic with gold gradient
rule below, ❧ ornament replacing ✦, synopsis body in Lora.
cover.js now reads 00-front-matter.md to inject author name into spine,
front, and removes the [AUTOR] placeholder.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-03 18:44:19 +02:00
parent 87a3925c3e
commit 96ba26559b
3 changed files with 115 additions and 44 deletions
BIN
View File
Binary file not shown.
+8
View File
@@ -3,6 +3,7 @@ import { readFile, writeFile, access } from 'fs/promises';
import { resolve, dirname } from 'path'; import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import nunjucks from 'nunjucks'; import nunjucks from 'nunjucks';
import matter from 'gray-matter';
const __dir = dirname(fileURLToPath(import.meta.url)); const __dir = dirname(fileURLToPath(import.meta.url));
const root = resolve(__dir, '..'); const root = resolve(__dir, '..');
@@ -48,6 +49,10 @@ async function generate() {
const backImage = await fileExists(resolve(root, 'images/cover/back.png')) const backImage = await fileExists(resolve(root, 'images/cover/back.png'))
? '../images/cover/back.png' : null; ? '../images/cover/back.png' : null;
// Load author / title from front matter
const fmRaw = await readFile(resolve(root, 'content', '00-front-matter.md'), 'utf-8');
const { data: fm } = matter(fmRaw);
// Render HTML from template // Render HTML from template
const env = nunjucks.configure(resolve(root, 'templates'), { autoescape: false }); const env = nunjucks.configure(resolve(root, 'templates'), { autoescape: false });
const html = env.render('cover.html', { const html = env.render('cover.html', {
@@ -63,6 +68,9 @@ async function generate() {
hasSpineText: pageCount >= MIN_SPINE_TEXT, hasSpineText: pageCount >= MIN_SPINE_TEXT,
frontImage, frontImage,
backImage, backImage,
author: fm.author || '',
title: fm.title || 'Das Kaleidoskop der Schlummerwelten',
subtitle: fm.subtitle || '',
}); });
const htmlOut = resolve(root, 'output', 'cover.html'); const htmlOut = resolve(root, 'output', 'cover.html');
+107 -44
View File
@@ -19,18 +19,60 @@
--spine-left: calc(var(--bleed) + var(--trim-w)); --spine-left: calc(var(--bleed) + var(--trim-w));
--front-left: calc(var(--bleed) + var(--trim-w) + var(--spine-w)); --front-left: calc(var(--bleed) + var(--trim-w) + var(--spine-w));
/* Design tokens */ /* Design tokens — matches interior "Illuminated Nocturne" palette */
--color-bg: #080820; --color-bg: #080820;
--color-mid: #111138; --color-mid: #0f0f30;
--color-gold: #c8a84b; --color-gold: #b89a4e;
--color-gold2: #f0d080; --color-gold2: #e8c96a;
--color-text: #e8e4d8; --color-text: #e8e4d8;
--color-muted: rgba(200,168,75,0.45); --color-muted: rgba(184,154,78,0.5);
--font-display: 'Cormorant Garamond', Georgia, serif;
--font-body: 'Lora', Georgia, serif;
}
/* ── Fonts ─────────────────────────────────────────────── */
@font-face {
font-family: 'Cormorant Garamond';
font-style: normal;
font-weight: 400;
src: url('../fonts/cormorant-garamond-400-normal.woff2') format('woff2');
}
@font-face {
font-family: 'Cormorant Garamond';
font-style: italic;
font-weight: 300;
src: url('../fonts/cormorant-garamond-300-italic.woff2') format('woff2');
}
@font-face {
font-family: 'Cormorant Garamond';
font-style: italic;
font-weight: 400;
src: url('../fonts/cormorant-garamond-400-italic.woff2') format('woff2');
}
@font-face {
font-family: 'Cormorant Garamond';
font-style: italic;
font-weight: 600;
src: url('../fonts/cormorant-garamond-600-italic.woff2') format('woff2');
}
@font-face {
font-family: 'Lora';
font-style: normal;
font-weight: 400;
src: url('../fonts/lora-400-normal.woff2') format('woff2');
}
@font-face {
font-family: 'Lora';
font-style: italic;
font-weight: 400;
src: url('../fonts/lora-400-italic.woff2') format('woff2');
} }
* { box-sizing: border-box; margin: 0; padding: 0; } * { box-sizing: border-box; margin: 0; padding: 0; }
html, body { html, body {
font-family: var(--font-body);
width: var(--total-w); width: var(--total-w);
height: var(--total-h); height: var(--total-h);
background: var(--color-bg); background: var(--color-bg);
@@ -107,18 +149,19 @@
} }
.back-headline { .back-headline {
font-family: Georgia, serif; font-family: var(--font-display);
font-style: italic; font-style: italic;
font-weight: 300;
font-size: 0.22in; font-size: 0.22in;
color: var(--color-gold); color: var(--color-gold);
letter-spacing: 0.02em; letter-spacing: 0.03em;
margin-bottom: 0.12in; margin-bottom: 0.14in;
} }
.back-synopsis { .back-synopsis {
font-family: Georgia, serif; font-family: var(--font-body);
font-size: 0.145in; font-size: 0.138in;
line-height: 1.7; line-height: 1.8;
color: var(--color-text); color: var(--color-text);
flex: 1; flex: 1;
} }
@@ -132,12 +175,13 @@
} }
.back-tagline { .back-tagline {
font-family: Georgia, serif; font-family: var(--font-display);
font-style: italic; font-style: italic;
font-size: 0.115in; font-weight: 300;
font-size: 0.118in;
color: var(--color-muted); color: var(--color-muted);
max-width: 60%; max-width: 60%;
line-height: 1.5; line-height: 1.6;
} }
/* Barcode placeholder — KDP places the barcode here if left blank */ /* Barcode placeholder — KDP places the barcode here if left blank */
@@ -175,23 +219,27 @@
} }
.spine-title { .spine-title {
font-family: Georgia, serif; font-family: var(--font-display);
font-style: italic; font-style: italic;
font-weight: 300;
font-size: 0.13in; font-size: 0.13in;
color: var(--color-gold); color: var(--color-gold);
letter-spacing: 0.04em; letter-spacing: 0.04em;
} }
.spine-divider { .spine-divider {
font-family: var(--font-display);
font-size: 0.1in; font-size: 0.1in;
color: var(--color-muted); color: var(--color-muted);
} }
.spine-author { .spine-author {
font-family: Georgia, serif; font-family: var(--font-display);
font-style: italic;
font-weight: 300;
font-size: 0.1in; font-size: 0.1in;
color: var(--color-text); color: rgba(232, 228, 216, 0.7);
letter-spacing: 0.05em; letter-spacing: 0.06em;
} }
.spine-too-narrow { .spine-too-narrow {
@@ -233,19 +281,29 @@
} }
.front-title { .front-title {
font-family: Georgia, serif; font-family: var(--font-display);
font-style: italic; font-style: italic;
font-size: 0.52in; font-weight: 300;
line-height: 1.2; font-size: 0.54in;
line-height: 1.18;
color: var(--color-gold2); color: var(--color-gold2);
text-shadow: 0 0 0.15in rgba(200,168,75,0.4), 0 2px 8px rgba(0,0,0,0.8); text-shadow: 0 0 0.18in rgba(184,154,78,0.45), 0 2px 10px rgba(0,0,0,0.9);
letter-spacing: 0.01em;
}
.front-rule {
width: 1.6in;
height: 1px;
background: linear-gradient(to right, transparent, var(--color-gold), transparent);
} }
.front-subtitle { .front-subtitle {
font-family: Georgia, serif; font-family: var(--font-display);
font-size: 0.18in; font-style: italic;
letter-spacing: 0.08em; font-weight: 300;
color: var(--color-text); font-size: 0.17in;
letter-spacing: 0.1em;
color: rgba(232, 228, 216, 0.75);
text-shadow: 0 1px 4px rgba(0,0,0,0.8); text-shadow: 0 1px 4px rgba(0,0,0,0.8);
} }
@@ -259,29 +317,33 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background: radial-gradient(ellipse at center, #1a1a4a 0%, #080820 70%); background: radial-gradient(ellipse at 50% 40%, #1a1a4a 0%, #080820 70%);
} }
.front-art-placeholder span { .front-art-placeholder span {
font-family: monospace; font-family: var(--font-display);
font-size: 0.12in; font-style: italic;
color: rgba(200,168,75,0.4); font-size: 0.13in;
border: 1px dashed rgba(200,168,75,0.2); color: rgba(184,154,78,0.4);
padding: 0.15in 0.3in; border: 1px solid rgba(184,154,78,0.15);
padding: 0.15in 0.35in;
letter-spacing: 0.05em;
} }
.front-author { .front-author {
font-family: Georgia, serif; font-family: var(--font-display);
font-size: 0.16in; font-style: italic;
letter-spacing: 0.1em; font-weight: 300;
color: rgba(200,168,75,0.7); font-size: 0.15in;
letter-spacing: 0.12em;
color: rgba(184,154,78,0.65);
text-shadow: 0 1px 4px rgba(0,0,0,0.8); text-shadow: 0 1px 4px rgba(0,0,0,0.8);
} }
.front-ornament-bottom { .front-ornament {
font-size: 0.14in; font-family: var(--font-display);
font-size: 0.16in;
color: var(--color-muted); color: var(--color-muted);
letter-spacing: 0.4em;
} }
/* ── Safe-zone & bleed guides overlay ───────────────────── */ /* ── Safe-zone & bleed guides overlay ───────────────────── */
@@ -372,8 +434,8 @@
{% if hasSpineText %} {% if hasSpineText %}
<div class="spine-text"> <div class="spine-text">
<span class="spine-title">Das Kaleidoskop der Schlummerwelten</span> <span class="spine-title">Das Kaleidoskop der Schlummerwelten</span>
<span class="spine-divider"></span> <span class="spine-divider"></span>
<span class="spine-author">[AUTOR]</span> {% if author %}<span class="spine-author">{{ author }}</span>{% endif %}
</div> </div>
{% else %} {% else %}
<span class="spine-too-narrow">too narrow ({{ pageCount }}p &lt; 79)</span> <span class="spine-too-narrow">too narrow ({{ pageCount }}p &lt; 79)</span>
@@ -393,11 +455,12 @@
{% endif %} {% endif %}
<div class="front-content"> <div class="front-content">
<p class="front-ornament-top">✦ ✦ ✦</p> <p class="front-ornament"></p>
<h1 class="front-title">Das Kaleidoskop<br>der Schlummerwelten</h1> <h1 class="front-title">Das Kaleidoskop<br>der Schlummerwelten</h1>
<div class="front-rule"></div>
<p class="front-subtitle">Zwölf magische Einschlafgeschichten</p> <p class="front-subtitle">Zwölf magische Einschlafgeschichten</p>
<p class="front-author">[AUTOR]</p> {% if author %}<p class="front-author">{{ author }}</p>{% endif %}
<p class="front-ornament-bottom">· · ·</p> <p class="front-ornament">· · ·</p>
</div> </div>
</div>{# end front #} </div>{# end front #}