/* ============================================================ liberated-templates.mjs — the eight deconstructed compositions, each piped through ONE signature liberation (the move that most amplifies it): luminous waves, open/dark grounds, directional or off-centre light, off-canvas bleed, and the high-Q resonance axis. Usage: node tools/liberated-templates.mjs [size] ============================================================ */ import { writeFileSync, mkdirSync } from 'node:fs'; import { TEMPLATES, buildTemplate } from '../src/compose/templates.js'; import { renderComposition } from '../src/compose/composition.js'; const SIZE = +(process.argv[2] || 1300); const OUT = 'output/templates-liberated'; mkdirSync(OUT, { recursive: true }); const merge = (a, b) => { const o = { ...a }; for (const k in b) o[k] = (b[k] && typeof b[k] === 'object' && !Array.isArray(b[k])) ? merge(a[k] || {}, b[k]) : b[k]; return o; }; // one signature liberation per template id const LIB = { 'great-wave': { note: 'luminous foam · waves lighter than a dusk ground', over: { fieldSea: { color: { light: 0.84 } }, background: { color: 'rgb(120,120,142)', glow: { strength: 0.3 }, vignette: { strength: 0.42 } } } }, 'monk-by-sea': { note: 'a lone light over a dark sea-void', over: { background: { color: 'rgb(26,28,38)', glow: { strength: 0.4, followSun: true }, vignette: { strength: 0.25 }, film: { opacity: 0.3 }, grain: { opacity: 0.3 } }, fieldSea: { color: { light: 0.72, sat: 0.3 } }, disk: { hue: 0.58, sat: 0.42, pressure: 0.2 } } }, 'rothko': { note: 'raking directional light across the fields', over: { background: { vignette: { mode: 'linear', angle: 115, strength: 0.55, start: 0.3 } } } }, 'turner': { note: 'light leaking in from a corner', over: { background: { vignette: { mode: 'linear', angle: 210, strength: 0.45, start: 0.4 }, glow: { strength: 1.0, followSun: true } } } }, 'ma': { note: 'the event bled off-canvas · asymmetric light', over: { bubble: { transform: { x: 1.18, y: 0.9, scale: 1.1 } }, background: { vignette: { mode: 'radial', cx: 0.7, cy: 0.35, radius: 0.7, strength: 0.55 } }, fiduciaries: { target: [0.85, 0.7], from: [0.2, -0.1] } } }, 'suprematist': { note: 'a luminous form on a dark void', over: { background: { color: 'rgb(24,22,30)', glow: { strength: 0.45, followSun: true }, vignette: { strength: 0.2 } }, disk: { hue: 0.04, sat: 0.9, pressure: 0.4, intensity: 0.95 }, bubble: { palette: 'kindrise' } } }, 'golden-thirds': { note: 'asymmetric light pulled toward the φ sun', over: { background: { vignette: { mode: 'radial', cx: 0.32, cy: 0.34, radius: 0.66, strength: 0.5 } }, fieldSea: { color: { light: 0.5 } } } }, 'wright': { note: 'a Cherokee-red high-Q resonance threading the grid', over: { fieldGrid: { resonance: { amp: 0.5, q: 16, axis: 'ties', hue: 0.03, sat: 0.85, light: 0.5 } } } }, }; let n = 0; const items = []; for (const t of TEMPLATES) { const lib = LIB[t.id] || { note: '', over: {} }; for (let i = 0; i < t.reps; i++) { const comp = merge(buildTemplate(t, i), lib.over); const name = `${String(++n).padStart(2, '0')}_${t.id}_v${i + 1}`; writeFileSync(`${OUT}/${name}.svg`, renderComposition(comp, SIZE)); writeFileSync(`${OUT}/${name}.mjs`, `/* ${t.name} (${t.source}) · liberated: ${lib.note} */\nexport const composition = ${JSON.stringify(comp, null, 2)};\n`); items.push({ name, t, lib }); console.log(` ${name} ${t.name} — ${lib.note}`); } } console.log(`liberated templates — ${n} → ${OUT}/`); const cols = 5; writeFileSync(`${OUT}/matrix.html`, `Traces of the Invisible — through the liberated lens

Traces of the Invisible — through the liberated lens

the eight grammars, each severed from one expectation · ${n} plates

${items.map((it, k) => `
${String(k + 1).padStart(2, '0')} · ${it.t.name}${it.lib.note}
`).join('\n')}
`); console.log(`-> ${OUT}/matrix.html`);