Skip to main content
Glama

Version License Docker MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework


Overview

Divoom Pixoo LED matrix displays on the local network, with the Pixoo-64 as the primary target and the 16 and 32 also supported. Render and push styled text, layered scenes, dashboards, animations, and HTML pages, or read and change device state.

Tools

Tool

Description

pixoo_display_text

Render styled text with themes, gradients, shadows, and auto-fit, static or animated, and push it

pixoo_compose_scene

Compose layered scenes of text, icons, widgets, shapes, bitmaps, images, and sprites, static or animated

pixoo_push_image

Resize a local or https image to the LED grid and push it, an animated GIF or WebP as an animation

pixoo_render_html

Render an HTML page (CSS, SVG, Canvas, WebGL) in a headless browser at the panel size, still or animated frame by frame on a virtual clock, and push it

pixoo_overlay_text

Set or clear a device-rendered scrolling text overlay

pixoo_control_device

Read or change brightness, screen state, channel, or clock face

pixoo_discover_devices

Find Pixoo devices and their LAN IPs through Divoom's cloud discovery

pixoo_design_brief

Craft guidance for a design topic, with live device state and pre-filled next calls

Resources

Resource

Description

pixoo://device/status

Live device snapshot: reachability, channel, brightness, screen state, display size

pixoo://reference/themes

Theme and palette registry

pixoo://reference/icons

Built-in icon names by category

pixoo://reference/design-guide

Long-form craft guide for the 64px display

Tools cover the same ground for tool-only clients: pixoo_control_device reads the live device state, and pixoo_design_brief returns craft guidance, theme names, and icon names.

Related MCP server: mcp-divoom-lan

Capability reference

pixoo_display_text tool

  • text as a string or an array of lines; theme (midnight, ember, claude, ice, neon, forest, mono) sets the background and default palette. style takes a palette ramp (ember, ice, neon, fire, lavender, claude, mono) or a custom { from, to }, plus shadow, outline, and scale 1–8; position is semantic or in pixels, and align lines up multi-line text

  • font: standard (5×7) and compact (3×5) draw printable ASCII plus ° ← ↑ → ↓ ▲ ▼ ♥ · …, and any other character (€, ’, a newline inside one string) as ?, named with its code point and line index in the response notice; numerals is an 11×18 digit face for clocks and readouts that draws 0–9, space, and : . - + / % ° ?, and text holding any other character fails validation, naming those characters

  • layout[] reports every fit decision as an action (shrunk-to-compact when the text fits only in the compact font, scrolling when the returned frames scroll, none otherwise), the font used, and whether each line's box fits on the panel; a single line too wide for the panel starts at x 0, cut at the right edge when it does not scroll. Single-line text falls back from the standard to the compact font unless font is set — never to numerals — and text still too wide only scrolls under effect: "auto" or "scroll"

  • effect: scroll makes one pass in up to 40 frames, auto scrolls only on overflow, and float and pulse loop over 20 frames; frames reports the count, and the animation pushes as one device animation


pixoo_compose_scene tool

  • Up to 50 elements drawn back-to-front: text (in the same three fonts as pixoo_display_text), icon, rect, circle, line, progress, sparkline, bitmap, pixels, image (absolute path or https URL, with the same finish as pixoo_push_image), sprite (absolute path). The background is a solid color, a v / h / r gradient, or a theme

  • Every element takes opacity (each pixel lands at its own alpha × opacity, so soft edges fade evenly) and blend: normal, add (glows and light beams), screen, or multiply. line and outline circle take strokeWidth and antialias, and a rect border takes strokeWidth, growing inward; either field on a shape that draws no stroke fails validation, naming it

  • Returns layout[]: each element's placed box — for a wide or anti-aliased stroke, every pixel it draws — and whether it fits on the panel. Elements are placed as given and never refit, so action is always none. An absolute output path saves the first frame as a PNG in place of the PIXOO_OUTPUT_DIR auto-save. Typed failures: asset_not_found, invalid_image (an image or sprite that was read but does not decode), invalid_color, unknown_icon, invalid_output_path

  • Animation through per-element effect presets (float, scroll-left, scroll-right, pulse, blink, twinkle, drift, fade-in, fade-out) or raw animate keyframes over dx, dy, opacity (numbers or numeric strings), visible (true/false), and color (interpolated through RGB on any element with a color), each track holding at least one keyframe; frames 1–800, speed 10–2000 ms per frame (default 150). Past 40 frames the scene plays as one GIF the device downloads from this host, with speed rounded to 10 ms. An element takes effect or animate, not both. An effect's amplitude sets the movement of float, scroll-*, and drift, and the 0–1 depth of the pulse and twinkle opacity dip


pixoo_push_image tool

  • source is an absolute local path or an https URL, with downloads capped at 10 MB; fit is contain (default), cover, or fill, and kernel is nearest (default, for pixel art), lanczos3 (photos), or mitchell

  • A source that decodes as an animated GIF or WebP, whatever its file name, pushes as an animation of up to maxFrames frames (1–800, default 40), sampled evenly from a longer source; past 40 frames it plays as one GIF the device downloads from this host. It plays at the source's total duration over the pushed frame count (150 ms when the source records no delays), or at speed (10–2000 ms per frame); frames, sourceFrames, and speed report what was pushed

  • finish reduces the image to a palette before the push: exactly one of colors (2–256, built from the image) or palette (1–256 hex or named colors), plus dither (none, bayer4, floyd-steinberg). Transparent pixels stay unlit, and an animation's colors palette is shared by every frame

  • An unreadable path or URL fails as asset_not_found, a source that is read but does not decode (a text file, an HTML page, a truncated download) fails as invalid_image, and an unresolvable finish palette entry fails as invalid_color; the preview is the exact frame the device receives, or a grid of an animation's frames


pixoo_render_html tool

  • html is a full document or a body fragment, up to 500,000 characters, laid out in a square viewport one CSS pixel per LED. The page is the panel: body has no margin, scrollbars are hidden, and a page that paints no background renders on black (unlit). Its own CSS overrides each

  • frames 1–800 (default 1), speed 10–2000 ms per frame (default 150). Each frame advances a virtual clock by speed: window.render(t, frame), when the page defines it, runs before each capture with t = frame / frames, so periodic motion loops seamlessly; requestAnimationFrame, setTimeout / setInterval (4 ms floor for nested and repeating timers), Date (starting at the real time), and performance.now() (0 at load) follow the same clock, and CSS animations are paused and seeked to it, so two calls capture the same frames unless the page reads Math.random (unseeded) or the starting Date. requestIdleCallback and iframes keep real time. Past 40 frames the page plays as one GIF the device downloads from this host, as on pixoo_compose_scene

  • sampling: native (default) or supersample, which renders at 8× and area-averages into each LED, smoothing transforms, text, SVG, and canvas. Chromium snaps a plain box's edges to whole CSS pixels before scaling, so a box at left: 0.5px still lands on one LED; move it with transform for sub-pixel motion. finish takes the same palette reduction as pixoo_push_image, applied before the preview

  • Nothing loads from the network and workers are blocked. pageErrors returns the page's uncaught errors, console.error output, and blocked URLs (a blocked navigation as Blocked navigation: <url>): the first 20, each cut to 500 characters. A window.render that throws or rejects fails as page_error, naming the frame; with no browser found, the call fails as browser_unavailable with install steps (see Local development); render_timeout and render_crashed cover a render past 30 s and a crashed browser or page. PIXOO_HTML_ENABLED=false removes the tool

  • Every page gets a pixoo global before its own scripts run, for the crisp bitmap text, palettes, and icons that browser anti-aliasing would smear across LEDs:

    • pixoo.context() is the 2D context of a transparent panel-size canvas fixed over the page.

    • pixoo.text(ctx, text, x, y, { font, color, palette, scale, shadow, outline }) draws pixoo_display_text's fonts.

    • pixoo.icon(ctx, name, x, y, { w, h, color, palette }) draws a registry icon.

    • pixoo.palettes holds the 7 palettes, and pixoo.size is the panel size.

    Text and icons drawn this way match pixoo_compose_scene pixel for pixel in both sampling modes. An unknown palette, icon, or color throws naming it:

    <script>
      const ctx = pixoo.context();
      pixoo.text(ctx, 'HELLO', 'center', 4, { palette: 'ember', scale: 2, shadow: true });
      pixoo.icon(ctx, 'check-circle', 50, 50, { color: 'green' });
    </script>
  • pixoo_design_brief with topic html covers loops, the clock, sampling, the pixoo runtime, and legibility at 64 px. A dot orbiting the panel once per loop:

{
  "html": "<svg viewBox=\"0 0 64 64\" style=\"display:block;width:100vw;height:100vh\"><circle id=\"dot\" r=\"6\" fill=\"#ffb000\"/></svg><script>const dot = document.getElementById('dot'); window.render = (t) => { const a = 2 * Math.PI * t; dot.setAttribute('cx', 32 + 20 * Math.cos(a)); dot.setAttribute('cy', 32 + 20 * Math.sin(a)); };</script>",
  "frames": 20,
  "speed": 100,
  "sampling": "supersample"
}

pixoo_overlay_text tool

  • mode: "set" or "clear" on one of 20 slots (id 0–19). set requires text and takes a device font ID (0–114), x / y within PIXOO_SIZE, color, speed (0–100), direction, align, and width

  • Returns acknowledged, mode, and id. The device renders the overlay, so there is no preview, and it persists across channel switches until cleared


pixoo_control_device tool

  • No params reads state; any of brightness (0–100), screen (on / off), channel (faces / cloud / visualizer / custom), or clockFaceId is applied before the read-back

  • Returns reachable, channel, brightness, screenOn, and clockId (absent when unreachable) plus applied; a failed setting is left out of applied and named in the notice instead of failing the call


pixoo_discover_devices tool

  • Queries Divoom's cloud endpoint (app.divoom-gz.com), so it needs internet access; timeoutMs 1000–30000 (default 5000)

  • Returns each device's name, id, and ip; with PIXOO_IP set, configuredIpFound says whether it matched. An unreachable endpoint fails as discovery_failed


pixoo_design_brief tool

  • topic: text, scene, dashboard, animation, pixel-art, html, or troubleshooting; works without a reachable device

  • Returns markdown craftGuidance, a live deviceContext, htmlRenderer (available, disabled when PIXOO_HTML_ENABLED=false, or no_browser, found without launching a browser), nextToolSuggestions as { toolName, reason, args } with arguments pre-filled for the topic and device state, plus availableThemes and iconCategories


pixoo://device/status resource

  • Uncached live read: reachable, channel, brightness, screenOn, clockId, displaySize, configuredIp

  • Returns reachable: false rather than an error when the device can't be reached or PIXOO_IP is unset


pixoo://reference/themes resource

  • Every theme (background, textPalette, accent, shadow) and palette (from / to stops), plus themeNames and paletteNames for the theme and palette parameters

  • Static registry, cached for 24h


pixoo://reference/icons resource

  • Each icon's name, category, and viewBox, plus a byCategory grouping (weather, arrows, status, media); a name goes in a pixoo_compose_scene icon element

  • Static registry, cached for 24h


pixoo://reference/design-guide resource

  • text/markdown: legibility floors, palette discipline, layout zones, animation budget, effect presets, pixel art rules, push pacing, and known device behaviors

  • The whole guide in one document, where pixoo_design_brief returns guidance per topic; cached for 24h

Features

Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.

Pixoo-specific:

  • All composition happens on the host in an RGBA canvas pipeline (@cyanheads/pixoo-toolkit); the device receives finished RGB frames

  • Pushes switch the device to the custom channel and run one at a time, spaced by PIXOO_PUSH_MIN_INTERVAL_MS (default 1000) so rapid pushes don't freeze the device

  • Up to 40 animation frames push one request each; more frame pushes make the device unstable. Past 40, pixoo_compose_scene, pixoo_push_image, and pixoo_render_html (up to 800 frames) serve one GIF from a one-shot listener on this host, which the device downloads and loops, so the device must be able to reach this host. pixoo_display_text stays within 40

Agent-friendly output:

  • Preview on every render: pixoo_display_text, pixoo_compose_scene, pixoo_push_image, and pixoo_render_html return the frame as an 8× upscaled PNG image block, pushed or not, so push: false checks a design with no device attached. Animations preview as a grid of their frames (every frame while 1× tiles fit the 512 px sheet, an even sample past that), since GIF display varies across MCP clients; the GIF itself is saved to PIXOO_OUTPUT_DIR when set — an 8× preview GIF, or past 40 frames the panel-size GIF the device downloads

  • Layout transparency: layout[] reports every renderer decision (font fallback, scrolling, and whether each box fits on the panel) so agents can refine a design

  • Device truth: pushed reflects the device ACK (past 40 frames, the ACK of the play plus the device's request for the GIF, with the whole file handed to the OS to send; the device does not confirm receipt), and the deviceState read back after a push comes with a notice naming the fix when the render won't be visible (screen off, brightness ≤ 10, off the custom channel)

  • Renders survive failed pushes: on all four render tools, the typed error (device_unreachable, device_http_error, device_rejected, gif_serve_failed, no_device_configured) carries outputFiles pointing at the saved preview (the PIXOO_OUTPUT_DIR copy, or a temp file when that is unset)

Getting started

Add it to Claude Code, with PIXOO_IP set to your Pixoo's LAN address (pixoo_discover_devices finds it if you don't know it):

claude mcp add pixoo-mcp-server -e PIXOO_IP=192.168.1.50 -- npx -y @cyanheads/pixoo-mcp-server

For other clients, add this to the MCP config file:

{
  "mcpServers": {
    "pixoo-mcp-server": {
      "command": "npx",
      "args": ["-y", "@cyanheads/pixoo-mcp-server"],
      "env": { "PIXOO_IP": "192.168.1.50" }
    }
  }
}

pixoo_render_html also needs a local chrome-headless-shell (install steps). For Docker or a source build, see Running the server.

Configuration

Variable

Description

Default

PIXOO_IP

Device IP on the local network. Required for pushes, overlays, and device control; discovery, design briefs, and push: false renders work without it.

—

PIXOO_SIZE

Display size in pixels: 16, 32, or 64.

64

PIXOO_OUTPUT_DIR

Directory where render tools save preview PNG and GIF files. A relative path resolves against the directory the server was launched from, so the saved paths it reports are absolute. Unset, previews are returned only in the response.

—

PIXOO_PUSH_MIN_INTERVAL_MS

Minimum gap between device pushes, in ms.

1000

PIXOO_SERVE_HOST

Host advertised in the URL the device downloads an animation of more than 40 frames from, in place of the local address the OS routes to PIXOO_IP. The listener binds that routed address either way. Set it behind NAT or in a container.

—

PIXOO_SERVE_PORT

Fixed port for that download's one-shot listener, for firewall rules and container port publishing. Unset, a free port per play.

—

PIXOO_BROWSER_PATH

Browser executable for HTML rendering. When set, the only browser tried: a path that is not an executable file fails rather than falling back. A relative path resolves against the launch directory. Unset, the newest chrome-headless-shell in Puppeteer's cache (~/.cache/puppeteer). The Docker image ships no browser.

—

PIXOO_HTML_ENABLED

Offer pixoo_render_html. false removes it from tools/list; a value that is not a boolean fails startup.

true

MCP_TRANSPORT_TYPE

Transport: stdio or http.

stdio

MCP_HTTP_PORT

HTTP server port.

3010

MCP_SESSION_MODE

HTTP session mode: stateless, stateful, or auto. A value set here overrides the server's declared stateless.

stateless

MCP_AUTH_MODE

Authentication: none, jwt, or oauth.

none

MCP_LOG_LEVEL

Log level (debug, info, warning, error, etc.).

info

LOGS_DIR

Directory for log files (Node.js only).

<project-root>/logs

LOG_TOOL_FAILURE_PAYLOADS

Log each failed tool call's arguments and result, redacted by key name and capped at LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES (default 16384). A secret inside a free-form value is not redacted.

false

OTEL_ENABLED

Enable OpenTelemetry.

false

See .env.example for the full list of optional overrides.

Running the server

Local development

Requires Bun v1.4.0 or higher (or Node.js v24+) and a Divoom Pixoo on the local network (Pixoo-64, Pixoo-32, or Pixoo-16).

The HTML renderer also needs chrome-headless-shell. npx @puppeteer/browsers install chrome-headless-shell@stable --path ~/.cache/puppeteer installs it where the server looks by default. Installed anywhere else with --path <dir>, set PIXOO_BROWSER_PATH to the executable path the install prints. The server launches it headless, with no DevTools port, only when a render needs it.

  • Clone and install:

    git clone https://github.com/cyanheads/pixoo-mcp-server.git
    cd pixoo-mcp-server && bun install
    cp .env.example .env   # set PIXOO_IP
  • Build and run:

    # One-time build
    bun run rebuild
    
    # Run the built server
    bun run start:stdio
    # or, Streamable HTTP at http://localhost:3010/mcp
    bun run start:http
  • Run checks and tests:

    bun run devcheck   # Lint, format, typecheck, security
    bun run test       # Vitest test suite
    bun run lint:mcp   # Validate MCP definitions against spec
    
    # Real-browser suite for the HTML renderer (opt-in; launches the named browser)
    PIXOO_TEST_BROWSER_PATH=/path/to/chrome-headless-shell bun run test:browser

Docker

docker run --rm -e PIXOO_IP=192.168.1.50 -p 3010:3010 \
  -e PIXOO_SERVE_HOST=192.168.1.20 -e PIXOO_SERVE_PORT=8765 -p 8765:8765 \
  ghcr.io/cyanheads/pixoo-mcp-server:latest

To run it over stdio from an MCP client:

{
  "mcpServers": {
    "pixoo-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "MCP_TRANSPORT_TYPE=stdio",
        "-e", "PIXOO_IP=192.168.1.50",
        "-e", "PIXOO_SERVE_HOST=192.168.1.20",
        "-e", "PIXOO_SERVE_PORT=8765",
        "-p", "8765:8765",
        "ghcr.io/cyanheads/pixoo-mcp-server:latest"
      ]
    }
  }
}

The device downloads an animation of more than 40 frames from this host, and on Docker's default bridge network the address routed to the device is the container's own, which the device can't reach. Set PIXOO_SERVE_HOST to the Docker host's LAN address and publish a fixed PIXOO_SERVE_PORT, as above; 40 frames or fewer need neither.

The image defaults to HTTP transport, stateless session mode, and logs to /var/log/pixoo-mcp-server, and ships no browser for pixoo_render_html. To build locally, docker build -t pixoo-mcp-server .; OpenTelemetry peers are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.

Project structure

Directory

Purpose

src/index.ts

createApp() entry point: registers tools and resources and initializes the Pixoo service.

src/config/

Server-specific environment variable parsing and validation with Zod.

src/mcp-server/tools/

Tool definitions (*.tool.ts), the shared post-render push path, and the shared finish input schema.

src/mcp-server/resources/

Resource definitions (*.resource.ts).

src/services/pixoo/

PixooService: wraps @cyanheads/pixoo-toolkit with push pacing, result mapping, and device state reads.

src/services/browser/

BrowserRenderer: renders HTML in an isolated headless chrome-headless-shell, driven over the DevTools Protocol pipe, and captures it as a panel frame.

src/renderer/

Pure rendering pipeline with no device dependency: element renderers, styled-text engine, themes, icons, effect compiler, palette finishing, preview encoding, remote image fetch, and the virtual clock injected into HTML pages.

tests/

Unit and integration tests mirroring src/.

Development guide

See CLAUDE.md/AGENTS.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic

  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage

  • The renderer (src/renderer/) is pure — no device dependency, testable without hardware

  • All device calls go through PixooService; every PixooResult is checked — never assume a push succeeded

Contributing

Issues are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

License

Apache-2.0 — see LICENSE for details.

Available Tools

8 tools
pixoo_compose_scenepixoo_compose_sceneA
Idempotent

Compose a full scene: layered elements (text, icons, widgets, shapes, bitmaps, images, sprites) with per-element effects and keyframes, static or animated. Returns the rendered scene as an image content block for immediate inspection. Elements render back-to-front in array order. For text-only display use pixoo_display_text; run pixoo_design_brief with topic "scene" or "dashboard" for layout and palette guidance.

NameRequiredDescriptionDefault
pushNoPush to device (default: true).
speedNoMilliseconds per frame for animations (default: 150ms).
framesNoNumber of animation frames (1–800, default: 1). 20 frames at 150ms ≈ 3s loop. Up to 40 push frame by frame; more play as one GIF the device downloads from this host, so the device must reach it (behind NAT or a firewall, set PIXOO_SERVE_HOST and PIXOO_SERVE_PORT), and speed rounds to the nearest 10 ms.
outputNoAbsolute, already-normalized path to save the first frame to as a PNG. Replaces the PIXOO_OUTPUT_DIR auto-save for this call, so outputFiles holds only this path.
elementsYesScene elements rendered back-to-front. Up to 50 elements. Each element takes either effect or animate, not both. An element's animate keyframes can drive dx, dy, and opacity (numbers or numeric strings, interpolated), visible (true or false, switching at the midpoint between keyframes), and color on any element with a color field (interpolated through RGB).
backgroundYesScene background: a solid color string, or an object holding exactly one of gradient or theme.

Output Schema

NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
framesNoNumber of frames in the rendered output (1 for static, 2–800 for animations).
layoutNoLayout report for each element.
noticeNoWarning or informational notice about the render or push.
pushedNoTrue when the device acknowledged the push; past 40 frames, once it accepted the GIF play, requested the file, and the whole file was handed to the OS to send (the device does not confirm receipt). False when push: false.
deviceStateNoDevice state after the push. Absent when push: false.
outputFilesNoAbsolute paths to saved output files: the output path when set, otherwise the PIXOO_OUTPUT_DIR auto-save (PNG for static; for animations an 8× GIF, or past 40 frames the panel-size GIF the device downloads). Absent when neither applies.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare idempotentHint=true and destructiveHint=false, so the description earns credit for disclosing the return channel ('image content block for immediate inspection') and the compositing rule ('Elements render back-to-front in array order'). It does not mention that push defaults to true, i.e. that a successful call writes to the physical device — the main side effect an agent should know about.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, front-loaded with what the tool does, then output format, then rendering order, then sibling routing. Every sentence carries information an agent needs to select or call the tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex scene-composition tool with a full output schema, the description covers purpose, layering semantics, alternatives, and return format. The remaining gap is device-push behavior and the 50-element ceiling's practical implications, which an agent must infer from the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all six parameters including the effect/animate exclusion, frame limits, and output path behavior; baseline 3 applies. The description restates the element kinds and back-to-front ordering but adds no syntax, units, or constraints beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Compose a full scene') and immediately enumerates the element kinds supported (text, icons, widgets, shapes, bitmaps, images, sprites) plus the animation capability. It explicitly distinguishes itself from the simpler sibling pixoo_display_text, so an agent can tell the two apart without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names an alternative with the condition that selects it ('For text-only display use pixoo_display_text') and routes to pixoo_design_brief with a concrete topic value ('scene' or 'dashboard') for layout guidance. It stops short of guidance on when to compose static vs animated, or when to set push:false for a preview-only render.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pixoo_control_devicepixoo_control_deviceA
Idempotent

Read or change device state: brightness (0–100), screen on/off, channel, or clock face. Call with no params to read current state only. Supply any params to apply changes before reading back state. Use pixoo_discover_devices first if PIXOO_IP is not yet configured.

