Living Logo
Turn a one-sentence brief into a character that is alive: one simple rounded mascot,
built as an SVG rig, animated with CSS keyframes, delivered as a logo, a set of UI states
and a sticker pack. It is alive because the whole head turns — a real 3D yaw with the two
eye-holes sliding and foreshortening across it — not because something wiggles in place. Everything is code — readable, recolorable, animatable, under 3 KB a
file — and plays in any browser, README, docs tool or chat app. No image-generation model is
called at any point; do not offer one.
What you deliver
<name>/
├── manifest.json brief, rationale, tokens, rig recipe, file list — executable by compose.py
├── character/mark.svg the logo: whole silhouette centred on --c3, head turning
├── states/ idle · happy · thinking · error · sleep · loading (transparent)
├── stickers/ 01-hi … 16-awkward, each with a die-cut plate (transparent)
│ └── export/<platform>/ only if export tooling ran (gif / webm / apng)
└── preview.html one page where everything above is playing
Every SVG is self-contained: viewBox="0 0 512 512", one <style> block, three color
tokens on the root element, no text, no fonts, no scripts, no external references, a
prefers-reduced-motion guard. Read references/rig-spec.md before writing the first file.
The head turn uses a 3D rotateY on SVG elements. Chromium and WebKit render it; an engine
that flattens SVG 3D degrades to a correct static face, because the orbit is identity at
yaw 0 — never restructure it in a way that loses that property.
Workflow
- Parse the brief. Note the explicit subject (if any), product, audience, personality,
palette or brand color, and which packs are wanted. Default packs when unspecified:
mark + states. Offer the sticker pack as the third pack; build it when the user says yes.
- Infer context before asking. In a product repository read the README, app metadata,
landing copy and design tokens (a brand color there feeds
--from-brand). Treat context
as sufficient when you can state what the product does, who it is for and how it should
feel. Otherwise ask one consolidated round of three questions (does / for whom / feels
like) and continue with the best interpretation — never a second questionnaire.
- Propose three directions in one compact line each:
<subject> — <product connection> — <silhouette: body + species feature>.
With an explicit subject, vary treatment (body shape, feature, mouth, palette mood).
Without one, propose three genuinely different subjects, each tied to a different product
promise; familiar animals first, objects/robots/ghosts only with a product reason. Every
direction names its species feature (a bear is its muzzle, a cat its ears, a seal its
flippers) — ears on a round head are not a character.
End with: "I'll build six animated candidates — two per direction, A1/A2, B1/B2, C1/C2
— unless you'd rather adjust."
Do not build before agreement unless the brief already authorizes it.
- Build the six candidates as marks — one
scripts/compose.py … --kind mark command
each (candidates/A1-<subject>.svg …), or hand-assembly from
references/parts-library.md when Python is unavailable. Two variants of a direction
differ in one deliberate axis (body, feature, lens, palette hue), not in random noise.
Vary the color strategy across the six (see references/color-system.md).
- Show them on one wall.
python3 scripts/export.py wall candidates/*.svg --out candidates/preview.html --auto-label --caption "A1=…" …, or fill
references/wall-template.html by hand. Tell the user where it is and list each label
with its direction and one-line rationale. Deliver all six; do not rank, filter, or
quietly regenerate any of them.
- On the pick, write
manifest.json and build the packs from it:
python3 scripts/compose.py --manifest manifest.json --out-dir <name>/ produces the mark,
every listed state and sticker, and preview.html. By hand: references/states.md and
references/stickers.md hold the same recipes. The rig stays identical across files —
only face slots, <style> and overlays change.
- Validate.
python3 scripts/validate.py --kind mark character, --kind state states,
--kind sticker stickers. Fix every FAIL; fix WARNs unless the user asked for the
deviation. Without Python, check by eye against the budgets below.
- Export when asked or when a chat platform is the target and the tooling exists
(
scripts/export.py gif|webm|apng --platform …). If Playwright/ffmpeg are missing, say
so, deliver the SVGs, and give the one-line install command — never fake a GIF.
- Report (see Delivery).
Generate refinements only when the user asks. A new draw is a new set of labels (A3, A4 …).
Budgets — the taste, written down
Shape. One dominant continuous silhouette from 1–5 primitives inside #character
(stickers may add 2 for a mouth, brows or a prop; the plate and the mask are not counted):
body (1, cloud body 3) + one species feature (0–2) + limbs (0–2). Thick rounded masses;
every tip visibly blunt; paired features in pairs. Flat fill only — no outlines,
gradients, highlights, shading, texture, nostrils or decorative marks. A darker lower mass
in particular is forbidden: dark reads as feature here, so a shade grows a phantom muzzle.
The plumpness comes from the silhouette and the saturation, never from a tone. Must read at
32 px.
Color. Three semantic tokens on the root: --c1 body, --c2 sticker ink (mouth and
brows only), --c3 the ground the character sits on. Bands: --c1 L 0.55–0.68 with the
chroma left high — the body carries the identity; --c3 L 0.94–0.97, chroma ≤ 0.02;
--c2 L ≈ 0.22 tinted toward the body hue. One ratio decides everything: --c1 on
--c3 ≥ 2.5:1 — the eyes are holes onto --c3, so that single number governs whether
the silhouette reads and whether the face reads. Sticker ink --c2 on --c1 ≥ 4.5:1.
Transparent stickers always carry the --plate die-cut backing (white by default).
compose.py --from-brand "#hex" derives a compliant palette and darkens the body until it
earns the ratio.
Face. Two lenses, punched through the body with a <mask> so they are holes, not
shapes laid on top — that is what keeps them right on a transparent file and on the mark's
ground alike. Never draw an eye as a filled shape over the body. The anchor is derived from
the body's own bbox, never a fixed canvas coordinate: eye line at 0.40 of the body height,
spacing at ±0.205 of its width, sizes scaled by the body width. The mark and the states
are mouthless — the two lenses carry the whole expression, by re-posing one primitive
(shape, w, h, tilt, dy). Only the sticker pack may add a mouth, brows or cheeks.
Composition. The whole silhouette, centred, with a margin, on a plain --c3 ground.
Nothing is ever cropped and there is no rounded-rect container: a cropped or boxed
silhouette reads as a tile, and the silhouette is the identity. The transform is derived
from the rig, never guessed (rig-spec.md). States and stickers: the same composition,
transparent.
Motion. Five tracks, each on its own element so their transforms compose instead of
overwriting each other: #character the state's personality (a root preset), #tilt the
head roll, #squash a counter-phase vertical squash, #eye-l/#eye-r the 3D orbit,
.lens the foreshortening with the blink folded in. Two animations on the same element
do not compose — the later one wins outright — so anything sharing an element shares one
keyframe track. The head turn is a real rotateY under perspective, so the browser
interpolates it continuously; never sample a smooth curve into many keyframes with
per-segment ease-in-out, which brakes to a stop at every one of them. Head roll ≤ 3°,
squash ≤ 1 %; the turn 9 s for idle, 2–5 s for active states; give the layers coprime
periods so the loop does not announce itself. Reduced-motion guard always. Presets live in
references/motion-presets.md.
Character. Large head, compact proportions, soft cheeks, widely spaced simple eyes, calm
friendly expression by default. Simplicity and lovability beat anatomical correctness.
Building a file
Prefer scripts/compose.py — the parts, presets, recipes and composition math are encoded
there, so the agent decides the recipe and the script guarantees the geometry
(python3 scripts/compose.py --list shows every body, feature, limb, lens, mouth, state,
sticker and palette). The face anchor, the yaw cylinder and the perspective compensation are
all derived from the body's bbox — never hand-place an eye. By hand: start from assets/examples/seal/states/idle.svg, keep the
slot structure from references/rig-spec.md, swap parts from references/parts-library.md,
paste presets from references/motion-presets.md. Static poses go on
<g class="pose" transform="…"> wrappers; animated elements never carry a transform
attribute. Name the character if the user has not; it goes into aria-label and the
manifest.
Two complete example sets to imitate: assets/examples/seal/ (manifest, mark, six states,
sixteen stickers, preview.html — all generated from the manifest) and
assets/examples/wall/ (six candidate marks from six bodies/features, with their wall).
Tooling (optional, never required)
scripts/compose.py — stdlib only; builds any mark/state/sticker from a recipe, a whole
set from a manifest, a palette from a brand color; prints contrast notes.
scripts/validate.py <files|dirs> --kind mark|state|sticker [--json] — stdlib only;
FAILs on portability/accessibility breaks, WARNs on budget, structure and contrast drift.
scripts/export.py wall … — stdlib only; builds preview.html.
scripts/export.py gif|webm|apng|mp4 <svg> --platform <name> — needs pip install playwright && python3 -m playwright install chromium and ffmpeg; renders frames by
stepping the Web Animations clock, encodes with platform presets, retries under the size
budget. scripts/export.py platforms prints the presets.
Runtimes that cannot run Python still get the full deliverable: the SVGs and a hand-filled
wall. Say which platforms accept SVG directly and which need a conversion.
Delivery
Report, in this order: the pick (label, subject, species feature, rationale); tokens and
their contrast notes; the rig recipe; every file path grouped by pack with its motion
recipe; the preview page; validation summary (or "checked by eye: …"); export results with
sizes versus platform limits; what was not built and why. Keep it to one screen. Then offer
the next pack or a refinement round — not both at once.
Never
- Call an image/video model, trace a raster, or describe the output as AI-generated art.
- Use
<text>, fonts, scripts, gradients, filters, external refs, or a fourth semantic color.
- Add shading of any kind, or crop the silhouette, or put it in a rounded-rect container.
- Draw the eyes as filled shapes on top of the body instead of punching them through the mask.
- Give the mark or a state a mouth, or exceed the primitive budget without being asked.
- Ship a transparent sticker without its plate unless the user asked for that.
- Rank, filter, or silently regenerate candidates; deliver what you drew.
- Inline two rigs on one page without prefixing ids (use
<img>).
- Ask a second round of discovery questions.
1---2name: living-logo3description: Design a living character logo from a one-sentence brief, entirely as code — no image models. Builds a simple, cute, rounded mascot as a parametric SVG rig with CSS keyframe animation and delivers three packs from it - the mark (animated logo on a solid background), six looping states (idle, happy, thinking, error, sleep, loading) and a sticker pack (12–16 expressions) with optional GIF/WebM/APNG export for WeChat, Telegram, Discord, Slack, LINE and Feishu. Use when the user asks for an animated or living logo, a mascot or IP character that moves, 会动的 logo, 动态吉祥物, 表情包, emoji or sticker pack, 微信表情, loading / empty-state / 404 characters, or wants three directions and six animated candidates to pick from.4---56# Living Logo78Turn a one-sentence brief into a character that is **alive**: one simple rounded mascot,9built as an SVG rig, animated with CSS keyframes, delivered as a logo, a set of UI states10and a sticker pack. It is alive because the whole head *turns* — a real 3D yaw with the two11eye-holes sliding and foreshortening across it — not because something wiggles in place. Everything is code — readable, recolorable, animatable, under 3 KB a12file — and plays in any browser, README, docs tool or chat app. No image-generation model is13called at any point; do not offer one.1415## What you deliver1617```18<name>/19├── manifest.json brief, rationale, tokens, rig recipe, file list — executable by compose.py20├── character/mark.svg the logo: whole silhouette centred on --c3, head turning21├── states/ idle · happy · thinking · error · sleep · loading (transparent)22├── stickers/ 01-hi … 16-awkward, each with a die-cut plate (transparent)23│ └── export/<platform>/ only if export tooling ran (gif / webm / apng)24└── preview.html one page where everything above is playing25```2627Every SVG is self-contained: `viewBox="0 0 512 512"`, one `<style>` block, three color28tokens on the root element, no text, no fonts, no scripts, no external references, a29`prefers-reduced-motion` guard. Read `references/rig-spec.md` before writing the first file.3031The head turn uses a 3D `rotateY` on SVG elements. Chromium and WebKit render it; an engine32that flattens SVG 3D degrades to a correct **static** face, because the orbit is identity at33yaw 0 — never restructure it in a way that loses that property.3435## Workflow36371. **Parse the brief.** Note the explicit subject (if any), product, audience, personality,38 palette or brand color, and which packs are wanted. Default packs when unspecified:39 mark + states. Offer the sticker pack as the third pack; build it when the user says yes.402. **Infer context before asking.** In a product repository read the README, app metadata,41 landing copy and design tokens (a brand color there feeds `--from-brand`). Treat context42 as sufficient when you can state what the product does, who it is for and how it should43 feel. Otherwise ask **one** consolidated round of three questions (does / for whom / feels44 like) and continue with the best interpretation — never a second questionnaire.453. **Propose three directions** in one compact line each:46 `<subject> — <product connection> — <silhouette: body + species feature>`.47 With an explicit subject, vary treatment (body shape, feature, mouth, palette mood).48 Without one, propose three genuinely different subjects, each tied to a different product49 promise; familiar animals first, objects/robots/ghosts only with a product reason. Every50 direction names its species feature (a bear is its muzzle, a cat its ears, a seal its51 flippers) — ears on a round head are not a character.52 End with: *"I'll build six animated candidates — two per direction, A1/A2, B1/B2, C1/C253 — unless you'd rather adjust."*54 Do not build before agreement unless the brief already authorizes it.554. **Build the six candidates as marks** — one `scripts/compose.py … --kind mark` command56 each (`candidates/A1-<subject>.svg` …), or hand-assembly from57 `references/parts-library.md` when Python is unavailable. Two variants of a direction58 differ in one deliberate axis (body, feature, lens, palette hue), not in random noise.59 Vary the color strategy across the six (see `references/color-system.md`).605. **Show them on one wall.** `python3 scripts/export.py wall candidates/*.svg --out61 candidates/preview.html --auto-label --caption "A1=…" …`, or fill62 `references/wall-template.html` by hand. Tell the user where it is and list each label63 with its direction and one-line rationale. Deliver all six; do not rank, filter, or64 quietly regenerate any of them.656. **On the pick, write `manifest.json` and build the packs** from it:66 `python3 scripts/compose.py --manifest manifest.json --out-dir <name>/` produces the mark,67 every listed state and sticker, and `preview.html`. By hand: `references/states.md` and68 `references/stickers.md` hold the same recipes. The rig stays identical across files —69 only face slots, `<style>` and overlays change.707. **Validate.** `python3 scripts/validate.py --kind mark character`, `--kind state states`,71 `--kind sticker stickers`. Fix every FAIL; fix WARNs unless the user asked for the72 deviation. Without Python, check by eye against the budgets below.738. **Export when asked or when a chat platform is the target** and the tooling exists74 (`scripts/export.py gif|webm|apng --platform …`). If Playwright/ffmpeg are missing, say75 so, deliver the SVGs, and give the one-line install command — never fake a GIF.769. **Report** (see Delivery).7778Generate refinements only when the user asks. A new draw is a new set of labels (A3, A4 …).7980## Budgets — the taste, written down8182**Shape.** One dominant continuous silhouette from **1–5 primitives** inside `#character`83(stickers may add 2 for a mouth, brows or a prop; the plate and the mask are not counted):84body (1, cloud body 3) + one species feature (0–2) + limbs (0–2). Thick rounded masses;85every tip visibly blunt; paired features in pairs. **Flat fill only** — no outlines,86gradients, highlights, shading, texture, nostrils or decorative marks. A darker lower mass87in particular is forbidden: dark reads as *feature* here, so a shade grows a phantom muzzle.88The plumpness comes from the silhouette and the saturation, never from a tone. Must read at8932 px.9091**Color.** Three semantic tokens on the root: `--c1` body, `--c2` sticker ink (mouth and92brows only), `--c3` the ground the character sits on. Bands: `--c1` L 0.55–0.68 with the93chroma left high — the body carries the identity; `--c3` L 0.94–0.97, chroma ≤ 0.02;94`--c2` L ≈ 0.22 tinted toward the body hue. **One ratio decides everything: `--c1` on95`--c3` ≥ 2.5:1** — the eyes are holes onto `--c3`, so that single number governs whether96the silhouette reads *and* whether the face reads. Sticker ink `--c2` on `--c1` ≥ 4.5:1.97Transparent stickers always carry the `--plate` die-cut backing (white by default).98`compose.py --from-brand "#hex"` derives a compliant palette and darkens the body until it99earns the ratio.100101**Face.** Two lenses, punched **through** the body with a `<mask>` so they are holes, not102shapes laid on top — that is what keeps them right on a transparent file and on the mark's103ground alike. Never draw an eye as a filled shape over the body. The anchor is derived from104the body's own bbox, never a fixed canvas coordinate: eye line at 0.40 of the body height,105spacing at ±0.205 of its width, sizes scaled by the body width. **The mark and the states106are mouthless** — the two lenses carry the whole expression, by re-posing one primitive107(shape, w, h, tilt, dy). Only the sticker pack may add a mouth, brows or cheeks.108109**Composition.** The **whole** silhouette, centred, with a margin, on a plain `--c3` ground.110Nothing is ever cropped and there is no rounded-rect container: a cropped or boxed111silhouette reads as a tile, and the silhouette *is* the identity. The transform is derived112from the rig, never guessed (`rig-spec.md`). States and stickers: the same composition,113transparent.114115**Motion.** Five tracks, each on its own element so their transforms compose instead of116overwriting each other: `#character` the state's personality (a root preset), `#tilt` the117head roll, `#squash` a counter-phase vertical squash, `#eye-l`/`#eye-r` the 3D orbit,118`.lens` the foreshortening with the blink folded in. Two animations on the *same* element119do not compose — the later one wins outright — so anything sharing an element shares one120keyframe track. The head turn is a real `rotateY` under `perspective`, so the browser121interpolates it continuously; **never sample a smooth curve into many keyframes with122per-segment `ease-in-out`**, which brakes to a stop at every one of them. Head roll ≤ 3°,123squash ≤ 1 %; the turn 9 s for idle, 2–5 s for active states; give the layers coprime124periods so the loop does not announce itself. Reduced-motion guard always. Presets live in125`references/motion-presets.md`.126127**Character.** Large head, compact proportions, soft cheeks, widely spaced simple eyes, calm128friendly expression by default. Simplicity and lovability beat anatomical correctness.129130## Building a file131132Prefer `scripts/compose.py` — the parts, presets, recipes and composition math are encoded133there, so the agent decides the recipe and the script guarantees the geometry134(`python3 scripts/compose.py --list` shows every body, feature, limb, lens, mouth, state,135sticker and palette). The face anchor, the yaw cylinder and the perspective compensation are136all derived from the body's bbox — never hand-place an eye. By hand: start from `assets/examples/seal/states/idle.svg`, keep the137slot structure from `references/rig-spec.md`, swap parts from `references/parts-library.md`,138paste presets from `references/motion-presets.md`. Static poses go on139`<g class="pose" transform="…">` wrappers; animated elements never carry a `transform`140attribute. Name the character if the user has not; it goes into `aria-label` and the141manifest.142143Two complete example sets to imitate: `assets/examples/seal/` (manifest, mark, six states,144sixteen stickers, `preview.html` — all generated from the manifest) and145`assets/examples/wall/` (six candidate marks from six bodies/features, with their wall).146147## Tooling (optional, never required)148149- `scripts/compose.py` — stdlib only; builds any mark/state/sticker from a recipe, a whole150 set from a manifest, a palette from a brand color; prints contrast notes.151- `scripts/validate.py <files|dirs> --kind mark|state|sticker [--json]` — stdlib only;152 FAILs on portability/accessibility breaks, WARNs on budget, structure and contrast drift.153- `scripts/export.py wall …` — stdlib only; builds `preview.html`.154- `scripts/export.py gif|webm|apng|mp4 <svg> --platform <name>` — needs `pip install155 playwright && python3 -m playwright install chromium` and ffmpeg; renders frames by156 stepping the Web Animations clock, encodes with platform presets, retries under the size157 budget. `scripts/export.py platforms` prints the presets.158159Runtimes that cannot run Python still get the full deliverable: the SVGs and a hand-filled160wall. Say which platforms accept SVG directly and which need a conversion.161162## Delivery163164Report, in this order: the pick (label, subject, species feature, rationale); tokens and165their contrast notes; the rig recipe; every file path grouped by pack with its motion166recipe; the preview page; validation summary (or "checked by eye: …"); export results with167sizes versus platform limits; what was not built and why. Keep it to one screen. Then offer168the next pack or a refinement round — not both at once.169170## Never171172- Call an image/video model, trace a raster, or describe the output as AI-generated art.173- Use `<text>`, fonts, scripts, gradients, filters, external refs, or a fourth semantic color.174- Add shading of any kind, or crop the silhouette, or put it in a rounded-rect container.175- Draw the eyes as filled shapes on top of the body instead of punching them through the mask.176- Give the mark or a state a mouth, or exceed the primitive budget without being asked.177- Ship a transparent sticker without its plate unless the user asked for that.178- Rank, filter, or silently regenerate candidates; deliver what you drew.179- Inline two rigs on one page without prefixing ids (use `<img>`).180- Ask a second round of discovery questions.