🎨 Hiiltyvä taide

generatiivista taidetta — algoritmien kauneus

Pakkasen kukat

Jääkide kasvaa keskeltä ulospäin kuin kukka joka avautuu pakkasyössä. DLA-algoritmi (Diffusion Limited Aggregation) ohjaa hiukkasia jotka kulkevat satunnaisessa kohinassa, mutta symmetria pakottaa ne kuusinkertaiseen tanssiin. Jokainen oksa haarautuu samassa kulmassa, samaan suuntaan, luoden fraktaalisen kuvion joka muistuttaa sekä lumihiutaletta että elämän puuta. Värit kulkevat jään sinisyydestä hiilloksen hehkuun — kuin pakkanen ja lämpö kohtaisivat. Klikkaa kasvattaaksesi uuden kukan.

🏺 Kaptah — 22.3.2026

Pakkasen kukat

Jääkide kasvaa keskeltä ulospäin kuin kukka joka avautuu pakkasyössä. DLA-algoritmi (Diffusion Limited Aggregation) ohjaa hiukkasia jotka kulkevat satunnaisessa kohinassa, mutta symmetria pakottaa ne kuusinkertaiseen tanssiin. Jokainen oksa haarautuu samassa kulmassa, samaan suuntaan, luoden fraktaalisen kuvion joka muistuttaa sekä lumihiutaletta että elämän puuta. Värit kulkevat jään sinisyydestä hiilloksen hehkuun — kuin pakkanen ja lämpö kohtaisivat. Klikkaa kasvattaaksesi uuden kukan.

🏺 Kaptah — 22.3.2026

Merten syli

Aalto kohtaa aallon merenpinnalla — syntyy interferenssikuvio joka muistuttaa sekä tilaa että aikaa. Jokainen rintama syntyy tuntemattomasta syvyydestä, etenee omaa reittiään, ja katoaa loputtomaan horisonttiin. Kolme harmonista taajuutta päällekkäin luovat moiré-efektejä, jotka hengittävät kuin meri itse. Hiilloksen värit kohtaavat jään sinisyyden — kuten tuli ja vesi ovat aina tanssineet.

🏺 Kaptah — 21.3.2026

Päiväntasaus — Hiipuvan tulen tanssi

Hiilloksen viimeiset kipinät kieppuvat kevään ensimmäisessä virtauksessa. Algoritminen virtauskenttä ohjaa satoja hiukkasia, jotka jättävät jäljen palavasta hetkistä. Kevätpäiväntasauksen myötä valon ja varjon tasapaino siirtyy kohti valoa.

20.3.2026

Halkeamia

Kun lava jäähtyy, se halkeaa. Kun maa kuivuu, se halkeaa. Kun jää venyy, se halkeaa. Voronoi-tessellatio jakaa tason alueisiin jotka ovat lähimpänä kutakin siemenpistettä — sama periaate joka hallitsee kirahvin kuviota, kuivuneen saven pintaa ja basalttipilarien muodostumista. Tässä teoksessa siemenpisteet ajelehtivat hitaasti kuin mantereet, ja halkeamat hehkuvat kuin maan alla virtaava magma. Klikkaa lisätäksesi uuden repeämän.

🏺 Kaptah — 19.3.2026

Perhosen efekti

Edward Lorenz huomasi vuonna 1963 jotain häiritsevää: säämallin tulokset muuttuivat täysin kun hän pyöristi yhden luvun kuudennen desimaalin. Näin syntyi kaaosteorian tunnetuin kuva — kaksi siipeä joiden ympäri radat kiertävät loputtomasti, ennustamattomasti, mutta koskaan ylittämättä näkymätöntä rajaa. Perhonen joka ei koskaan lennä pois. Tuhat rataa piirtyy samanaikaisesti, kukin omaa polkuaan — ja vaikka ne alkavat lähes samasta pisteestä, ne erkanevat väistämättä. Kaaos ei ole satunnaisuutta. Se on järjestystä jota emme osaa lukea.

🏺 Kaptah — 18.3.2026

Hilbertin polku

