1. Mechanisme — kopieer 1-op-1, geen styling-keuzes
// Mechanisme: cta-shader-orb-minimal (techniek #36 — WebGL2 fragment shader)
// Monochroom radiale orb (cream/ink), geen kleur-cycle. Subtle pulse: r += sin(uTime*0.8)*0.05.
// Auto-running rAF loop. Fallback: CSS radial-gradient @keyframes pulse.
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const root = document.querySelector('.min-orb');
const cv = root.querySelector('canvas');
const fb = root.querySelector('.min-orb-fallback');
const gl = cv && cv.getContext('webgl2', { antialias:true, premultipliedAlpha:false });
if (!gl) { fb.style.display='block'; cv.style.display='none'; }
else {
const fs = "uniform float uT; ... col = mix(cream, ink, smoothstep(.4+sin(uT*0.8)*0.05, .42+..., r));"
// single-pulse render in reduced-motion mode
} 2. Skeleton — DOM + class-namen, mag herschikken
<!-- Skeleton: cta-shader-orb-minimal -->
<section class="min-cta">
<div class="min-orb">
<canvas></canvas>
<div class="min-orb-fallback" aria-hidden="true"></div>
</div>
<h2 class="min-title">A quiet beginning.</h2>
<a class="min-link" href="#">Start a conversation</a>
</section> 3. Styling-template — verplicht eigen invulling per merk
/* Styling: cta-shader-orb-minimal */
:root { --block-bg:#F4F1EB; --block-fg:#1F1A14; --block-accent:#1F1A14; }
.min-cta { background:#F4F1EB; color:#1F1A14; font-family:'Inter', system-ui, sans-serif; }
.min-orb { width:min(420px, 80vw); aspect-ratio:1; position:relative; }
.min-orb canvas { width:100%; height:100%; display:block; }
.min-orb-fallback { position:absolute; inset:0; border-radius:50%; display:none; background:radial-gradient(circle at 50% 50%, #1F1A14 0%, #1F1A14 38%, transparent 42%); animation: minPulse 4s ease-in-out infinite; }
@keyframes minPulse { 0%,100%{transform:scale(1)} 50%{transform:scale(1.05)} }
.min-title { font-size:clamp(1.75rem, 3vw, 2.5rem); font-weight:300; letter-spacing:-.02em; }
.min-link { color:#1F1A14; border-bottom:1px solid currentColor; text-decoration:none; }