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}
(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’]});});
})();
Plantae bettinae
Hold to start & shape FX (up = high-pass, left→right = reduce noise). Release to sustain. Double-click to stop.
Volume
Galactia heterophylla
Verbascum densiflorum
Phemeranthus aurantiacus