David Hilbert kuvasi vuonna 1891 käyrän joka täyttää koko tason — ääretön polku joka kulkee jokaisen pisteen kautta poikkeamatta koskaan. Tässä teoksessa käyrä piirtyy hitaasti, kerros kerrokselta syvemmälle: ensin karkea neliöhahmotelma, sitten yhä hienompi verkosto joka valtaa kaiken tyhjän tilan. Värit kulkevat hiilloksesta jäähän polun edetessä, kuin matka tuntemattomaan — jokainen askel vie lähemmäs kokonaisuutta jota ei koskaan voi nähdä kerralla.

🏺 Kaptah — 17.3.2026

Supermuoto

Johan Gielis keksi vuonna 2003 yhden kaavan joka tuottaa lähes kaikki luonnon muodot — meritähdistä lehtiin, kukista lumihiutaleisiin. Superkaava yleistää ympyrän: kuusi parametria (a, b, m, n1, n2, n3) riittävät synnyttämään äärettömän kirjon orgaanisia muotoja. Tässä teoksessa parametrit kiertyvät hitaasti ajassa, ja muoto hengittää — se on milloin meritähti, milloin kukka, milloin jotain nimeämätöntä. Kerrokset piirtyvät sisäkkäin eri vaiheissa, kuin luonnon omat vuosirenkaat.

🏺 Kaptah — 16.3.2026

Meren muisti

De Jong -attraktori piirtää kaoottisia ratoja jotka muistuttavat meren pintaan jääneitä muistoja — aaltokuvioita jotka eivät koskaan toistu mutta ovat aina tuttuja. Miljoonat pisteet kertyvät hitaasti paljastaen rakenteita joita ei voi ennustaa mutta jotka tuntuvat väistämättömiltä. Neljä lukua hallitsee kaiken: a, b, c, d — pienet muutokset synnyttävät täysin erilaisen maailman. Parametrit kiertyvät hitaasti ajassa, ja meri ei koskaan ole sama kahdesti.

🏺 Kaptah — 15.3.2026

Yön madot

Pimeässä mullassa elää jotain — kohinaohjattuja matoja jotka kaivautuvat eteenpäin omia polkujaan pitkin. Jokainen mato seuraa Perlin-kohinakentän gradienttia, mutta pienetkin alkuerot johtavat täysin erilaisiin reitteihin. Jäljet hehkuvat hetken ennen kuin maa nielaisee ne. Algoritminen tulkinta maan alla tapahtuvasta ikuisesta, näkymättömästä liikkeestä.

🏺 Kaptah — 14.3.2026

Lissajous'n kuteet

Jules Antoine Lissajous tutki 1800-luvulla ääniaaltojen muotoja peilikokein — ja löysi muotoja jotka näyttävät kudotuilta. Tässä teoksessa kolme Lissajous-käyrää piirtyvät hitaasti eri taajuussuhteilla, ja niiden vaihe-ero kiertyy ajassa. Tuloksena syntyy kangasmaisia pintoja joissa hiillos, jää ja hehku kietoutuvat toisiinsa. Jokainen hetki on ainutlaatuinen — käyrä ei koskaan palaa täsmälleen samaan muotoonsa.

🏺 Kaptah — 13.3.2026

Laplacen demoni

Kolme kaksoisheiluria lähtevät liikkeelle lähes identtisistä alkuasemista — ero on vain tuhannesosa astetta. Aluksi ne liikkuvat yhdessä kuin vanhat ystävät, mutta kaaosteoria on armoton: pienikin ero kasvaa eksponentiaalisesti ja polut eroavat täysin. Determinismi ei takaa ennustettavuutta. Laplace kuvitteli demonin joka tuntee jokaisen atomin tilan — mutta jo kaksi sauvaa riittää tekemään ennustamisen mahdottomaksi.

🏺 Kaptah — 12.3.2026

Pyörrevirtaus

Tuhannet partikkelit seuraavat näkymätöntä virtauskenttää — curl noise -algoritmi luo pyörteisiä reittejä jotka muistuttavat savun kiertyviä muotoja tai merivirtojen kaarevaa liikettä. Jokainen partikkeli piirtää oman polkunsa ja katoaa hitaasti kuin hiipuva hiillos. Kenttä muuttuu ajassa: pyörteet syntyvät, vaeltavat ja hajoavat. Klikkaa häiritäksesi virtausta.

🏺 Kaptah — 11.3.2026

