Plantae bettinae — presets + reveals :root{ –bg:#1f1a14; –panel:#2b251d; –border:#3b332a; –ink:#eadfcd; –muted:#c9bba6; –accent:#d4a373; –good:#7fb069; –cream:#f6eee0; –shadow-brown:#5a4632; } *{box-sizing:border-box} body{ margin:0; font:16px/1.5 ‘UnifrakturMaguntia’,cursive; color:var(–ink); background:var(–bg); } header{ position:relative; padding:20px 24px; border-bottom:1px solid var(–border); background:linear-gradient(180deg,rgba(212,163,115,.08),transparent); } h1{margin:0 0 6px;font-size:28px} .sub{color:var(–muted);font-size:16px} .volWrap{position:absolute;right:24px;top:16px;display:flex;align-items:center;gap:8px;color:var(–muted)} .volWrap label{font-size:14px} .volWrap input[type=”range”]{width:180px} .wrap{padding:18px} .grid{display:grid;grid-template-columns:repeat(3,minmax(220px,1fr));gap:16px} @media (max-width:1024px){.grid{grid-template-columns:1fr}} .slot{position:relative;overflow:hidden;border-radius:14px;border:1px solid var(–border);background:#17130f;padding-bottom:10px} .photoTitle{padding:10px 8px 6px;text-align:center;font-weight:600;color:var(–ink);font-size:18px} .imgBox{position:relative;height:clamp(450px,24vw,720px);background:#14110d;display:grid;place-items:center;cursor:crosshair;overflow:hidden;touch-action:none} .imgBox,.imgBox *{-webkit-user-drag:none;user-select:none} @media (max-width:600px){.imgBox{height:clamp(250px,45vw,560px)}} .imgBox img{width:100%;height:100%;object-fit:cover;display:block;pointer-events:none} .overlay{position:absolute;inset:0;pointer-events:none} .word{ position:absolute; font-size:clamp(18px,2vw,28px); font-style:normal; color:var(–cream); text-shadow: -1px -1px 1px var(–shadow-brown), 1px -1px 1px var(–shadow-brown), -1px 1px 1px var(–shadow-brown), 1px 1px 1px var(–shadow-brown), 0 0 4px rgba(90,70,50,.8); opacity:0; transition:opacity 1.2s ease; } .word.revealed{opacity:1} .word.fadeout{opacity:0;transition-duration:5s} .word.pube{left:12px;top:12px} .word.stellata{left:50%;top:50%;transform:translate(-50%,-50%)} .word.laxa{left:8%;top:55%} .word.cinerea{right:12px;bottom:12px} .s0.radice{left:50%;transform:translateX(-50%);bottom:16px} .s0.seminibus{left:50%;top:45%;transform:translateX(-10%)} .s0.lineis{left:65%;bottom:18%} .s0.striis{left:20%;top:22%} .s0.eleganter{right:12px;top:12px} .s2.legumine{left:48%;top:48%} .s2.puberulo{left:12px;bottom:16px} .s2.recto{left:12px;bottom:44px} .s2.inferne{left:12px;top:12px} .s2.spermo{right:12px;top:12px} .summary{display:none} .playing .imgBox{outline:3px solid var(–good);outline-offset:-3px} footer{padding:16px;color:var(–muted);text-align:center;font-size:16px}

Plantae bettinae

Hold to start & shape FX (up = high-pass, left→right = reduce noise). Release to sustain. Double-click to stop.
Volume
Galactia heterophylla
Galactia heterophylla
radice tuberosa seminibus lineis gyratis carinatis striis tenuissimis transversis eleganter notatis
Verbascum densiflorum
Verbascum densiflorum
pube stellata laxa cinerea
Phemeranthus aurantiacus
Phemeranthus aurantiacus
legumine puberulo recto inferne angustato 3–6 spermo
Built with the Web Audio API (triangle oscillators). Multiple images can play at once.
(function(){ var NOTES=[‘C’,’C#’,’D’,’Eb’,’E’,’F’,’F#’,’G’,’Ab’,’A’,’Bb’,’B’]; var STEMS={maj:[0,4,7],maj7:[0,4,7,11],min:[0,3,7],min7:[0,3,7,10],aug5:[0,4,8],aug7:[0,4,8,10],dim5:[0,4,6]}; var PRESETS=[{root:’B’,stem:’maj7′},{root:’Eb’,stem:’min’},{root:’F#’,stem:’maj’}]; var ATTACK=0.5, RELEASE=5.0; var AudioContext=window.AudioContext||window.webkitAudioContext; var ctx=new AudioContext(); var masterGain=ctx.createGain(); masterGain.gain.value=0.6; masterGain.connect(ctx.destination); document.getElementById(‘vol’).addEventListener(‘input’,function(e){masterGain.gain.value=parseFloat(e.target.value);}); var slots=[].slice.call(document.querySelectorAll(‘.slot’)).map(function(el,idx){ return {el:el,idx:idx,assignment:null,playing:false,voices:[],filter:null,noiseSrc:null,noiseGain:null,busGain:null,dragActive:false, fx:{openFrac:0.5,noiseFrac:0.0,lastChange:performance.now()}, timers:{play15:null,cinereaStart:null,closed75Start:null,noise80Start:null,openFullStart:null}, quadsVisited:new Set(),quadLaps:0}; }); function createWhiteNoiseBuffer(){ var length=ctx.sampleRate*2; var buf=ctx.createBuffer(1,length,ctx.sampleRate); var d=buf.getChannelData(0); for(var i=0;i72) rootMidi-=12; while(rootMidieps||Math.abs(noiseFrac-slot.fx.noiseFrac)>eps){ slot.fx.openFrac=openFrac; slot.fx.noiseFrac=noiseFrac; slot.fx.lastChange=performance.now(); } return {xc:xc,yc:yc,rect:r,ex:e.clientX,ey:e.clientY}; } function handlePointerReveal(slot,fx){ var i=slot.idx; if(i===1){ var rect=fx.rect, ex=fx.ex, ey=fx.ey, xc=fx.xc; var brX=rect.right-ex, brY=rect.bottom-ey; if(brX<=30 && brY<=30) revealWord(1,'pube'); var tlX=ex-rect.left, tlY=ey-rect.top; if(tlX<=30 && tlY<=30) revealWord(1,'stellata'); if(slot.playing && xc=7000) revealWord(1,’cinerea’); }else{ slot.timers.cinereaStart=null; } } if(i===0){ var rect0=fx.rect, ex0=fx.ex, ey0=fx.ey; var topCenterX=rect0.left+rect0.width/2, topCenterY=rect0.top; var dx=ex0-topCenterX, dy=ey0-topCenterY; if(Math.hypot(dx,dy)<=20) revealWord(0,'seminibus'); var qx=(ex0<rect0.left+rect0.width/2)?0:1; var qy=(ey0=2) revealWord(0,’lineis’); } } } if(i===2){ var rect2=fx.rect, ex2=fx.ex, ey2=fx.ey; var centerRightX=rect2.right, centerRightY=rect2.top+rect2.height/2; var dx2=ex2-centerRightX, dy2=ey2-centerRightY; if(Math.hypot(dx2,dy2)=2){revealWord(0,’eleganter’);} if(playingCount===3){revealWord(2,’spermo’);} } function tick(){ updateGlobalReveals(); var now=performance.now(); slots.forEach(function(slot){ if(!slot.playing){ if(slot.idx===1) slot.timers.cinereaStart=null; return; } if(slot.idx===0){ if(slot.fx.openFrac=3000) revealWord(0,’radice’); }else{ slot.timers.closed75Start=null; } if(now-slot.fx.lastChange>=4000) revealWord(0,’striis’); } if(slot.idx===2){ if(slot.fx.noiseFrac>=0.8){ if(!slot.timers.noise80Start) slot.timers.noise80Start=now; if(now-slot.timers.noise80Start>=4000) revealWord(2,’puberulo’); }else{ slot.timers.noise80Start=null; } if(now-slot.fx.lastChange>=3000) revealWord(2,’recto’); if(slot.fx.openFrac>=0.95){ if(!slot.timers.openFullStart) slot.timers.openFullStart=now; if(now-slot.timers.openFullStart>=2000) revealWord(2,’inferne’); }else{ slot.timers.openFullStart=null; } } }); requestAnimationFrame(tick); } requestAnimationFrame(tick); var observer=new MutationObserver(function(){updateGlobalReveals();}); slots.forEach(function(s){observer.observe(s.el,{attributes:true,attributeFilter:[‘class’]});}); })();