-**Claude beantwortet eine Frage, die zuvor kein Chatbot beantworten konnte**, weil die Daten in einem Außendienstsystem liegen, das REST statt MCP spricht:
+**Eine Frage in Claude, beantwortet aus Etsy, SAP und einer Logistik-API.** AnythingMCP bindet den Shop aus dem Marktplatz an, SAP S/4HANA über OData und eine REST-API über ihre OpenAPI-Spezifikation. Danach arbeitet Claude mit allen drei Systemen:
+
**自分で動かす** — 3 行のコマンドで、リポジトリのクローンは不要です。[詳しい手順はこちら](#run-it-yourself)。
```bash
diff --git a/README.md b/README.md
index 15ffbee8..bcebb34d 100644
--- a/README.md
+++ b/README.md
@@ -23,12 +23,14 @@
-**Claude answering a question no chatbot could answer**, because the data lives in a field-service system that speaks REST, not MCP:
+**One question in Claude, answered from Etsy, SAP and a logistics API.** AnythingMCP connects the shop from the marketplace, SAP S/4HANA over OData and a REST API from its OpenAPI spec, then Claude works across all three:
+
**自己运行试试** — 三行命令,无需克隆仓库,[详细说明见下文](#run-it-yourself):
```bash
diff --git a/docs/assets/demo-claude.gif b/docs/assets/demo-claude.gif
deleted file mode 100644
index e6b1d476..00000000
Binary files a/docs/assets/demo-claude.gif and /dev/null differ
diff --git a/docs/assets/demo-lumen-clay.gif b/docs/assets/demo-lumen-clay.gif
new file mode 100644
index 00000000..6ce8001f
Binary files /dev/null and b/docs/assets/demo-lumen-clay.gif differ
diff --git a/video/demo/.gitignore b/video/demo/.gitignore
new file mode 100644
index 00000000..ffedb799
--- /dev/null
+++ b/video/demo/.gitignore
@@ -0,0 +1,20 @@
+footage/
+renders/
+node_modules/
+.wrangler/
+director/native/humanio
+*.recordly
+director/mock-backend/*.snapshot.json
+dist/
+compositions/.media/
+compositions/.motion/
+compositions/snapshots/
+compositions/assets/footage/
+styleframes/handoff/
+styleframes/attach/
+styleframes/renders/
+.DS_Store
+compositions/.hyperframes/
+compositions/.thumbnails/
+__pycache__/
+compositions/.waveform-cache/
diff --git a/video/demo/README.md b/video/demo/README.md
new file mode 100644
index 00000000..e23ebbe2
--- /dev/null
+++ b/video/demo/README.md
@@ -0,0 +1,122 @@
+# AnythingMCP demo video ("Lumen & Clay")
+
+Source of the product demo on anythingmcp.com/video-promo and in the README (2:40, English).
+No voice-over: on-screen type, captions, music, and screen recordings of the product and of Claude.
+
+The story: *Lumen & Clay*, a fictional ceramics studio, sells on Etsy, runs SAP S/4HANA and
+has its own logistics API. The video connects all three through AnythingMCP (a marketplace
+adapter, a custom OData connector, an OpenAPI import) and ends with Claude answering a
+question that spans them. **All data is fictional**: nothing here touches a real shop, SAP
+system or customer.
+
+```
+fixtures/ the one source of the Lumen & Clay data (products, orders, SAP, logistics)
+mock-api/ mock backend (Etsy v3, SAP Gateway OData V2, logistics API): Worker-style handler, run on Node
+director/ drives the recordings: real-cursor input helper, mock backend, scene scripts
+styleframes/ Claude Design brief (the exported styleframes stay local)
+compositions/ HyperFrames project: build.py generates index.html from the cut list
+export-web.py web and README files derived from the final render
+footage/ raw Recordly exports (git-ignored; compositions/assets/footage/ too)
+renders/ final renders and web files (git-ignored)
+```
+
+## 1. Mock backend
+
+```bash
+cd mock-api
+npm install
+npm run dev # local, http://localhost:8787 (wrangler)
+npm run build:node # dist/server.mjs, the same handler on plain Node
+```
+
+On AnythingMCP Cloud it runs as an internal container next to the backend, with no
+public port. The backend reaches it by a dotted network alias (connector base URLs must
+contain a dot), which is on the instance SSRF allowlist:
+
+```bash
+scp dist/server.mjs root@:/opt/lumen-demo-api/server.mjs
+docker run -d --name lumen-demo-api --network amcp-cloud_default \
+ --network-alias demo-api.lumenandclay.internal --restart unless-stopped --memory 128m \
+ -v /opt/lumen-demo-api/server.mjs:/app/server.mjs:ro -e PORT=8787 node:22-alpine node /app/server.mjs
+# site_settings.ssrf_allowed_hosts must contain "demo-api.lumenandclay.internal"
+```
+
+Endpoints:
+
+| Path | What |
+|---|---|
+| `/etsy/v3/application/...` | the nine endpoints of the Etsy adapter |
+| `/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/ServiceCollection` | SAP service catalog (42 services) |
+| `/sap/opu/odata/sap/ZLC_STOCK_OVERVIEW_SRV` | stock by plant with safety stock (the one the demo queries) |
+| `/sap/opu/odata/sap/API_PRODUCT_SRV`, `API_SALES_ORDER_SRV` | products, sales orders |
+| `/logistics/openapi.json` | OpenAPI 3.1 of the logistics API (12 operations) |
+| `/logistics/v1/...` | the logistics API |
+
+Dates are relative to the day of the request, so "last 30 days" and "this week" hold
+whenever the video is recorded.
+
+## 2. Cloud connectors used by Claude
+
+`mock-api/cloud-setup.cjs` creates, through the backend's own API, one MCP server
+**"Lumen & Clay Demo"** with only these connectors (`--reset` replaces a previous run):
+
+| Connector | Type | Base URL | Notes |
+|---|---|---|---|
+| Etsy | the Etsy marketplace adapter, re-pointed | `/etsy/v3/application` | auth switched to none |
+| SAP S/4HANA | OData, SAP Gateway on, client 100, tool prefix `s4` | `` | Basic auth, any credentials |
+| Lumen Logistics API | REST from OpenAPI | spec `/logistics/openapi.json` | API key, any value |
+
+The server instructions tell Claude where things are (shop id, the stock service, the
+order_ref convention), so answers need fewer calls on camera.
+
+## 3. Recording
+
+The web-app scenes run against the real frontend with a local mock backend (so no real
+workspace, connector or email is ever on screen); the Claude scenes run in claude.ai.
+Both are driven by `director/`, which moves the **real** macOS cursor with human timing,
+so Recordly's auto-zoom and cursor effects work as with a person at the mouse.
+
+One-time setup:
+
+1. System Settings → Privacy & Security → **Accessibility**: enable the app that runs the
+ director (Conductor or Terminal). **Screen Recording**: enable Recordly.
+2. `cd director && npm install && npm run build:native`
+3. Build the frontend for the harness:
+ `cd packages/frontend && BACKEND_INTERNAL_URL=http://127.0.0.1:4100 NEXT_PUBLIC_API_URL= npx next build`
+4. Log in to claude.ai once in the recording profile (`~/.lumen-demo-chrome`), which the
+ director opens as an app window.
+
+Run a take with `cd director && npx tsx run.ts `; with Recordly recording, press
+Ctrl+Option+G in the demo window (or `npx tsx go.ts`). Scenes: `etsy-ui`, `sap-ui`,
+`openapi-ui`, `connect-claude`, `etsy-claude`, `sap-claude`, `finale-claude`
+(`--dry` checks a web-app scene headless). The director takes care of what bit us:
+
+- the window opens on the Retina display, so a take is 3200×1800 even with a 1x monitor as main display;
+- claude.ai is forced to English for the take, chats are incognito (no sidebar, history or memory);
+- the notification nudge over the composer is hidden, Chrome autocomplete is off (its dropdown swallows real clicks);
+- the consent page shows the demo user's email instead of the real account;
+- `connect-claude` disconnects and removes the connector off camera first: removing alone keeps the OAuth grant and skips the consent page. Set `LUMEN_MCP_URL` to the server URL.
+
+Before every take: Do Not Disturb on, nothing over the recording area, Recordly in
+**window** mode. Export every clip **untrimmed** (Recordly otherwise cuts idle stretches,
+the Claude waits among them) at full resolution. Clip names: `01-etsy-ui`,
+`02-etsy-claude`, `03-sap-ui`, `04-sap-claude`, `05-openapi-ui`, `06b-finale-claude`,
+`07-connect-claude`, in `compositions/assets/footage/`.
+
+## 4. Edit and render
+
+```bash
+cd compositions
+# frame-difference per frame, used to snap cuts to still frames
+for n in assets/footage/*.mp4; do b=$(basename $n .mp4); ffmpeg -i $n -vf "scale=320:180,tblend=all_mode=difference,signalstats,metadata=print:key=lavfi.signalstats.YAVG:file=.motion/$b.txt" -f null -; done
+python3 build.py # cut list, captions, overlays -> index.html (see the script's docstring for .motion/motion.json)
+npx hyperframes check
+npx hyperframes preview --background
+npx hyperframes render --output ../renders/anythingmcp-demo-lumen-clay-en.mp4 --fps 30 --quality delivery
+cd .. && python3 export-web.py # demo.mp4/.webm, 23 s preview loop, poster, README GIF
+```
+
+- **Cut list**: `SCENES` in `build.py`, one line per kept range: clip, source in/out, speed, caption. Claude waits run at 6–8× with a visible speed label; cut after the Send click, before Recordly's zoom-out.
+- **Look**: overlays follow the Claude Design styleframes (AnythingMCP Design System: Fraunces, Geist, cream/ink/blue); recordings fly in and out in 3D on a dark stage, captions sit below them.
+- **Music**: a HeyGen catalog track (`npx hyperframes media-use resolve --type bgm`, needs `heygen auth login --oauth`), kept out of git in `compositions/.media/`. Its licence for use outside HeyGen is not confirmed.
+- **Publishing**: the site streams the files from DigitalOcean Spaces (`koch-katalog` bucket, `anythingmcp/demo//`, public-read, `Cache-Control: immutable`), so a new cut goes into a new dated folder and `lib/demo-media.ts` in the website repo points at it. The README uses `docs/assets/demo-lumen-clay.gif`.
diff --git a/video/demo/compositions/AGENTS.md b/video/demo/compositions/AGENTS.md
new file mode 100644
index 00000000..ff89fb99
--- /dev/null
+++ b/video/demo/compositions/AGENTS.md
@@ -0,0 +1,107 @@
+# HyperFrames Composition Project
+
+## Skills — USE THESE FIRST
+
+**Always invoke the relevant skill before writing or modifying compositions.** Skills encode framework-specific patterns (e.g., `window.__timelines` registration, `data-*` attribute semantics, shader-compatible CSS rules) that are NOT in generic web docs. Skipping them produces broken compositions.
+
+**Doing anything with HyperFrames?** Start at `/hyperframes` — it tells you what HyperFrames can do and which skill or workflow handles your intent (make a video, TTS / BGM, prep footage, author / animate, render, install blocks), confirms your brief up front (the intent layer), and routes every "make me a…" request (a video, a deck, a composition port) to the right workflow. Read it first, especially when there's no project context to orient you. The workflows it routes to:
+
+- `/product-launch-video` — any **website** URL or brief / script → a product launch / SaaS / promo video, or a site tour / showcase featuring the site's own captured visuals.
+- `/faceless-explainer` — arbitrary text (topic / article / notes), **no URL, no website capture** → 60-90s faceless explainer.
+- `/embedded-captions` — an existing talking-head video (MP4) → the same footage with captions / subtitles added (rail + embed, or pure-cinematic embed); the footage itself is untouched.
+- `/talking-head-recut` — an existing talking-head / interview / podcast video (MP4) → the same footage **packaged with designed graphic overlays** (kinetic titles, lower-thirds, data callouts, pull-quotes, side panels, pip) synced to the transcript; the clip plays unchanged underneath. (Plain captions/subtitles → `/embedded-captions`.)
+- `/pr-to-video` — a GitHub PR (URL / `owner/repo#N` / "this PR") → 30-90s code-change explainer (changelog / feature reveal / fix / refactor).
+- `/motion-graphics` — a short (typically under 10s) design-led **motion graphic**, motion-is-the-message, no narration: kinetic type, a stat / number count-up, a chart, a logo sting, a lower-third / overlay, or an animated tweet / headline / captured-page highlight; rendered to MP4 or a transparent overlay. Longer / narrated / custom → `/general-video`.
+- `/music-to-video` — a **music track** (audio file, video to pull audio from, or one generated from a mood brief) → beat-synced video (lyric / slideshow / kinetic promo). Music drives pacing; user-supplied images / videos are cut onto the same beat grid.
+- `/slideshow` — a **presentation / pitch deck / interactive deck** — discrete slides, fragment reveals, branching, hotspot navigation, presenter mode. Output is a navigable deck, not a rendered video.
+- `/general-video` — fallback for any other video (title card, longer brand / sizzle reel, multi-scene montage, static loop, custom composition) and the home of **companion mode** — co-create with the full HyperFrames toolbox; the original hyperframes authoring flow, any length.
+
+**Porting an existing composition?** `/remotion-to-hyperframes` translates a Remotion (React) composition into HyperFrames HTML — a source migration, separate from the creation workflows above.
+
+The domain skills (`/hyperframes-core`, `/hyperframes-animation`, `/hyperframes-keyframes`, `/hyperframes-creative`, `/hyperframes-cli`, `/media-use`, `/hyperframes-audio`, `/hyperframes-registry`, `/figma`) and the full capability map live inside `/hyperframes` — it is the single source of truth for which skill handles which intent.
+
+**Changing how real footage or images look or reveal?** Load `/media-use` and read its `references/media-treatments.md` before editing, even when the request only says dark, flat, boring, retro, private, or “make the reveal cooler.” It governs how footage is treated, never whether media may be used. Use canonical media treatments and seek-safe motion; do not improvise equivalent CSS/SVG filters or overlays.
+
+> **Tailwind v4 projects** (`hyperframes init --tailwind`): see `/hyperframes-core` → `references/tailwind.md`.
+
+> **Using a HyperFrames plugin?** Load skills from that installed bundle and follow
+> its `hyperframes/references/plugin-installation.md` execution rules. Update via
+> the plugin manager, not the standalone commands below.
+>
+> **Standalone skill missing or stale?** Run `npx hyperframes skills update ` to install/refresh
+> the specific skill you need (the `/hyperframes` router does this automatically before
+> entering a workflow), or bare `npx hyperframes skills update` to refresh the core set plus
+> everything already installed — neither pulls the full set. Restart the agent session so
+> newly installed skills load.
+
+## Commands
+
+```bash
+npm run dev # human-operated foreground preview (blocks until stopped)
+npx hyperframes preview --background # agent-safe persistent Studio preview
+npx hyperframes preview --status # verify the persistent preview is listening
+npx hyperframes preview --stop # stop it when review is finished
+npm run check # lint + runtime + layout + motion + contrast (one command)
+npm run render # render to MP4
+npm run publish # publish and get a shareable link
+npx hyperframes lint --verbose # include info-level findings
+npx hyperframes lint --json # machine-readable output for CI
+npx hyperframes docs # reference docs in terminal
+```
+
+> **Agents must use `npx hyperframes preview --background` for Studio handoff.** Do not rely
+> on a shell/tool `run_in_background` wrapper around `npm run dev`: that foreground process
+> remains owned by the invoking session and can disappear while the browser stays open,
+> leaving refreshes at `ERR_CONNECTION_TIMED_OUT`. Verify with `preview --status`, keep it
+> alive through review, and stop it explicitly with `preview --stop` afterward.
+
+> **Pinned CLI version.** These scripts pin an exact `hyperframes@X.Y.Z` so this project re-renders identically over time. Weeks later that pin lags fixes shipped since. To move up: `npx hyperframes@latest upgrade --project . --check` (shows the delta), then `npx hyperframes@latest upgrade --project .` to rewrite the pins. Always unpinned — the pinned script re-runs the old version against itself.
+
+## Documentation
+
+**For quick reference**, use the local CLI docs command (no network required):
+
+```bash
+npx hyperframes docs
+```
+
+Topics: `data-attributes`, `gsap`, `compositions`, `rendering`, `examples`, `troubleshooting`
+
+**For full documentation**, discover pages via the machine-readable index — do NOT guess URLs:
+
+```
+https://hyperframes.heygen.com/llms.txt
+```
+
+## Project Structure
+
+- `index.html` — main composition (root timeline)
+- `compositions/` — sub-compositions referenced via `data-composition-src`
+- `meta.json` — project metadata (id, name)
+- `transcript.json` — whisper word-level transcript (if generated)
+
+## Linting — ALWAYS RUN AFTER CHANGES
+
+After creating or editing any `.html` composition, **always** run the full check before considering the task complete:
+
+```bash
+npm run check
+```
+
+Fix all errors before presenting the result. Warnings should be reviewed before rendering.
+
+## Key Rules
+
+1. Every timed element needs `data-start` and a duration. `data-start` is what marks it as timed; `data-track-index` is an optional Studio display lane the render never reads
+2. Give timed visual elements `class="clip"`. The framework keys visibility off `data-start`, not the class, but the shared `.clip` CSS is what gives a scene its full-frame box, and `lint` warns without it
+3. Register one paused root timeline per composition on `window.__timelines`:
+ ```js
+ window.__timelines = window.__timelines || {};
+ window.__timelines["composition-id"] = gsap.timeline({ paused: true });
+ ```
+ Scene timelines manually added to this root must not be paused. A paused
+ child does not advance when the root is seeked. The runtime activates
+ registered composition siblings, not arbitrary nested scene timelines.
+4. Videos use `muted` with a separate `