{
  "schemaVersion": 1,
  "id": "hypnotic-tunnel-title",
  "version": "1.0.0",
  "status": "published",
  "kind": "example",
  "title": "Hypnotic Tunnel Title",
  "summary": "Fly through a neon particle tunnel while your title springs into place in the middle.",
  "description": "An intro you can make your own in seconds: a twisting tunnel of colourful light streaks rushes past while a bold title rises letter by letter, with an underline and a subtitle. Type your words, pick the colours and the speed. Plain browser JavaScript (Canvas 2D) — no React, no frameworks.",
  "role": "Complete example scene.",
  "collections": [
    "hypnotic-loops",
    "kinetic-text",
    "particles"
  ],
  "tags": [
    "tunnel",
    "title",
    "intro",
    "particles",
    "text",
    "neon",
    "warp",
    "2d",
    "canvas",
    "example",
    "hypnotic"
  ],
  "synonyms": [
    "hypnotic tunnel with title",
    "intro animation",
    "title over particles",
    "warp intro",
    "launch intro",
    "youtube intro"
  ],
  "useCases": [
    "Video intro or channel opener",
    "Launch announcement",
    "Event or episode title card"
  ],
  "featured": 0,
  "publishedAt": "2026-10-02",
  "uses": [
    {
      "id": "particle-tunnel",
      "version": "1.0.0",
      "role": "Animated background layer."
    },
    {
      "id": "kinetic-title",
      "version": "1.0.0",
      "role": "Title reveal layer on top."
    }
  ],
  "implementation": {
    "target": "canvas2d",
    "runtime": "browser",
    "language": "javascript",
    "module": "esm",
    "entry": "demo.js",
    "exports": [
      {
        "name": "createDemo",
        "signature": "createDemo({ canvas, width, height, params, fps, duration }) => { renderFrame(info), dispose() }",
        "description": "Draws the two layers each frame."
      }
    ],
    "reusable": [],
    "demo": "demo.js",
    "harness": "index.html"
  },
  "dependencies": [
    {
      "id": "particle-tunnel",
      "version": "1.0.0",
      "reason": "Background layer."
    },
    {
      "id": "kinetic-title",
      "version": "1.0.0",
      "reason": "Title layer."
    },
    {
      "id": "apw-runtime",
      "version": "1.0.0",
      "reason": "Harness and export tools."
    }
  ],
  "params": [
    {
      "key": "text",
      "label": "Title",
      "type": "text",
      "default": "INTO THE FLOW",
      "maxLength": 40,
      "sensitive": true
    },
    {
      "key": "subtitle",
      "label": "Subtitle",
      "type": "text",
      "default": "Episode 01",
      "maxLength": 60,
      "sensitive": true
    },
    {
      "key": "titleDelay",
      "label": "Title appears after (s)",
      "type": "number",
      "min": 0,
      "max": 4,
      "step": 0.1,
      "default": 1.2
    },
    {
      "key": "hue",
      "label": "Tunnel colour",
      "type": "number",
      "min": 0,
      "max": 360,
      "step": 1,
      "default": 280
    },
    {
      "key": "colorSpread",
      "label": "Colour spread",
      "type": "number",
      "min": 0,
      "max": 360,
      "step": 5,
      "default": 200
    },
    {
      "key": "speed",
      "label": "Speed",
      "type": "integer",
      "min": 1,
      "max": 4,
      "step": 1,
      "default": 2
    },
    {
      "key": "twist",
      "label": "Twist",
      "type": "integer",
      "min": -2,
      "max": 2,
      "step": 1,
      "default": 1
    },
    {
      "key": "accent",
      "label": "Underline colour",
      "type": "color",
      "default": "#ff6fb5"
    },
    {
      "key": "background",
      "label": "Background",
      "type": "color",
      "default": "#04030a"
    }
  ],
  "presets": [
    {
      "id": "default",
      "label": "Neon intro",
      "params": {}
    },
    {
      "id": "ember",
      "label": "Ember",
      "params": {
        "hue": 10,
        "colorSpread": 50,
        "accent": "#ffd166",
        "twist": 0
      }
    },
    {
      "id": "ice",
      "label": "Ice",
      "params": {
        "hue": 185,
        "colorSpread": 60,
        "accent": "#7cf7ff",
        "speed": 1
      }
    }
  ],
  "output": {
    "width": 1080,
    "height": 1080,
    "fps": 30,
    "durationSeconds": 6,
    "posterSeconds": 4,
    "alpha": false,
    "motion": "procedural",
    "loop": {
      "seamless": false,
      "method": "The background loops, but the title reveal plays once."
    },
    "seed": null
  },
  "composition": {
    "inputs": "Parameters only.",
    "outputs": "A Canvas 2D frame.",
    "coordinates": "Pixels.",
    "lighting": "Additive tunnel, darkened centre for readability.",
    "timing": "Pure function of time/progress.",
    "compatibleWith": [],
    "notes": [
      "Works without React, Remotion or a bundler: one HTML file plus ES modules."
    ]
  },
  "reuse": [
    "Replace the title with Rolling Number Counter for a milestone intro.",
    "Use only the tunnel layer behind your own HTML/CSS text.",
    "Change the canvas size to 1920×1080 or 1080×1920; the layout adapts."
  ],
  "integration": {
    "newProject": "Download the pack, npm install, npm run serve and open hypnotic-tunnel-title/1.0.0/index.html. Export with npm run render -- hypnotic-tunnel-title/1.0.0 --param text=\"YOUR TITLE\".",
    "existingProject": "Copy the two ingredient files and call tunnel.draw then title.draw from your own canvas loop."
  },
  "performance": {
    "notes": "Light: ~1,600 line strokes and a few text draws per frame.",
    "limits": "None notable."
  },
  "limitations": [
    "Uses the system font; specify fontFamily in kinetic-title for a brand font."
  ],
  "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.",
  "changelog": [
    {
      "version": "1.0.0",
      "date": "2026-10-02",
      "notes": "Initial release."
    }
  ]
}