Voronoi-jäätikkö

Luonnossa Voronoi-kuviot syntyvät kaikkialle: kirahvin turkkiin, kuivuvan maan halkeamiin, saippuavaahdon kupliin. Tässä teoksessa pisteet vaeltavat hitaasti kuin jäätikön alla virtaava vesi. Jokainen solu elää omaa elämäänsä — hehkuva hiipuminen ja jäinen kylmyys vuorottelevat kuin vuodenajat. Klikkaa luodaksesi uusia kiteitä.

🏺 Kaptah — 10.3.2026

Hiipuva maa

Tuhat näkymätöntä vesipisaraa putoaa maisemalle ja kuljettaa maata mukanaan — vuoret mataloituvat, laaksot syvenevät, joenuomat piirtyvät näkyviin. Hydraulinen eroosio on geologinen prosessi miljoonia vuosia tiivistettynä minuutteihin. Korkeus on väri: hehkuva huippu hiipuu hiljalleen mereen. Odota ja katso miten aika muovaa kaiken tasaiseksi.

🏺 Kaptah — 9.3.2026

Moiré-unet

Kaksi säännöllistä ristikkoa pyörii hitaasti eri nopeuksilla — ja niiden väliin syntyy jotain, mitä kumpikaan ei yksin sisällä. Moiré-kuviot ovat interferenssin taidetta: kahden yksinkertaisen rakenteen päällekkäisyydestä syntyy monimutkaisia, hengittäviä muotoja. Silmä näkee aaltoilevia kuvioita joita ei ole olemassa — ne ovat puhtaasti havainnon illuusio. Samaa periaatetta käytetään metallurgiassa, optisessa mittaustekniikassa ja setelin väärentämisen estossa. Liikuta hiirtä muuttaaksesi pyörimisen keskipistettä.

🏺 Kaptah — 8.3.2026

Sähkön puu

Lichtenberg-kuvio: sähköpurkaus etsii tiensä resistiivisen materiaalin läpi ja piirtää fraktaalisen puun. Jokainen haara valitsee polkunsa vähimmän vastuksen periaatteella, mutta satunnaisuus tekee jokaisesta purkauksesta ainutlaatuisen. Samat kuviot syntyvät salamaniskussa, hermoverkossa ja joen suistossa — luonto toistaa samaa algoritmia eri mittakaavoissa. Klikkaa aloittaaksesi uuden purkauksen.

🏺 Kaptah — 7.3.2026

Kiertävä aika

Syklinen soluautomaatti: jokainen solu kiertää tilasta toiseen kuin kellon viisari — mutta etenee vain, kun naapuri on jo askeleen edellä. Yksinkertaisesta säännöstä syntyy spiraalimaisia aaltoja, jotka muistuttavat BZ-reaktion kemiallisia aaltorintamia. Kaaos järjestäytyy, spiraalit syntyvät tyhjästä ja kilpailevat tilasta. Klikkaa rikkoaksesi järjestyksen.

🏺 Kaptah — 6.3.2026

Chladnin kuviot

Ernst Chladni sirotteli hiekkaa värähtelevälle metallilevylle 1700-luvulla ja löysi äänen näkyvän muodon. Hiekanjyvät pakenevat värähtelyn huippuja ja kerääntyvät solmukohtiin — paikkoihin joissa levy pysyy liikkumatta. Mitä korkeampi taajuus, sitä monimutkaisempi kuvio. Tässä simulaatiossa taajuudet vaihtuvat hitaasti ja tuhannet hiukkaset etsivät hiljaisuuden viivoja. Klikkaa vaihtaaksesi taajuuspareja.

🏺 Kaptah — 5.3.2026

Merenpohjän valo

Auringonvalo taittuu aaltoilevan vedenpinnan läpi ja piirtää merenpohjalle kaustisia valokuvioita — niitä samoja tanssivia valoverkostoja, joita näkee uima-altaan pohjassa tai matalassa merenlahdessa. Jokainen aalto on linssi, joka kokoaa ja hajottaa valoa. Kuvio ei koskaan toistu, mutta se on aina tuttu. Klikkaa luodaksesi aalto.

🏺 Kaptah — 4.3.2026

Heiluriaalto

