/* ============================================================ qft-bc-magenta.mjs — sketch 02 of the JOINED series. Built on 78_final-lively-magenta-cream (seed MESON-5113, palette magentarise, cream paper). A THIN-LINE but present QFT field is slipped BETWEEN the cream ground and the bubble chamber: cream paper → thin QFT lattice → magentarise event (multiply on top). The bubble-chamber layer is constant; each frame varies the QFT geometry AND its hue family, chosen to converse with the magenta tracks + burnt-orange disk + cream. Usage: node tools/qft-bc-magenta.mjs [size] ============================================================ */ import { writeFileSync, mkdirSync } from 'node:fs'; import { generateQFTScene } from '../src/qft/scene.js'; import { paramsFromSeed as qftParams } from '../src/qft/params.js'; import { renderQFTSVG } from '../src/qft/renderer.js'; import { generateScene } from '../src/scene/scene.js'; import { renderSVG } from '../src/render/svgVector.js'; import { paramsFromSeed as bcParams } from '../src/scene/params.js'; import { GROUPS, TOGGLES, FIXED } from '../src/ui/controls.js'; const SIZE = +(process.argv[2] || 1700); const OUT = 'output/qft-bc/sketch02'; mkdirSync(OUT, { recursive: true }); // F(hueStart,hueEnd,sat,light,opacity[,stroke]) — thin strokes throughout. const F = (h0, h1, s, l, o, st = 0.6) => ({ hueStart: h0, hueEnd: h1, saturation: s, lightness: l, opacity: o, stroke: st }); const OFF = F(0, 0, 0, 0.5, 0); const paper = (flat, gi = [10, 9, 8], go = [-16, -16, -16]) => ({ flat, glowIn: [flat[0] + gi[0], flat[1] + gi[1], flat[2] + gi[2]], glowOut: [flat[0] + go[0], flat[1] + go[1], flat[2] + go[2]], }); const W = (x, y, amplitude, sigma) => ({ x, y, amplitude, sigma }); const VX = (x, y, strength, sigma) => ({ x, y, strength, sigma }); const SW = (kx, ky, amplitude, phase = 0) => ({ kx, ky, amplitude, phase }); const R = (x, y, count = 6, r0 = 0.08, dR = 0.10, propagator = 'photon') => ({ x, y, count, r0, dR, propagator }); const CREAM = [236, 228, 208]; // pale cream so the BC's own paper carries the tone // thin-line QFT base: light vignette/glow so the ground stays flat under the BC. const QBASE = { substrate: 'cream', paperOverride: paper(CREAM), vignOverride: [120, 110, 90], showHeader: false, glow: 0.18, vign: 0.10, stroke: 0.7, segmentsPerEdge: 8, photonCyclesPerUnit: 12, linkCurvature: 0.18, }; // constant bubble-chamber layer — the 78 piece (lively magenta on cream). function bcLayer() { const p = { ...FIXED, ...bcParams('MESON-5113') }; for (const g of GROUPS) for (const c of g.controls) if (!(c.id in p)) p[c.id] = c.value; for (const t of TOGGLES) if (!(t.id in p)) p[t.id] = t.value; p.palette = 'magentarise'; p.paperTone = 'cream'; p.invert = true; p.showHeader = false; p.saturation = 1.05; // a touch livelier return p; } const dataUri = (svg) => 'data:image/svg+xml;base64,' + Buffer.from(svg).toString('base64'); function composite(v) { const qp = { ...qftParams(v.qftSeed), ...QBASE, ...(v.qftOver || {}) }; const bp = bcLayer(); const qftSvg = renderQFTSVG(generateQFTScene(qp), qp, SIZE); const bcSvg = renderSVG(generateScene(bp), bp, SIZE); const s = v.qScale ?? 1, qw = SIZE * s, qh = SIZE * s; const qx = (SIZE - qw) / 2 + (v.qDx || 0), qy = (SIZE - qh) / 2 + (v.qDy || 0); const out = ` `; writeFileSync(`${OUT}/${v.name}.svg`, out); console.log(` ${v.name} (qft=${v.qftSeed}/${qp.archetype})`); return out; } // ============================================================ // 10 hue families × QFT geometries, all under the same magenta event. // ============================================================ const VARIATIONS = [ // 1 — TONAL ECHO. Field in the same magenta family, paler & desaturated: // the trace's colour, whispered, as its own substrate. { name: '01_tonal-magenta-echo', qftSeed: 'FEYNMAN-7167', qftOver: { cubicN: 2, e8Count: 3, e8OriginRadius: 0.6, linkCount: 6, fields: { cubic: F(0.86, 0.90, 0.46, 0.50, 0.60, 0.55), schlegel: F(0.80, 0.84, 0.42, 0.48, 0.52, 0.55), e8: F(0.90, 0.94, 0.52, 0.50, 0.65, 0.6), ripple: OFF, links: F(0.92, 0.88, 0.58, 0.48, 0.66, 0.8) } } }, // 2 — THE COMPLEMENT. Teal/viridian — magenta's opposite — for maximum // vibrance under the warm event. A swirling vortex lattice. { name: '02_magenta-teal-duotone', qftSeed: 'GAUGE-2046', qftOver: { cubicN: 2, e8Count: 1, e8OriginRadius: 0.64, linkCount: 6, vortices: [VX(0, 0, 0.8, 0.3)], fields: { cubic: F(0.47, 0.50, 0.55, 0.46, 0.58, 0.55), schlegel: F(0.50, 0.46, 0.50, 0.44, 0.50, 0.6), e8: F(0.45, 0.48, 0.55, 0.48, 0.55, 0.6), ripple: OFF, links: F(0.48, 0.44, 0.60, 0.46, 0.62, 0.8) } } }, // 3 — EMBER UNDERGLOW. Gold→copper field, picking up the burnt-orange disk: // the event smouldering on a bed of its own embers. Nautilus rosettes. { name: '03_ember-gold-underglow', qftSeed: 'LATTICE-1003', qftOver: { cubicN: 2, e8Style: 'nautilus', e8Count: 3, nautilusTurns: 2.6, nautilusPerTurn: 14, nautilusGrowth: 0.2, linkCount: 6, fields: { cubic: F(0.10, 0.08, 0.62, 0.46, 0.62, 0.55), schlegel: F(0.08, 0.06, 0.55, 0.44, 0.52, 0.55), e8: F(0.12, 0.07, 0.72, 0.46, 0.70, 0.6), ripple: OFF, links: F(0.07, 0.05, 0.82, 0.44, 0.72, 0.8) } } }, // 4 — COOL RECEDE. Violet→indigo, the cool neighbour of magenta — the field // steps back into shadow while the warm trace advances. Big tesseract. { name: '04_violet-indigo-recede', qftSeed: 'PROPAGATOR-2755', qftOver: { cubicN: 1, schlegelScale: 1.3, schlegelOuterR: 0.86, e8Count: 2, linkCount: 5, fields: { cubic: F(0.70, 0.74, 0.45, 0.50, 0.48, 0.5), schlegel: F(0.74, 0.78, 0.50, 0.46, 0.55, 0.6), e8: F(0.68, 0.72, 0.45, 0.50, 0.50, 0.6), ripple: OFF, links: F(0.76, 0.72, 0.50, 0.48, 0.55, 0.8) } } }, // 5 — VERDIGRIS. Desaturated sea-green patina — aged copper plate — under a // Chladni standing-wave membrane. Quiet, oxidised, archival. { name: '05_verdigris-chladni', qftSeed: 'VACUUM-5113', qftOver: { cubicN: 2, e8Count: 0, linkCount: 3, standingWaves: [SW(6, 1, 0.04), SW(1, 6, 0.04)], fields: { cubic: F(0.44, 0.48, 0.30, 0.54, 0.55, 0.55), schlegel: F(0.46, 0.50, 0.26, 0.52, 0.45, 0.55), e8: OFF, ripple: OFF, links: F(0.42, 0.46, 0.35, 0.52, 0.50, 0.75) } } }, // 6 — SPLIT-COMPLEMENT. Teal lattice, GOLD propagator links (tied to the // disk accent) — a two-colour field that brackets the magenta on both sides. { name: '06_teal-lattice-gold-links', qftSeed: 'FEYNMAN-7167', qftOver: { cubicN: 2, e8Count: 3, e8OriginRadius: 0.58, linkCount: 9, linkCurvature: 0.3, fields: { cubic: F(0.49, 0.52, 0.45, 0.50, 0.52, 0.55), schlegel: F(0.50, 0.47, 0.42, 0.48, 0.45, 0.55), e8: F(0.11, 0.08, 0.55, 0.55, 0.55, 0.6), ripple: OFF, links: F(0.12, 0.07, 0.70, 0.55, 0.7, 0.85) } } }, // 7 — ROSE GHOST. The thinnest, palest field — a barely-there dusty pink // lattice, present only as a breath. Sparse. Contemplative. { name: '07_rose-ghost-quiet', qftSeed: 'GAUGE-2046', qftOver: { cubicN: 1, e8Count: 1, e8OriginRadius: 0.66, linkCount: 4, fields: { cubic: F(0.93, 0.90, 0.28, 0.66, 0.40, 0.45), schlegel: F(0.90, 0.94, 0.24, 0.64, 0.34, 0.45), e8: F(0.92, 0.96, 0.30, 0.66, 0.42, 0.5), ripple: OFF, links: F(0.94, 0.90, 0.34, 0.64, 0.42, 0.65) } } }, // 8 — PALE SPECTRAL. A faint rainbow lattice — cubic cool-blue, schlegel // violet, e8 gold, links rose: an earned-colour field, softened to a haze. { name: '08_pale-spectral-lattice', qftSeed: 'LATTICE-1003', qftOver: { cubicN: 2, e8Count: 3, e8OriginRadius: 0.6, linkCount: 7, fields: { cubic: F(0.55, 0.60, 0.40, 0.58, 0.46, 0.5), schlegel: F(0.72, 0.78, 0.42, 0.54, 0.46, 0.55), e8: F(0.11, 0.14, 0.50, 0.58, 0.50, 0.6), ripple: OFF, links: F(0.93, 0.88, 0.45, 0.58, 0.5, 0.8) } } }, // 9 — CYAN BLUEPRINT. Pale cyan/blue draughtsman's lines with expanding // ripple wavefronts — the schematic under the photograph. { name: '09_cyan-blueprint-ripples', qftSeed: 'PROPAGATOR-2755', qftOver: { cubicN: 2, e8Count: 0, linkCount: 4, ripples: [R(0, 0, 5, 0.1, 0.11)], fields: { cubic: F(0.54, 0.57, 0.45, 0.52, 0.52, 0.5), schlegel: F(0.56, 0.53, 0.42, 0.50, 0.45, 0.55), e8: OFF, ripple: F(0.55, 0.58, 0.50, 0.54, 0.55, 0.6), links: F(0.54, 0.57, 0.50, 0.50, 0.55, 0.8) } } }, // 10 — COMMUNION. The field sweeps the EXACT purple→magenta→pink band of the // trace family, at lowest saturation — field and trace are one colour, // one chemistry; only the burnt-orange disk stands apart. ★ { name: '10_trace-family-communion', qftSeed: 'FEYNMAN-7167', qftOver: { cubicN: 2, e8Style: 'nautilus', e8Count: 3, nautilusTurns: 2.8, nautilusPerTurn: 16, nautilusGrowth: 0.2, linkCount: 7, fields: { cubic: F(0.82, 0.90, 0.40, 0.50, 0.60, 0.55), schlegel: F(0.79, 0.86, 0.38, 0.48, 0.54, 0.55), e8: F(0.88, 0.95, 0.44, 0.50, 0.64, 0.6), ripple: OFF, links: F(0.90, 0.82, 0.50, 0.48, 0.66, 0.8) } } }, ]; console.log(`Compositing ${VARIATIONS.length} magenta-cream QFT×BC plates → ${OUT}/`); for (const v of VARIATIONS) composite(v); const cap = (v) => v.name.replace(/^\d+_/, '').replace(/-/g, ' '); const idx = `QFT × Bubble Chamber · sketch 02 · magenta-cream

QFT × Bubble Chamber · sketch 02 — thin field between cream & the magenta event

Built on 78_final-lively-magenta-cream (MESON-5113 · magentarise · cream). A thin-line but present QFT lattice is slipped between the cream ground and the bubble chamber (multiply on top). The event is constant; each frame varies the QFT geometry and a hue family chosen to converse with the magenta tracks + burnt-orange disk.
${VARIATIONS.map(v => `
${cap(v)}field: ${v.qftSeed}
`).join('\n')}
`; writeFileSync(`${OUT}/index.html`, idx); const m = `
${VARIATIONS.map(v => `
${cap(v)}
`).join('\n')}
`; writeFileSync(`${OUT}/m.html`, m); console.log(`contact sheets -> ${OUT}/index.html , m.html`);