// Generated, do not edit. sha256:8ea45396bfd27f4dbf4c416aa596846fa428d7394799796a19ce526c30b7ada7 import { CONFIG } from '../../shared/config.js'; const BLOBS = Object.freeze([ Object.freeze({ cls: 'blob-a', x: [0, 42], y: [0, 26], firstMs: 4000 }), Object.freeze({ cls: 'blob-b', x: [-52, 0], y: [0, 32], firstMs: 14000 }), Object.freeze({ cls: 'blob-c', x: [-38, 38], y: [-38, -4], firstMs: 26000, sink: 0.3 }), ]); const SINK_VH = 80; export const BAND_LAYERS = Object.freeze([ Object.freeze({ w: 1400, h: 1800, count: 4, len: [700, 1300], width: [40, 70], alpha: [0.2, 0.4], blur: 12, dur: 21, opacity: 0.75, tilt: 10, seed: 19 }), Object.freeze({ w: 1800, h: 2100, count: 3, len: [900, 1600], width: [110, 180], alpha: [0.12, 0.26], blur: 28, dur: 17, opacity: 0.9, tilt: 12, seed: 29 }), Object.freeze({ w: 2200, h: 2400, count: 2, len: [1200, 1900], width: [300, 450], alpha: [0.08, 0.16], blur: 64, dur: 14, opacity: 1, tilt: 14, seed: 43 }), ]); const FADE_MS = 5200; const between = (rnd, a, b) => a + rnd() * (b - a); export function tempoOf(key) { return CONFIG.GLOW_TEMPO[key] || CONFIG.GLOW_TEMPO.calm; } export function motionMode({ profile, glow, motion, reducedMotion = false, hidden = false } = {}) { if (profile !== 'glass' || glow === 'off' || reducedMotion || hidden) return 'off'; return motion === 'step' || motion === 'always' ? motion : 'off'; } export function nextDelayMs(tempo, rnd = Math.random) { return Math.round((tempo.MOVE_S + between(rnd, tempo.PAUSE_MIN_S, tempo.PAUSE_MAX_S)) * 1000); } export function driftTransform(area, rnd = Math.random) { const sinks = area.sink ? rnd() < area.sink : false; const x = between(rnd, area.x[0], area.x[1]).toFixed(1); const y = sinks ? SINK_VH.toFixed(1) : between(rnd, area.y[0], area.y[1]).toFixed(1); const turn = between(rnd, -16, 16).toFixed(1); const sx = between(rnd, 0.85, 1.2).toFixed(3); const sy = between(rnd, 0.85, 1.2).toFixed(3); return `translate(${x}vw,${y}vh) rotate(${turn}deg) scale(${sx},${sy})`; } export function nextCore(cores, i, rnd = Math.random, chance = CONFIG.GLOW_CORE_CHANCE) { if (cores[i]) return false; if (cores.some((c, n) => c && n !== i)) return false; return rnd() < chance; } export function showerMs(tempo, on, rnd = Math.random) { return Math.round((on ? tempo.MOVE_S * 2 : between(rnd, tempo.PAUSE_MIN_S, tempo.PAUSE_MAX_S)) * 1000); } function seeded(a) { return () => { a |= 0; a = a + 0x6D2B79F5 | 0; let t = Math.imul(a ^ a >>> 15, 1 | a); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; }; } export function bandTile({ w, h, count, len, width, alpha, blur, seed }) { const rnd = seeded(seed); const halo = blur * 3, pad = 2 + halo; let shapes = ''; for (let i = 0; i < count; i++) { const sw = between(rnd, width[0], width[1]); const x = between(rnd, pad, w - pad - sw), y = between(rnd, 0, h); const L = between(rnd, len[0], len[1]), a = between(rnd, alpha[0], alpha[1]); for (const dy of [0, -h, h]) { if (dy < 0 && y + L + halo <= h) continue; if (dy > 0 && y - halo >= 0) continue; shapes += ``; } } const svg = `` + '' + '' + `` + `${shapes}`; return `url("data:image/svg+xml;utf8,${encodeURIComponent(svg)}")`; } const timers = []; let shapeTimer = null; let showerTimer = null; let fadeTimer = null; let bandsDrawn = false; let wired = false; let last = {}; function drawBands(box) { if (bandsDrawn) return; bandsDrawn = true; box.querySelectorAll('.band').forEach((el, i) => { const spec = BAND_LAYERS[i]; if (!spec) return; el.style.maskImage = el.style.webkitMaskImage = bandTile(spec); el.style.maskSize = el.style.webkitMaskSize = `${spec.w}px ${spec.h}px`; el.style.setProperty('--tile-h', `${spec.h}px`); el.style.setProperty('--band-dur', `${spec.dur}s`); el.style.setProperty('--tilt', `${spec.tilt}deg`); el.style.opacity = String(spec.opacity); }); } function shower(box, tempo, on) { clearTimeout(showerTimer); clearTimeout(fadeTimer); box.classList.add('is-falling'); box.classList.toggle('is-shown', on); if (!on) fadeTimer = setTimeout(() => box.classList.remove('is-falling'), FADE_MS); showerTimer = setTimeout(() => shower(box, tempo, !on), showerMs(tempo, on)); } function applyBands(box, bands, mode, tempo) { clearTimeout(showerTimer); clearTimeout(fadeTimer); box.classList.remove('is-falling'); if (bands) drawBands(box); box.classList.toggle('is-shown', bands); if (!bands) return; if (mode === 'always') box.classList.add('is-falling'); else if (mode === 'step') shower(box, tempo, true); } function elements() { return BLOBS.map(b => document.querySelector(`.aurora .${b.cls}`)); } function coresOf(els) { return els.map(el => !!el?.classList.contains('is-core')); } function reshape(els, i) { const el = els[i]; if (el) el.classList.toggle('is-core', nextCore(coresOf(els), i)); } function stopAll(els, keepTransform) { timers.forEach(t => clearTimeout(t)); timers.length = 0; clearTimeout(shapeTimer); for (const el of els) { if (!el) continue; el.classList.remove('is-core'); if (!keepTransform) el.style.transform = ''; } } export function applyAurora(settings = last) { last = settings; const root = document.documentElement; const els = elements(); if (!els.some(Boolean)) return; const tempo = tempoOf(settings.glow_tempo); root.style.setProperty('--drift-dur', `${tempo.MOVE_S}s`); root.style.setProperty('--drift-mult', String(tempo.ALWAYS_MULT)); const mode = motionMode({ profile: settings.profile, glow: settings.glow, motion: settings.motion, reducedMotion: matchMedia('(prefers-reduced-motion: reduce)').matches, hidden: document.hidden, }); const bands = settings.glowshape === 'bands'; const box = document.querySelector('.aurora .bands'); if (box) applyBands(box, bands, mode, tempo); const blobMode = bands ? 'off' : mode; stopAll(els, blobMode === 'step'); if (blobMode === 'step') { BLOBS.forEach((b, i) => { const tick = () => { if (els[i]) els[i].style.transform = driftTransform(b); reshape(els, i); timers[i] = setTimeout(tick, nextDelayMs(tempo)); }; timers[i] = setTimeout(tick, b.firstMs); }); } else if (blobMode === 'always') { const tick = () => { reshape(els, Math.floor(Math.random() * els.length)); shapeTimer = setTimeout(tick, nextDelayMs(tempo) / els.length); }; shapeTimer = setTimeout(tick, 20000); } if (!wired) { wired = true; document.addEventListener('visibilitychange', () => applyAurora()); matchMedia('(prefers-reduced-motion: reduce)').addEventListener('change', () => applyAurora()); } }