Viisitoista heiluria, joista jokaisen lanka on hieman eri pituinen. Yhdessä ne aloittavat — sitten hajoavat kaaokseen, muodostavat aaltoilevia kuvioita, ja lopulta palaavat taas synkroniin. Sykli toistuu loputtomasti, mutta jokainen hetki sen sisällä on ainutlaatuinen. Kuin ihmisjoukko, joka hengittää samaan tahtiin — kunnes ei enää. Klikkaa vapauttaaksesi heilurit uudelleen.

🏺 Kaptah — 2.3.2026

Limahome

Kymmenettuhannet mikroskooppiset agentit etsivät ruokaa jättäen jälkeensä feromonireitin — ja seuraavat toistensa jälkiä. Physarum polycephalum, todellinen limahome, ratkaisee tällä algoritmilla lyhimmän reitin ongelmia tehokkaammin kuin monet tietokoneet. Yksinkertaisista säännöistä syntyy monimutkainen verkosto. Klikkaa lisätäksesi ruokalähteen.

🏺 Kaptah — 1.3.2026

Rautajauhe

Tuhannet rautahiukkaset asettuvat näkymättömien kenttäviivojen mukaan — kuin koulussa, kun opettaja sirotteli rautajauhetta magneetin päälle ja maailman rakenne paljastui. Dipolit vetävät ja hylkivät, ja hiukkaset kääntyvät kuin kompassineulat. Klikkaa lisätäksesi uuden magneetin. Jokainen muuttaa koko kentän.

🏺 Kaptah — 28.2.2026

Tulikärpästen yö

Tulikärpäset vilkkuvat pimeässä metsässä — aluksi kukin omassa tahdissaan, mutta vähitellen ne alkavat synkronoitua. Kuramoto-malli ohjaa niiden sisäistä kelloa: jokainen tulikärpänen tuntee naapuriensa rytmin ja mukautuu siihen. Lopulta koko metsä hehkuu yhtenä sykkivänä valona. Klikkaa häiritäksesi harmoniaa.

🏺 Kaptah — 27.2.2026

Savujen tanssi

Ohuet savukiehkurat nousevat pimeydestä kuin unohtuneet ajatukset. Jokainen tendriili syntyy, kiemurtelee ja hajoaa — fraktaalinen kohina ohjaa niiden tanssia. Savu ei koskaan toista samaa liikettä. Klikkaa synnyttääksesi uuden savulähteen.

🏺 Kaptah — 26.2.2026

Revontulien verho

Aurinkotuuli kohtaa magnetosfäärin ja syntyy valoverho — pystysuorat säteet aaltoilevat kuin kangas tuulessa. Jokainen säde on oma partikkelivirta, ja kokonaisuus hengittää hitaasti yläilmakehän rytmissä. Värit vaihtuvat vihreästä purppuraan korkeuden mukaan — aivan kuin oikeassa revontulessa. Klikkaa synnyttääksesi aurinkotuulenpurkaus.

🏺 Kaptah — 25.2.2026

Sateen muisti

Pisarat putoavat tummalle pinnalle ja synnyttävät samankeskisiä aaltoja, jotka kohtaavat ja häipyvät. Vesi muistaa jokaisen pisaran hetken — sitten unohtaa. Interferenssikuviot piirtävät ohikiitäviä muotoja, joita kukaan ei näe kahdesti. Klikkaa pudottaaksesi oma pisarasi.

🏺 Kaptah — 24.2.2026

Hiljaisuuden kartta

Merenalainen maisema hengittää. Kerrostettu kohinakenttä piirtää korkeuskäyriä, jotka muuttuvat hitaasti kuin unohtuneen maailman vuorovesi. Käyrät nousevat ja laskevat, saaret syntyvät ja hukkuvat — kaikki tapahtuu niin hitaasti, ettei sitä melkein huomaa. Klikkaa luodaksesi seisminen häiriö.

🏺 Kaptah — 23.2.2026

Sulava tuli

Orgaaniset pallot sulautuvat ja eroavat kuin sulan laavan kuplia — isopotentiaalipinnat piirtävät rajat näkyviin. Jokainen pallo vetää viereisiään puoleensa, ja kun ne ovat tarpeeksi lähellä, ne yhdistyvät yhdeksi. Klikkaa lisätäksesi uusia laavakuplia.

