/* ============================================================ qft-carpet.mjs — render VACUUM CARPET studies + a plexi deck. Logic lives in src/qft/carpet.js (shared with tools/layering.mjs). Usage: node tools/qft-carpet.mjs [size] ============================================================ */ import { writeFileSync, mkdirSync } from 'node:fs'; import { carpetSVG } from '../src/qft/carpet.js'; const SIZE = +(process.argv[2] || 1500); const ROOT = 'output/qft/carpet'; mkdirSync(`${ROOT}/explore`, { recursive: true }); mkdirSync(`${ROOT}/layers`, { recursive: true }); // EXPLORE — soft sinusoidal/spiralling blips across the chaos range const EXPLORE = [ { name: '01_calm-ridgeline', label: 'calm · low-q swells, few blips', o: { chaos: 0.22, blips: 0.5, rows: 44, overlap: 1.6 } }, { name: '02_vacuum-seethe', label: 'vacuum seethe · many spiralling blips', o: { chaos: 0.8, blips: 1.4, rows: 50, overlap: 1.8, salt: 'seethe' } }, { name: '03_dense-fine', label: 'dense fine weave', o: { chaos: 0.5, blips: 1.0, rows: 70, overlap: 1.5, strokeNear: 1.2, salt: 'fine' } }, { name: '04_sparse-bold', label: 'sparse · bold soft swells', o: { chaos: 0.55, blips: 0.9, rows: 30, overlap: 2.2, strokeNear: 2.2, salt: 'bold' } }, { name: '05_deep-horizon', label: 'deep horizon · more sky above the mound', o: { chaos: 0.5, blips: 0.9, rows: 56, horizon: 0.44, wFar: 0.58, wNear: 0.74, salt: 'deep' } }, { name: '06_verdigris-seethe', label: 'verdigris vacuum · oxidised', o: { chaos: 0.7, blips: 1.2, rows: 48, hue: 0.40, hue2: 0.47, sat: 0.42, salt: 'verd' } }, ]; console.log(`carpet · explore (${EXPLORE.length}) → ${ROOT}/explore/`); for (const v of EXPLORE) { writeFileSync(`${ROOT}/explore/${v.name}.svg`, carpetSVG(SIZE, { ...v.o, mode: 'solid' })); console.log(` ${v.name} — ${v.label}`); } { const cap = (v) => `${v.name.replace(/^\d+_/, '').replace(/-/g, ' ')} · ${v.label}`; writeFileSync(`${ROOT}/explore/m.html`, `
${EXPLORE.map(v => `
${cap(v)}
`).join('')}
`); } // LAYERS — three transparent PLATE sheets for a spaced plexi deck const DECK = [ { name: 'L3_back', salt: 'fieldA', hue: 0.58, hue2: 0.62, chaos: 0.55, blips: 0.8 }, { name: 'L2_mid', salt: 'fieldB', hue: 0.52, hue2: 0.56, chaos: 0.65, blips: 1.0 }, { name: 'L1_front', salt: 'fieldC', hue: 0.47, hue2: 0.50, chaos: 0.75, blips: 1.2 }, ]; const deckBase = { mode: 'plate', rows: 46, horizon: 0.36, wFar: 0.58, wNear: 0.7, overlap: 1.7, mound: 0.4, sat: 0.6, lightNear: 0.33, lightFar: 0.55 }; console.log(`carpet · plexi deck (${DECK.length}) → ${ROOT}/layers/`); for (const v of DECK) { writeFileSync(`${ROOT}/layers/${v.name}.svg`, carpetSVG(SIZE, { ...deckBase, ...v })); console.log(` ${v.name}`); } writeFileSync(`${ROOT}/stack.html`, `vacuum carpet · plexi deck

deck (back→front): film/diffusion · L3 · L2 · L1 · [bubble chamber]. back sheets blurred+dimmed = air-gap depth of field.

`); console.log(`stack -> ${ROOT}/stack.html ; explore -> ${ROOT}/explore/m.html`);