{
  "schemaVersion": 1,
  "id": "confetti-burst",
  "version": "1.0.0",
  "status": "published",
  "kind": "effect",
  "title": "Confetti Burst",
  "summary": "A cannon fires hundreds of tumbling paper confetti in the party colours: they fly, flutter and drift down. One-shot, seeded and exact.",
  "description": "A celebration: a cannon at the bottom of the frame fires hundreds of pieces of paper confetti. Each piece is a small rectangle, ribbon or disc with its own colour, speed and spin; it flies on an arc with air drag, tumbles in 3D (it thins to a line when edge-on and darkens on its underside) and flutters down. Choose the number of pieces, the colours (party, gold, pastel or mono), the launch (one cannon, two corner cannons or a shower from above), the power, the seed and the backdrop colour.",
  "role": "Effect overlay (Canvas 2D): the celebration moment for wins, launches and milestones.",
  "collections": [
    "particles",
    "satisfying"
  ],
  "tags": [
    "confetti",
    "celebration",
    "party",
    "burst",
    "cannon",
    "paper",
    "particles",
    "win",
    "launch",
    "effect"
  ],
  "synonyms": [
    "party popper",
    "confetti cannon",
    "confetti explosion",
    "celebration effect",
    "ticker tape",
    "streamers"
  ],
  "useCases": [
    "A win, milestone or launch moment",
    "A birthday, holiday or event greeting",
    "A reveal that needs a pop"
  ],
  "featured": null,
  "publishedAt": "2026-10-08",
  "implementation": {
    "target": "canvas2d",
    "runtime": "browser",
    "language": "javascript",
    "module": "esm",
    "entry": "src/confetti-burst.js",
    "exports": [
      {
        "name": "createConfettiBurst",
        "signature": "createConfettiBurst({ pieces?, palette?, at?, mode?, power?, seed? }) => { draw(ctx, info, width, height), revealDuration }",
        "description": "Canvas 2D effect layer driven by info.time (seconds); draws on top of the canvas."
      },
      {
        "name": "PALETTES",
        "signature": "PALETTES: { party, gold, pastel, mono }",
        "description": "Confetti colour sets."
      }
    ],
    "reusable": [
      "src/confetti-burst.js"
    ],
    "demo": "demo.js",
    "harness": "index.html"
  },
  "dependencies": [
    {
      "id": "apw-runtime",
      "version": "1.0.0",
      "scope": "demo",
      "reason": "Demo harness. The reusable source has no dependencies."
    }
  ],
  "params": [
    {
      "key": "pieces",
      "label": "Pieces",
      "type": "integer",
      "min": 60,
      "max": 900,
      "step": 10,
      "default": 420
    },
    {
      "key": "palette",
      "label": "Colours",
      "type": "select",
      "default": "party",
      "options": [
        {
          "value": "party",
          "label": "Party"
        },
        {
          "value": "gold",
          "label": "Gold"
        },
        {
          "value": "pastel",
          "label": "Pastel"
        },
        {
          "value": "mono",
          "label": "Mono"
        }
      ]
    },
    {
      "key": "mode",
      "label": "Launch",
      "type": "select",
      "default": "cannon",
      "options": [
        {
          "value": "cannon",
          "label": "One cannon"
        },
        {
          "value": "twin",
          "label": "Two cannons"
        },
        {
          "value": "rain",
          "label": "Shower from above"
        }
      ]
    },
    {
      "key": "power",
      "label": "Power",
      "type": "number",
      "min": 0.6,
      "max": 1.5,
      "step": 0.1,
      "default": 1
    },
    {
      "key": "seed",
      "label": "Seed",
      "type": "integer",
      "min": 1,
      "max": 999,
      "step": 1,
      "default": 21
    },
    {
      "key": "background",
      "label": "Backdrop",
      "type": "color",
      "default": "#1b1530"
    }
  ],
  "presets": [
    {
      "id": "default",
      "label": "Party cannon",
      "params": {}
    },
    {
      "id": "gold",
      "label": "Gold, two cannons",
      "params": {
        "palette": "gold",
        "mode": "twin",
        "background": "#14110a"
      }
    },
    {
      "id": "pastel",
      "label": "Pastel shower",
      "params": {
        "palette": "pastel",
        "mode": "rain",
        "pieces": 300,
        "background": "#2a2540"
      }
    },
    {
      "id": "mono",
      "label": "Mono, big blast",
      "params": {
        "palette": "mono",
        "power": 1.4,
        "pieces": 700,
        "background": "#101218"
      }
    }
  ],
  "output": {
    "width": 1080,
    "height": 1080,
    "fps": 30,
    "durationSeconds": 6,
    "posterSeconds": 1.4,
    "alpha": false,
    "motion": "procedural",
    "loop": {
      "seamless": false,
      "method": "Not a loop: the burst fires at 0.6 s and the pieces fall out of frame."
    },
    "seed": {
      "param": "seed",
      "behavior": "Seed gives every piece its colour, shape, speed, spin and flutter: same seed, same burst."
    }
  },
  "composition": {
    "inputs": "Canvas 2D context, info.time (seconds), width, height.",
    "outputs": "Draws the confetti on top of the canvas; does not clear it.",
    "coordinates": "Positions are fractions of the canvas; the cannon is at the bottom centre (or the corners), the shower starts above the top edge; sizes scale with the smaller side.",
    "lighting": "None; undersides are drawn darker.",
    "timing": "Pure function of time since the burst and a seeded number per piece; revealDuration says when the last piece has gone.",
    "compatibleWith": [
      "kinetic-title",
      "gradient-background"
    ],
    "notes": [
      "Each piece follows v(t) = v0 e^(−kt) with a terminal fall speed, so frames can be rendered in any order."
    ]
  },
  "reuse": [
    "Win moment: Party cannon.",
    "Premium launch: Gold, two cannons.",
    "Soft greeting: Pastel shower."
  ],
  "integration": {
    "newProject": "Create the burst once, then each frame draw your picture and call burst.draw(ctx, { time: frame / fps }, width, height).",
    "existingProject": "Copy src/confetti-burst.js. Call draw on your existing 2D canvas after the rest of the frame."
  },
  "performance": {
    "notes": "Up to 900 small shapes per frame; about 2 ms on an integrated GPU.",
    "limits": "The frame is not cleared; call it after your backdrop."
  },
  "limitations": [
    "Pieces do not collide or pile up on the ground; they leave the frame.",
    "The 3D tumble is simulated by squashing flat shapes, not true 3D."
  ],
  "license": {
    "spdx": "MIT",
    "notice": "Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder.",
    "thirdParty": []
  },
  "provenance": "Original code written for AI Pixel Wizard in October 2026, to the catalog quality bar (docs/QUALITY.md).",
  "changelog": [
    {
      "version": "1.0.0",
      "date": "2026-10-08",
      "notes": "Initial release."
    }
  ]
}
