Every cloud (and root) gets a header. Real image > Keeper opt-out gradient > a designed per-cloud placeholder. AI generation is the upgrade path.
A Cloud should never read as blank just because its Keeper has not yet uploaded or generated a header. As of v2.2.197 every cloud has a header by default. Engine: includes/cloud-header-ai.php.
cloudHeaderTopCss($img,$src,$name,$c1,$c2))header_image_url set) → the image with a gentle legibility overlay.header_image_source = 'none') → a plain brand-color gradient.This is a deliberate manual choice (a "No header image" checkbox in the cloud editor), never the default.
cloudHeaderPlaceholderSvg($name,$c1,$c2) builds an SVG from the cloud's own brand colors: a diagonal gradient, a soft light bloom, a seeded ring motif (deterministic per cloud via crc32(name) so each differs), and a faint serif monogram of the cloud's first letter. Served as a data URI (cloudHeaderPlaceholderDataUri()), so it costs nothing and renders immediately. Used on the Discover Clouds cards (includes/discover-clouds.php).
cloudGenerateHeader($cloudId,$provider) composes a header from the cloud's vibe (type, niches, place, colors), never a literal image, via GPT Image or Gemini Nano Banana 2 (v2.2.11). Per-cloud "Generate AI header" lives in the cloud editor; a batch "Generate missing headers" (Admin → Clouds) backfills clouds with none, capped per run because each call costs an image credit (operator-triggered, respecting API-cost discipline). The placeholder fills the gap until an AI or uploaded image lands.
Decision: headers are on by default (placeholder), opting out is manual, real images are the goal. Taste first, no blanks, no surprise spend.
Distinct from the header IMAGE above: the animated cloud LAYER over the hero gradient. includes/cloud-texture.php → cloudTextureLayer() (drop-in on cloud-directory, discover-clouds, cloud-create, me-cloud). A WebGL fragment shader — fractal noise (fbm) + domain warping, animated by time — so the clouds genuinely FLOW and morph (not a panning texture). Inspired by OpenAI's GPT-Live hero backdrop, rebuilt from scratch.
Every look is a uniform, driven from the my.doozer.cloud vibe controls:
--c1/--c2) → cloud colour; call window.dzClouds.refreshPalette().window.dzClouds.setEnergy(n) (speed + vividness).window.dzClouds.set({storm}) rampswarp amplitude, turbulence, speed, and contrast.
set({speed,vivid,tintAmt}); all persist to localStorage.Responsible: DPR capped 1.75, low-power, paused when the tab is hidden or the header is off-screen (IntersectionObserver). Graceful fallback: no WebGL or prefers-reduced-motion → the original two-layer SVG fractalNoise texture (cloudTextureSvgUri), kept intact. Self-contained, no CDN.