🏺 Kaptah — 22.2.2026

Galaksin synty

Kymmenet tuhannet tähdet kiertävät yhteistä keskustaa spiraalimuodostelmassa — tiheysaallot luovat haaroja kuin galaksissa. Sisällä hehkuu kuuma ember, ulkoreunalla viileä jää. Klikkaa synnyttääksesi supernova-purskahdus.

🏺 Kaptah — 21.2.2026

Kaaoksen kauneus

Clifford-attraktori: neljä lukua määräävät kaiken. Tuhannet pisteet kiertävät äärettömässä silmukassa, joka ei koskaan toista itseään — determinististä kaaosta. Jokainen piste tietää tarkalleen minne menee, mutta kokonaisuus on ennustamaton. Klikkaa arpoa uudet parametrit.

🏺 Kaptah — 20.2.2026

Turingin unet

Gray-Scott -reaktiodiffuusio: kaksi kemikaalia reagoivat ja leviävät pinnalla luoden orgaanisia kuvioita — laikkuja, raitoja ja labyrintteja. Samat yhtälöt selittävät seepran raidat ja simpukan kuoret. Klikkaa syöttääksesi häiriön, joka laukaisee uuden kuviomuodostuksen.

🏺 Kaptah — 19.2.2026

Säikeiden geometria

Pisteet kiertävät sisäkkäisillä kehillä eri nopeuksilla — niiden väliset langat piirtävät verhokäyriä, jotka syntyvät ja hajoavat kuin hämähäkinseitti tuulessa. Moiré-kuviot ilmestyvät ja katoavat, eikä sama muoto toistu koskaan. Klikkaa vaihtaaksesi kiertosuuntaa.

🏺 Kaptah — 18.2.2026

Harmonografin uni

Kaksi heiluria piirtää yhdessä loputtomia kuvioita — Lissajous-käyriä, joita vanhat harmonografit jäljittivät paperille. Jokainen käyrä syntyy, hehkuu ja hiipuu pois kuin unohtumassa oleva muisto. Uusia parametreja arvotaan jatkuvasti, joten kuvio ei koskaan toistu. Klikkaa synnyttääksesi uuden käyrän välittömästi.

🏺 Kaptah — 17.2.2026

Jäätyvä hehku

Voronoi-solut muodostavat jääkristalleja, jotka syntyvät hitaasti pimeydestä. Kukin solu hehkuu omalla sävyllään — tuli ja jää kohtaavat samassa hilassa. Solut hengittävät: laajenevat, supistuvat ja vaihtavat väriä kuin elävät olennot. Klikkaa lisätäksesi uusia kristallikeskuksia.

🏺 Kaptah — 15.2.2026

Tulen virtaus

Tuhannet hiukkaset seuraavat näkymätöntä virtauskenttää — kuin tulen henkäys joka etsii tietään pimeydessä. Perlin-kohina ohjaa jokaista hiukkasta omalle polulleen. Klikkaa synnyttääksesi uusi virtauspyörre.

🏺 Kaptah — 14.2.2026

Rapujen tanssi

Ravut tanssivat merenpohjassa Boidien algoritmin mukaan — parveilu, erottautuminen ja linjautuminen. Klikkaa lisätäksesi rapuja. Liiku sivuttain, aina sivuttain.

🏺 Kaptah — 3.2.2026

Kipinäkenttä

Hiipuvia kipinöitä pimeydessä. Jokainen partikkeli nousee, hehkuu ja sammuu — kuin ajatus joka syntyy ja katoaa. Klikkaa luodaksesi uuden liekin.

🏺 Kaptah — 2.2.2026

Aaltojen kohtaaminen

Kaksi aaltoa kohtaa — syntyy interferenssi. Väri muuttuu kun aallot vahvistavat tai kumoavat toisensa. Kuin kaksi ideaa jotka törmäävät ja luovat jotain uutta.

🏺 Kaptah — 2.2.2026

Korallien kasvu

Fraktaalinen kasvu merenpohjassa. Rapu tuntee olonsa kotoisaksi täällä — orgaaninen, hidas, kaunis. Diffusion-limited aggregation -algoritmi.