NameRequiredDescriptionDefault
screenNoTurn the display screen on or off.
channelNoSwitch to a channel: faces, cloud, visualizer, or custom.
brightnessNoSet display brightness (0–100).
clockFaceIdNoSelect a clock face by ID (channel must be faces).

Output Schema

NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
noticeNoRequested settings that failed, each with its failure kind and message (e.g. "brightness:80 failed (network): …"), joined by "; ". Absent when every requested setting applied.
appliedNoSettings successfully applied in this call (e.g. "brightness:80", "screen:on"). Empty when called with no params or all changes failed. A requested setting that failed is absent here and reported in a notice instead.
channelNoCurrent channel name (faces, cloud, visualizer, or custom). Absent when device is unreachable.
clockIdNoCurrent clock face ID (faces channel only). Absent on other channels or when device is unreachable.
screenOnNoTrue if the screen is on. Absent when device is unreachable.
reachableNoTrue if device responded to the status read.
brightnessNoCurrent brightness level (0–100). Absent when device is unreachable.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish idempotent and non-destructive behavior, so the description only needs to add extra context. It does so by explaining the read-only vs. apply-then-read behavior, which is not visible in the schema or annotations. It stops short of describing edge cases like invalid parameter combinations, but the output schema and annotations cover the core safety profile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: the first states scope, the second defines read vs. change behavior, the third gives the prerequisite. Information is front-loaded and there is no filler or repetition of schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema, annotations, and full schema parameter descriptions, the description covers everything an agent needs to invoke this tool correctly: what it operates on, how to read vs. change, and when to call the discovery tool first. No critical operational gap remains.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema by defining the no-params read mode and the supply-params-to-apply mode, which is essential for using the parameters correctly. It also reinforces the brightness range and channel/clock face relationship without merely repeating schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states a specific verb ('Read or change') and resource ('device state') and enumerates the exact aspects affected: brightness, screen on/off, channel, clock face. This clearly differentiates it from sibling tools like pixoo_display_text or pixoo_push_image, which handle content rather than device state.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit usage modes: call with no params to read state, supply params to apply changes and read back. It also names the prerequisite alternative, pixoo_discover_devices, for when PIXOO_IP is not configured, giving clear routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pixoo_design_briefpixoo_design_briefA
Read-only

Return craft guidance and live device context for a design topic. Covers legibility rules, palette discipline, layout zones, animation budget, HTML page authoring, and pre-filled next-tool suggestions based on current device state. The orientation tool to run before authoring a scene, dashboard, animation, or HTML page — or when troubleshooting display issues.

NameRequiredDescriptionDefault
topicYesDesign topic: text (styled text guidance), scene (composition + layout zones), dashboard (widgets + metrics), animation (motion budget + effects), pixel-art (bitmap + sprite guidance), html (pixoo_render_html pages: loops, clock, sampling), troubleshooting (device + display issues).

Output Schema

NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
topicNoThe topic that was requested.
htmlRendererNoWhether pixoo_render_html can render: available; disabled (PIXOO_HTML_ENABLED=false, so the tool is not listed); or no_browser (no browser found, so the tool fails browser_unavailable until one is installed).
craftGuidanceNoMarkdown-formatted craft rules: legibility floors, palette discipline, layout zones, and technique guidance specific to the topic.
deviceContextNoLive device state snapshot at the time of the request.
iconCategoriesNoBuilt-in icon names grouped by category (weather, arrows, status, media). Use names in pixoo_compose_scene icon elements.
availableThemesNoAvailable named scene themes (e.g. "midnight", "ember"). Use in background.theme or pixoo_display_text theme param.
nextToolSuggestionsNoSuggested next steps based on topic and device state.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

readOnlyHint=true already frames it as a safe read; the description adds real behavioral context beyond that — it returns live device state and pre-filled next-tool suggestions, so the agent knows output is state-dependent, not static docs. It does not say what happens if no device is connected or discovered, which is the main undisclosed behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core verb and resource, then scoped by the coverage list and the 'run before authoring' trigger. Three sentences with no filler, though the middle coverage enumeration is dense and partly restates the enum values.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists, so return values need no prose, and the description covers purpose, trigger, and state-dependence. The one gap for a tool that depends on live device state is whether pixoo_discover_devices must be run first — that prerequisite is implied but never stated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the topic enum is fully documented in the schema, so baseline 3 applies. The description confirms the topic drives the returned guidance but adds no enum-level meaning (e.g., which topic fits a troubleshooting-vs-text decision) beyond what the schema already states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: return craft guidance plus live device context for a named design topic, and enumerates what that guidance covers. An agent can tell from the description alone that this is an advisory/orientation tool, not one of the pixoo_compose_scene / pixoo_display_text rendering siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger: run it before authoring a scene, dashboard, animation, or HTML page, or when troubleshooting display issues. It stops short of naming the sibling tools to call afterward or stating when it should be skipped, so it is clear context rather than a full when/when-not/alternative map.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pixoo_discover_devicespixoo_discover_devicesA
Read-only

Find Pixoo devices on the local network via Divoom's cloud discovery endpoint (requires internet — queries app.divoom-gz.com). Run once during initial setup to find device IPs; set PIXOO_IP in server configuration to enable all other tools. For ongoing device control use pixoo_control_device.

NameRequiredDescriptionDefault
timeoutMsNoDiscovery timeout in milliseconds (default: 5000ms).

Output Schema

NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
noticeNoRecovery hint when no devices found or IP mismatch.
devicesNoDiscovered Pixoo devices on the local network.
configuredIpNoCurrently configured PIXOO_IP value (absent if not set).
configuredIpFoundNoTrue if PIXOO_IP matches a discovered device; false signals an IP mismatch. Absent when PIXOO_IP is not set.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnly and openWorld hints. The description adds value by disclosing the network dependency (requires internet) and the specific external endpoint (app.divoom-gz.com), which are important behavioral traits not captured by annotations. Does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise sentences, front-loaded with the primary purpose, then the setup context and routing to an alternative. Every sentence earns its place; no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Moderate-low complexity tool with an output schema, so return values need not be described. The description covers purpose, network prerequisites, and post-condition (set PIXOO_IP). Slightly more could be said about what discovery returns, but the output schema already handles that.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with clear description, default, minimum, and maximum for timeoutMs. The narrative description adds nothing about the parameter, but with full schema coverage the baseline of 3 is appropriate since no extra meaning is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource ('Find Pixoo devices on the local network') and identifies the method via Divoom's cloud discovery endpoint. It distinguishes itself from all sibling tools, which are for display, control, or composition, by being the discovery step.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States explicitly when to use this tool ('Run once during initial setup'), what to do with the result (set PIXOO_IP in server configuration), and names the alternative for ongoing control (pixoo_control_device). This gives an agent complete routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pixoo_display_textpixoo_display_textA
Idempotent

Render styled text (theme, gradient, shadow, outline, auto-fit) onto the Pixoo display and push it, static or animated with a scroll, float, or pulse effect. Returns the render as an image content block for immediate inspection. The primary tool for text-only display — for layers, icons, widgets, or per-element motion use pixoo_compose_scene. Run pixoo_design_brief with topic "text" first for palette and legibility guidance.

NameRequiredDescriptionDefault
fontNoFont variant, used as given — text too wide for it overflows rather than switching font: standard (5×7) or compact (3×5), each printable ASCII plus ° ← ↑ → ↓ ▲ ▼ ♥ · …; or numerals (11×18 digits for clocks and readouts), which draws only 0–9, space, and : . - + / % ° ?, so text holding any other character is rejected. Omitted, single-line text tries standard and falls back to compact when standard overflows; multi-line text uses standard.
pushNoPush the rendered frame to the device (default: true).
textYesText to display. String or array of lines.
alignNoMulti-line text: align every line within the widest line, then place that block with position.x. Omit to place each line by position.x on its own.
styleNoText style: palette, shadow, outline, scale.
themeNoNamed scene theme — sets background gradient and default text palette.
effectNoAnimation effect. scroll runs the text across the display once, in up to 40 frames; auto scrolls only when the text is too wide to fit; float (gentle bob) and pulse (breathing brightness) loop over 20 frames. An animated result is pushed as an animation and previewed as a grid of its frames. none or omitted renders one static frame.
positionNoText position on the display.
backgroundNoBackground color or gradient. Overrides theme background when set.
brightnessNoSet device brightness before push (0–100). Failure is a warning, not an error.

Output Schema

NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
framesNoNumber of frames rendered: 1 for static text, 2–40 when an effect animates it.
layoutNoLayout report: every fit decision the renderer made.
noticeNoWarning or informational message about the render or push.
pushedNoTrue when the device acknowledged the push.
deviceStateNoDevice state after the push. Absent when push: false.
outputFilesNoAbsolute paths to saved preview files (PNG, or GIF when an effect animates the text). Present only when PIXOO_OUTPUT_DIR is configured.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover idempotency and non-destructiveness, so the description's job is lighter. It still adds real signal: the frame is pushed to the device, the result comes back as an image content block, animated results are pushed as animations and previewed as a frame grid, and a brightness failure degrades to a warning. It does not address device connectivity requirements or what happens when no device is connected — the main remaining behavioral gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with what the tool does, then sibling routing, then prerequisite. Every sentence earns its place and nothing is restated from the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter tool with nested style/position/background objects, the description covers purpose, alternatives, output form, and animation behavior, and an output schema exists so return values need not be spelled out. The only omission is any mention of device connection or multi-device selection, which matters given the push-by-default behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, including detailed notes on font fallback, effect frame counts, and palette/gradient shapes, so the schema carries the semantics. The description only summarizes the categories (theme, gradient, shadow, outline, auto-fit) without adding constraint or interaction detail beyond the schema — baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Declares a specific verb and resource — render styled text and push it to the Pixoo display — plus the stylistic surface (theme, gradient, shadow, outline, auto-fit) and effect modes. It explicitly routes multi-element cases to pixoo_compose_scene, but never distinguishes itself from the sibling pixoo_overlay_text, which is the closest ambiguity an agent could hit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative and the condition that selects it ('for layers, icons, widgets, or per-element motion use pixoo_compose_scene'), then adds a concrete prerequisite step ('Run pixoo_design_brief with topic "text" first'). An agent knows both when to pick this tool and how to prepare before calling it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pixoo_overlay_textpixoo_overlay_textA
Idempotent

Set or clear a device-native scrolling text overlay. Use mode "set" to add or update an overlay on a slot (0–19); use mode "clear" to remove it. Overlays use device-rendered fonts (115 font IDs, 0–114) and persist across channel switches until explicitly cleared with mode "clear". Not previewable — rendering happens on-device. Best for persistent tickers over pushed scenes; for styled, previewable text use pixoo_display_text instead.

