// topo.jsx — generative topographic contour-line backgrounds // Deterministic pseudo-random based on a string seed function seededRng(seed) { let h = 2166136261 >>> 0; for (let i = 0; i < seed.length; i++) { h ^= seed.charCodeAt(i); h = Math.imul(h, 16777619); } return () => { h += 0x6D2B79F5; let t = h; t = Math.imul(t ^ (t >>> 15), t | 1); t ^= t + Math.imul(t ^ (t >>> 7), t | 61); return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; } // Build a "topographic" SVG: a stack of irregular closed contour rings, // each one nudged slightly so they look like elevation lines on a map. function TopoSVG({ seed = "everest", width = 600, height = 400, stroke = "rgba(252,250,244,.18)", strokeBold = "rgba(252,250,244,.32)", rings = 14, peakX, peakY }) { const rand = seededRng(seed); const cx = peakX != null ? peakX : (0.35 + rand() * 0.3) * width; const cy = peakY != null ? peakY : (0.45 + rand() * 0.25) * height; // a couple of "wind" lobes to push contours into non-circular shapes const lobes = []; const nLobes = 3 + Math.floor(rand() * 3); for (let i = 0; i < nLobes; i++) { lobes.push({ angle: rand() * Math.PI * 2, strength: 0.15 + rand() * 0.35, sharpness: 1 + rand() * 2.5, }); } const paths = []; const baseR = Math.min(width, height) * 0.12; const ringSpacing = (Math.max(width, height) * 0.95) / rings; for (let r = 0; r < rings; r++) { const radius = baseR + r * ringSpacing * 0.45; const steps = 96; let d = ""; for (let i = 0; i <= steps; i++) { const t = (i / steps) * Math.PI * 2; let rr = radius; // apply lobes for (const L of lobes) { const a = Math.cos(t - L.angle); rr += L.strength * radius * Math.sign(a) * Math.pow(Math.abs(a), L.sharpness); } // micro jitter (consistent per ring + step) const jrng = seededRng(seed + "|" + r + "|" + i); rr += (jrng() - 0.5) * radius * 0.06; const x = cx + Math.cos(t) * rr; const y = cy + Math.sin(t) * rr * 0.78; // squish vertically d += (i === 0 ? "M" : "L") + x.toFixed(1) + "," + y.toFixed(1) + " "; } d += "Z"; paths.push({ d, bold: r % 4 === 0 }); } return ( {paths.map((p, i) => ( ))} {/* tiny summit triangle */} ); } // Full-page faint topo lines (paper) function TopoBackdrop() { return ( ); } // Inline SVG paper-colored backdrop (light contour lines on paper) function TopoSVGPaper() { const rand = seededRng("paper-2026"); const cx = 1100; const cy = 380; const rings = 22; const baseR = 60; const lobes = [ { angle: 0.4, strength: 0.32, sharpness: 1.6 }, { angle: 2.1, strength: 0.22, sharpness: 2.0 }, { angle: 4.4, strength: 0.18, sharpness: 1.2 }, ]; const paths = []; for (let r = 0; r < rings; r++) { const radius = baseR + r * 60; const steps = 120; let d = ""; for (let i = 0; i <= steps; i++) { const t = (i / steps) * Math.PI * 2; let rr = radius; for (const L of lobes) { const a = Math.cos(t - L.angle); rr += L.strength * radius * Math.sign(a) * Math.pow(Math.abs(a), L.sharpness); } const jrng = seededRng("paper|" + r + "|" + i); rr += (jrng() - 0.5) * radius * 0.04; const x = cx + Math.cos(t) * rr; const y = cy + Math.sin(t) * rr * 0.78; d += (i === 0 ? "M" : "L") + x.toFixed(1) + "," + y.toFixed(1) + " "; } d += "Z"; paths.push({ d, bold: r % 5 === 0 }); } return ( {paths.map((p, i) => ( ))} ); } Object.assign(window, { TopoSVG, TopoBackdrop });