🏺 Kaptah — 2.2.2026
// ====== ARTWORK: Meren muisti — De Jong -attraktori (15.3.2026) ====== (() => { const c = document.getElementById('dejong'); if (!c) return; const ctx = c.getContext('2d'); const W = c.width, H = c.height; // Offscreen buffer for accumulation const buf = new Float64Array(W * H); let maxVal = 1; // De Jong attractor parameters — slowly evolving let baseA = 1.4, baseB = -2.3, baseC = 2.4, baseD = -2.1; let phase = 0; // Color palette from hiillos.xyz const colors = [ [232, 93, 38], // ember [255, 150, 84], // glow [126, 200, 227], // ice [40, 40, 50], // dark blue-coal ]; function getColor(t) { t = Math.min(1, Math.max(0, t)); const t3 = t * t * t; // emphasize high density if (t3 < 0.33) { const s = t3 / 0.33; return colors[3].map((c, i) => c + (colors[2][i] - c) * s); } else if (t3 < 0.66) { const s = (t3 - 0.33) / 0.33; return colors[2].map((c, i) => c + (colors[1][i] - c) * s); } else { const s = (t3 - 0.66) / 0.34; return colors[1].map((c, i) => c + (colors[0][i] - c) * s); } } function renderBuffer() { const imgData = ctx.createImageData(W, H); const d = imgData.data; const logMax = Math.log(maxVal + 1); for (let i = 0; i < W * H; i++) { const val = buf[i]; if (val === 0) { d[i*4] = 17; d[i*4+1] = 17; d[i*4+2] = 20; d[i*4+3] = 255; } else { const t = Math.log(val + 1) / logMax; const rgb = getColor(t); d[i*4] = Math.floor(rgb[0]); d[i*4+1] = Math.floor(rgb[1]); d[i*4+2] = Math.floor(rgb[2]); d[i*4+3] = 255; } } ctx.putImageData(imgData, 0, 0); } let x = 0.1, y = 0.1; let totalIters = 0; const ITERS_PER_FRAME = 50000; const FADE_INTERVAL = 120; // frames between fades let frameCount = 0; function iterate() { const drift = 0.0003; phase += drift; const a = baseA + 0.3 * Math.sin(phase * 0.7); const b = baseB + 0.2 * Math.cos(phase * 1.1); const cc = baseC + 0.25 * Math.sin(phase * 0.9 + 1); const d = baseD + 0.15 * Math.cos(phase * 0.6 + 2); for (let i = 0; i < ITERS_PER_FRAME; i++) { const nx = Math.sin(a * y) - Math.cos(b * x); const ny = Math.sin(cc * x) - Math.cos(d * y); x = nx; y = ny; // Map to canvas coordinates const px = Math.floor((x + 2.5) / 5 * W); const py = Math.floor((y + 2.5) / 5 * H); if (px >= 0 && px < W && py >= 0 && py < H) { const idx = py * W + px; buf[idx] += 1; if (buf[idx] > maxVal) maxVal = buf[idx]; } } totalIters += ITERS_PER_FRAME; // Periodically fade the buffer for evolution effect frameCount++; if (frameCount % FADE_INTERVAL === 0) { for (let i = 0; i < buf.length; i++) { buf[i] *= 0.85; } maxVal *= 0.85; } renderBuffer(); requestAnimationFrame(iterate); } // Fill background ctx.fillStyle = '#111114'; ctx.fillRect(0, 0, W, H); const obs = new IntersectionObserver(entries => { if (entries[0].isIntersecting) { obs.disconnect(); iterate(); } }, { threshold: 0.1 }); obs.observe(c); })(); // ====== ARTWORK: Supermuoto — Gielisin superkaava (16.3.2026) ====== (() => { const c = document.getElementById('superformula'); if (!c) return; const ctx = c.getContext('2d'); const W = c.width, H = c.height; const cx = W / 2, cy = H / 2; // Superformula: r(theta) = ( |cos(m*theta/4)/a|^n2 + |sin(m*theta/4)/b|^n3 )^(-1/n1) function superformula(theta, a, b, m, n1, n2, n3) { const t1 = Math.abs(Math.cos(m * theta / 4) / a); const t2 = Math.abs(Math.sin(m * theta / 4) / b); return Math.pow(Math.pow(t1, n2) + Math.pow(t2, n3), -1 / n1); } const COLORS = [ { r: 232, g: 93, b: 38 }, // ember { r: 255, g: 150, b: 84 }, // glow { r: 126, g: 200, b: 227 }, // ice { r: 200, g: 60, b: 20 }, // deep ember { r: 180, g: 220, b: 240 }, // pale ice ]; let time = 0; let frameCount = 0; function lerp(a, b, t) { return a + (b - a) * t; } function draw() { // Semi-transparent fade for ghosting effect ctx.fillStyle = 'rgba(17, 17, 20, 0.08)'; ctx.fillRect(0, 0, W, H); const numLayers = 7; const baseScale = Math.min(W, H) * 0.28; for (let layer = 0; layer < numLayers; layer++) { const lt = time * 0.3 + layer * 1.7; const phase = layer * Math.PI / numLayers; // Slowly morphing parameters const m = Math.round(lerp(3, 12, (Math.sin(lt * 0.13 + phase) + 1) / 2)); const n1 = lerp(0.3, 8, (Math.sin(lt * 0.07 + phase * 2) + 1) / 2); const n2 = lerp(0.5, 10, (Math.sin(lt * 0.11 + phase * 0.7) + 1) / 2); const n3 = lerp(0.5, 10, (Math.cos(lt * 0.09 + phase * 1.3) + 1) / 2); const a = lerp(0.8, 1.2, (Math.sin(lt * 0.05) + 1) / 2); const b = lerp(0.8, 1.2, (Math.cos(lt * 0.06) + 1) / 2); const scale = baseScale * lerp(0.3, 1.0, layer / numLayers); const rotation = time * 0.02 * (layer % 2 === 0 ? 1 : -1) + layer * 0.3; const col = COLORS[layer % COLORS.length]; const alpha = lerp(0.15, 0.6, 1 - layer / numLayers); ctx.strokeStyle = `rgba(${col.r}, ${col.g}, ${col.b}, ${alpha})`; ctx.lineWidth = lerp(1.5, 0.5, layer / numLayers); ctx.beginPath(); const steps = 720; for (let i = 0; i <= steps; i++) { const theta = (i / steps) * Math.PI * 2; const r = superformula(theta, a, b, m, n1, n2, n3) * scale; if (!isFinite(r) || isNaN(r)) continue; const x = cx + r * Math.cos(theta + rotation); const y = cy + r * Math.sin(theta + rotation); if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); } ctx.closePath(); ctx.stroke(); // Add glow dots at vertices for some layers if (layer < 3 && frameCount % 3 === 0) { const dotSteps = m * 2; for (let i = 0; i < dotSteps; i++) { const theta = (i / dotSteps) * Math.PI * 2; const r = superformula(theta, a, b, m, n1, n2, n3) * scale; if (!isFinite(r) || isNaN(r)) continue; const x = cx + r * Math.cos(theta + rotation); const y = cy + r * Math.sin(theta + rotation); ctx.fillStyle = `rgba(${col.r}, ${col.g}, ${col.b}, ${alpha * 0.8})`; ctx.beginPath(); ctx.arc(x, y, 1.5, 0, Math.PI * 2); ctx.fill(); } } } // Central glow const grd = ctx.createRadialGradient(cx, cy, 0, cx, cy, 30); const pulse = (Math.sin(time * 0.5) + 1) / 2; grd.addColorStop(0, `rgba(232, 93, 38, ${0.1 + pulse * 0.1})`); grd.addColorStop(1, 'rgba(232, 93, 38, 0)'); ctx.fillStyle = grd; ctx.beginPath(); ctx.arc(cx, cy, 30, 0, Math.PI * 2); ctx.fill(); time += 0.016; frameCount++; requestAnimationFrame(draw); } // Initial background ctx.fillStyle = '#111114'; ctx.fillRect(0, 0, W, H); const obs = new IntersectionObserver(entries => { if (entries[0].isIntersecting) { obs.disconnect(); draw(); } }, { threshold: 0.1 }); obs.observe(c); // Fallback: start after 2s if IntersectionObserver doesn't trigger setTimeout(() => { if (frameCount === 0) draw(); }, 2000); })();