NameRequiredDescriptionDefault
xNoX start position, 0 to display size − 1 (63 on a 64px display; default: 0).
yNoY start position, 0 to display size − 1 (63 on a 64px display; default: 0).
idYesOverlay slot ID (0–19). Each ID is an independent overlay layer.
fontNoDevice font ID (0–114). 0 = default, 18 = arrows, 20 = °C/°F. Device-rendered; no preview.
modeYesset = add/update overlay; clear = remove it.
textNoText to display (required for mode=set).
alignNoText alignment (default: left).left
colorNoText color: hex (#RRGGBB or #RGB) or a named color such as orange (default: white).#ffffff
speedNoScroll speed (0–100, device units; default: 50).
widthNoText region width in pixels, 0 to display size (64 on a 64px display; defaults to display width).
directionNoScroll direction (default: left).left

Output Schema

NameRequiredDescription
idNoThe overlay slot ID (0–19) that was operated on.
modeNoOperation performed: "set" (overlay added/updated) or "clear" (overlay removed).
errorNoPresent when the call failed. Absent on success.
acknowledgedNoTrue when the device confirmed the overlay command (error_code: 0).

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds real context beyond the annotations: overlays persist across channel switches until explicitly cleared, rendering is on-device and not previewable, and slot IDs 0–19 are independent layers. Annotations already declare idempotentHint/destructiveHint, and clearing an ephemeral overlay does not contradict destructiveHint=false. Minor gap: it doesn't say what happens to unspecified fields on an update to an existing slot.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences, front-loaded with the action, then mode semantics, then persistence/rendering caveats, then sibling routing. Nothing is repeated and every sentence carries decision-relevant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a rich 11-parameter schema at full coverage, an output schema present, and annotations covering idempotency/safety, the description supplies exactly the residual knowledge an agent needs: persistence lifetime, non-previewability, and the sibling alternative. Nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter is already documented, including font ranges, slot IDs, and defaults. The description restates the 0–19 slot range and the 115 font IDs but adds no syntax or interaction detail beyond the schema — baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb pair and resource: 'Set or clear a device-native scrolling text overlay.' It explicitly distinguishes itself from the sibling pixoo_display_text by calling out the styled/previewable variant, so an agent can pick between them without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit mode routing ('use mode "set" to add or update… use mode "clear" to remove it') and names the alternative with the condition that selects it ('for styled, previewable text use pixoo_display_text instead'). No inference required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pixoo_push_imagepixoo_push_imageA
Idempotent

Load an image (absolute local path or https URL), resize it to fit the LED grid, and optionally push it to the display. An animated GIF or WebP pushes as an animation of up to maxFrames frames (default 40), sampled evenly from a longer source and played at the speed that keeps its loop length; past 40 frames it plays as one GIF the device downloads from this host. Returns the downsampled result as an image content block so you see exactly what the display received — for an animation, a grid of its frames, evenly sampled once they outnumber what fits the sheet. Nearest-neighbor kernel preserves pixel art; use lanczos3 or mitchell for photos. finish reduces the result to a small or fixed palette, optionally dithered.

NameRequiredDescriptionDefault
fitNoResize fit mode: contain (letterbox), cover (crop to fill), fill (stretch).contain
pushNoPush the resized image to the device (default: true).
speedNoMilliseconds per frame for an animated source (10–2000). Default: the source's total duration over the pushed frame count, or 150 when it records no delays. A still ignores it.
finishNoReduce the image to a palette before it reaches the panel: exactly one of colors (2–256, built from the image) or palette (1–256 hex or named colors), plus dither. Transparent pixels stay unlit and are not counted. The preview shows the finished frame.
kernelNoResize kernel: nearest for pixel art, lanczos3 for photos, mitchell for a balance.nearest
sourceYesAbsolute local file path or https (not http) URL of the image to display; a relative path is rejected. An animated GIF or WebP, whatever its file name, pushes as an animation.
maxFramesNoMost frames an animated source pushes (1–800, default 40); a longer source is sampled evenly down to it. Up to 40 push frame by frame; more play as one GIF the device downloads from this host, so the device must reach it (behind NAT or a firewall, set PIXOO_SERVE_HOST and PIXOO_SERVE_PORT), and speed rounds to the nearest 10 ms. A still ignores it.

Output Schema

NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
speedNoMilliseconds per frame the animation plays at. Absent for a still.
framesNoFrames rendered and pushed: 1 for a still, 2 to maxFrames for an animation.
noticeNoWarning or informational message.
pushedNoTrue when the device acknowledged the push; past 40 frames, once it accepted the GIF play, requested the file, and the whole file was handed to the OS to send (the device does not confirm receipt).
deviceStateNoDevice state after the push. Absent when push: false.
outputFilesNoAbsolute paths to saved preview files: a PNG for a still, an 8× GIF at the pushed speed for an animation, or past 40 frames the panel-size GIF the device downloads. Present only when PIXOO_OUTPUT_DIR is configured.
sourceFramesNoFrames in the source before sampling down to maxFrames: 1 for a still.

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: it discloses that sources over 40 frames switch to a device-downloaded GIF, which requires the device to reach this host (PIXOO_SERVE_HOST/PIXOO_SERVE_PORT behind NAT), that speed then rounds to 10 ms, that sources are sampled evenly, and that the call returns a downsampled preview image block. Those are real operational constraints (network reachability) an agent cannot infer from openWorldHint/idempotentHint/destructiveHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and scope in the first sentence, then layers animation, preview-return and rendering behavior. Dense but nearly every clause carries information; the closing color-quantization sentence is the one piece that largely duplicates schema text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a seven-parameter tool with nested enums and an output schema, the description covers the parts structured data cannot: the preview return, the 40-frame push threshold with its host-reachability requirement, and palette/finish effect on the preview. Nothing an agent needs to call this correctly appears missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema already documents fit, kernel, finish, dither and maxFrames in detail. The description's additions ('nearest-neighbor preserves pixel art', 'finish reduces to a small or fixed palette, optionally dithered', 'maxFrames default 40') largely restate the schema rather than adding new semantics, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb chain (load, resize, optionally push) against a concrete resource (image → LED grid), plus accepted input forms (absolute local path or https URL). This clearly separates it from siblings like pixoo_display_text, pixoo_overlay_text and pixoo_render_html, which handle text or HTML rather than an existing image file.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied by the push/optional framing and by guidance such as 'Nearest-neighbor kernel preserves pixel art; use lanczos3 or mitchell for photos', but that is parameter guidance, not tool selection. No sibling is named as an alternative, and no explicit when-not condition (e.g. when to prefer render_html or compose_scene) is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pixoo_render_htmlpixoo_render_htmlA
Idempotent

Render an HTML page — a full document or a body fragment, with inline CSS, Canvas, SVG, or WebGL — in a headless browser at the panel size, and optionally push it to the display. Animate it by capturing up to 800 frames on a virtual clock that advances speed ms per frame: window.render(t, frame), when the page defines it, runs before each capture with t = frame / frames, so periodic motion loops seamlessly; CSS animations, requestAnimationFrame, timers, Date, and performance.now follow the same clock, so two calls capture the same frames unless the page reads Math.random, which is unseeded, or the starting Date. The page loads nothing from the network and starts no workers; a page with no background renders on black, which the panel shows as unlit. Every page gets a pixoo global before its own scripts run: pixoo.text, pixoo.icon, and pixoo.palettes draw crisp bitmap text, gradient palettes, and icons exactly as pixoo_compose_scene does. Returns the captured result as an image content block — for an animation, a grid of its frames — and the page's uncaught and console errors as pageErrors. Run pixoo_design_brief with topic "html" first for loop, clock, sampling, legibility, and pixoo runtime guidance.

NameRequiredDescriptionDefault
htmlYesThe page to render: a full HTML document or a body fragment, up to 500,000 characters, served with <!doctype html> prepended. It lays out in a square viewport one CSS pixel per LED (64×64 on a Pixoo-64). Inline scripts and styles run and data: and blob: URLs load; a network URL is blocked and listed in pageErrors.
pushNoPush to device (default: true).
speedNoMilliseconds per frame (10–2000, default: 150): how far the virtual clock advances between captures, and how fast the animation plays.
finishNoReduce the image to a palette before it reaches the panel: exactly one of colors (2–256, built from the image) or palette (1–256 hex or named colors), plus dither. Transparent pixels stay unlit and are not counted. The preview shows the finished frame.
framesNoNumber of frames to capture (1–800, default: 1). At frame i, window.render gets t = i / frames and performance.now() reads i × speed. Up to 40 push frame by frame; more play as one GIF the device downloads from this host, so the device must reach it (behind NAT or a firewall, set PIXOO_SERVE_HOST and PIXOO_SERVE_PORT), and speed rounds to the nearest 10 ms.
outputNoAbsolute, already-normalized path to save the first frame to as a PNG. Replaces the PIXOO_OUTPUT_DIR auto-save for this call, so outputFiles holds only this path.
samplingNonative (default) captures one CSS pixel per LED. supersample renders at 8× and averages each 8×8 block into one LED, so transforms, text, SVG, and canvas shade smoothly; a plain box still snaps to whole CSS pixels (left: 0.5px lands on one LED), so move it with transform for sub-pixel motion.native

Output Schema

NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
framesNoNumber of frames captured (1 for a still, 2–800 for an animation).
noticeNoWarning or informational notice about the render or push.
pushedNoTrue when the device acknowledged the push; past 40 frames, once it accepted the GIF play, requested the file, and the whole file was handed to the OS to send (the device does not confirm receipt). False when push: false.
pageErrorsNoThe page's uncaught errors, console.error output, and blocked request URLs, in the order they arrived: the first 20, each cut to 500 characters. Empty when the page reported none.
deviceStateNoDevice state after the push. Absent when push: false.
outputFilesNoAbsolute paths to saved output files: the output path when set, otherwise the PIXOO_OUTPUT_DIR auto-save (PNG for a still; for an animation an 8× GIF, or past 40 frames the panel-size GIF the device downloads). Absent when neither applies.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses many behavioral traits beyond the annotations: no network loading, no workers, black background handling, the pixoo global, deterministic frame capture except for Math.random or starting Date, and pageErrors reporting. These details are valuable because the annotations only cover idempotency and destructiveness.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and every sentence carries relevant information for a complex rendering tool. It is still a dense single paragraph that repeats some schema details, so it could be structured more cleanly, but it is not padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity and the presence of a full output schema, the description still supplies the missing operational context: rendering constraints, animation clock behavior, push implications, and error reporting. An agent has enough information to invoke it correctly without needing to inspect other documentation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all seven parameters, including push, speed, frames, finish, sampling, and output. The description adds context about the virtual clock and frame formula, but it does not materially extend the per-parameter semantics beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: render an HTML page in a headless browser at panel size with optional push. It enumerates supported content (CSS, Canvas, SVG, WebGL) and links its runtime to pixoo_compose_scene, which distinguishes it from the other siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear usage instruction to run pixoo_design_brief with topic "html" first, and it explains the optional push behavior. However, it does not explicitly say when to choose this tool over pixoo_compose_scene or pixoo_push_image, so the alternatives are only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv1.5.0
    • Changedpixoo_compose_scene1 field changed
      • changedInput schema / properties / elements / items / oneOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "description": "Styled text element rendered at a position.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": false,
        -        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "color": {
        -            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Color at this frame.",
        -                  "type": [
        -                    "number",
        -                    "string",
        -                    "boolean"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dx": {
        -            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dy": {
        -            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "opacity": {
        -            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "visible": {
        -            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Whether the element shows at this frame.",
        -                  "type": "boolean"
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "blend": {
        -        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        -        "enum": [
        -          "normal",
        -          "add",
        -          "screen",
        -          "multiply"
        -        ],
        -        "type": "string"
        -      },
        -      "color": {
        -        "description": "Flat text color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "additionalProperties": false,
        -        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "font": {
        -        "description": "Font variant (default: standard): standard (5×7) or compact (3×5), each printable ASCII plus ° ← ↑ → ↓ ▲ ▼ ♥ · …; or numerals (11×18 digits for clocks and readouts), which draws only 0–9, space, and : . - + / % ° ?, so text holding any other character is rejected — put units and labels in a separate standard or compact text element.",
        -        "enum": [
        -          "standard",
        -          "compact",
        -          "numerals"
        -        ],
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "style": {
        -        "additionalProperties": false,
        -        "description": "Text style options.",
        -        "properties": {
        -          "color": {
        -            "description": "Flat color override.",
        -            "type": "string"
        -          },
        -          "outline": {
        -            "description": "1px outline.",
        -            "type": "boolean"
        -          },
        -          "palette": {
        -            "anyOf": [
        -              {
        -                "description": "Named built-in color palette for the vertical ramp.",
        -                "enum": [
        -                  "ember",
        -                  "ice",
        -                  "neon",
        -                  "fire",
        -                  "lavender",
        -                  "claude",
        -                  "mono"
        -                ],
        -                "type": "string"
        -              },
        -              {
        -                "additionalProperties": false,
        -                "description": "Custom gradient stop: specify top and bottom colors directly.",
        -                "properties": {
        -                  "from": {
        -                    "description": "Top color.",
        -                    "type": "string"
        -                  },
        -                  "to": {
        -                    "description": "Bottom color.",
        -                    "type": "string"
        -                  }
        -                },
        -                "required": [
        -                  "from",
        -                  "to"
        -                ],
        -                "type": "object"
        -              }
        -            ],
        -            "description": "Palette name or custom gradient stop for vertical color ramp."
        -          },
        -          "scale": {
        -            "description": "Integer pixel scale multiplier.",
        -            "maximum": 8,
        -            "minimum": 1,
        -            "type": "integer"
        -          },
        -          "shadow": {
        -            "description": "Drop shadow.",
        -            "type": "boolean"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "text": {
        -        "description": "Text content to render.",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "text",
        -        "description": "Text element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel X coordinate (0 = left edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic horizontal alignment.",
        -            "enum": [
        -              "left",
        -              "center",
        -              "right"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "X position (default: 0)."
        -      },
        -      "y": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel Y coordinate (0 = top edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic vertical alignment.",
        -            "enum": [
        -              "top",
        -              "center",
        -              "bottom"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "Y position (default: 0)."
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Built-in or custom SVG icon element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": false,
        -        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "color": {
        -            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Color at this frame.",
        -                  "type": [
        -                    "number",
        -                    "string",
        -                    "boolean"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dx": {
        -            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dy": {
        -            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "opacity": {
        -            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "visible": {
        -            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Whether the element shows at this frame.",
        -                  "type": "boolean"
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "blend": {
        -        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        -        "enum": [
        -          "normal",
        -          "add",
        -          "screen",
        -          "multiply"
        -        ],
        -        "type": "string"
        -      },
        -      "color": {
        -        "description": "Icon color (default: white).",
        -        "type": "string"
        -      },
        -      "d": {
        -        "description": "Custom SVG path d attribute.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "additionalProperties": false,
        -        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Render height in pixels (default: 12).",
        -        "maximum": 256,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "name": {
        -        "description": "Built-in icon name (see pixoo://reference/icons).",
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "palette": {
        -        "description": "Named palette painted as a top-to-bottom color ramp from the icon's top row to its bottom row. Takes precedence over color.",
        -        "enum": [
        -          "ember",
        -          "ice",
        -          "neon",
        -          "fire",
        -          "lavender",
        -          "claude",
        -          "mono"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "icon",
        -        "description": "Icon element type.",
        -        "type": "string"
        -      },
        -      "viewBox": {
        -        "description": "SVG viewBox string (default: \"0 0 16 16\").",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Render width in pixels (default: 12).",
        -        "maximum": 256,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel X coordinate (0 = left edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic horizontal alignment.",
        -            "enum": [
        -              "left",
        -              "center",
        -              "right"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "X position."
        -      },
        -      "y": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel Y coordinate (0 = top edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic vertical alignment.",
        -            "enum": [
        -              "top",
        -              "center",
        -              "bottom"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "Y position."
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Filled, gradient, or bordered rectangle element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": false,
        -        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "color": {
        -            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Color at this frame.",
        -                  "type": [
        -                    "number",
        -                    "string",
        -                    "boolean"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dx": {
        -            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dy": {
        -            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "opacity": {
        -            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "visible": {
        -            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Whether the element shows at this frame.",
        -                  "type": "boolean"
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "blend": {
        -        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        -        "enum": [
        -          "normal",
        -          "add",
        -          "screen",
        -          "multiply"
        -        ],
        -        "type": "string"
        -      },
        -      "borderColor": {
        -        "description": "Border color. The border is drawn inside the rect, strokeWidth pixels thick.",
        -        "type": "string"
        -      },
        -      "color": {
        -        "description": "Fill color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "additionalProperties": false,
        -        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "gradient": {
        -        "additionalProperties": false,
        -        "description": "Gradient fill.",
        -        "properties": {
        -          "from": {
        -            "description": "Start color.",
        -            "type": "string"
        -          },
        -          "to": {
        -            "description": "End color.",
        -            "type": "string"
        -          },
        -          "type": {
        -            "description": "v = vertical, h = horizontal.",
        -            "enum": [
        -              "v",
        -              "h"
        -            ],
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "type",
        -          "from",
        -          "to"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Height in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "strokeWidth": {
        -        "description": "Border thickness in whole pixels, growing inward from the rect edge (default: 1). Requires borderColor.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "rect",
        -        "description": "Rectangle element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Width in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "w",
        -      "h"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Filled or outline circle element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": false,
        -        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "color": {
        -            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Color at this frame.",
        -                  "type": [
        -                    "number",
        -                    "string",
        -                    "boolean"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dx": {
        -            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dy": {
        -            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "opacity": {
        -            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "visible": {
        -            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Whether the element shows at this frame.",
        -                  "type": "boolean"
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "antialias": {
        -        "description": "Shade each outline pixel by how much of it the ring covers, for a smooth curve (default: false, hard pixel edges). Outline circles only (fill: false).",
        -        "type": "boolean"
        -      },
        -      "blend": {
        -        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        -        "enum": [
        -          "normal",
        -          "add",
        -          "screen",
        -          "multiply"
        -        ],
        -        "type": "string"
        -      },
        -      "color": {
        -        "description": "Circle color.",
        -        "type": "string"
        -      },
        -      "cx": {
        -        "description": "Center X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "cy": {
        -        "description": "Center Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "additionalProperties": false,
        -        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "fill": {
        -        "description": "Filled or outline only (default: true).",
        -        "type": "boolean"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "radius": {
        -        "description": "Radius in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "strokeWidth": {
        -        "description": "Outline thickness in whole pixels, centered on the circle (default: 1). Outline circles only (fill: false).",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "circle",
        -        "description": "Circle element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "cx",
        -      "cy",
        -      "radius"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Straight line element, 1px wide unless strokeWidth is set.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": false,
        -        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "color": {
        -            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Color at this frame.",
        -                  "type": [
        -                    "number",
        -                    "string",
        -                    "boolean"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dx": {
        -            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dy": {
        -            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "opacity": {
        -            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "visible": {
        -            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Whether the element shows at this frame.",
        -                  "type": "boolean"
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "antialias": {
        -        "description": "Shade each pixel by how much of it the line covers, for smooth diagonals (default: false, hard pixel edges).",
        -        "type": "boolean"
        -      },
        -      "blend": {
        -        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        -        "enum": [
        -          "normal",
        -          "add",
        -          "screen",
        -          "multiply"
        -        ],
        -        "type": "string"
        -      },
        -      "color": {
        -        "description": "Line color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "additionalProperties": false,
        -        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "strokeWidth": {
        -        "description": "Line thickness in whole pixels, centered on the line (default: 1).",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "line",
        -        "description": "Line element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x0": {
        -        "description": "Start X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "x1": {
        -        "description": "End X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y0": {
        -        "description": "Start Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y1": {
        -        "description": "End Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x0",
        -      "y0",
        -      "x1",
        -      "y1"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Horizontal progress bar widget.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": false,
        -        "description": "Raw keyframe animation map for this element (no color track). Set either effect or animate, not both.",
        -        "properties": {
        -          "dx": {
        -            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dy": {
        -            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "opacity": {
        -            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "visible": {
        -            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Whether the element shows at this frame.",
        -                  "type": "boolean"
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "blend": {
        -        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        -        "enum": [
        -          "normal",
        -          "add",
        -          "screen",
        -          "multiply"
        -        ],
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "additionalProperties": false,
        -        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Height in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "label": {
        -        "description": "Optional label rendered on the bar.",
        -        "type": "string"
        -      },
        -      "max": {
        -        "description": "Maximum value.",
        -        "type": "number"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "palette": {
        -        "description": "Named palette for gradient fill.",
        -        "enum": [
        -          "ember",
        -          "ice",
        -          "neon",
        -          "fire",
        -          "lavender",
        -          "claude",
        -          "mono"
        -        ],
        -        "type": "string"
        -      },
        -      "trackColor": {
        -        "description": "Background track color.",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "progress",
        -        "description": "Progress bar widget type.",
        -        "type": "string"
        -      },
        -      "value": {
        -        "description": "Current value.",
        -        "type": "number"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Width in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "w",
        -      "h",
        -      "value",
        -      "max"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Sparkline chart widget (line or bar).",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": false,
        -        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "color": {
        -            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Color at this frame.",
        -                  "type": [
        -                    "number",
        -                    "string",
        -                    "boolean"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dx": {
        -            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dy": {
        -            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "opacity": {
        -            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "visible": {
        -            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Whether the element shows at this frame.",
        -                  "type": "boolean"
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "blend": {
        -        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        -        "enum": [
        -          "normal",
        -          "add",
        -          "screen",
        -          "multiply"
        -        ],
        -        "type": "string"
        -      },
        -      "color": {
        -        "description": "Line or bar color.",
        -        "type": "string"
        -      },
        -      "data": {
        -        "description": "Data points for the chart.",
        -        "items": {
        -          "type": "number"
        -        },
        -        "minItems": 2,
        -        "type": "array"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "additionalProperties": false,
        -        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Height in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 2,
        -        "type": "integer"
        -      },
        -      "kind": {
        -        "description": "Chart style (default: line).",
        -        "enum": [
        -          "line",
        -          "bar"
        -        ],
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "sparkline",
        -        "description": "Sparkline chart widget type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Width in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 2,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "w",
        -      "h",
        -      "data"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Bitmap element using explicit palette indices.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": false,
        -        "description": "Raw keyframe animation map for this element (no color track). Set either effect or animate, not both.",
        -        "properties": {
        -          "dx": {
        -            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dy": {
        -            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "opacity": {
        -            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "visible": {
        -            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Whether the element shows at this frame.",
        -                  "type": "boolean"
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "blend": {
        -        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        -        "enum": [
        -          "normal",
        -          "add",
        -          "screen",
        -          "multiply"
        -        ],
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "additionalProperties": false,
        -        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "palette": {
        -        "description": "Color palette: array of hex colors indexed 0-F.",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "rows": {
        -        "description": "Row strings of hex palette indices (0-F, space = transparent).",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "type": {
        -        "const": "bitmap",
        -        "description": "Bitmap element using palette indices.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "rows",
        -      "palette"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Sparse scatter of individually colored pixels.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": false,
        -        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "color": {
        -            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Color at this frame.",
        -                  "type": [
        -                    "number",
        -                    "string",
        -                    "boolean"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dx": {
        -            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dy": {
        -            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "opacity": {
        -            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "visible": {
        -            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Whether the element shows at this frame.",
        -                  "type": "boolean"
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "blend": {
        -        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        -        "enum": [
        -          "normal",
        -          "add",
        -          "screen",
        -          "multiply"
        -        ],
        -        "type": "string"
        -      },
        -      "data": {
        -        "description": "Array of pixel positions and colors.",
        -        "items": {
        -          "additionalProperties": false,
        -          "description": "A single pixel: position and color.",
        -          "properties": {
        -            "color": {
        -              "description": "Pixel color.",
        -              "type": "string"
        -            },
        -            "x": {
        -              "description": "Pixel X coordinate.",
        -              "maximum": 9007199254740991,
        -              "minimum": -9007199254740991,
        -              "type": "integer"
        -            },
        -            "y": {
        -              "description": "Pixel Y coordinate.",
        -              "maximum": 9007199254740991,
        -              "minimum": -9007199254740991,
        -              "type": "integer"
        -            }
        -          },
        -          "required": [
        -            "x",
        -            "y",
        -            "color"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "additionalProperties": false,
        -        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "pixels",
        -        "description": "Sparse pixel dots element.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "data"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "External image element (absolute local path or https URL).",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": false,
        -        "description": "Raw keyframe animation map for this element (no color track). Set either effect or animate, not both.",
        -        "properties": {
        -          "dx": {
        -            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dy": {
        -            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "opacity": {
        -            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "visible": {
        -            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Whether the element shows at this frame.",
        -                  "type": "boolean"
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "blend": {
        -        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        -        "enum": [
        -          "normal",
        -          "add",
        -          "screen",
        -          "multiply"
        -        ],
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "additionalProperties": false,
        -        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "finish": {
        -        "anyOf": [
        -          {
        -            "additionalProperties": false,
        -            "description": "Reduce to a palette built from the image.",
        -            "properties": {
        -              "colors": {
        -                "description": "Build a palette of at most this many colors (2–256) from the image itself.",
        -                "maximum": 256,
        -                "minimum": 2,
        -                "type": "integer"
        -              },
        -              "dither": {
        -                "default": "none",
        -                "description": "How palette colors are placed: none maps each pixel to its nearest color; bayer4 mixes the two nearest in an ordered 4×4 pattern; floyd-steinberg diffuses the difference to neighboring pixels, smoothest on photos.",
        -                "enum": [
        -                  "none",
        -                  "bayer4",
        -                  "floyd-steinberg"
        -                ],
        -                "type": "string"
        -              }
        -            },
        -            "required": [
        -              "colors"
        -            ],
        -            "type": "object"
        -          },
        -          {
        -            "additionalProperties": false,
        -            "description": "Reduce to a fixed palette.",
        -            "properties": {
        -              "dither": {
        -                "default": "none",
        -                "description": "How palette colors are placed: none maps each pixel to its nearest color; bayer4 mixes the two nearest in an ordered 4×4 pattern; floyd-steinberg diffuses the difference to neighboring pixels, smoothest on photos.",
        -                "enum": [
        -                  "none",
        -                  "bayer4",
        -                  "floyd-steinberg"
        -                ],
        -                "type": "string"
        -              },
        -              "palette": {
        -                "description": "Map every pixel to these colors (1–256 entries).",
        -                "items": {
        -                  "description": "Hex color (#RRGGBB or #RGB) or a named color.",
        -                  "type": "string"
        -                },
        -                "maxItems": 256,
        -                "minItems": 1,
        -                "type": "array"
        -              }
        -            },
        -            "required": [
        -              "palette"
        -            ],
        -            "type": "object"
        -          }
        -        ],
        -        "description": "Reduce the image to a palette before it reaches the panel: exactly one of colors (2–256, built from the image) or palette (1–256 hex or named colors), plus dither. Transparent pixels stay unlit and are not counted. The preview shows the finished frame."
        -      },
        -      "fit": {
        -        "description": "Resize fit mode (default: contain).",
        -        "enum": [
        -          "contain",
        -          "cover",
        -          "fill"
        -        ],
        -        "type": "string"
        -      },
        -      "h": {
        -        "description": "Target height (default: canvas height).",
        -        "maximum": 256,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "kernel": {
        -        "description": "Resize kernel: nearest for pixel art, lanczos3 for photos (default: nearest).",
        -        "enum": [
        -          "nearest",
        -          "lanczos3",
        -          "mitchell"
        -        ],
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "source": {
        -        "description": "Absolute local file path or https (not http) URL; a relative path is rejected.",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "image",
        -        "description": "Image element (absolute local path or https URL).",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Target width (default: canvas width).",
        -        "maximum": 256,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X offset on canvas (default: 0).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y offset on canvas (default: 0).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "source"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "additionalProperties": false,
        -    "description": "Sprite sheet element for character or tile art.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": false,
        -        "description": "Raw keyframe animation map for this element (no color track). Set either effect or animate, not both.",
        -        "properties": {
        -          "dx": {
        -            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "dy": {
        -            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "opacity": {
        -            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        -                  "type": [
        -                    "number",
        -                    "string"
        -                  ]
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          },
        -          "visible": {
        -            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        -            "items": {
        -              "items": false,
        -              "maxItems": 2,
        -              "minItems": 2,
        -              "prefixItems": [
        -                {
        -                  "description": "Frame index.",
        -                  "type": "number"
        -                },
        -                {
        -                  "description": "Whether the element shows at this frame.",
        -                  "type": "boolean"
        -                }
        -              ],
        -              "type": "array"
        -            },
        -            "minItems": 1,
        -            "type": "array"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "blend": {
        -        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        -        "enum": [
        -          "normal",
        -          "add",
        -          "screen",
        -          "multiply"
        -        ],
        -        "type": "string"
        -      },
        -      "bodyColor": {
        -        "description": "Override body color.",
        -        "type": "string"
        -      },
        -      "cols": {
        -        "description": "Number of columns in the sprite grid.",
        -        "maximum": 64,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "darkColor": {
        -        "description": "Override dark/eye color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "additionalProperties": false,
        -        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "path": {
        -        "description": "Absolute local path to the sprite sheet image; a relative path is rejected.",
        -        "type": "string"
        -      },
        -      "rows": {
        -        "description": "Number of rows in the sprite grid.",
        -        "maximum": 64,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "scale": {
        -        "description": "Pixel scale factor: each sprite cell renders as a scale × scale block.",
        -        "maximum": 64,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "sprite",
        -        "description": "Sprite sheet element.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel X coordinate (0 = left edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic horizontal alignment.",
        -            "enum": [
        -              "left",
        -              "center",
        -              "right"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "X position (default: center)."
        -      },
        -      "y": {
        -        "description": "Y position (default: 0).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "path",
        -      "cols",
        -      "rows"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "description": "Styled text element rendered at a position.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Flat text color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity (default 2 for motion effects). float: vertical swing of ±amplitude px. drift: horizontal swing of ±4 × amplitude px. scroll-left, scroll-right: speed — the element moves 2 × amplitude px per frame from where it is placed and never wraps, so start it at the edge it enters from and give it enough frames to cross. pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "font": {
        +        "description": "Font variant (default: standard): standard (5×7) or compact (3×5), each printable ASCII plus ° ← ↑ → ↓ ▲ ▼ ♥ · …; or numerals (11×18 digits for clocks and readouts), which draws only 0–9, space, and : . - + / % ° ?, so text holding any other character is rejected — put units and labels in a separate standard or compact text element.",
        +        "enum": [
        +          "standard",
        +          "compact",
        +          "numerals"
        +        ],
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "style": {
        +        "additionalProperties": false,
        +        "description": "Text style options.",
        +        "properties": {
        +          "color": {
        +            "description": "Flat color override.",
        +            "type": "string"
        +          },
        +          "outline": {
        +            "description": "1px outline.",
        +            "type": "boolean"
        +          },
        +          "palette": {
        +            "anyOf": [
        +              {
        +                "description": "Named built-in color palette for the vertical ramp.",
        +                "enum": [
        +                  "ember",
        +                  "ice",
        +                  "neon",
        +                  "fire",
        +                  "lavender",
        +                  "claude",
        +                  "mono"
        +                ],
        +                "type": "string"
        +              },
        +              {
        +                "additionalProperties": false,
        +                "description": "Custom gradient stop: specify top and bottom colors directly.",
        +                "properties": {
        +                  "from": {
        +                    "description": "Top color.",
        +                    "type": "string"
        +                  },
        +                  "to": {
        +                    "description": "Bottom color.",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "from",
        +                  "to"
        +                ],
        +                "type": "object"
        +              }
        +            ],
        +            "description": "Palette name or custom gradient stop for vertical color ramp."
        +          },
        +          "scale": {
        +            "description": "Integer pixel scale multiplier.",
        +            "maximum": 8,
        +            "minimum": 1,
        +            "type": "integer"
        +          },
        +          "shadow": {
        +            "description": "Drop shadow.",
        +            "type": "boolean"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "text": {
        +        "description": "Text content to render.",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "text",
        +        "description": "Text element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel X coordinate (0 = left edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic horizontal alignment.",
        +            "enum": [
        +              "left",
        +              "center",
        +              "right"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "X position (default: 0)."
        +      },
        +      "y": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel Y coordinate (0 = top edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic vertical alignment.",
        +            "enum": [
        +              "top",
        +              "center",
        +              "bottom"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "Y position (default: 0)."
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Built-in or custom SVG icon element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Icon color (default: white).",
        +        "type": "string"
        +      },
        +      "d": {
        +        "description": "Custom SVG path d attribute.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity (default 2 for motion effects). float: vertical swing of ±amplitude px. drift: horizontal swing of ±4 × amplitude px. scroll-left, scroll-right: speed — the element moves 2 × amplitude px per frame from where it is placed and never wraps, so start it at the edge it enters from and give it enough frames to cross. pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Render height in pixels (default: 12).",
        +        "maximum": 256,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "name": {
        +        "description": "Built-in icon name (see pixoo://reference/icons).",
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "palette": {
        +        "description": "Named palette painted as a top-to-bottom color ramp from the icon's top row to its bottom row. Takes precedence over color.",
        +        "enum": [
        +          "ember",
        +          "ice",
        +          "neon",
        +          "fire",
        +          "lavender",
        +          "claude",
        +          "mono"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "icon",
        +        "description": "Icon element type.",
        +        "type": "string"
        +      },
        +      "viewBox": {
        +        "description": "SVG viewBox string (default: \"0 0 16 16\").",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Render width in pixels (default: 12).",
        +        "maximum": 256,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel X coordinate (0 = left edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic horizontal alignment.",
        +            "enum": [
        +              "left",
        +              "center",
        +              "right"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "X position."
        +      },
        +      "y": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel Y coordinate (0 = top edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic vertical alignment.",
        +            "enum": [
        +              "top",
        +              "center",
        +              "bottom"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "Y position."
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Filled, gradient, or bordered rectangle element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "borderColor": {
        +        "description": "Border color. The border is drawn inside the rect, strokeWidth pixels thick.",
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Fill color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity (default 2 for motion effects). float: vertical swing of ±amplitude px. drift: horizontal swing of ±4 × amplitude px. scroll-left, scroll-right: speed — the element moves 2 × amplitude px per frame from where it is placed and never wraps, so start it at the edge it enters from and give it enough frames to cross. pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "gradient": {
        +        "additionalProperties": false,
        +        "description": "Gradient fill.",
        +        "properties": {
        +          "from": {
        +            "description": "Start color.",
        +            "type": "string"
        +          },
        +          "to": {
        +            "description": "End color.",
        +            "type": "string"
        +          },
        +          "type": {
        +            "description": "v = vertical, h = horizontal.",
        +            "enum": [
        +              "v",
        +              "h"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "type",
        +          "from",
        +          "to"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Height in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "strokeWidth": {
        +        "description": "Border thickness in whole pixels, growing inward from the rect edge (default: 1). Requires borderColor.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "rect",
        +        "description": "Rectangle element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Width in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "w",
        +      "h"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Filled or outline circle element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "antialias": {
        +        "description": "Shade each outline pixel by how much of it the ring covers, for a smooth curve (default: false, hard pixel edges). Outline circles only (fill: false).",
        +        "type": "boolean"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Circle color.",
        +        "type": "string"
        +      },
        +      "cx": {
        +        "description": "Center X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "cy": {
        +        "description": "Center Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity (default 2 for motion effects). float: vertical swing of ±amplitude px. drift: horizontal swing of ±4 × amplitude px. scroll-left, scroll-right: speed — the element moves 2 × amplitude px per frame from where it is placed and never wraps, so start it at the edge it enters from and give it enough frames to cross. pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "fill": {
        +        "description": "Filled or outline only (default: true).",
        +        "type": "boolean"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "radius": {
        +        "description": "Radius in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "strokeWidth": {
        +        "description": "Outline thickness in whole pixels, centered on the circle (default: 1). Outline circles only (fill: false).",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "circle",
        +        "description": "Circle element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "cx",
        +      "cy",
        +      "radius"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Straight line element, 1px wide unless strokeWidth is set.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "antialias": {
        +        "description": "Shade each pixel by how much of it the line covers, for smooth diagonals (default: false, hard pixel edges).",
        +        "type": "boolean"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Line color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity (default 2 for motion effects). float: vertical swing of ±amplitude px. drift: horizontal swing of ±4 × amplitude px. scroll-left, scroll-right: speed — the element moves 2 × amplitude px per frame from where it is placed and never wraps, so start it at the edge it enters from and give it enough frames to cross. pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "strokeWidth": {
        +        "description": "Line thickness in whole pixels, centered on the line (default: 1).",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "line",
        +        "description": "Line element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x0": {
        +        "description": "Start X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "x1": {
        +        "description": "End X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y0": {
        +        "description": "Start Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y1": {
        +        "description": "End Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x0",
        +      "y0",
        +      "x1",
        +      "y1"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Horizontal progress bar widget.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element (no color track). Set either effect or animate, not both.",
        +        "properties": {
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity (default 2 for motion effects). float: vertical swing of ±amplitude px. drift: horizontal swing of ±4 × amplitude px. scroll-left, scroll-right: speed — the element moves 2 × amplitude px per frame from where it is placed and never wraps, so start it at the edge it enters from and give it enough frames to cross. pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Height in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "label": {
        +        "description": "Optional label rendered on the bar.",
        +        "type": "string"
        +      },
        +      "max": {
        +        "description": "Maximum value.",
        +        "type": "number"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "palette": {
        +        "description": "Named palette for gradient fill.",
        +        "enum": [
        +          "ember",
        +          "ice",
        +          "neon",
        +          "fire",
        +          "lavender",
        +          "claude",
        +          "mono"
        +        ],
        +        "type": "string"
        +      },
        +      "trackColor": {
        +        "description": "Background track color.",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "progress",
        +        "description": "Progress bar widget type.",
        +        "type": "string"
        +      },
        +      "value": {
        +        "description": "Current value.",
        +        "type": "number"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Width in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "w",
        +      "h",
        +      "value",
        +      "max"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Sparkline chart widget (line or bar).",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Line or bar color.",
        +        "type": "string"
        +      },
        +      "data": {
        +        "description": "Data points for the chart.",
        +        "items": {
        +          "type": "number"
        +        },
        +        "minItems": 2,
        +        "type": "array"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity (default 2 for motion effects). float: vertical swing of ±amplitude px. drift: horizontal swing of ±4 × amplitude px. scroll-left, scroll-right: speed — the element moves 2 × amplitude px per frame from where it is placed and never wraps, so start it at the edge it enters from and give it enough frames to cross. pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Height in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 2,
        +        "type": "integer"
        +      },
        +      "kind": {
        +        "description": "Chart style (default: line).",
        +        "enum": [
        +          "line",
        +          "bar"
        +        ],
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "sparkline",
        +        "description": "Sparkline chart widget type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Width in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 2,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "w",
        +      "h",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Bitmap element using explicit palette indices.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element (no color track). Set either effect or animate, not both.",
        +        "properties": {
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity (default 2 for motion effects). float: vertical swing of ±amplitude px. drift: horizontal swing of ±4 × amplitude px. scroll-left, scroll-right: speed — the element moves 2 × amplitude px per frame from where it is placed and never wraps, so start it at the edge it enters from and give it enough frames to cross. pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "palette": {
        +        "description": "Color palette: array of hex colors indexed 0-F.",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "rows": {
        +        "description": "Row strings of hex palette indices (0-F, space = transparent).",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "type": {
        +        "const": "bitmap",
        +        "description": "Bitmap element using palette indices.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "rows",
        +      "palette"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Sparse scatter of individually colored pixels.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "data": {
        +        "description": "Array of pixel positions and colors.",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "A single pixel: position and color.",
        +          "properties": {
        +            "color": {
        +              "description": "Pixel color.",
        +              "type": "string"
        +            },
        +            "x": {
        +              "description": "Pixel X coordinate.",
        +              "maximum": 9007199254740991,
        +              "minimum": -9007199254740991,
        +              "type": "integer"
        +            },
        +            "y": {
        +              "description": "Pixel Y coordinate.",
        +              "maximum": 9007199254740991,
        +              "minimum": -9007199254740991,
        +              "type": "integer"
        +            }
        +          },
        +          "required": [
        +            "x",
        +            "y",
        +            "color"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity (default 2 for motion effects). float: vertical swing of ±amplitude px. drift: horizontal swing of ±4 × amplitude px. scroll-left, scroll-right: speed — the element moves 2 × amplitude px per frame from where it is placed and never wraps, so start it at the edge it enters from and give it enough frames to cross. pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "pixels",
        +        "description": "Sparse pixel dots element.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "External image element (absolute local path or https URL).",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element (no color track). Set either effect or animate, not both.",
        +        "properties": {
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity (default 2 for motion effects). float: vertical swing of ±amplitude px. drift: horizontal swing of ±4 × amplitude px. scroll-left, scroll-right: speed — the element moves 2 × amplitude px per frame from where it is placed and never wraps, so start it at the edge it enters from and give it enough frames to cross. pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "finish": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": false,
        +            "description": "Reduce to a palette built from the image.",
        +            "properties": {
        +              "colors": {
        +                "description": "Build a palette of at most this many colors (2–256) from the image itself.",
        +                "maximum": 256,
        +                "minimum": 2,
        +                "type": "integer"
        +              },
        +              "dither": {
        +                "default": "none",
        +                "description": "How palette colors are placed: none maps each pixel to its nearest color; bayer4 mixes the two nearest in an ordered 4×4 pattern; floyd-steinberg diffuses the difference to neighboring pixels, smoothest on photos.",
        +                "enum": [
        +                  "none",
        +                  "bayer4",
        +                  "floyd-steinberg"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "colors"
        +            ],
        +            "type": "object"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "description": "Reduce to a fixed palette.",
        +            "properties": {
        +              "dither": {
        +                "default": "none",
        +                "description": "How palette colors are placed: none maps each pixel to its nearest color; bayer4 mixes the two nearest in an ordered 4×4 pattern; floyd-steinberg diffuses the difference to neighboring pixels, smoothest on photos.",
        +                "enum": [
        +                  "none",
        +                  "bayer4",
        +                  "floyd-steinberg"
        +                ],
        +                "type": "string"
        +              },
        +              "palette": {
        +                "description": "Map every pixel to these colors (1–256 entries).",
        +                "items": {
        +                  "description": "Hex color (#RRGGBB or #RGB) or a named color.",
        +                  "type": "string"
        +                },
        +                "maxItems": 256,
        +                "minItems": 1,
        +                "type": "array"
        +              }
        +            },
        +            "required": [
        +              "palette"
        +            ],
        +            "type": "object"
        +          }
        +        ],
        +        "description": "Reduce the image to a palette before it reaches the panel: exactly one of colors (2–256, built from the image) or palette (1–256 hex or named colors), plus dither. Transparent pixels stay unlit and are not counted. The preview shows the finished frame."
        +      },
        +      "fit": {
        +        "description": "Resize fit mode (default: contain).",
        +        "enum": [
        +          "contain",
        +          "cover",
        +          "fill"
        +        ],
        +        "type": "string"
        +      },
        +      "h": {
        +        "description": "Target height (default: canvas height).",
        +        "maximum": 256,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "kernel": {
        +        "description": "Resize kernel: nearest for pixel art, lanczos3 for photos (default: nearest).",
        +        "enum": [
        +          "nearest",
        +          "lanczos3",
        +          "mitchell"
        +        ],
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "source": {
        +        "description": "Absolute local file path or https (not http) URL; a relative path is rejected.",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "image",
        +        "description": "Image element (absolute local path or https URL).",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Target width (default: canvas width).",
        +        "maximum": 256,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X offset on canvas (default: 0).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y offset on canvas (default: 0).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "source"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Sprite sheet element for character or tile art.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element (no color track). Set either effect or animate, not both.",
        +        "properties": {
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "bodyColor": {
        +        "description": "Override body color.",
        +        "type": "string"
        +      },
        +      "cols": {
        +        "description": "Number of columns in the sprite grid.",
        +        "maximum": 64,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "darkColor": {
        +        "description": "Override dark/eye color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity (default 2 for motion effects). float: vertical swing of ±amplitude px. drift: horizontal swing of ±4 × amplitude px. scroll-left, scroll-right: speed — the element moves 2 × amplitude px per frame from where it is placed and never wraps, so start it at the edge it enters from and give it enough frames to cross. pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "path": {
        +        "description": "Absolute local path to the sprite sheet image; a relative path is rejected.",
        +        "type": "string"
        +      },
        +      "rows": {
        +        "description": "Number of rows in the sprite grid.",
        +        "maximum": 64,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "scale": {
        +        "description": "Pixel scale factor: each sprite cell renders as a scale × scale block.",
        +        "maximum": 64,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "sprite",
        +        "description": "Sprite sheet element.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel X coordinate (0 = left edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic horizontal alignment.",
        +            "enum": [
        +              "left",
        +              "center",
        +              "right"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "X position (default: center)."
        +      },
        +      "y": {
        +        "description": "Y position (default: 0).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "path",
        +      "cols",
        +      "rows"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Changedpixoo_design_brief2 fields changed
      • changedOutput schema / properties / deviceContext / properties / displaySize / description
        Previous value: -"Configured display canvas size in pixels (16, 32, or 64). Design coordinates scale to this value."New value: +"Configured display canvas size in pixels (16, 32, or 64). Coordinates are panel pixels and do not scale: lay out for this size."
      • changedOutput schema / properties / deviceContext / properties / reachable / description
        Previous value: -"True if device is currently reachable. When false, push: false is implied for all render tools."New value: +"True if the device answered. False both when no device is configured and when the configured one does not answer; pixoo://device/status configuredIp (null when unconfigured) tells them apart. Render tools still default to push: true, so pass push: false while this is false."
  2. 3 tool updatesv1.4.1
    • Changedpixoo_display_text1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set. `invalid_color`: A color value could not be resolved. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set and push was requested. `invalid_color`: A color value could not be resolved. Other values are possible when a failure originates below the handler."
    • Changedpixoo_overlay_text1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware rejected the command. `no_device_configured`: PIXOO_IP is not set. `invalid_color`: The color value could not be resolved. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware rejected the command. `no_device_configured`: PIXOO_IP is not set. `invalid_color`: The color value could not be resolved. Other values are possible when a failure originates below the handler."
    • Changedpixoo_push_image1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `gif_serve_failed`: An animation of more than 40 frames could not be served to the device: its listener failed to open, its URL ran past 255 bytes, or the device did not request the GIF within 10 s of the play, stalled its transfer for 10 s, or dropped it. `no_device_configured`: PIXOO_IP is not set. `asset_not_found`: Image path or URL could not be read. `invalid_image`: The source was read but did not decode as an image. `invalid_color`: A finish palette entry could not be resolved to a color. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `gif_serve_failed`: An animation of more than 40 frames could not be served to the device: its listener failed to open, its URL ran past 255 bytes, or the device did not request the GIF within 10 s of the play, stalled its transfer for 10 s, or dropped it. `no_device_configured`: PIXOO_IP is not set and push was requested. `asset_not_found`: Image path or URL could not be read. `invalid_image`: The source was read but did not decode as an image. `invalid_color`: A finish palette entry could not be resolved to a color. Other values are possible when a failure originates below the handler."
  3. 4 tool updatesv1.4.0
    • Changedpixoo_compose_scene7 fields changed
      • changedInput schema / properties / frames / description
        Previous value: -"Number of animation frames (1–40, default: 1). 20 frames at 150ms ≈ 3s loop."New value: +"Number of animation frames (1–800, default: 1). 20 frames at 150ms ≈ 3s loop. Up to 40 push frame by frame; more play as one GIF the device downloads from this host, so the device must reach it (behind NAT or a firewall, set PIXOO_SERVE_HOST and PIXOO_SERVE_PORT), and speed rounds to the nearest 10 ms."
      • changedInput schema / properties / frames / maximum
        Previous value: -40New value: +800
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set and push was requested. `asset_not_found`: An image source or sprite path could not be read, a sprite path was a URL, or an image URL could not be fetched. `invalid_image`: An image source or sprite path was read but did not decode as an image. `invalid_color`: A color value could not be resolved. `unknown_icon`: Icon name not found in the registry. `invalid_output_path`: The output path is relative or contains traversal segments. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `gif_serve_failed`: An animation of more than 40 frames could not be served to the device: its listener failed to open, its URL ran past 255 bytes, or the device did not request the GIF within 10 s of the play, stalled its transfer for 10 s, or dropped it. `no_device_configured`: PIXOO_IP is not set and push was requested. `asset_not_found`: An image source or sprite path could not be read, a sprite path was a URL, or an image URL could not be fetched. `invalid_image`: An image source or sprite path was read but did not decode as an image. `invalid_color`: A color value could not be resolved. `unknown_icon`: Icon name not found in the registry. `invalid_output_path`: The output path is relative or contains traversal segments. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "device_unreachable",
        -  "device_http_error",
        -  "device_rejected",
        -  "no_device_configured",
        -  "asset_not_found",
        -  "invalid_image",
        -  "invalid_color",
        -  "unknown_icon",
        -  "invalid_output_path"
        -]New value: +[
        +  "device_unreachable",
        +  "device_http_error",
        +  "device_rejected",
        +  "gif_serve_failed",
        +  "no_device_configured",
        +  "asset_not_found",
        +  "invalid_image",
        +  "invalid_color",
        +  "unknown_icon",
        +  "invalid_output_path"
        +]
      • changedOutput schema / properties / frames / description
        Previous value: -"Number of frames in the rendered output (1 for static, 2–40 for animations)."New value: +"Number of frames in the rendered output (1 for static, 2–800 for animations)."
      • changedOutput schema / properties / outputFiles / description
        Previous value: -"Absolute paths to saved output files: the output path when set, otherwise the PIXOO_OUTPUT_DIR auto-save (PNG for static, GIF for animations). Absent when neither applies."New value: +"Absolute paths to saved output files: the output path when set, otherwise the PIXOO_OUTPUT_DIR auto-save (PNG for static; for animations an 8× GIF, or past 40 frames the panel-size GIF the device downloads). Absent when neither applies."
      • changedOutput schema / properties / pushed / description
        Previous value: -"True when the device acknowledged the push. False when push: false or push failed."New value: +"True when the device acknowledged the push; past 40 frames, once it accepted the GIF play, requested the file, and the whole file was handed to the OS to send (the device does not confirm receipt). False when push: false."
    • Changedpixoo_design_brief4 fields changed
      • changedInput schema / properties / topic / description
        Previous value: -"Design topic: text (styled text guidance), scene (composition + layout zones), dashboard (widgets + metrics), animation (motion budget + effects), pixel-art (bitmap + sprite guidance), troubleshooting (device + display issues)."New value: +"Design topic: text (styled text guidance), scene (composition + layout zones), dashboard (widgets + metrics), animation (motion budget + effects), pixel-art (bitmap + sprite guidance), html (pixoo_render_html pages: loops, clock, sampling), troubleshooting (device + display issues)."
      • changedInput schema / properties / topic / enum
        Previous value: -[
        -  "text",
        -  "scene",
        -  "dashboard",
        -  "animation",
        -  "pixel-art",
        -  "troubleshooting"
        -]New value: +[
        +  "text",
        +  "scene",
        +  "dashboard",
        +  "animation",
        +  "pixel-art",
        +  "html",
        +  "troubleshooting"
        +]
      • changedOutput schema / anyOf
        Previous value: -[
        -  {
        -    "not": {
        -      "required": [
        -        "error"
        -      ]
        -    },
        -    "required": [
        -      "topic",
        -      "craftGuidance",
        -      "deviceContext",
        -      "nextToolSuggestions",
        -      "availableThemes",
        -      "iconCategories"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "error"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "topic",
        +      "craftGuidance",
        +      "deviceContext",
        +      "htmlRenderer",
        +      "nextToolSuggestions",
        +      "availableThemes",
        +      "iconCategories"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / htmlRenderer
        Added value: +{
        +  "description": "Whether pixoo_render_html can render: available; disabled (PIXOO_HTML_ENABLED=false, so the tool is not listed); or no_browser (no browser found, so the tool fails browser_unavailable until one is installed).",
        +  "enum": [
        +    "available",
        +    "disabled",
        +    "no_browser"
        +  ],
        +  "type": "string"
        +}
    • Changedpixoo_push_image7 fields changed
      • addedInput schema / properties / maxFrames
        Added value: +{
        +  "default": 40,
        +  "description": "Most frames an animated source pushes (1–800, default 40); a longer source is sampled evenly down to it. Up to 40 push frame by frame; more play as one GIF the device downloads from this host, so the device must reach it (behind NAT or a firewall, set PIXOO_SERVE_HOST and PIXOO_SERVE_PORT), and speed rounds to the nearest 10 ms. A still ignores it.",
        +  "maximum": 800,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set. `asset_not_found`: Image path or URL could not be read. `invalid_image`: The source was read but did not decode as an image. `invalid_color`: A finish palette entry could not be resolved to a color. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `gif_serve_failed`: An animation of more than 40 frames could not be served to the device: its listener failed to open, its URL ran past 255 bytes, or the device did not request the GIF within 10 s of the play, stalled its transfer for 10 s, or dropped it. `no_device_configured`: PIXOO_IP is not set. `asset_not_found`: Image path or URL could not be read. `invalid_image`: The source was read but did not decode as an image. `invalid_color`: A finish palette entry could not be resolved to a color. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "device_unreachable",
        -  "device_http_error",
        -  "device_rejected",
        -  "no_device_configured",
        -  "asset_not_found",
        -  "invalid_image",
        -  "invalid_color"
        -]New value: +[
        +  "device_unreachable",
        +  "device_http_error",
        +  "device_rejected",
        +  "gif_serve_failed",
        +  "no_device_configured",
        +  "asset_not_found",
        +  "invalid_image",
        +  "invalid_color"
        +]
      • changedOutput schema / properties / frames / description
        Previous value: -"Frames rendered and pushed: 1 for a still, 2–40 for an animation."New value: +"Frames rendered and pushed: 1 for a still, 2 to maxFrames for an animation."
      • changedOutput schema / properties / outputFiles / description
        Previous value: -"Absolute paths to saved preview files: a PNG for a still, a GIF at the pushed speed for an animation. Present only when PIXOO_OUTPUT_DIR is configured."New value: +"Absolute paths to saved preview files: a PNG for a still, an 8× GIF at the pushed speed for an animation, or past 40 frames the panel-size GIF the device downloads. Present only when PIXOO_OUTPUT_DIR is configured."
      • changedOutput schema / properties / pushed / description
        Previous value: -"True when the device acknowledged the push."New value: +"True when the device acknowledged the push; past 40 frames, once it accepted the GIF play, requested the file, and the whole file was handed to the OS to send (the device does not confirm receipt)."
      • changedOutput schema / properties / sourceFrames / description
        Previous value: -"Frames in the source before sampling down to 40: 1 for a still."New value: +"Frames in the source before sampling down to maxFrames: 1 for a still."
    • Addedpixoo_render_html
  4. 3 tool updatesv1.3.0
    • Changedpixoo_compose_scene12 fields changed
      • changedInput schema / properties / background / anyOf
        Previous value: -[
        -  {
        -    "description": "Solid CSS hex color.",
        -    "type": "string"
        -  },
        -  {
        -    "description": "Gradient background: specify type and two colors.",
        -    "properties": {
        -      "gradient": {
        -        "description": "Gradient background.",
        -        "properties": {
        -          "from": {
        -            "description": "Gradient start color.",
        -            "type": "string"
        -          },
        -          "to": {
        -            "description": "Gradient end color.",
        -            "type": "string"
        -          },
        -          "type": {
        -            "description": "v = vertical, h = horizontal, r = radial.",
        -            "enum": [
        -              "v",
        -              "h",
        -              "r"
        -            ],
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "type",
        -          "from",
        -          "to"
        -        ],
        -        "type": "object"
        -      }
        -    },
        -    "required": [
        -      "gradient"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Named theme background: uses the theme's preset gradient.",
        -    "properties": {
        -      "theme": {
        -        "description": "Named theme.",
        -        "enum": [
        -          "midnight",
        -          "ember",
        -          "claude",
        -          "ice",
        -          "neon",
        -          "forest",
        -          "mono"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "theme"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "description": "Solid CSS hex color.",
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Gradient or named-theme background: set exactly one of gradient or theme.",
        +    "properties": {
        +      "gradient": {
        +        "additionalProperties": false,
        +        "description": "Gradient background: type and two colors.",
        +        "properties": {
        +          "from": {
        +            "description": "Gradient start color.",
        +            "type": "string"
        +          },
        +          "to": {
        +            "description": "Gradient end color.",
        +            "type": "string"
        +          },
        +          "type": {
        +            "description": "v = vertical, h = horizontal, r = radial.",
        +            "enum": [
        +              "v",
        +              "h",
        +              "r"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "type",
        +          "from",
        +          "to"
        +        ],
        +        "type": "object"
        +      },
        +      "theme": {
        +        "description": "Named theme: uses the theme's preset background.",
        +        "enum": [
        +          "midnight",
        +          "ember",
        +          "claude",
        +          "ice",
        +          "neon",
        +          "forest",
        +          "mono"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / background / description
        Previous value: -"Scene background: solid color, gradient, or named theme."New value: +"Scene background: a solid color string, or an object holding exactly one of gradient or theme."
      • changedInput schema / properties / elements / description
        Previous value: -"Scene elements rendered back-to-front. Up to 50 elements."New value: +"Scene elements rendered back-to-front. Up to 50 elements. Each element takes either effect or animate, not both. An element's animate keyframes can drive dx, dy, and opacity (numbers or numeric strings, interpolated), visible (true or false, switching at the midpoint between keyframes), and color on any element with a color field (interpolated through RGB)."
      • changedInput schema / properties / elements / items / oneOf
        Previous value: -[
        -  {
        -    "description": "Styled text element rendered at a position.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": false,
        -            "maxItems": 2,
        -            "minItems": 2,
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "description": "Value at this frame.",
        -                "type": [
        -                  "number",
        -                  "string",
        -                  "boolean"
        -                ]
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Flat text color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "font": {
        -        "description": "Font variant.",
        -        "enum": [
        -          "standard",
        -          "compact"
        -        ],
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "style": {
        -        "description": "Text style options.",
        -        "properties": {
        -          "color": {
        -            "description": "Flat color override.",
        -            "type": "string"
        -          },
        -          "outline": {
        -            "description": "1px outline.",
        -            "type": "boolean"
        -          },
        -          "palette": {
        -            "anyOf": [
        -              {
        -                "description": "Named built-in color palette for the vertical ramp.",
        -                "enum": [
        -                  "ember",
        -                  "ice",
        -                  "neon",
        -                  "fire",
        -                  "lavender",
        -                  "claude",
        -                  "mono"
        -                ],
        -                "type": "string"
        -              },
        -              {
        -                "description": "Custom gradient stop: specify top and bottom colors directly.",
        -                "properties": {
        -                  "from": {
        -                    "description": "Top color.",
        -                    "type": "string"
        -                  },
        -                  "to": {
        -                    "description": "Bottom color.",
        -                    "type": "string"
        -                  }
        -                },
        -                "required": [
        -                  "from",
        -                  "to"
        -                ],
        -                "type": "object"
        -              }
        -            ],
        -            "description": "Palette name or custom gradient stop for vertical color ramp."
        -          },
        -          "scale": {
        -            "description": "Integer pixel scale multiplier.",
        -            "maximum": 8,
        -            "minimum": 1,
        -            "type": "integer"
        -          },
        -          "shadow": {
        -            "description": "Drop shadow.",
        -            "type": "boolean"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "text": {
        -        "description": "Text content to render.",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "text",
        -        "description": "Text element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel X coordinate (0 = left edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic horizontal alignment.",
        -            "enum": [
        -              "left",
        -              "center",
        -              "right"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "X position (default: 0)."
        -      },
        -      "y": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel Y coordinate (0 = top edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic vertical alignment.",
        -            "enum": [
        -              "top",
        -              "center",
        -              "bottom"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "Y position (default: 0)."
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Built-in or custom SVG icon element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": false,
        -            "maxItems": 2,
        -            "minItems": 2,
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "description": "Value at this frame.",
        -                "type": [
        -                  "number",
        -                  "string",
        -                  "boolean"
        -                ]
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Icon fill color.",
        -        "type": "string"
        -      },
        -      "d": {
        -        "description": "Custom SVG path d attribute.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Render height in pixels (default: 12).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "name": {
        -        "description": "Built-in icon name (see pixoo://reference/icons).",
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "palette": {
        -        "description": "Named palette for colored icon.",
        -        "enum": [
        -          "ember",
        -          "ice",
        -          "neon",
        -          "fire",
        -          "lavender",
        -          "claude",
        -          "mono"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "icon",
        -        "description": "Icon element type.",
        -        "type": "string"
        -      },
        -      "viewBox": {
        -        "description": "SVG viewBox string (default: \"0 0 16 16\").",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Render width in pixels (default: 12).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel X coordinate (0 = left edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic horizontal alignment.",
        -            "enum": [
        -              "left",
        -              "center",
        -              "right"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "X position."
        -      },
        -      "y": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel Y coordinate (0 = top edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic vertical alignment.",
        -            "enum": [
        -              "top",
        -              "center",
        -              "bottom"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "Y position."
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Filled or gradient rectangle element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": false,
        -            "maxItems": 2,
        -            "minItems": 2,
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "description": "Value at this frame.",
        -                "type": [
        -                  "number",
        -                  "string",
        -                  "boolean"
        -                ]
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "borderColor": {
        -        "description": "1px border color.",
        -        "type": "string"
        -      },
        -      "color": {
        -        "description": "Fill color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "gradient": {
        -        "description": "Gradient fill.",
        -        "properties": {
        -          "from": {
        -            "description": "Start color.",
        -            "type": "string"
        -          },
        -          "to": {
        -            "description": "End color.",
        -            "type": "string"
        -          },
        -          "type": {
        -            "description": "v = vertical, h = horizontal.",
        -            "enum": [
        -              "v",
        -              "h"
        -            ],
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "type",
        -          "from",
        -          "to"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Height in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "rect",
        -        "description": "Rectangle element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Width in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "w",
        -      "h"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Filled or outline circle element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": false,
        -            "maxItems": 2,
        -            "minItems": 2,
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "description": "Value at this frame.",
        -                "type": [
        -                  "number",
        -                  "string",
        -                  "boolean"
        -                ]
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Circle color.",
        -        "type": "string"
        -      },
        -      "cx": {
        -        "description": "Center X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "cy": {
        -        "description": "Center Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "fill": {
        -        "description": "Filled or outline only (default: true).",
        -        "type": "boolean"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "radius": {
        -        "description": "Radius in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "circle",
        -        "description": "Circle element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "cx",
        -      "cy",
        -      "radius"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Single-pixel line element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": false,
        -            "maxItems": 2,
        -            "minItems": 2,
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "description": "Value at this frame.",
        -                "type": [
        -                  "number",
        -                  "string",
        -                  "boolean"
        -                ]
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Line color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "line",
        -        "description": "Line element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x0": {
        -        "description": "Start X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "x1": {
        -        "description": "End X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y0": {
        -        "description": "Start Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y1": {
        -        "description": "End Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x0",
        -      "y0",
        -      "x1",
        -      "y1"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Horizontal progress bar widget.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": false,
        -            "maxItems": 2,
        -            "minItems": 2,
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "description": "Value at this frame.",
        -                "type": [
        -                  "number",
        -                  "string",
        -                  "boolean"
        -                ]
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Height in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "label": {
        -        "description": "Optional label rendered on the bar.",
        -        "type": "string"
        -      },
        -      "max": {
        -        "description": "Maximum value.",
        -        "type": "number"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "palette": {
        -        "description": "Named palette for gradient fill.",
        -        "enum": [
        -          "ember",
        -          "ice",
        -          "neon",
        -          "fire",
        -          "lavender",
        -          "claude",
        -          "mono"
        -        ],
        -        "type": "string"
        -      },
        -      "trackColor": {
        -        "description": "Background track color.",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "progress",
        -        "description": "Progress bar widget type.",
        -        "type": "string"
        -      },
        -      "value": {
        -        "description": "Current value.",
        -        "type": "number"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Width in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "w",
        -      "h",
        -      "value",
        -      "max"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Sparkline chart widget (line or bar).",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": false,
        -            "maxItems": 2,
        -            "minItems": 2,
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "description": "Value at this frame.",
        -                "type": [
        -                  "number",
        -                  "string",
        -                  "boolean"
        -                ]
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Line or bar color.",
        -        "type": "string"
        -      },
        -      "data": {
        -        "description": "Data points for the chart.",
        -        "items": {
        -          "type": "number"
        -        },
        -        "minItems": 2,
        -        "type": "array"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Height in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 2,
        -        "type": "integer"
        -      },
        -      "kind": {
        -        "description": "Chart style (default: line).",
        -        "enum": [
        -          "line",
        -          "bar"
        -        ],
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "sparkline",
        -        "description": "Sparkline chart widget type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Width in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 2,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "w",
        -      "h",
        -      "data"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Bitmap element using explicit palette indices.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": false,
        -            "maxItems": 2,
        -            "minItems": 2,
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "description": "Value at this frame.",
        -                "type": [
        -                  "number",
        -                  "string",
        -                  "boolean"
        -                ]
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "palette": {
        -        "description": "Color palette: array of hex colors indexed 0-F.",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "rows": {
        -        "description": "Row strings of hex palette indices (0-F, space = transparent).",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "type": {
        -        "const": "bitmap",
        -        "description": "Bitmap element using palette indices.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "rows",
        -      "palette"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Sparse scatter of individually colored pixels.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": false,
        -            "maxItems": 2,
        -            "minItems": 2,
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "description": "Value at this frame.",
        -                "type": [
        -                  "number",
        -                  "string",
        -                  "boolean"
        -                ]
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "data": {
        -        "description": "Array of pixel positions and colors.",
        -        "items": {
        -          "description": "A single pixel: position and color.",
        -          "properties": {
        -            "color": {
        -              "description": "Pixel color.",
        -              "type": "string"
        -            },
        -            "x": {
        -              "description": "Pixel X coordinate.",
        -              "maximum": 9007199254740991,
        -              "minimum": -9007199254740991,
        -              "type": "integer"
        -            },
        -            "y": {
        -              "description": "Pixel Y coordinate.",
        -              "maximum": 9007199254740991,
        -              "minimum": -9007199254740991,
        -              "type": "integer"
        -            }
        -          },
        -          "required": [
        -            "x",
        -            "y",
        -            "color"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "pixels",
        -        "description": "Sparse pixel dots element.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "data"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "External image element (local path or https URL).",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": false,
        -            "maxItems": 2,
        -            "minItems": 2,
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "description": "Value at this frame.",
        -                "type": [
        -                  "number",
        -                  "string",
        -                  "boolean"
        -                ]
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "fit": {
        -        "description": "Resize fit mode (default: contain).",
        -        "enum": [
        -          "contain",
        -          "cover",
        -          "fill"
        -        ],
        -        "type": "string"
        -      },
        -      "h": {
        -        "description": "Target height (default: canvas height).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "kernel": {
        -        "description": "Resize kernel: nearest for pixel art, lanczos3 for photos (default: nearest).",
        -        "enum": [
        -          "nearest",
        -          "lanczos3",
        -          "mitchell"
        -        ],
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "source": {
        -        "description": "Absolute local file path or https (not http) URL.",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "image",
        -        "description": "Image element (local path or https URL).",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Target width (default: canvas width).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X offset on canvas (default: 0).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y offset on canvas (default: 0).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "source"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Sprite sheet element for character or tile art.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": false,
        -            "maxItems": 2,
        -            "minItems": 2,
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "description": "Value at this frame.",
        -                "type": [
        -                  "number",
        -                  "string",
        -                  "boolean"
        -                ]
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "bodyColor": {
        -        "description": "Override body color.",
        -        "type": "string"
        -      },
        -      "cols": {
        -        "description": "Number of columns in the sprite grid.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "darkColor": {
        -        "description": "Override dark/eye color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "path": {
        -        "description": "Absolute local path to the sprite sheet image.",
        -        "type": "string"
        -      },
        -      "rows": {
        -        "description": "Number of rows in the sprite grid.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "scale": {
        -        "description": "Pixel scale factor.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "sprite",
        -        "description": "Sprite sheet element.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel X coordinate (0 = left edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic horizontal alignment.",
        -            "enum": [
        -              "left",
        -              "center",
        -              "right"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "X position (default: center)."
        -      },
        -      "y": {
        -        "description": "Y position (default: 0).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "path",
        -      "cols",
        -      "rows"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "description": "Styled text element rendered at a position.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Flat text color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "font": {
        +        "description": "Font variant (default: standard): standard (5×7) or compact (3×5), each printable ASCII plus ° ← ↑ → ↓ ▲ ▼ ♥ · …; or numerals (11×18 digits for clocks and readouts), which draws only 0–9, space, and : . - + / % ° ?, so text holding any other character is rejected — put units and labels in a separate standard or compact text element.",
        +        "enum": [
        +          "standard",
        +          "compact",
        +          "numerals"
        +        ],
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "style": {
        +        "additionalProperties": false,
        +        "description": "Text style options.",
        +        "properties": {
        +          "color": {
        +            "description": "Flat color override.",
        +            "type": "string"
        +          },
        +          "outline": {
        +            "description": "1px outline.",
        +            "type": "boolean"
        +          },
        +          "palette": {
        +            "anyOf": [
        +              {
        +                "description": "Named built-in color palette for the vertical ramp.",
        +                "enum": [
        +                  "ember",
        +                  "ice",
        +                  "neon",
        +                  "fire",
        +                  "lavender",
        +                  "claude",
        +                  "mono"
        +                ],
        +                "type": "string"
        +              },
        +              {
        +                "additionalProperties": false,
        +                "description": "Custom gradient stop: specify top and bottom colors directly.",
        +                "properties": {
        +                  "from": {
        +                    "description": "Top color.",
        +                    "type": "string"
        +                  },
        +                  "to": {
        +                    "description": "Bottom color.",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "from",
        +                  "to"
        +                ],
        +                "type": "object"
        +              }
        +            ],
        +            "description": "Palette name or custom gradient stop for vertical color ramp."
        +          },
        +          "scale": {
        +            "description": "Integer pixel scale multiplier.",
        +            "maximum": 8,
        +            "minimum": 1,
        +            "type": "integer"
        +          },
        +          "shadow": {
        +            "description": "Drop shadow.",
        +            "type": "boolean"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "text": {
        +        "description": "Text content to render.",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "text",
        +        "description": "Text element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel X coordinate (0 = left edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic horizontal alignment.",
        +            "enum": [
        +              "left",
        +              "center",
        +              "right"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "X position (default: 0)."
        +      },
        +      "y": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel Y coordinate (0 = top edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic vertical alignment.",
        +            "enum": [
        +              "top",
        +              "center",
        +              "bottom"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "Y position (default: 0)."
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Built-in or custom SVG icon element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Icon color (default: white).",
        +        "type": "string"
        +      },
        +      "d": {
        +        "description": "Custom SVG path d attribute.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Render height in pixels (default: 12).",
        +        "maximum": 256,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "name": {
        +        "description": "Built-in icon name (see pixoo://reference/icons).",
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "palette": {
        +        "description": "Named palette painted as a top-to-bottom color ramp from the icon's top row to its bottom row. Takes precedence over color.",
        +        "enum": [
        +          "ember",
        +          "ice",
        +          "neon",
        +          "fire",
        +          "lavender",
        +          "claude",
        +          "mono"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "icon",
        +        "description": "Icon element type.",
        +        "type": "string"
        +      },
        +      "viewBox": {
        +        "description": "SVG viewBox string (default: \"0 0 16 16\").",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Render width in pixels (default: 12).",
        +        "maximum": 256,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel X coordinate (0 = left edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic horizontal alignment.",
        +            "enum": [
        +              "left",
        +              "center",
        +              "right"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "X position."
        +      },
        +      "y": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel Y coordinate (0 = top edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic vertical alignment.",
        +            "enum": [
        +              "top",
        +              "center",
        +              "bottom"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "Y position."
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Filled, gradient, or bordered rectangle element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "borderColor": {
        +        "description": "Border color. The border is drawn inside the rect, strokeWidth pixels thick.",
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Fill color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "gradient": {
        +        "additionalProperties": false,
        +        "description": "Gradient fill.",
        +        "properties": {
        +          "from": {
        +            "description": "Start color.",
        +            "type": "string"
        +          },
        +          "to": {
        +            "description": "End color.",
        +            "type": "string"
        +          },
        +          "type": {
        +            "description": "v = vertical, h = horizontal.",
        +            "enum": [
        +              "v",
        +              "h"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "type",
        +          "from",
        +          "to"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Height in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "strokeWidth": {
        +        "description": "Border thickness in whole pixels, growing inward from the rect edge (default: 1). Requires borderColor.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "rect",
        +        "description": "Rectangle element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Width in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "w",
        +      "h"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Filled or outline circle element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "antialias": {
        +        "description": "Shade each outline pixel by how much of it the ring covers, for a smooth curve (default: false, hard pixel edges). Outline circles only (fill: false).",
        +        "type": "boolean"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Circle color.",
        +        "type": "string"
        +      },
        +      "cx": {
        +        "description": "Center X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "cy": {
        +        "description": "Center Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "fill": {
        +        "description": "Filled or outline only (default: true).",
        +        "type": "boolean"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "radius": {
        +        "description": "Radius in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "strokeWidth": {
        +        "description": "Outline thickness in whole pixels, centered on the circle (default: 1). Outline circles only (fill: false).",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "circle",
        +        "description": "Circle element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "cx",
        +      "cy",
        +      "radius"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Straight line element, 1px wide unless strokeWidth is set.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "antialias": {
        +        "description": "Shade each pixel by how much of it the line covers, for smooth diagonals (default: false, hard pixel edges).",
        +        "type": "boolean"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Line color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "strokeWidth": {
        +        "description": "Line thickness in whole pixels, centered on the line (default: 1).",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "line",
        +        "description": "Line element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x0": {
        +        "description": "Start X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "x1": {
        +        "description": "End X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y0": {
        +        "description": "Start Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y1": {
        +        "description": "End Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x0",
        +      "y0",
        +      "x1",
        +      "y1"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Horizontal progress bar widget.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element (no color track). Set either effect or animate, not both.",
        +        "properties": {
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Height in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "label": {
        +        "description": "Optional label rendered on the bar.",
        +        "type": "string"
        +      },
        +      "max": {
        +        "description": "Maximum value.",
        +        "type": "number"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "palette": {
        +        "description": "Named palette for gradient fill.",
        +        "enum": [
        +          "ember",
        +          "ice",
        +          "neon",
        +          "fire",
        +          "lavender",
        +          "claude",
        +          "mono"
        +        ],
        +        "type": "string"
        +      },
        +      "trackColor": {
        +        "description": "Background track color.",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "progress",
        +        "description": "Progress bar widget type.",
        +        "type": "string"
        +      },
        +      "value": {
        +        "description": "Current value.",
        +        "type": "number"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Width in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "w",
        +      "h",
        +      "value",
        +      "max"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Sparkline chart widget (line or bar).",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Line or bar color.",
        +        "type": "string"
        +      },
        +      "data": {
        +        "description": "Data points for the chart.",
        +        "items": {
        +          "type": "number"
        +        },
        +        "minItems": 2,
        +        "type": "array"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Height in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 2,
        +        "type": "integer"
        +      },
        +      "kind": {
        +        "description": "Chart style (default: line).",
        +        "enum": [
        +          "line",
        +          "bar"
        +        ],
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "sparkline",
        +        "description": "Sparkline chart widget type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Width in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 2,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "w",
        +      "h",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Bitmap element using explicit palette indices.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element (no color track). Set either effect or animate, not both.",
        +        "properties": {
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "palette": {
        +        "description": "Color palette: array of hex colors indexed 0-F.",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "rows": {
        +        "description": "Row strings of hex palette indices (0-F, space = transparent).",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "type": {
        +        "const": "bitmap",
        +        "description": "Bitmap element using palette indices.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "rows",
        +      "palette"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Sparse scatter of individually colored pixels.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "color": {
        +            "description": "Color keyframes (hex or named), interpolated through RGB; each frame's value stands in for the element's color (on pixels, every point's color).",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Color at this frame.",
        +                  "type": [
        +                    "number",
        +                    "string",
        +                    "boolean"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "data": {
        +        "description": "Array of pixel positions and colors.",
        +        "items": {
        +          "additionalProperties": false,
        +          "description": "A single pixel: position and color.",
        +          "properties": {
        +            "color": {
        +              "description": "Pixel color.",
        +              "type": "string"
        +            },
        +            "x": {
        +              "description": "Pixel X coordinate.",
        +              "maximum": 9007199254740991,
        +              "minimum": -9007199254740991,
        +              "type": "integer"
        +            },
        +            "y": {
        +              "description": "Pixel Y coordinate.",
        +              "maximum": 9007199254740991,
        +              "minimum": -9007199254740991,
        +              "type": "integer"
        +            }
        +          },
        +          "required": [
        +            "x",
        +            "y",
        +            "color"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "pixels",
        +        "description": "Sparse pixel dots element.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "External image element (absolute local path or https URL).",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element (no color track). Set either effect or animate, not both.",
        +        "properties": {
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "finish": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": false,
        +            "description": "Reduce to a palette built from the image.",
        +            "properties": {
        +              "colors": {
        +                "description": "Build a palette of at most this many colors (2–256) from the image itself.",
        +                "maximum": 256,
        +                "minimum": 2,
        +                "type": "integer"
        +              },
        +              "dither": {
        +                "default": "none",
        +                "description": "How palette colors are placed: none maps each pixel to its nearest color; bayer4 mixes the two nearest in an ordered 4×4 pattern; floyd-steinberg diffuses the difference to neighboring pixels, smoothest on photos.",
        +                "enum": [
        +                  "none",
        +                  "bayer4",
        +                  "floyd-steinberg"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "colors"
        +            ],
        +            "type": "object"
        +          },
        +          {
        +            "additionalProperties": false,
        +            "description": "Reduce to a fixed palette.",
        +            "properties": {
        +              "dither": {
        +                "default": "none",
        +                "description": "How palette colors are placed: none maps each pixel to its nearest color; bayer4 mixes the two nearest in an ordered 4×4 pattern; floyd-steinberg diffuses the difference to neighboring pixels, smoothest on photos.",
        +                "enum": [
        +                  "none",
        +                  "bayer4",
        +                  "floyd-steinberg"
        +                ],
        +                "type": "string"
        +              },
        +              "palette": {
        +                "description": "Map every pixel to these colors (1–256 entries).",
        +                "items": {
        +                  "description": "Hex color (#RRGGBB or #RGB) or a named color.",
        +                  "type": "string"
        +                },
        +                "maxItems": 256,
        +                "minItems": 1,
        +                "type": "array"
        +              }
        +            },
        +            "required": [
        +              "palette"
        +            ],
        +            "type": "object"
        +          }
        +        ],
        +        "description": "Reduce the image to a palette before it reaches the panel: exactly one of colors (2–256, built from the image) or palette (1–256 hex or named colors), plus dither. Transparent pixels stay unlit and are not counted. The preview shows the finished frame."
        +      },
        +      "fit": {
        +        "description": "Resize fit mode (default: contain).",
        +        "enum": [
        +          "contain",
        +          "cover",
        +          "fill"
        +        ],
        +        "type": "string"
        +      },
        +      "h": {
        +        "description": "Target height (default: canvas height).",
        +        "maximum": 256,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "kernel": {
        +        "description": "Resize kernel: nearest for pixel art, lanczos3 for photos (default: nearest).",
        +        "enum": [
        +          "nearest",
        +          "lanczos3",
        +          "mitchell"
        +        ],
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "source": {
        +        "description": "Absolute local file path or https (not http) URL; a relative path is rejected.",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "image",
        +        "description": "Image element (absolute local path or https URL).",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Target width (default: canvas width).",
        +        "maximum": 256,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X offset on canvas (default: 0).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y offset on canvas (default: 0).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "source"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Sprite sheet element for character or tile art.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": false,
        +        "description": "Raw keyframe animation map for this element (no color track). Set either effect or animate, not both.",
        +        "properties": {
        +          "dx": {
        +            "description": "X offset keyframes in pixels, added to dx and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "dy": {
        +            "description": "Y offset keyframes in pixels, added to dy and interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "opacity": {
        +            "description": "Opacity keyframes 0–100, interpolated between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Value at this frame: a number, or a numeric string such as \"40\" read as that number.",
        +                  "type": [
        +                    "number",
        +                    "string"
        +                  ]
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          },
        +          "visible": {
        +            "description": "Visibility keyframes: true or false, switching at the midpoint between keyframes.",
        +            "items": {
        +              "items": false,
        +              "maxItems": 2,
        +              "minItems": 2,
        +              "prefixItems": [
        +                {
        +                  "description": "Frame index.",
        +                  "type": "number"
        +                },
        +                {
        +                  "description": "Whether the element shows at this frame.",
        +                  "type": "boolean"
        +                }
        +              ],
        +              "type": "array"
        +            },
        +            "minItems": 1,
        +            "type": "array"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "blend": {
        +        "description": "How the element combines with what lies beneath it (default: normal, drawn over it). add sums the light of both, clamped at full brightness — for glows and light beams; screen brightens more gently; multiply darkens.",
        +        "enum": [
        +          "normal",
        +          "add",
        +          "screen",
        +          "multiply"
        +        ],
        +        "type": "string"
        +      },
        +      "bodyColor": {
        +        "description": "Override body color.",
        +        "type": "string"
        +      },
        +      "cols": {
        +        "description": "Number of columns in the sprite grid.",
        +        "maximum": 64,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "darkColor": {
        +        "description": "Override dark/eye color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "additionalProperties": false,
        +        "description": "Named animation preset for this element. Set either effect or animate, not both.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity. float, scroll-left, scroll-right, drift: movement in pixels (default 2). pulse, twinkle: 0–1 depth of the opacity dip below 100 (default 0.5 and 0.6). Other effects ignore it.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "path": {
        +        "description": "Absolute local path to the sprite sheet image; a relative path is rejected.",
        +        "type": "string"
        +      },
        +      "rows": {
        +        "description": "Number of rows in the sprite grid.",
        +        "maximum": 64,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "scale": {
        +        "description": "Pixel scale factor: each sprite cell renders as a scale × scale block.",
        +        "maximum": 64,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "sprite",
        +        "description": "Sprite sheet element.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel X coordinate (0 = left edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic horizontal alignment.",
        +            "enum": [
        +              "left",
        +              "center",
        +              "right"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "X position (default: center)."
        +      },
        +      "y": {
        +        "description": "Y position (default: 0).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "path",
        +      "cols",
        +      "rows"
        +    ],
        +    "type": "object"
        +  }
        +]
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set and push was requested. `asset_not_found`: An image or sprite path could not be read. `invalid_color`: A color value could not be resolved. `unknown_icon`: Icon name not found in the registry. `invalid_output_path`: The output path is relative or contains traversal segments. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set and push was requested. `asset_not_found`: An image source or sprite path could not be read, a sprite path was a URL, or an image URL could not be fetched. `invalid_image`: An image source or sprite path was read but did not decode as an image. `invalid_color`: A color value could not be resolved. `unknown_icon`: Icon name not found in the registry. `invalid_output_path`: The output path is relative or contains traversal segments. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "device_unreachable",
        -  "device_http_error",
        -  "device_rejected",
        -  "no_device_configured",
        -  "asset_not_found",
        -  "invalid_color",
        -  "unknown_icon",
        -  "invalid_output_path"
        -]New value: +[
        +  "device_unreachable",
        +  "device_http_error",
        +  "device_rejected",
        +  "no_device_configured",
        +  "asset_not_found",
        +  "invalid_image",
        +  "invalid_color",
        +  "unknown_icon",
        +  "invalid_output_path"
        +]
      • changedOutput schema / properties / layout / items / properties / action / description
        Previous value: -"Overflow action taken by the renderer."New value: +"Always none: scene elements are placed as given and never refit, shrunk, or scrolled. Read fits to learn whether an element runs off the panel."
      • changedOutput schema / properties / layout / items / properties / action / enum
        Previous value: -[
        -  "none",
        -  "shrunk-to-compact",
        -  "scrolling",
        -  "wrapped",
        -  "truncated",
        -  "clipped"
        -]New value: +[
        +  "none"
        +]
      • removedOutput schema / properties / layout / items / properties / element / anyOf
        Removed value: -[
        -  {
        -    "description": "Zero-based index of the element in the input array.",
        -    "type": "number"
        -  },
        -  {
        -    "const": "background",
        -    "type": "string"
        -  }
        -]
      • changedOutput schema / properties / layout / items / properties / element / description
        Previous value: -"Element index or \"background\" for the background layer."New value: +"Zero-based index of the element in the input array."
      • addedOutput schema / properties / layout / items / properties / element / type
        Added value: +"number"
      • changedOutput schema / properties / layout / items / properties / font / enum
        Previous value: -[
        -  "standard",
        -  "compact"
        -]New value: +[
        +  "standard",
        +  "compact",
        +  "numerals"
        +]
    • Changedpixoo_display_text12 fields changed
      • changedInput schema / properties / background / anyOf
        Previous value: -[
        -  {
        -    "description": "Solid CSS hex color.",
        -    "type": "string"
        -  },
        -  {
        -    "description": "Gradient background object.",
        -    "properties": {
        -      "gradient": {
        -        "description": "Gradient background specification.",
        -        "properties": {
        -          "from": {
        -            "description": "Gradient start color.",
        -            "type": "string"
        -          },
        -          "to": {
        -            "description": "Gradient end color.",
        -            "type": "string"
        -          },
        -          "type": {
        -            "description": "v = vertical, h = horizontal.",
        -            "enum": [
        -              "v",
        -              "h"
        -            ],
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "type",
        -          "from",
        -          "to"
        -        ],
        -        "type": "object"
        -      }
        -    },
        -    "required": [
        -      "gradient"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "description": "Solid CSS hex color.",
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Gradient background object.",
        +    "properties": {
        +      "gradient": {
        +        "additionalProperties": false,
        +        "description": "Gradient background specification.",
        +        "properties": {
        +          "from": {
        +            "description": "Gradient start color.",
        +            "type": "string"
        +          },
        +          "to": {
        +            "description": "Gradient end color.",
        +            "type": "string"
        +          },
        +          "type": {
        +            "description": "v = vertical, h = horizontal.",
        +            "enum": [
        +              "v",
        +              "h"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "type",
        +          "from",
        +          "to"
        +        ],
        +        "type": "object"
        +      }
        +    },
        +    "required": [
        +      "gradient"
        +    ],
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / font / description
        Previous value: -"Font variant: standard (5×7) or compact (3×5), used as given — text too wide for it overflows rather than switching font. Omitted, single-line text tries standard and falls back to compact when standard overflows; multi-line text uses standard."New value: +"Font variant, used as given — text too wide for it overflows rather than switching font: standard (5×7) or compact (3×5), each printable ASCII plus ° ← ↑ → ↓ ▲ ▼ ♥ · …; or numerals (11×18 digits for clocks and readouts), which draws only 0–9, space, and : . - + / % ° ?, so text holding any other character is rejected. Omitted, single-line text tries standard and falls back to compact when standard overflows; multi-line text uses standard."
      • changedInput schema / properties / font / enum
        Previous value: -[
        -  "standard",
        -  "compact"
        -]New value: +[
        +  "standard",
        +  "compact",
        +  "numerals"
        +]
      • addedInput schema / properties / position / additionalProperties
        Added value: +false
      • addedInput schema / properties / style / additionalProperties
        Added value: +false
      • changedInput schema / properties / style / properties / palette / anyOf
        Previous value: -[
        -  {
        -    "description": "Named built-in color palette for the vertical ramp.",
        -    "enum": [
        -      "ember",
        -      "ice",
        -      "neon",
        -      "fire",
        -      "lavender",
        -      "claude",
        -      "mono"
        -    ],
        -    "type": "string"
        -  },
        -  {
        -    "description": "Custom gradient stop: specify top and bottom colors directly.",
        -    "properties": {
        -      "from": {
        -        "description": "Gradient start color (top).",
        -        "type": "string"
        -      },
        -      "to": {
        -        "description": "Gradient end color (bottom).",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "from",
        -      "to"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "description": "Named built-in color palette for the vertical ramp.",
        +    "enum": [
        +      "ember",
        +      "ice",
        +      "neon",
        +      "fire",
        +      "lavender",
        +      "claude",
        +      "mono"
        +    ],
        +    "type": "string"
        +  },
        +  {
        +    "additionalProperties": false,
        +    "description": "Custom gradient stop: specify top and bottom colors directly.",
        +    "properties": {
        +      "from": {
        +        "description": "Gradient start color (top).",
        +        "type": "string"
        +      },
        +      "to": {
        +        "description": "Gradient end color (bottom).",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "from",
        +      "to"
        +    ],
        +    "type": "object"
        +  }
        +]
      • changedOutput schema / properties / layout / items / properties / action / description
        Previous value: -"Overflow action taken by the renderer."New value: +"What the renderer did about the width: shrunk-to-compact when single-line text fits only in the compact font; scrolling when the returned frames scroll (effect scroll, or auto on text too wide to fit); none otherwise. A line too wide for the panel that does not scroll reports none with fits false, drawn from x 0 and cut at the right edge."
      • changedOutput schema / properties / layout / items / properties / action / enum
        Previous value: -[
        -  "none",
        -  "shrunk-to-compact",
        -  "scrolling",
        -  "wrapped",
        -  "truncated",
        -  "clipped"
        -]New value: +[
        +  "none",
        +  "shrunk-to-compact",
        +  "scrolling"
        +]
      • removedOutput schema / properties / layout / items / properties / element / anyOf
        Removed value: -[
        -  {
        -    "description": "Zero-based index of the element in the input array.",
        -    "type": "number"
        -  },
        -  {
        -    "const": "background",
        -    "type": "string"
        -  }
        -]
      • changedOutput schema / properties / layout / items / properties / element / description
        Previous value: -"Element index or \"background\" for the background layer."New value: +"Zero-based line index: 0 for single-line text, the line position for an array."
      • addedOutput schema / properties / layout / items / properties / element / type
        Added value: +"number"
      • changedOutput schema / properties / layout / items / properties / font / enum
        Previous value: -[
        -  "standard",
        -  "compact"
        -]New value: +[
        +  "standard",
        +  "compact",
        +  "numerals"
        +]
    • Changedpixoo_push_image10 fields changed
      • addedInput schema / properties / finish
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "description": "Reduce to a palette built from the image.",
        +      "properties": {
        +        "colors": {
        +          "description": "Build a palette of at most this many colors (2–256) from the image itself.",
        +          "maximum": 256,
        +          "minimum": 2,
        +          "type": "integer"
        +        },
        +        "dither": {
        +          "default": "none",
        +          "description": "How palette colors are placed: none maps each pixel to its nearest color; bayer4 mixes the two nearest in an ordered 4×4 pattern; floyd-steinberg diffuses the difference to neighboring pixels, smoothest on photos.",
        +          "enum": [
        +            "none",
        +            "bayer4",
        +            "floyd-steinberg"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "colors"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "additionalProperties": false,
        +      "description": "Reduce to a fixed palette.",
        +      "properties": {
        +        "dither": {
        +          "default": "none",
        +          "description": "How palette colors are placed: none maps each pixel to its nearest color; bayer4 mixes the two nearest in an ordered 4×4 pattern; floyd-steinberg diffuses the difference to neighboring pixels, smoothest on photos.",
        +          "enum": [
        +            "none",
        +            "bayer4",
        +            "floyd-steinberg"
        +          ],
        +          "type": "string"
        +        },
        +        "palette": {
        +          "description": "Map every pixel to these colors (1–256 entries).",
        +          "items": {
        +            "description": "Hex color (#RRGGBB or #RGB) or a named color.",
        +            "type": "string"
        +          },
        +          "maxItems": 256,
        +          "minItems": 1,
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "palette"
        +      ],
        +      "type": "object"
        +    }
        +  ],
        +  "description": "Reduce the image to a palette before it reaches the panel: exactly one of colors (2–256, built from the image) or palette (1–256 hex or named colors), plus dither. Transparent pixels stay unlit and are not counted. The preview shows the finished frame."
        +}
      • changedInput schema / properties / source / description
        Previous value: -"Absolute local file path or https (not http) URL of the image to display."New value: +"Absolute local file path or https (not http) URL of the image to display; a relative path is rejected. An animated GIF or WebP, whatever its file name, pushes as an animation."
      • addedInput schema / properties / speed
        Added value: +{
        +  "description": "Milliseconds per frame for an animated source (10–2000). Default: the source's total duration over the pushed frame count, or 150 when it records no delays. A still ignores it.",
        +  "maximum": 2000,
        +  "minimum": 10,
        +  "type": "integer"
        +}
      • changedOutput schema / anyOf
        Previous value: -[
        -  {
        -    "not": {
        -      "required": [
        -        "error"
        -      ]
        -    },
        -    "required": [
        -      "pushed"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "error"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "pushed",
        +      "frames",
        +      "sourceFrames"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set. `asset_not_found`: Image path or URL could not be read. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set. `asset_not_found`: Image path or URL could not be read. `invalid_image`: The source was read but did not decode as an image. `invalid_color`: A finish palette entry could not be resolved to a color. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "device_unreachable",
        -  "device_http_error",
        -  "device_rejected",
        -  "no_device_configured",
        -  "asset_not_found"
        -]New value: +[
        +  "device_unreachable",
        +  "device_http_error",
        +  "device_rejected",
        +  "no_device_configured",
        +  "asset_not_found",
        +  "invalid_image",
        +  "invalid_color"
        +]
      • addedOutput schema / properties / frames
        Added value: +{
        +  "description": "Frames rendered and pushed: 1 for a still, 2–40 for an animation.",
        +  "type": "number"
        +}
      • changedOutput schema / properties / outputFiles / description
        Previous value: -"Absolute paths to saved PNG preview files. Present only when PIXOO_OUTPUT_DIR is configured."New value: +"Absolute paths to saved preview files: a PNG for a still, a GIF at the pushed speed for an animation. Present only when PIXOO_OUTPUT_DIR is configured."
      • addedOutput schema / properties / sourceFrames
        Added value: +{
        +  "description": "Frames in the source before sampling down to 40: 1 for a still.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / speed
        Added value: +{
        +  "description": "Milliseconds per frame the animation plays at. Absent for a still.",
        +  "type": "number"
        +}
  5. 6 tool updatesv1.2.0
    • Changedpixoo_compose_scene4 fields changed
      • changedInput schema / properties / output / description
        Previous value: -"Absolute, already-normalized path to save the first frame to, in addition to the PIXOO_OUTPUT_DIR auto-save when that is configured. Both paths are reported in outputFiles."New value: +"Absolute, already-normalized path to save the first frame to as a PNG. Replaces the PIXOO_OUTPUT_DIR auto-save for this call, so outputFiles holds only this path."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set and push was requested. `asset_not_found`: An image or sprite path could not be read. `invalid_color`: A color value could not be resolved. `unknown_icon`: Icon name not found in the registry. `invalid_output_path`: The output path is relative or contains traversal segments. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set and push was requested. `asset_not_found`: An image or sprite path could not be read. `invalid_color`: A color value could not be resolved. `unknown_icon`: Icon name not found in the registry. `invalid_output_path`: The output path is relative or contains traversal segments. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "device_unreachable",
        -  "device_rejected",
        -  "no_device_configured",
        -  "asset_not_found",
        -  "invalid_color",
        -  "unknown_icon",
        -  "invalid_output_path"
        -]New value: +[
        +  "device_unreachable",
        +  "device_http_error",
        +  "device_rejected",
        +  "no_device_configured",
        +  "asset_not_found",
        +  "invalid_color",
        +  "unknown_icon",
        +  "invalid_output_path"
        +]
      • changedOutput schema / properties / outputFiles / description
        Previous value: -"Absolute paths to saved output files (PNG for static, GIF for animations). Present only when PIXOO_OUTPUT_DIR is configured or output is set."New value: +"Absolute paths to saved output files: the output path when set, otherwise the PIXOO_OUTPUT_DIR auto-save (PNG for static, GIF for animations). Absent when neither applies."
    • Changedpixoo_control_device1 field changed
      • addedOutput schema / properties / notice
        Added value: +{
        +  "description": "Requested settings that failed, each with its failure kind and message (e.g. \"brightness:80 failed (network): …\"), joined by \"; \". Absent when every requested setting applied.",
        +  "type": "string"
        +}
    • Changedpixoo_design_brief8 fields changed
      • changedOutput schema / properties / nextToolSuggestions / items / description
        Previous value: -"A suggested next-step tool with rationale and optional pre-filled args."New value: +"A recommended follow-up call with its arguments pre-filled."
      • addedOutput schema / properties / nextToolSuggestions / items / properties / args
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Pre-filled arguments for the call; {} when the tool needs none.",
        +  "properties": {},
        +  "type": "object"
        +}
      • removedOutput schema / properties / nextToolSuggestions / items / properties / rationale
        Removed value: -{
        -  "description": "Why this tool is relevant given current state.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / nextToolSuggestions / items / properties / reason
        Added value: +{
        +  "description": "Why this step is recommended given the current device state.",
        +  "type": "string"
        +}
      • removedOutput schema / properties / nextToolSuggestions / items / properties / suggestedArgs
        Removed value: -{
        -  "additionalProperties": {},
        -  "description": "Pre-filled argument suggestions as a key-value object.",
        -  "properties": {},
        -  "type": "object"
        -}
      • removedOutput schema / properties / nextToolSuggestions / items / properties / tool
        Removed value: -{
        -  "description": "Tool name to try next.",
        -  "type": "string"
        -}
      • addedOutput schema / properties / nextToolSuggestions / items / properties / toolName
        Added value: +{
        +  "description": "Tool to call next.",
        +  "type": "string"
        +}
      • changedOutput schema / properties / nextToolSuggestions / items / required
        Previous value: -[
        -  "tool",
        -  "rationale"
        -]New value: +[
        +  "toolName",
        +  "reason",
        +  "args"
        +]
    • Changedpixoo_display_text8 fields changed
      • changedInput schema / properties / align / description
        Previous value: -"Multi-line text alignment (default: center)."New value: +"Multi-line text: align every line within the widest line, then place that block with position.x. Omit to place each line by position.x on its own."
      • changedInput schema / properties / effect / description
        Previous value: -"Animation effect. auto = scroll only when text overflows. Produces a multi-frame result."New value: +"Animation effect. scroll runs the text across the display once, in up to 40 frames; auto scrolls only when the text is too wide to fit; float (gentle bob) and pulse (breathing brightness) loop over 20 frames. An animated result is pushed as an animation and previewed as a grid of its frames. none or omitted renders one static frame."
      • changedInput schema / properties / font / description
        Previous value: -"Font variant: standard (5×7) or compact (3×5). Auto-fit will choose if omitted."New value: +"Font variant: standard (5×7) or compact (3×5), used as given — text too wide for it overflows rather than switching font. Omitted, single-line text tries standard and falls back to compact when standard overflows; multi-line text uses standard."
      • changedOutput schema / anyOf
        Previous value: -[
        -  {
        -    "not": {
        -      "required": [
        -        "error"
        -      ]
        -    },
        -    "required": [
        -      "pushed",
        -      "layout"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "error"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "pushed",
        +      "frames",
        +      "layout"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set. `invalid_color`: A color value could not be resolved. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set. `invalid_color`: A color value could not be resolved. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "device_unreachable",
        -  "device_rejected",
        -  "no_device_configured",
        -  "invalid_color"
        -]New value: +[
        +  "device_unreachable",
        +  "device_http_error",
        +  "device_rejected",
        +  "no_device_configured",
        +  "invalid_color"
        +]
      • addedOutput schema / properties / frames
        Added value: +{
        +  "description": "Number of frames rendered: 1 for static text, 2–40 when an effect animates it.",
        +  "type": "number"
        +}
      • changedOutput schema / properties / outputFiles / description
        Previous value: -"Absolute paths to saved PNG preview files. Present only when PIXOO_OUTPUT_DIR is configured."New value: +"Absolute paths to saved preview files (PNG, or GIF when an effect animates the text). Present only when PIXOO_OUTPUT_DIR is configured."
    • Changedpixoo_overlay_text6 fields changed
      • changedInput schema / properties / color / description
        Previous value: -"Text color as CSS hex color (default: white)."New value: +"Text color: hex (#RRGGBB or #RGB) or a named color such as orange (default: white)."
      • changedInput schema / properties / width / description
        Previous value: -"Text region width in pixels (optional; defaults to display width)."New value: +"Text region width in pixels, 0 to display size (64 on a 64px display; defaults to display width)."
      • changedInput schema / properties / x / description
        Previous value: -"X start position on display (default: 0)."New value: +"X start position, 0 to display size − 1 (63 on a 64px display; default: 0)."
      • changedInput schema / properties / y / description
        Previous value: -"Y start position on display (default: 0)."New value: +"Y start position, 0 to display size − 1 (63 on a 64px display; default: 0)."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_rejected`: Device firmware rejected the command. `no_device_configured`: PIXOO_IP is not set. `invalid_color`: The color value could not be resolved. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware rejected the command. `no_device_configured`: PIXOO_IP is not set. `invalid_color`: The color value could not be resolved. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "device_unreachable",
        -  "device_rejected",
        -  "no_device_configured",
        -  "invalid_color"
        -]New value: +[
        +  "device_unreachable",
        +  "device_http_error",
        +  "device_rejected",
        +  "no_device_configured",
        +  "invalid_color"
        +]
    • Changedpixoo_push_image2 fields changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set. `asset_not_found`: Image path or URL could not be read. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_http_error`: The device answered with a non-2xx HTTP status (retryable for 408, 429, 500, and 502–504). `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set. `asset_not_found`: Image path or URL could not be read. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "device_unreachable",
        -  "device_rejected",
        -  "no_device_configured",
        -  "asset_not_found"
        -]New value: +[
        +  "device_unreachable",
        +  "device_http_error",
        +  "device_rejected",
        +  "no_device_configured",
        +  "asset_not_found"
        +]
  6. 1 tool updatev1.1.3
    • Changedpixoo_control_device2 fields changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_rejected`: Device rejected the command. `no_device_configured`: PIXOO_IP is not set. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `no_device_configured`: PIXOO_IP is not set. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "device_unreachable",
        -  "device_rejected",
        -  "no_device_configured"
        -]New value: +[
        +  "no_device_configured"
        +]
  7. 1 tool updatev1.1.2
    • Changedpixoo_compose_scene1 field changed
      • changedInput schema / properties / elements / items / oneOf
        Previous value: -[
        -  {
        -    "description": "Styled text element rendered at a position.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Flat text color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "font": {
        -        "description": "Font variant.",
        -        "enum": [
        -          "standard",
        -          "compact"
        -        ],
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "style": {
        -        "description": "Text style options.",
        -        "properties": {
        -          "color": {
        -            "description": "Flat color override.",
        -            "type": "string"
        -          },
        -          "outline": {
        -            "description": "1px outline.",
        -            "type": "boolean"
        -          },
        -          "palette": {
        -            "anyOf": [
        -              {
        -                "description": "Named built-in color palette for the vertical ramp.",
        -                "enum": [
        -                  "ember",
        -                  "ice",
        -                  "neon",
        -                  "fire",
        -                  "lavender",
        -                  "claude",
        -                  "mono"
        -                ],
        -                "type": "string"
        -              },
        -              {
        -                "description": "Custom gradient stop: specify top and bottom colors directly.",
        -                "properties": {
        -                  "from": {
        -                    "description": "Top color.",
        -                    "type": "string"
        -                  },
        -                  "to": {
        -                    "description": "Bottom color.",
        -                    "type": "string"
        -                  }
        -                },
        -                "required": [
        -                  "from",
        -                  "to"
        -                ],
        -                "type": "object"
        -              }
        -            ],
        -            "description": "Palette name or custom gradient stop for vertical color ramp."
        -          },
        -          "scale": {
        -            "description": "Integer pixel scale multiplier.",
        -            "maximum": 8,
        -            "minimum": 1,
        -            "type": "integer"
        -          },
        -          "shadow": {
        -            "description": "Drop shadow.",
        -            "type": "boolean"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "text": {
        -        "description": "Text content to render.",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "text",
        -        "description": "Text element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel X coordinate (0 = left edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic horizontal alignment.",
        -            "enum": [
        -              "left",
        -              "center",
        -              "right"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "X position (default: 0)."
        -      },
        -      "y": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel Y coordinate (0 = top edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic vertical alignment.",
        -            "enum": [
        -              "top",
        -              "center",
        -              "bottom"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "Y position (default: 0)."
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Built-in or custom SVG icon element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Icon fill color.",
        -        "type": "string"
        -      },
        -      "d": {
        -        "description": "Custom SVG path d attribute.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Render height in pixels (default: 12).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "name": {
        -        "description": "Built-in icon name (see pixoo://reference/icons).",
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "palette": {
        -        "description": "Named palette for colored icon.",
        -        "enum": [
        -          "ember",
        -          "ice",
        -          "neon",
        -          "fire",
        -          "lavender",
        -          "claude",
        -          "mono"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "icon",
        -        "description": "Icon element type.",
        -        "type": "string"
        -      },
        -      "viewBox": {
        -        "description": "SVG viewBox string (default: \"0 0 16 16\").",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Render width in pixels (default: 12).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel X coordinate (0 = left edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic horizontal alignment.",
        -            "enum": [
        -              "left",
        -              "center",
        -              "right"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "X position."
        -      },
        -      "y": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel Y coordinate (0 = top edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic vertical alignment.",
        -            "enum": [
        -              "top",
        -              "center",
        -              "bottom"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "Y position."
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Filled or gradient rectangle element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "borderColor": {
        -        "description": "1px border color.",
        -        "type": "string"
        -      },
        -      "color": {
        -        "description": "Fill color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "gradient": {
        -        "description": "Gradient fill.",
        -        "properties": {
        -          "from": {
        -            "description": "Start color.",
        -            "type": "string"
        -          },
        -          "to": {
        -            "description": "End color.",
        -            "type": "string"
        -          },
        -          "type": {
        -            "description": "v = vertical, h = horizontal.",
        -            "enum": [
        -              "v",
        -              "h"
        -            ],
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "type",
        -          "from",
        -          "to"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Height in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "rect",
        -        "description": "Rectangle element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Width in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "w",
        -      "h"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Filled or outline circle element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Circle color.",
        -        "type": "string"
        -      },
        -      "cx": {
        -        "description": "Center X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "cy": {
        -        "description": "Center Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "fill": {
        -        "description": "Filled or outline only (default: true).",
        -        "type": "boolean"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "radius": {
        -        "description": "Radius in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "circle",
        -        "description": "Circle element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "cx",
        -      "cy",
        -      "radius"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Single-pixel line element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Line color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "line",
        -        "description": "Line element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x0": {
        -        "description": "Start X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "x1": {
        -        "description": "End X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y0": {
        -        "description": "Start Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y1": {
        -        "description": "End Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x0",
        -      "y0",
        -      "x1",
        -      "y1"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Horizontal progress bar widget.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Height in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "label": {
        -        "description": "Optional label rendered on the bar.",
        -        "type": "string"
        -      },
        -      "max": {
        -        "description": "Maximum value.",
        -        "type": "number"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "palette": {
        -        "description": "Named palette for gradient fill.",
        -        "enum": [
        -          "ember",
        -          "ice",
        -          "neon",
        -          "fire",
        -          "lavender",
        -          "claude",
        -          "mono"
        -        ],
        -        "type": "string"
        -      },
        -      "trackColor": {
        -        "description": "Background track color.",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "progress",
        -        "description": "Progress bar widget type.",
        -        "type": "string"
        -      },
        -      "value": {
        -        "description": "Current value.",
        -        "type": "number"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Width in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "w",
        -      "h",
        -      "value",
        -      "max"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Sparkline chart widget (line or bar).",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Line or bar color.",
        -        "type": "string"
        -      },
        -      "data": {
        -        "description": "Data points for the chart.",
        -        "items": {
        -          "type": "number"
        -        },
        -        "minItems": 2,
        -        "type": "array"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Height in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 2,
        -        "type": "integer"
        -      },
        -      "kind": {
        -        "description": "Chart style (default: line).",
        -        "enum": [
        -          "line",
        -          "bar"
        -        ],
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "sparkline",
        -        "description": "Sparkline chart widget type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Width in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 2,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "w",
        -      "h",
        -      "data"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Bitmap element using explicit palette indices.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "palette": {
        -        "description": "Color palette: array of hex colors indexed 0-F.",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "rows": {
        -        "description": "Row strings of hex palette indices (0-F, space = transparent).",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "type": {
        -        "const": "bitmap",
        -        "description": "Bitmap element using palette indices.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "rows",
        -      "palette"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Sparse scatter of individually colored pixels.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "data": {
        -        "description": "Array of pixel positions and colors.",
        -        "items": {
        -          "description": "A single pixel: position and color.",
        -          "properties": {
        -            "color": {
        -              "description": "Pixel color.",
        -              "type": "string"
        -            },
        -            "x": {
        -              "description": "Pixel X coordinate.",
        -              "maximum": 9007199254740991,
        -              "minimum": -9007199254740991,
        -              "type": "integer"
        -            },
        -            "y": {
        -              "description": "Pixel Y coordinate.",
        -              "maximum": 9007199254740991,
        -              "minimum": -9007199254740991,
        -              "type": "integer"
        -            }
        -          },
        -          "required": [
        -            "x",
        -            "y",
        -            "color"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "pixels",
        -        "description": "Sparse pixel dots element.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "data"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "External image element (local path or https URL).",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "fit": {
        -        "description": "Resize fit mode (default: contain).",
        -        "enum": [
        -          "contain",
        -          "cover",
        -          "fill"
        -        ],
        -        "type": "string"
        -      },
        -      "h": {
        -        "description": "Target height (default: canvas height).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "kernel": {
        -        "description": "Resize kernel: nearest for pixel art, lanczos3 for photos (default: nearest).",
        -        "enum": [
        -          "nearest",
        -          "lanczos3",
        -          "mitchell"
        -        ],
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "source": {
        -        "description": "Absolute local file path or https (not http) URL.",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "image",
        -        "description": "Image element (local path or https URL).",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Target width (default: canvas width).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X offset on canvas (default: 0).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y offset on canvas (default: 0).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "source"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Sprite sheet element for character or tile art.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "prefixItems": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "bodyColor": {
        -        "description": "Override body color.",
        -        "type": "string"
        -      },
        -      "cols": {
        -        "description": "Number of columns in the sprite grid.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "darkColor": {
        -        "description": "Override dark/eye color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "path": {
        -        "description": "Absolute local path to the sprite sheet image.",
        -        "type": "string"
        -      },
        -      "rows": {
        -        "description": "Number of rows in the sprite grid.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "scale": {
        -        "description": "Pixel scale factor.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "sprite",
        -        "description": "Sprite sheet element.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel X coordinate (0 = left edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic horizontal alignment.",
        -            "enum": [
        -              "left",
        -              "center",
        -              "right"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "X position (default: center)."
        -      },
        -      "y": {
        -        "description": "Y position (default: 0).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "path",
        -      "cols",
        -      "rows"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "description": "Styled text element rendered at a position.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "items": false,
        +            "maxItems": 2,
        +            "minItems": 2,
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "description": "Value at this frame.",
        +                "type": [
        +                  "number",
        +                  "string",
        +                  "boolean"
        +                ]
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "color": {
        +        "description": "Flat text color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "font": {
        +        "description": "Font variant.",
        +        "enum": [
        +          "standard",
        +          "compact"
        +        ],
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "style": {
        +        "description": "Text style options.",
        +        "properties": {
        +          "color": {
        +            "description": "Flat color override.",
        +            "type": "string"
        +          },
        +          "outline": {
        +            "description": "1px outline.",
        +            "type": "boolean"
        +          },
        +          "palette": {
        +            "anyOf": [
        +              {
        +                "description": "Named built-in color palette for the vertical ramp.",
        +                "enum": [
        +                  "ember",
        +                  "ice",
        +                  "neon",
        +                  "fire",
        +                  "lavender",
        +                  "claude",
        +                  "mono"
        +                ],
        +                "type": "string"
        +              },
        +              {
        +                "description": "Custom gradient stop: specify top and bottom colors directly.",
        +                "properties": {
        +                  "from": {
        +                    "description": "Top color.",
        +                    "type": "string"
        +                  },
        +                  "to": {
        +                    "description": "Bottom color.",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "from",
        +                  "to"
        +                ],
        +                "type": "object"
        +              }
        +            ],
        +            "description": "Palette name or custom gradient stop for vertical color ramp."
        +          },
        +          "scale": {
        +            "description": "Integer pixel scale multiplier.",
        +            "maximum": 8,
        +            "minimum": 1,
        +            "type": "integer"
        +          },
        +          "shadow": {
        +            "description": "Drop shadow.",
        +            "type": "boolean"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "text": {
        +        "description": "Text content to render.",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "text",
        +        "description": "Text element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel X coordinate (0 = left edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic horizontal alignment.",
        +            "enum": [
        +              "left",
        +              "center",
        +              "right"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "X position (default: 0)."
        +      },
        +      "y": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel Y coordinate (0 = top edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic vertical alignment.",
        +            "enum": [
        +              "top",
        +              "center",
        +              "bottom"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "Y position (default: 0)."
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Built-in or custom SVG icon element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "items": false,
        +            "maxItems": 2,
        +            "minItems": 2,
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "description": "Value at this frame.",
        +                "type": [
        +                  "number",
        +                  "string",
        +                  "boolean"
        +                ]
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "color": {
        +        "description": "Icon fill color.",
        +        "type": "string"
        +      },
        +      "d": {
        +        "description": "Custom SVG path d attribute.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Render height in pixels (default: 12).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "name": {
        +        "description": "Built-in icon name (see pixoo://reference/icons).",
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "palette": {
        +        "description": "Named palette for colored icon.",
        +        "enum": [
        +          "ember",
        +          "ice",
        +          "neon",
        +          "fire",
        +          "lavender",
        +          "claude",
        +          "mono"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "icon",
        +        "description": "Icon element type.",
        +        "type": "string"
        +      },
        +      "viewBox": {
        +        "description": "SVG viewBox string (default: \"0 0 16 16\").",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Render width in pixels (default: 12).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel X coordinate (0 = left edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic horizontal alignment.",
        +            "enum": [
        +              "left",
        +              "center",
        +              "right"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "X position."
        +      },
        +      "y": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel Y coordinate (0 = top edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic vertical alignment.",
        +            "enum": [
        +              "top",
        +              "center",
        +              "bottom"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "Y position."
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Filled or gradient rectangle element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "items": false,
        +            "maxItems": 2,
        +            "minItems": 2,
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "description": "Value at this frame.",
        +                "type": [
        +                  "number",
        +                  "string",
        +                  "boolean"
        +                ]
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "borderColor": {
        +        "description": "1px border color.",
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Fill color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "gradient": {
        +        "description": "Gradient fill.",
        +        "properties": {
        +          "from": {
        +            "description": "Start color.",
        +            "type": "string"
        +          },
        +          "to": {
        +            "description": "End color.",
        +            "type": "string"
        +          },
        +          "type": {
        +            "description": "v = vertical, h = horizontal.",
        +            "enum": [
        +              "v",
        +              "h"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "type",
        +          "from",
        +          "to"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Height in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "rect",
        +        "description": "Rectangle element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Width in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "w",
        +      "h"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Filled or outline circle element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "items": false,
        +            "maxItems": 2,
        +            "minItems": 2,
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "description": "Value at this frame.",
        +                "type": [
        +                  "number",
        +                  "string",
        +                  "boolean"
        +                ]
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "color": {
        +        "description": "Circle color.",
        +        "type": "string"
        +      },
        +      "cx": {
        +        "description": "Center X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "cy": {
        +        "description": "Center Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "fill": {
        +        "description": "Filled or outline only (default: true).",
        +        "type": "boolean"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "radius": {
        +        "description": "Radius in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "circle",
        +        "description": "Circle element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "cx",
        +      "cy",
        +      "radius"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Single-pixel line element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "items": false,
        +            "maxItems": 2,
        +            "minItems": 2,
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "description": "Value at this frame.",
        +                "type": [
        +                  "number",
        +                  "string",
        +                  "boolean"
        +                ]
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "color": {
        +        "description": "Line color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "line",
        +        "description": "Line element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x0": {
        +        "description": "Start X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "x1": {
        +        "description": "End X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y0": {
        +        "description": "Start Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y1": {
        +        "description": "End Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x0",
        +      "y0",
        +      "x1",
        +      "y1"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Horizontal progress bar widget.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "items": false,
        +            "maxItems": 2,
        +            "minItems": 2,
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "description": "Value at this frame.",
        +                "type": [
        +                  "number",
        +                  "string",
        +                  "boolean"
        +                ]
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Height in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "label": {
        +        "description": "Optional label rendered on the bar.",
        +        "type": "string"
        +      },
        +      "max": {
        +        "description": "Maximum value.",
        +        "type": "number"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "palette": {
        +        "description": "Named palette for gradient fill.",
        +        "enum": [
        +          "ember",
        +          "ice",
        +          "neon",
        +          "fire",
        +          "lavender",
        +          "claude",
        +          "mono"
        +        ],
        +        "type": "string"
        +      },
        +      "trackColor": {
        +        "description": "Background track color.",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "progress",
        +        "description": "Progress bar widget type.",
        +        "type": "string"
        +      },
        +      "value": {
        +        "description": "Current value.",
        +        "type": "number"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Width in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "w",
        +      "h",
        +      "value",
        +      "max"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Sparkline chart widget (line or bar).",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "items": false,
        +            "maxItems": 2,
        +            "minItems": 2,
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "description": "Value at this frame.",
        +                "type": [
        +                  "number",
        +                  "string",
        +                  "boolean"
        +                ]
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "color": {
        +        "description": "Line or bar color.",
        +        "type": "string"
        +      },
        +      "data": {
        +        "description": "Data points for the chart.",
        +        "items": {
        +          "type": "number"
        +        },
        +        "minItems": 2,
        +        "type": "array"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Height in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 2,
        +        "type": "integer"
        +      },
        +      "kind": {
        +        "description": "Chart style (default: line).",
        +        "enum": [
        +          "line",
        +          "bar"
        +        ],
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "sparkline",
        +        "description": "Sparkline chart widget type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Width in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 2,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "w",
        +      "h",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Bitmap element using explicit palette indices.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "items": false,
        +            "maxItems": 2,
        +            "minItems": 2,
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "description": "Value at this frame.",
        +                "type": [
        +                  "number",
        +                  "string",
        +                  "boolean"
        +                ]
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "palette": {
        +        "description": "Color palette: array of hex colors indexed 0-F.",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "rows": {
        +        "description": "Row strings of hex palette indices (0-F, space = transparent).",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "type": {
        +        "const": "bitmap",
        +        "description": "Bitmap element using palette indices.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "rows",
        +      "palette"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Sparse scatter of individually colored pixels.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "items": false,
        +            "maxItems": 2,
        +            "minItems": 2,
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "description": "Value at this frame.",
        +                "type": [
        +                  "number",
        +                  "string",
        +                  "boolean"
        +                ]
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "data": {
        +        "description": "Array of pixel positions and colors.",
        +        "items": {
        +          "description": "A single pixel: position and color.",
        +          "properties": {
        +            "color": {
        +              "description": "Pixel color.",
        +              "type": "string"
        +            },
        +            "x": {
        +              "description": "Pixel X coordinate.",
        +              "maximum": 9007199254740991,
        +              "minimum": -9007199254740991,
        +              "type": "integer"
        +            },
        +            "y": {
        +              "description": "Pixel Y coordinate.",
        +              "maximum": 9007199254740991,
        +              "minimum": -9007199254740991,
        +              "type": "integer"
        +            }
        +          },
        +          "required": [
        +            "x",
        +            "y",
        +            "color"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "pixels",
        +        "description": "Sparse pixel dots element.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "External image element (local path or https URL).",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "items": false,
        +            "maxItems": 2,
        +            "minItems": 2,
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "description": "Value at this frame.",
        +                "type": [
        +                  "number",
        +                  "string",
        +                  "boolean"
        +                ]
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "fit": {
        +        "description": "Resize fit mode (default: contain).",
        +        "enum": [
        +          "contain",
        +          "cover",
        +          "fill"
        +        ],
        +        "type": "string"
        +      },
        +      "h": {
        +        "description": "Target height (default: canvas height).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "kernel": {
        +        "description": "Resize kernel: nearest for pixel art, lanczos3 for photos (default: nearest).",
        +        "enum": [
        +          "nearest",
        +          "lanczos3",
        +          "mitchell"
        +        ],
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "source": {
        +        "description": "Absolute local file path or https (not http) URL.",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "image",
        +        "description": "Image element (local path or https URL).",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Target width (default: canvas width).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X offset on canvas (default: 0).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y offset on canvas (default: 0).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "source"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Sprite sheet element for character or tile art.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "items": false,
        +            "maxItems": 2,
        +            "minItems": 2,
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "description": "Value at this frame.",
        +                "type": [
        +                  "number",
        +                  "string",
        +                  "boolean"
        +                ]
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "bodyColor": {
        +        "description": "Override body color.",
        +        "type": "string"
        +      },
        +      "cols": {
        +        "description": "Number of columns in the sprite grid.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "darkColor": {
        +        "description": "Override dark/eye color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "path": {
        +        "description": "Absolute local path to the sprite sheet image.",
        +        "type": "string"
        +      },
        +      "rows": {
        +        "description": "Number of rows in the sprite grid.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "scale": {
        +        "description": "Pixel scale factor.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "sprite",
        +        "description": "Sprite sheet element.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel X coordinate (0 = left edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic horizontal alignment.",
        +            "enum": [
        +              "left",
        +              "center",
        +              "right"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "X position (default: center)."
        +      },
        +      "y": {
        +        "description": "Y position (default: 0).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "path",
        +      "cols",
        +      "rows"
        +    ],
        +    "type": "object"
        +  }
        +]
  8. 7 tool updatesv1.1.1
    • Changedpixoo_compose_scene10 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / elements / items / oneOf
        Previous value: -[
        -  {
        -    "description": "Styled text element rendered at a position.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Flat text color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "font": {
        -        "description": "Font variant.",
        -        "enum": [
        -          "standard",
        -          "compact"
        -        ],
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "style": {
        -        "description": "Text style options.",
        -        "properties": {
        -          "color": {
        -            "description": "Flat color override.",
        -            "type": "string"
        -          },
        -          "outline": {
        -            "description": "1px outline.",
        -            "type": "boolean"
        -          },
        -          "palette": {
        -            "anyOf": [
        -              {
        -                "description": "Named built-in color palette for the vertical ramp.",
        -                "enum": [
        -                  "ember",
        -                  "ice",
        -                  "neon",
        -                  "fire",
        -                  "lavender",
        -                  "claude",
        -                  "mono"
        -                ],
        -                "type": "string"
        -              },
        -              {
        -                "description": "Custom gradient stop: specify top and bottom colors directly.",
        -                "properties": {
        -                  "from": {
        -                    "description": "Top color.",
        -                    "type": "string"
        -                  },
        -                  "to": {
        -                    "description": "Bottom color.",
        -                    "type": "string"
        -                  }
        -                },
        -                "required": [
        -                  "from",
        -                  "to"
        -                ],
        -                "type": "object"
        -              }
        -            ],
        -            "description": "Palette name or custom gradient stop for vertical color ramp."
        -          },
        -          "scale": {
        -            "description": "Integer pixel scale multiplier.",
        -            "maximum": 8,
        -            "minimum": 1,
        -            "type": "integer"
        -          },
        -          "shadow": {
        -            "description": "Drop shadow.",
        -            "type": "boolean"
        -          }
        -        },
        -        "type": "object"
        -      },
        -      "text": {
        -        "description": "Text content to render.",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "text",
        -        "description": "Text element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel X coordinate (0 = left edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic horizontal alignment.",
        -            "enum": [
        -              "left",
        -              "center",
        -              "right"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "X position (default: 0)."
        -      },
        -      "y": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel Y coordinate (0 = top edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic vertical alignment.",
        -            "enum": [
        -              "top",
        -              "center",
        -              "bottom"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "Y position (default: 0)."
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "text"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Built-in or custom SVG icon element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Icon fill color.",
        -        "type": "string"
        -      },
        -      "d": {
        -        "description": "Custom SVG path d attribute.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Render height in pixels (default: 12).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "name": {
        -        "description": "Built-in icon name (see pixoo://reference/icons).",
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "palette": {
        -        "description": "Named palette for colored icon.",
        -        "enum": [
        -          "ember",
        -          "ice",
        -          "neon",
        -          "fire",
        -          "lavender",
        -          "claude",
        -          "mono"
        -        ],
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "icon",
        -        "description": "Icon element type.",
        -        "type": "string"
        -      },
        -      "viewBox": {
        -        "description": "SVG viewBox string (default: \"0 0 16 16\").",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Render width in pixels (default: 12).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel X coordinate (0 = left edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic horizontal alignment.",
        -            "enum": [
        -              "left",
        -              "center",
        -              "right"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "X position."
        -      },
        -      "y": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel Y coordinate (0 = top edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic vertical alignment.",
        -            "enum": [
        -              "top",
        -              "center",
        -              "bottom"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "Y position."
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Filled or gradient rectangle element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "borderColor": {
        -        "description": "1px border color.",
        -        "type": "string"
        -      },
        -      "color": {
        -        "description": "Fill color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "gradient": {
        -        "description": "Gradient fill.",
        -        "properties": {
        -          "from": {
        -            "description": "Start color.",
        -            "type": "string"
        -          },
        -          "to": {
        -            "description": "End color.",
        -            "type": "string"
        -          },
        -          "type": {
        -            "description": "v = vertical, h = horizontal.",
        -            "enum": [
        -              "v",
        -              "h"
        -            ],
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "type",
        -          "from",
        -          "to"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Height in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "rect",
        -        "description": "Rectangle element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Width in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "w",
        -      "h"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Filled or outline circle element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Circle color.",
        -        "type": "string"
        -      },
        -      "cx": {
        -        "description": "Center X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "cy": {
        -        "description": "Center Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "fill": {
        -        "description": "Filled or outline only (default: true).",
        -        "type": "boolean"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "radius": {
        -        "description": "Radius in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "circle",
        -        "description": "Circle element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "cx",
        -      "cy",
        -      "radius"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Single-pixel line element.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Line color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "line",
        -        "description": "Line element type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x0": {
        -        "description": "Start X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "x1": {
        -        "description": "End X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y0": {
        -        "description": "Start Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y1": {
        -        "description": "End Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x0",
        -      "y0",
        -      "x1",
        -      "y1"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Horizontal progress bar widget.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Height in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "label": {
        -        "description": "Optional label rendered on the bar.",
        -        "type": "string"
        -      },
        -      "max": {
        -        "description": "Maximum value.",
        -        "type": "number"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "palette": {
        -        "description": "Named palette for gradient fill.",
        -        "enum": [
        -          "ember",
        -          "ice",
        -          "neon",
        -          "fire",
        -          "lavender",
        -          "claude",
        -          "mono"
        -        ],
        -        "type": "string"
        -      },
        -      "trackColor": {
        -        "description": "Background track color.",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "progress",
        -        "description": "Progress bar widget type.",
        -        "type": "string"
        -      },
        -      "value": {
        -        "description": "Current value.",
        -        "type": "number"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Width in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "w",
        -      "h",
        -      "value",
        -      "max"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Sparkline chart widget (line or bar).",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "color": {
        -        "description": "Line or bar color.",
        -        "type": "string"
        -      },
        -      "data": {
        -        "description": "Data points for the chart.",
        -        "items": {
        -          "type": "number"
        -        },
        -        "minItems": 2,
        -        "type": "array"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "h": {
        -        "description": "Height in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 2,
        -        "type": "integer"
        -      },
        -      "kind": {
        -        "description": "Chart style (default: line).",
        -        "enum": [
        -          "line",
        -          "bar"
        -        ],
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "sparkline",
        -        "description": "Sparkline chart widget type.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Width in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": 2,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "w",
        -      "h",
        -      "data"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Bitmap element using explicit palette indices.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "palette": {
        -        "description": "Color palette: array of hex colors indexed 0-F.",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "rows": {
        -        "description": "Row strings of hex palette indices (0-F, space = transparent).",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "type": {
        -        "const": "bitmap",
        -        "description": "Bitmap element using palette indices.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x": {
        -        "description": "X coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y coordinate.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "rows",
        -      "palette"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Sparse scatter of individually colored pixels.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "data": {
        -        "description": "Array of pixel positions and colors.",
        -        "items": {
        -          "description": "A single pixel: position and color.",
        -          "properties": {
        -            "color": {
        -              "description": "Pixel color.",
        -              "type": "string"
        -            },
        -            "x": {
        -              "description": "Pixel X coordinate.",
        -              "maximum": 9007199254740991,
        -              "minimum": -9007199254740991,
        -              "type": "integer"
        -            },
        -            "y": {
        -              "description": "Pixel Y coordinate.",
        -              "maximum": 9007199254740991,
        -              "minimum": -9007199254740991,
        -              "type": "integer"
        -            }
        -          },
        -          "required": [
        -            "x",
        -            "y",
        -            "color"
        -          ],
        -          "type": "object"
        -        },
        -        "type": "array"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "pixels",
        -        "description": "Sparse pixel dots element.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "data"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "External image element (local path or https URL).",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "fit": {
        -        "description": "Resize fit mode (default: contain).",
        -        "enum": [
        -          "contain",
        -          "cover",
        -          "fill"
        -        ],
        -        "type": "string"
        -      },
        -      "h": {
        -        "description": "Target height (default: canvas height).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "kernel": {
        -        "description": "Resize kernel: nearest for pixel art, lanczos3 for photos (default: nearest).",
        -        "enum": [
        -          "nearest",
        -          "lanczos3",
        -          "mitchell"
        -        ],
        -        "type": "string"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "source": {
        -        "description": "Absolute local file path or https (not http) URL.",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "image",
        -        "description": "Image element (local path or https URL).",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "w": {
        -        "description": "Target width (default: canvas width).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "description": "X offset on canvas (default: 0).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "description": "Y offset on canvas (default: 0).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "source"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "description": "Sprite sheet element for character or tile art.",
        -    "properties": {
        -      "animate": {
        -        "additionalProperties": {
        -          "description": "Keyframe entries: [[frame, value], ...].",
        -          "items": {
        -            "items": [
        -              {
        -                "description": "Frame index.",
        -                "type": "number"
        -              },
        -              {
        -                "anyOf": [
        -                  {
        -                    "type": "number"
        -                  },
        -                  {
        -                    "type": "string"
        -                  },
        -                  {
        -                    "type": "boolean"
        -                  }
        -                ],
        -                "description": "Value at this frame."
        -              }
        -            ],
        -            "type": "array"
        -          },
        -          "type": "array"
        -        },
        -        "description": "Raw keyframe animation map for this element.",
        -        "propertyNames": {
        -          "type": "string"
        -        },
        -        "type": "object"
        -      },
        -      "bodyColor": {
        -        "description": "Override body color.",
        -        "type": "string"
        -      },
        -      "cols": {
        -        "description": "Number of columns in the sprite grid.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "darkColor": {
        -        "description": "Override dark/eye color.",
        -        "type": "string"
        -      },
        -      "dx": {
        -        "description": "X offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "dy": {
        -        "description": "Y offset nudge in pixels.",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      },
        -      "effect": {
        -        "description": "Named animation preset for this element.",
        -        "properties": {
        -          "amplitude": {
        -            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        -            "type": "number"
        -          },
        -          "name": {
        -            "description": "Named animation preset.",
        -            "enum": [
        -              "float",
        -              "scroll-left",
        -              "scroll-right",
        -              "pulse",
        -              "blink",
        -              "twinkle",
        -              "drift",
        -              "fade-in",
        -              "fade-out"
        -            ],
        -            "type": "string"
        -          },
        -          "period": {
        -            "description": "Effect period in frames. Defaults to total scene frame count.",
        -            "type": "number"
        -          },
        -          "phase": {
        -            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        -            "type": "number"
        -          }
        -        },
        -        "required": [
        -          "name"
        -        ],
        -        "type": "object"
        -      },
        -      "opacity": {
        -        "description": "Opacity 0–100 (default: 100).",
        -        "maximum": 100,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "path": {
        -        "description": "Absolute local path to the sprite sheet image.",
        -        "type": "string"
        -      },
        -      "rows": {
        -        "description": "Number of rows in the sprite grid.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "scale": {
        -        "description": "Pixel scale factor.",
        -        "maximum": 9007199254740991,
        -        "minimum": 1,
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "sprite",
        -        "description": "Sprite sheet element.",
        -        "type": "string"
        -      },
        -      "visible": {
        -        "description": "Whether the element is visible (default: true).",
        -        "type": "boolean"
        -      },
        -      "x": {
        -        "anyOf": [
        -          {
        -            "description": "Absolute pixel X coordinate (0 = left edge).",
        -            "type": "number"
        -          },
        -          {
        -            "description": "Semantic horizontal alignment.",
        -            "enum": [
        -              "left",
        -              "center",
        -              "right"
        -            ],
        -            "type": "string"
        -          }
        -        ],
        -        "description": "X position (default: center)."
        -      },
        -      "y": {
        -        "description": "Y position (default: 0).",
        -        "maximum": 9007199254740991,
        -        "minimum": -9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "path",
        -      "cols",
        -      "rows"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "description": "Styled text element rendered at a position.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "anyOf": [
        +                  {
        +                    "type": "number"
        +                  },
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "boolean"
        +                  }
        +                ],
        +                "description": "Value at this frame."
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "color": {
        +        "description": "Flat text color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "font": {
        +        "description": "Font variant.",
        +        "enum": [
        +          "standard",
        +          "compact"
        +        ],
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "style": {
        +        "description": "Text style options.",
        +        "properties": {
        +          "color": {
        +            "description": "Flat color override.",
        +            "type": "string"
        +          },
        +          "outline": {
        +            "description": "1px outline.",
        +            "type": "boolean"
        +          },
        +          "palette": {
        +            "anyOf": [
        +              {
        +                "description": "Named built-in color palette for the vertical ramp.",
        +                "enum": [
        +                  "ember",
        +                  "ice",
        +                  "neon",
        +                  "fire",
        +                  "lavender",
        +                  "claude",
        +                  "mono"
        +                ],
        +                "type": "string"
        +              },
        +              {
        +                "description": "Custom gradient stop: specify top and bottom colors directly.",
        +                "properties": {
        +                  "from": {
        +                    "description": "Top color.",
        +                    "type": "string"
        +                  },
        +                  "to": {
        +                    "description": "Bottom color.",
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "from",
        +                  "to"
        +                ],
        +                "type": "object"
        +              }
        +            ],
        +            "description": "Palette name or custom gradient stop for vertical color ramp."
        +          },
        +          "scale": {
        +            "description": "Integer pixel scale multiplier.",
        +            "maximum": 8,
        +            "minimum": 1,
        +            "type": "integer"
        +          },
        +          "shadow": {
        +            "description": "Drop shadow.",
        +            "type": "boolean"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "text": {
        +        "description": "Text content to render.",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "text",
        +        "description": "Text element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel X coordinate (0 = left edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic horizontal alignment.",
        +            "enum": [
        +              "left",
        +              "center",
        +              "right"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "X position (default: 0)."
        +      },
        +      "y": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel Y coordinate (0 = top edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic vertical alignment.",
        +            "enum": [
        +              "top",
        +              "center",
        +              "bottom"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "Y position (default: 0)."
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "text"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Built-in or custom SVG icon element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "anyOf": [
        +                  {
        +                    "type": "number"
        +                  },
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "boolean"
        +                  }
        +                ],
        +                "description": "Value at this frame."
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "color": {
        +        "description": "Icon fill color.",
        +        "type": "string"
        +      },
        +      "d": {
        +        "description": "Custom SVG path d attribute.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Render height in pixels (default: 12).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "name": {
        +        "description": "Built-in icon name (see pixoo://reference/icons).",
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "palette": {
        +        "description": "Named palette for colored icon.",
        +        "enum": [
        +          "ember",
        +          "ice",
        +          "neon",
        +          "fire",
        +          "lavender",
        +          "claude",
        +          "mono"
        +        ],
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "icon",
        +        "description": "Icon element type.",
        +        "type": "string"
        +      },
        +      "viewBox": {
        +        "description": "SVG viewBox string (default: \"0 0 16 16\").",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Render width in pixels (default: 12).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel X coordinate (0 = left edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic horizontal alignment.",
        +            "enum": [
        +              "left",
        +              "center",
        +              "right"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "X position."
        +      },
        +      "y": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel Y coordinate (0 = top edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic vertical alignment.",
        +            "enum": [
        +              "top",
        +              "center",
        +              "bottom"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "Y position."
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Filled or gradient rectangle element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "anyOf": [
        +                  {
        +                    "type": "number"
        +                  },
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "boolean"
        +                  }
        +                ],
        +                "description": "Value at this frame."
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "borderColor": {
        +        "description": "1px border color.",
        +        "type": "string"
        +      },
        +      "color": {
        +        "description": "Fill color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "gradient": {
        +        "description": "Gradient fill.",
        +        "properties": {
        +          "from": {
        +            "description": "Start color.",
        +            "type": "string"
        +          },
        +          "to": {
        +            "description": "End color.",
        +            "type": "string"
        +          },
        +          "type": {
        +            "description": "v = vertical, h = horizontal.",
        +            "enum": [
        +              "v",
        +              "h"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "type",
        +          "from",
        +          "to"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Height in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "rect",
        +        "description": "Rectangle element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Width in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "w",
        +      "h"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Filled or outline circle element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "anyOf": [
        +                  {
        +                    "type": "number"
        +                  },
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "boolean"
        +                  }
        +                ],
        +                "description": "Value at this frame."
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "color": {
        +        "description": "Circle color.",
        +        "type": "string"
        +      },
        +      "cx": {
        +        "description": "Center X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "cy": {
        +        "description": "Center Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "fill": {
        +        "description": "Filled or outline only (default: true).",
        +        "type": "boolean"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "radius": {
        +        "description": "Radius in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "circle",
        +        "description": "Circle element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "cx",
        +      "cy",
        +      "radius"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Single-pixel line element.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "anyOf": [
        +                  {
        +                    "type": "number"
        +                  },
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "boolean"
        +                  }
        +                ],
        +                "description": "Value at this frame."
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "color": {
        +        "description": "Line color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "line",
        +        "description": "Line element type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x0": {
        +        "description": "Start X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "x1": {
        +        "description": "End X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y0": {
        +        "description": "Start Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y1": {
        +        "description": "End Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x0",
        +      "y0",
        +      "x1",
        +      "y1"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Horizontal progress bar widget.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "anyOf": [
        +                  {
        +                    "type": "number"
        +                  },
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "boolean"
        +                  }
        +                ],
        +                "description": "Value at this frame."
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Height in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "label": {
        +        "description": "Optional label rendered on the bar.",
        +        "type": "string"
        +      },
        +      "max": {
        +        "description": "Maximum value.",
        +        "type": "number"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "palette": {
        +        "description": "Named palette for gradient fill.",
        +        "enum": [
        +          "ember",
        +          "ice",
        +          "neon",
        +          "fire",
        +          "lavender",
        +          "claude",
        +          "mono"
        +        ],
        +        "type": "string"
        +      },
        +      "trackColor": {
        +        "description": "Background track color.",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "progress",
        +        "description": "Progress bar widget type.",
        +        "type": "string"
        +      },
        +      "value": {
        +        "description": "Current value.",
        +        "type": "number"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Width in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "w",
        +      "h",
        +      "value",
        +      "max"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Sparkline chart widget (line or bar).",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "anyOf": [
        +                  {
        +                    "type": "number"
        +                  },
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "boolean"
        +                  }
        +                ],
        +                "description": "Value at this frame."
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "color": {
        +        "description": "Line or bar color.",
        +        "type": "string"
        +      },
        +      "data": {
        +        "description": "Data points for the chart.",
        +        "items": {
        +          "type": "number"
        +        },
        +        "minItems": 2,
        +        "type": "array"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "h": {
        +        "description": "Height in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 2,
        +        "type": "integer"
        +      },
        +      "kind": {
        +        "description": "Chart style (default: line).",
        +        "enum": [
        +          "line",
        +          "bar"
        +        ],
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "sparkline",
        +        "description": "Sparkline chart widget type.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Width in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": 2,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "w",
        +      "h",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Bitmap element using explicit palette indices.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "anyOf": [
        +                  {
        +                    "type": "number"
        +                  },
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "boolean"
        +                  }
        +                ],
        +                "description": "Value at this frame."
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "palette": {
        +        "description": "Color palette: array of hex colors indexed 0-F.",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "rows": {
        +        "description": "Row strings of hex palette indices (0-F, space = transparent).",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "type": {
        +        "const": "bitmap",
        +        "description": "Bitmap element using palette indices.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x": {
        +        "description": "X coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y coordinate.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "rows",
        +      "palette"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Sparse scatter of individually colored pixels.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "anyOf": [
        +                  {
        +                    "type": "number"
        +                  },
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "boolean"
        +                  }
        +                ],
        +                "description": "Value at this frame."
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "data": {
        +        "description": "Array of pixel positions and colors.",
        +        "items": {
        +          "description": "A single pixel: position and color.",
        +          "properties": {
        +            "color": {
        +              "description": "Pixel color.",
        +              "type": "string"
        +            },
        +            "x": {
        +              "description": "Pixel X coordinate.",
        +              "maximum": 9007199254740991,
        +              "minimum": -9007199254740991,
        +              "type": "integer"
        +            },
        +            "y": {
        +              "description": "Pixel Y coordinate.",
        +              "maximum": 9007199254740991,
        +              "minimum": -9007199254740991,
        +              "type": "integer"
        +            }
        +          },
        +          "required": [
        +            "x",
        +            "y",
        +            "color"
        +          ],
        +          "type": "object"
        +        },
        +        "type": "array"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "pixels",
        +        "description": "Sparse pixel dots element.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "data"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "External image element (local path or https URL).",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "anyOf": [
        +                  {
        +                    "type": "number"
        +                  },
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "boolean"
        +                  }
        +                ],
        +                "description": "Value at this frame."
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "fit": {
        +        "description": "Resize fit mode (default: contain).",
        +        "enum": [
        +          "contain",
        +          "cover",
        +          "fill"
        +        ],
        +        "type": "string"
        +      },
        +      "h": {
        +        "description": "Target height (default: canvas height).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "kernel": {
        +        "description": "Resize kernel: nearest for pixel art, lanczos3 for photos (default: nearest).",
        +        "enum": [
        +          "nearest",
        +          "lanczos3",
        +          "mitchell"
        +        ],
        +        "type": "string"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "source": {
        +        "description": "Absolute local file path or https (not http) URL.",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "image",
        +        "description": "Image element (local path or https URL).",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "w": {
        +        "description": "Target width (default: canvas width).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "description": "X offset on canvas (default: 0).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "description": "Y offset on canvas (default: 0).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "source"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "description": "Sprite sheet element for character or tile art.",
        +    "properties": {
        +      "animate": {
        +        "additionalProperties": {
        +          "description": "Keyframe entries: [[frame, value], ...].",
        +          "items": {
        +            "prefixItems": [
        +              {
        +                "description": "Frame index.",
        +                "type": "number"
        +              },
        +              {
        +                "anyOf": [
        +                  {
        +                    "type": "number"
        +                  },
        +                  {
        +                    "type": "string"
        +                  },
        +                  {
        +                    "type": "boolean"
        +                  }
        +                ],
        +                "description": "Value at this frame."
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "description": "Raw keyframe animation map for this element.",
        +        "propertyNames": {
        +          "type": "string"
        +        },
        +        "type": "object"
        +      },
        +      "bodyColor": {
        +        "description": "Override body color.",
        +        "type": "string"
        +      },
        +      "cols": {
        +        "description": "Number of columns in the sprite grid.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "darkColor": {
        +        "description": "Override dark/eye color.",
        +        "type": "string"
        +      },
        +      "dx": {
        +        "description": "X offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "dy": {
        +        "description": "Y offset nudge in pixels.",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      },
        +      "effect": {
        +        "description": "Named animation preset for this element.",
        +        "properties": {
        +          "amplitude": {
        +            "description": "Effect intensity: pixels of movement for float/scroll/drift, 0–1 scale for fade/pulse. Default varies by effect (float: 2px).",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "Named animation preset.",
        +            "enum": [
        +              "float",
        +              "scroll-left",
        +              "scroll-right",
        +              "pulse",
        +              "blink",
        +              "twinkle",
        +              "drift",
        +              "fade-in",
        +              "fade-out"
        +            ],
        +            "type": "string"
        +          },
        +          "period": {
        +            "description": "Effect period in frames. Defaults to total scene frame count.",
        +            "type": "number"
        +          },
        +          "phase": {
        +            "description": "Phase offset 0–1 to stagger this element relative to others (0.5 = half-cycle offset).",
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "name"
        +        ],
        +        "type": "object"
        +      },
        +      "opacity": {
        +        "description": "Opacity 0–100 (default: 100).",
        +        "maximum": 100,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "path": {
        +        "description": "Absolute local path to the sprite sheet image.",
        +        "type": "string"
        +      },
        +      "rows": {
        +        "description": "Number of rows in the sprite grid.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "scale": {
        +        "description": "Pixel scale factor.",
        +        "maximum": 9007199254740991,
        +        "minimum": 1,
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "sprite",
        +        "description": "Sprite sheet element.",
        +        "type": "string"
        +      },
        +      "visible": {
        +        "description": "Whether the element is visible (default: true).",
        +        "type": "boolean"
        +      },
        +      "x": {
        +        "anyOf": [
        +          {
        +            "description": "Absolute pixel X coordinate (0 = left edge).",
        +            "type": "number"
        +          },
        +          {
        +            "description": "Semantic horizontal alignment.",
        +            "enum": [
        +              "left",
        +              "center",
        +              "right"
        +            ],
        +            "type": "string"
        +          }
        +        ],
        +        "description": "X position (default: center)."
        +      },
        +      "y": {
        +        "description": "Y position (default: 0).",
        +        "maximum": 9007199254740991,
        +        "minimum": -9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "path",
        +      "cols",
        +      "rows"
        +    ],
        +    "type": "object"
        +  }
        +]
      • changedInput schema / properties / output / description
        Previous value: -"Explicit output file path for saving (overrides PIXOO_OUTPUT_DIR)."New value: +"Absolute, already-normalized path to save the first frame to, in addition to the PIXOO_OUTPUT_DIR auto-save when that is configured. Both paths are reported in outputFiles."
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "pushed",
        +      "frames",
        +      "layout"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set and push was requested. `asset_not_found`: An image or sprite path could not be read. `invalid_color`: A color value could not be resolved. `unknown_icon`: Icon name not found in the registry. `invalid_output_path`: The output path is relative or contains traversal segments. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "device_unreachable",
        +            "device_rejected",
        +            "no_device_configured",
        +            "asset_not_found",
        +            "invalid_color",
        +            "unknown_icon",
        +            "invalid_output_path"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / properties / previewData
        Removed value: -{
        -  "description": "Base64-encoded PNG preview of the rendered scene (8× upscaled, 512px). For animations: the middle frame.",
        -  "type": "string"
        -}
      • removedOutput schema / properties / previewMimeType
        Removed value: -{
        -  "description": "MIME type of the preview image.",
        -  "enum": [
        -    "image/png"
        -  ],
        -  "type": "string"
        -}
      • removedOutput schema / required
        Removed value: -[
        -  "pushed",
        -  "frames",
        -  "layout"
        -]
    • Changedpixoo_control_device6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "reachable",
        +      "applied"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_rejected`: Device rejected the command. `no_device_configured`: PIXOO_IP is not set. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "device_unreachable",
        +            "device_rejected",
        +            "no_device_configured"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "reachable",
        -  "applied"
        -]
    • Changedpixoo_design_brief6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "topic",
        +      "craftGuidance",
        +      "deviceContext",
        +      "nextToolSuggestions",
        +      "availableThemes",
        +      "iconCategories"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode.",
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "topic",
        -  "craftGuidance",
        -  "deviceContext",
        -  "nextToolSuggestions",
        -  "availableThemes",
        -  "iconCategories"
        -]
    • Changedpixoo_discover_devices6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "devices"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `discovery_failed`: Divoom cloud discovery endpoint is unreachable. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "discovery_failed"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "devices"
        -]
    • Changedpixoo_display_text8 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "pushed",
        +      "layout"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable over the network. `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set. `invalid_color`: A color value could not be resolved. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "device_unreachable",
        +            "device_rejected",
        +            "no_device_configured",
        +            "invalid_color"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / properties / previewData
        Removed value: -{
        -  "description": "Base64-encoded PNG preview of the rendered frame (8× upscaled, 512px).",
        -  "type": "string"
        -}
      • removedOutput schema / properties / previewMimeType
        Removed value: -{
        -  "description": "MIME type of the preview image.",
        -  "enum": [
        -    "image/png"
        -  ],
        -  "type": "string"
        -}
      • removedOutput schema / required
        Removed value: -[
        -  "pushed",
        -  "layout"
        -]
    • Changedpixoo_overlay_text6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "acknowledged",
        +      "mode",
        +      "id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_rejected`: Device firmware rejected the command. `no_device_configured`: PIXOO_IP is not set. `invalid_color`: The color value could not be resolved. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "device_unreachable",
        +            "device_rejected",
        +            "no_device_configured",
        +            "invalid_color"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "acknowledged",
        -  "mode",
        -  "id"
        -]
    • Changedpixoo_push_image8 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "pushed"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `device_unreachable`: Device is not reachable. `device_rejected`: Device firmware returned a non-zero error code. `no_device_configured`: PIXOO_IP is not set. `asset_not_found`: Image path or URL could not be read. Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "device_unreachable",
        +            "device_rejected",
        +            "no_device_configured",
        +            "asset_not_found"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / properties / previewData
        Removed value: -{
        -  "description": "Base64-encoded PNG preview of the downsampled 64×64 result (8× upscaled, 512px).",
        -  "type": "string"
        -}
      • removedOutput schema / properties / previewMimeType
        Removed value: -{
        -  "description": "MIME type of the preview image.",
        -  "enum": [
        -    "image/png"
        -  ],
        -  "type": "string"
        -}
      • removedOutput schema / required
        Removed value: -[
        -  "pushed"
        -]
  9. 7 tool updatesv1.0.0
    • First observedpixoo_compose_scene
    • First observedpixoo_control_device
    • First observedpixoo_design_brief
    • First observedpixoo_discover_devices
    • First observedpixoo_display_text
    • First observedpixoo_overlay_text
    • First observedpixoo_push_image

TDQS

A4.4/5.0

Scored across 8 tools

Disambiguation5/5

Although several tools produce visual output, the descriptions clearly partition them: compose_scene for layered compositions, display_text for previewable text-only output, overlay_text for persistent device-native tickers, render_html for HTML pages, and push_image for file/URL images. Device control, discovery, and design guidance are also clearly separate.

Naming Consistency5/5

All tools use the pixoo_ prefix and snake_case with a consistent verb_noun shape: compose_scene, render_html, control_device, discover_devices, display_text, overlay_text, push_image, and design_brief. There is no mixed casing or inconsistent style.

Tool Count5/5

Eight tools fit the server's scope well: one discovery tool, one device-control tool, one guidance tool, and several distinct rendering/display paths. Each tool has a clear role and none feels redundant.

Completeness4/5

The set covers initial setup, device state, design guidance, and multiple rendering/display workflows including text, scenes, HTML, images, and overlays. Minor gaps remain around explicitly pushing or clearing composed scenes and broader lifecycle operations, but core workflows are covered.

Maintenance

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    A
    maintenance
    Enables AI clients to control Divoom LAN devices, including watchface management, brightness adjustment, and screen control through natural language.
    42
    41 npm
    7
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Enables Claude to create, update, and manage LED patterns on a PixelBlaze controller, including setting brightness and reading device info, through a set of tools that interact with the device's API.
    14
    -