/** * Cumulus clouds for the generated cards. * * The shapes are overlapping circles sharing one `userSpaceOnUse` gradient, so * the silhouette reads as a single lit volume rather than a pile of discs: lit * from above, duskier along the flat base. Each puff also carries a glow that * fades to nothing, which is what keeps the silhouette soft at its edges. * * No blur filter, deliberately: resvg silently drops what it cannot render, and * a missing cloud is worse than a crisp one. */ export function cloudSvg(options: { /** Unique per SVG document, so gradients do not collide. */ uid: string; x: number; y: number; /** 1 draws a cloud about 200x120. */ scale?: number; opacity?: number; }): string { const { uid, x, y, scale = 1, opacity = 1 } = options; const puffs = [ { cx: 50, cy: 68, r: 38 }, { cx: 104, cy: 48, r: 46 }, { cx: 152, cy: 64, r: 34 }, { cx: 28, cy: 86, r: 28 }, { cx: 176, cy: 88, r: 24 }, { cx: 100, cy: 92, r: 42 }, ]; const circles = () => puffs.map((p) => ``).join(''); // A soft glow per puff, fading to nothing: two sized-up passes would read as // hard concentric outlines instead. const halo = puffs .map( (p, i) => ` ` ) .join(''); const halos = puffs .map( (p, i) => `` ) .join(''); return ` ${halo} ${halos} ${circles()} ${circles()} `; }