← back to the editor · about

OTTOMANCER — CHANGELOG
=============================
(for people who use it — what changed, in plain language)

v0.64.0 — the version you are running
--------------------------------------
  - **Mesh effects.** Select an image layer and the properties panel has a new
    "Mesh effect" section: Twist, Bloat, Warp, Suck In and Caustics. They bend
    the artwork itself rather than moving it — a vortex, a swell, a travelling
    wave, a collapse to the centre, light through moving water — with sliders
    for each and a readout of what the detail setting costs.

    They run over the length of the animation, so press play. Twist, Bloat and
    Suck In are at rest on the very first frame by design; the panel says so.

    **Where they appear:** the editor, and the PNG sequence, WebP and video
    exports. **Not yet in the Spine .json** — those layers export with their
    artwork undeformed, the Spine badge in the toolbar says so, and the export
    dialog lists it before you export rather than afterwards. The Spine half is
    built and tested and is the next thing being wired up.

    A layer inside a clipping folder keeps its artwork and does not take the
    effect; that is listed too.

v0.64.0
--------------------------------------
  - **New layers no longer land where you cannot see them.** Whatever you add —
    an emitter, a folder, a path, an image, a paste, a premade effect — the
    Scene list now scrolls to it and opens the folder it went into. The layer
    list is only a few rows tall on most screens, so a new layer could land well
    below the fold: it was there, it was selected, and nothing on screen changed
    except the panel on the right. It only scrolls when the new layer is out of
    view, so it will not jump around while you are looking at something else.

  - **Adding something now puts it next to what you had selected.** Pasting, the
    Premade Particles scenes and your saved effects used to drop the result at
    the bottom of the folder instead, which on a long list could be dozens of
    rows away from where you were working.

  - **Double-clicking an image no longer changes an emitter behind your back.**
    Double-clicking a sprite places it as its own layer — but it was also adding
    that sprite to whichever emitter you had touched last, which changes what
    that emitter draws. Single-clicking to give a sprite to the selected emitter
    works exactly as before.

  - **Ctrl+Z now really does undo one thing at a time.** Two quick clicks on the
    "+" buttons used to merge into a single undo step, so one Ctrl+Z took back
    both.

  - Pasting layers with Ctrl+V was broken for part of yesterday and is fixed.

v0.64.0
--------------------------------------
  - **Click a folder and you can now add things straight into it.** The
    properties panel on the right has a new "Add to <your folder>" section
    under the transform, with + Emitter, + Folder and + Path. They go inside
    that folder, the folder opens so you can see them arrive, and Ctrl+Z undoes
    each one.

    It stays on the folder after each add, so you can put several things in
    without clicking back and forth. The buttons in the left toolbar still work
    exactly as before.

  - **Adding a path to a closed folder no longer looks like nothing happened.**
    The path went in correctly but the folder stayed shut, so you saw no new
    layer anywhere while the panel jumped to it. The folder now opens, the same
    way it already did for emitters and folders.

  - **A path is called a path.** The properties panel used to label it
    "emitter", which was wrong the moment you made one.

v0.64.0
--------------------------------------
  - **Pressing Delete with keyframes selected no longer deletes the whole
    layer.** If you selected keys in the timeline and pressed Delete, the layer
    itself was removed. Backspace did the right thing, which made it doubly
    confusing. Ctrl+Z always brought the layer back, but it should never have
    happened. Delete now removes the selected keys, and still deletes the layer
    when nothing is selected.

  - **Keyframes on particle settings now show up on the layer's own row.** If
    you animated something like Rate over Time or Start Speed, the layer showed
    NO keyframes at all unless you expanded it — and the timeline header said
    the layer had none. They are drawn and counted now, and you can select,
    move and delete them from the layer row like any other key.

  - **The timeline header counts correctly.** With "All layers" on it counts
    layers that have keyframes; on a single layer it counts that layer's
    animated properties. It was over-counting.

  - **Clicking near the bottom edge of a button in a dialog now works.** A hint
    line at the bottom of some dialogs was floating over the row above it and
    swallowing clicks, so a button could look perfectly normal, be clicked, and
    do nothing.

  - **"Estimate" in the export window now scrolls its answer into view.** It was
    written below the visible area, so the button looked like it did nothing.

  - **The light theme is readable.** Several small labels — the status bar,
    panel hints and the names of switched-off particle features — were too faint
    against the background. The switched-off names were the worst, using a
    colour picked for the dark theme. Both themes now meet the standard
    contrast level everywhere.

v0.62.0
--------------------------------------
  - **Spine animations are now named "play_loop", "idle_loop", "in_once" and so
    on.** The ending tells you how the animation is meant to be played without
    opening the file. **If you have already put an Ottomancer skeleton into a
    game and your code asks for "play", it will need to ask for "play_loop"
    instead** — re-exporting an old project gives it the new names. Nothing else
    about the file changes, and the effect plays exactly as before.

  - **Every exported skeleton now hangs off a single bone** called MASTER, so you
    can move, rotate or scale the whole effect in Spine by grabbing one thing
    instead of selecting everything.

  - **The export instructions were naming an animation that was not in the file.**
    The little report in the zip said to play "play" while the skeleton
    contained "play_loop" — a Spine runtime asked for a name it does not have
    shows nothing at all, with no error, so this looked like a broken effect.
    Fixed, and the same mistake in the READ-ME files that ship beside the
    effects is fixed too.

  - **Choosing Spine 3.8 now tells you what 3.8 cannot carry.** 3.8 still works
    and the file still opens — but two things only exist in 4.0 and later: the
    editable colour (on 3.8 every colour is keyed on every frame, so you cannot
    just retint it in Spine) and curved keys (they flatten to straight lines).
    You are told before the export runs instead of finding out afterwards.

  - **The ready-made effects are now "Particles".** The ✨ button that drops in
    one of the 119 built-in effects said "Effects", and that group is labelled
    **Premades** so it is clear these are finished things to start from.

  - **The timeline header no longer says "no keys" on an animated project.** With
    "All layers" on it reported no keyframes at all, however many you had.

  - **Undo keeps your selection.** Pressing Ctrl+Z no longer clears which layers
    were selected, including a multi-selection.

  - **Editing a range across several layers no longer destroys the other end.**
    Typing a new minimum into two selected layers used to overwrite both the
    minimum and the maximum.

  - **The colour-tag dot in the layer list is easier to hit.** It is a 7-pixel
    dot with a much larger invisible target around it now.

  - The changelog page itself is rendered as plain text rather than as markup, so
    nothing in it can be interpreted as code.

v0.61.0
--------------------------------------
  - **Every particle feature is always in the list now.** Unticking one used to
    make it vanish from the panel, and the way back was a small "Add behaviour"
    row at the very bottom that was easy to miss entirely — on a new project the
    panel showed seven modules and hid thirteen. An unticked feature now stays
    exactly where it was, collapsed to a single line, and you can open it by
    **clicking its name** whether it is ticked or not. Ticking it still turns it
    on and opens it.

    Each one that is off also now says what it would do, in plain words —
    "make them wander instead of travelling straight", "bounce them off a
    floor" — so the panel tells you what is on offer instead of listing
    nineteen pieces of jargon.

  - **The colour and curve windows open small.** The gradient editor was opening
    at about 57% of the width and 70% of the height of the screen every time,
    which is most of a laptop display for one colour ramp. It now opens at
    roughly the size Spine's does — under half the height, about a third of the
    width. Both windows are still resizable, and the size you drag them to is
    still remembered.

  - **The supporters page is gone.** If you support the project on Ko-fi,
    Patreon or itch.io, you are already listed there; there is no reason for a
    second list here. Supporting the project is unchanged — the support page is
    where it always was.

  - **A description of the editor that a program can read.** New at
    /schema.json: every module and every property, with its type, its default,
    its unit and a one-line explanation — 19 modules and 112 properties, all of
    them described. It is generated from the editor itself, so it cannot fall
    out of step, and it is there so an AI assistant can find out what the tool
    can do without clicking through the interface to guess. Nothing in the app
    changes because of it.

  - **Typing a value into Position, Rotation, Scale or Opacity now keys it at
    the frame you are actually on.** This is the important one, and it was
    silent. The panel read the playhead when it was *drawn*, not when you
    pressed Enter — and nothing redrew it when you moved the playhead. So every
    transform you typed landed one move behind.

    What that looked like: put a key at frame 0, drag to frame 83, type a new
    number — and instead of a second key, the frame-0 key was **overwritten**
    and nothing was written at frame 83. The layer then did not animate at all,
    with no error and nothing on screen to say why.

    It only ever affected those transform boxes. The emitter settings and
    dragging the handles in the canvas always read the playhead correctly, which
    is exactly what made it so confusing: the same idea worked or did not
    depending on which control you reached for.

  - **The keyframe diamond now records the value the property actually has at
    the playhead.** It was planting the value the panel had been showing —
    measured, a key written as 111 where the real value at that frame was 122.5,
    which visibly changed the motion you had just made.

  - **The properties panel follows the playhead.** Move the playhead and the
    numbers update to that frame. It deliberately does *not* refresh while you
    are typing in one of those boxes, so a half-typed number can never be wiped
    out from under you.

  - **Copying layers into another project now brings their artwork.** Copy an
    emitter, open a different project, paste — previously you got the layer,
    the particles and the settings, and no art. Nothing failed and nothing was
    said; the layer simply drew nothing. Folders, texture sheets, layers using
    several sprites and multi-selections all carry their images now, and only
    the images actually in use travel.

  - **Cleaner Spine exports.** Three faults in the exported curves, none of
    which showed up in a preview because they all happened *between* frames, so
    only a game engine playing the file at its own frame rate would ever draw
    them:

      - a spinning particle could sweep through a pose it never held, by up to
        90 degrees;
      - a bar or panel that grows in steps could be drawn briefly **mirrored**;
      - some curves were written in a form a game runtime cannot read back.

    Exported animations are the same size as before — the whole change is one
    extra keyframe across the entire library.

  - **An export warning that cried wolf.** Ottomancer warns when two layers
    share a name, because Spine can then mix them up. It was counting a folder
    and a layer inside it — which can never be confused — so it fired on half
    of every project. It now fires on the five cases that are genuinely
    ambiguous.

  - **Seven new effects**, all in the dark and gothic set: shadow bloom, blood
    mist, rot spread, candle guttering, raven scatter, iron sparks and steam
    vent burst. **Ink splat and speed lines were rebuilt** — the ink now throws
    proper droplets and ligaments instead of round blobs, and the speed lines
    are hard-edged strokes that taper at one end the way a drawn one does.
    **Fog roll** is twice as long, because at its old length the whole bank of
    fog visibly swelled and shrank once a loop, like a metronome.

v0.60.0
-------
  - **A "Settled" button, so the preview shows what you actually get.** A
    looping effect is delivered already running — the gif, the video and the
    Spine export all start with the effect in full flow. The editor did the
    opposite: it started from an empty screen and filled up, and every change
    you made reset it back to empty.

    That mattered more than it sounds. Across the built-in looping effects,
    most showed *nothing at all* on the first frame while the delivered version
    of that same frame was full. So the thing you were adjusting was not the
    thing you were shipping.

    The "Settled" button in the timeline bar switches the preview to the
    delivered behaviour: the effect is already running when you look at it. It
    is off by default because it costs a moment of extra work on every change —
    on the very heaviest effects about a second — so it is there for when you
    are judging the final look rather than something you pay for constantly.

    Your project file is not touched either way. This only changes what the
    preview shows you.

  - **The colour and gradient window no longer grows until it is unusable.**
    Opening a colour or gradient editor and clicking in it made the window a
    little bigger every single time — a few clicks and it had swallowed the
    screen. Shaping a gradient is dozens of clicks, so in practice the feature
    could not be used. It was one word in one line: the editor measured itself
    including its own border and then grew by that border, over and over.

  - **Clicking a point in the Curves window selects it again, instead of adding
    another one.** This only ever happened if your Windows display scaling is
    set above 100% — 125%, 150% and 200% are all common, and at 100% it worked
    perfectly, which is why it survived so long. The window drew in one set of
    units and listened for the mouse in another, so every click landed slightly
    off and fell through to "add a point".

  - **The hex box in the colour picker showed the colour you picked.** It read
    #ffffff for every colour, always — the picker itself was right, the little
    white swatch beside it was right, and only the number was wrong.

  - **Saving and renaming can no longer be blocked by the browser.** Save As,
    renaming a layer, naming a curve or a gradient and eight other places asked
    for a name through a browser pop-up. Browsers are allowed to refuse those:
    Chrome offers a "stop this page creating more dialogs" tick-box, and after
    that every one of them fails. Save As is not something that should be able
    to die because of a tick-box. They are all ordinary windows in the app now,
    with Enter to accept and Escape to cancel.

  - **Keyboard shortcuts no longer reach through an open window.** With a dialog
    open, Ctrl+Z and Ctrl+A were still reaching the project behind it — in one
    case deleting a five-layer folder while the window in front carried on
    showing its old contents. Escape sometimes needed two presses for the same
    reason.

  - **Undo no longer leaves the panel saying the scene is empty.** After a
    single Ctrl+Z the panel under the layer list could read "nothing in the
    scene yet" while the tree plainly showed your layers, with Delete still
    live underneath it.

  - **Curve handles on straight segments.** A segment stayed straight until you
    bent it, and a straight segment had no handles — so there was nothing to
    take hold of to start an ease. Every segment now has them, and each end key
    shows a dashed marker for the other side of the loop, with a "Match for
    loop" button that lines the two up in one click.

  - **The timeline zooms out further.** It used to stop at exactly the length of
    your animation; it now goes to four times that, so you can see the whole
    thing with room around it.

  - **Layout fixes you would have hit on a laptop.** The toolbar no longer
    shifts sideways as the CHECK badge changes its wording, so Export stays
    where you left it. The layer tree is no longer squeezed to a sliver on a
    short window. Dragging the timeline tall and then making the window smaller
    no longer leaves the stage 46 pixels high with the overlays on top of each
    other. The readout under the stage no longer runs off the edge.

  - **Things you can now read.** Active buttons in the toolbar were a mix of two
    text colours, one of which failed every contrast guideline; they match now.
    In the light theme the three panels over the stage were dark-on-dark —
    including the button you press to get back out of the light theme. Status
    messages are readable while a window is open, which is where the important
    ones appear. Switched-off buttons now look switched off.

  - **Smaller things.** The colour picker opens fully on screen instead of
    hanging off the bottom, and its hue and transparency strips are no longer
    thinner than a scrollbar. Two rows in the timeline that used to draw
    identically now show which is which. The tabs in the Export window stop
    jumping under the cursor. The Export window explains the tab you are on
    rather than always leading with Spine.

v0.59.0
--------------------------------------
  - **Each effect now shows a bar in the timeline saying when it plays, and you
    can drag it.** Turn on "All layers" under the timeline and every emitter
    gets its own bar: a solid block for as long as it is throwing particles, and
    a fainter tail for as long as those particles are still on screen after it
    stops.

    That second part is the useful one. An emitter stops emitting long before
    the picture goes away, so the tail is what tells you when a layer has
    actually finished fading — which is the moment you usually want the next
    thing to start on.

    Drag a bar left or right to move that effect earlier or later. Say you have
    a firework: a launch trail, then the burst. Drag the burst so it goes off
    exactly as the trail fades, or leave a gap to build anticipation. You are
    not editing the particle system to do it — nothing about the effect changes
    except when it starts. It snaps to whole frames, and Ctrl+Z takes it back.

    Clicking the empty part of a row still drags a selection box over keys, the
    way it always did.

v0.58.0
--------------------------------------
  - **A layer following a path now moves in an exported web page.** It didn't.
    If you attached a layer to a path and exported the web bundle, the effect
    played and that one layer sat perfectly still — no error, no warning,
    nothing to notice unless you knew where it should have gone.

    The small player that runs a web bundle has no idea what a path is, and it
    can't be taught one. It doesn't need to be: where a layer sits on a path is
    just a position over time, and position is something the player has always
    animated. So the export now works out the movement itself and writes it as
    ordinary keyframes, exactly as if you had animated the layer by hand.

    Your saved project is untouched — the path is still a path, still editable.
    Only the exported copy is flattened, in the same way images with a tint are
    baked into the bundle's artwork.

v0.57.0
--------------------------------------
  - **Spine exports carry about a third fewer keyframes, for the same motion.**
    A particle that is simply falling traces a curve, and until now the exporter
    could only describe a curve as a chain of straight lines — so it wrote a key
    every few frames to keep up. Across the whole effect library that came to
    two million keys, and not one of them was curved.

    A Spine 4.x export now fits a real curve to each stretch of movement. Over
    40 effects that took 191,849 keys down to 123,927. A falling arc that needed
    61 keys now needs 2, the animation looks the same, and the export is also
    faster to produce than it was before.

    Checked frame by frame against the old export — 6.4 million samples, every
    one inside the tolerance each effect sets — and then imported into Spine
    4.0.64, edited there, and exported again with the curves intact.

    **This applies to Spine 4.0, 4.1 and 4.2 only.** Spine 3.8's format shares
    one curve between every property of a key and stores it as a proportion of
    the value change, so it cannot describe this. 3.8 exports are unchanged. The
    export window now says which versions give you the smaller file.

  - **The settings panel on the right had controls nobody could read.** The
    dropdown that picks how a value works — one number, a random range, or a
    curve — was 26 pixels wide, while its longest option reads "Random between
    two constants". About ten pixels of text were visible.

    It is now a labelled button that says which mode it is in and opens a proper
    menu explaining each one. Alongside that: 110 controls were under 20 pixels
    tall, the keyframe diamonds on the transform rows were too faint to see
    against the panel in either light or dark, and the small × that removes a
    sprite was the tiniest target on the whole panel despite deleting something.

  - **Six effects showed a colour they never declared.** Anything that stays put
    for the whole animation — a ring, a pool of liquid, a corner bracket — was
    written as though it slowly changed colour over its life. Because those
    elements are built to last an hour, that change never got started: they held
    their opening colour for ever, which was always the palest end. The files
    now say what they actually draw, so the next person to edit one is not
    misled. Nothing on screen changed.

v0.56.0
--------------------------------------
  - **The effects page now shows the effects.** All 119 of them, playing, as
    small looping animations. Until now that page described 119 visual effects
    entirely in words — the only picture on it was the site icon.

    Each one is rendered by the editor itself, using the same code that draws
    the thumbnails in the Effects picker, so what you see on the page is the
    effect as the editor actually draws it rather than a screenshot taken once
    and left to go stale.

    The whole set is 1.6 MB and loads only as you scroll, so the page still
    arrives as fast as it did.

  - **The gif colour fix from v0.55.0 did not cover gifs with transparency.**
    Same symptom, reached by a second route: when an effect had transparent
    areas, the exporter counted only the pixels it could see, and the sampling
    step could line up with the picture again — a 251-colour test came out with
    ONE colour in its palette. Exporting a gif with a transparent background now
    picks its colours from the whole picture, the way an opaque one already did.

v0.55.0
--------------------------------------
  - **GIF export could produce a blank file, and every gif was picking its
    colours from a few narrow stripes.** A gif can only hold 256 colours, so the
    exporter samples your frames to choose them. The sampling step could line up
    with the image width — and then it read the same few columns of every row of
    every frame, and judged the whole effect from those.

    At worst it read **column zero alone**. For one effect that column is empty,
    so a 9,395-colour animation came out as a valid 44 KB GIF of flat
    background — a blank file that looks like a broken effect rather than a
    broken exporter.

    The blank case was the extreme, not the whole problem. **At the default
    export size it was choosing from five columns out of 1080** — half a percent
    of the picture. That has been true of every gif this tool has ever written.

    Now it reads the whole frame. Measured on the effect that came out blank:
    the same frames went from a 2-colour palette to 255.

  - One delivered gif was affected and has been rebuilt. Every gif is now
    checked against the colour its own frames actually carry.

v0.54.0
--------------------------------------
  - **A project file could load perfectly and then never be saved again.** Two
    shapes of file did it: an animation event carrying a zero or an empty text
    value, and a layer glint saved with only some of its settings. Both loaded
    fine. Both then failed every save, with the tool telling you it was a fault
    in the tool — which it was.

    The cause was the file being written one way and read back another, so the
    save's own safety check saw them disagree and refused. Both directions now
    match. Nothing you have made can be in that state — the editor cannot
    produce either shape — but a file that opens and will never save is exactly
    the kind of trouble that is impossible to work out from the outside.

  - **Asset tints now travel in web bundle exports.** If you tinted an image and
    exported a web bundle, the bundle shipped the ORIGINAL untinted picture and
    said nothing — the effect played in the wrong colours. The bundle now
    carries the artwork you were looking at.

    This works the opposite way round from the Spine export on purpose: Spine
    gets white art plus an editable colour, because you can recolour it there. A
    web bundle is finished when it leaves, so it gets the picture as you saw it.
    If you turn "Embed images" off, the tint cannot travel and the export now
    tells you so rather than quietly dropping it.

v0.53.0
--------------------------------------
  - **Spine export was refusing 57 of the 184 effects, and now works.** Every
    effect built as a set of animations — an "in", an "idle" and an "out" over
    the same layers — was blocked at the export dialog with:

        EXPORT BLOCKED — the file does not match what was asked for:
        animation(s) missing from the file: play

    That covered every frame effect: chain, electric, fire and frost, and all
    their tall and square variants.

    The export itself was correct the whole time. The safety check standing in
    front of it was asking the wrong question — it looked for an animation named
    "play", the default, even when your project declares its own names. So it
    refused a perfectly good file and told you it was a fault in the tool, which
    it was.

    All 184 now export. Checked one at a time, through the dialog's own
    refusals, not around them.

  - **This is the third time in two days that something you would hit was
    invisible to us**, and all three had the same shape: the automatic checks
    exercised the code the way a BUILD does, and nobody had ever driven the
    thing the way a person does. The export dialog, the Spine file validator and
    the web-bundle player were each checked for existing and starting up, never
    for working. All three now have a check that goes through the front door.

v0.52.0
--------------------------------------
  - **Web bundle exports were broken, and are now fixed.** If you exported an
    effect as a web bundle — the self-playing HTML page — it showed a BLANK
    canvas for any effect where a layer uses more than one image. No error
    message, no warning: just black.

    That is most of the library. 174 layers across the shipped effects use more
    than one image, and any effect containing one of them played as nothing.

    The cause was a single missing line in the player. The editor's own drawing
    code checks "is this image part of a sprite sheet?" before cutting it up;
    the player's copy did not, and fell over the first time it met an image that
    was not. Both are now the same.

    Verified by building a real bundle and opening it: before, zero pixels drawn
    and the animation stopped on frame one; after, twenty frames clean and the
    effect plays.

  - **Why this was never caught:** everything that watched the player only asked
    whether it LOADED — that it was present, that it started up, that it matched
    the editor. Nothing ever asked it to play something. A player that started
    perfectly and drew nothing passed every check. There is now one that opens a
    real effect and counts what reaches the screen.

v0.51.0
--------------------------------------
  - **Asset tint now reaches Spine — recolour a whole effect from one value.**
    The editor half shipped last version; this is the half that matters. When
    you tint an image, the export now sends the artwork as plain WHITE and puts
    your colour on the slot itself, in Spine's setup pose, where it is a single
    editable value and not a keyframe.

    So in Spine you select the slot, change one colour, and the whole effect
    recolours. No keys to hunt, nothing to re-export. **60,308 of 83,407 slots
    across the delivered library — 72% — now carry an editable colour where
    before every one of them was locked into keyframes.**

    Proved by round-tripping through Spine itself: all 429 setup colours came
    back identical, 429 alpha tracks, no colour keys left, and the exported
    artwork measured pure white.

    **Two limits, said plainly rather than left for you to find.** If you export
    for Spine 3.x the colour is folded into keys as before and is NOT editable —
    3.x has no separate alpha track, so this cannot be fixed. And in effects
    with several animations, some slots still settle on different colours in
    different animations and stay keyed; those are correct on screen but not yet
    recolourable.

  - **Files got slightly SMALLER**, which was not the point but is worth saying:
    155.6 MB to 153.5 MB across the library. Much less than we first estimated —
    the colour keys mostly still exist because your fades still need them. This
    is a workflow feature, not a size one.

  - **The changelog has a jump list.** This page is 106 releases long; there is
    now an index of the recent ones at the top instead of scrolling for them.

v0.50.0
--------------------------------------
  - **Colour an image itself, with no keyframes.** Right-click any image in the
    Images list and choose **Asset tint**. The picture takes that colour
    everywhere it is used, and nothing is keyed — the effect's own tint and
    alpha still work on top of it exactly as before.

    This is the editor half. The point of it is Spine: because the colour sits
    on the artwork rather than in the animation, the export can send plain white
    art plus a single slot colour, and a whole effect can then be recoloured in
    Spine by changing that one value instead of editing keyed colours. The
    export half is being built now; the tint is stored in your project and will
    be picked up when it lands.

    Your saved artwork is never altered — the tint is stored as a value beside
    it, so it can be changed or cleared at any time and the original is exactly
    what it was.

v0.49.0
--------------------------------------
  - **You can see where you are in the timeline.** There is now a strip above
    the sheet showing the WHOLE animation, with a pale block marking the part
    you are looking at. Drag the block to move along, or click anywhere on the
    strip to jump there — it is the scrollbar the timeline never had.

    Beside it: zoom in, zoom out and Fit buttons, and a readout of how far in
    you are. Zooming was previously the mouse wheel or the H key, neither of
    which is visible unless somebody tells you.

    Worth saying plainly, because it explains why this took so little: the
    timeline always KNEW which part of the animation was on screen. It simply
    never drew it. Nothing about how it navigates has changed.

  - **The animation's length handle is now visible.** The bright band on the
    ruler has always shown where the animation ends; the handle for dragging
    that edge was five invisible pixels you found by sweeping the cursor until
    it changed shape. It now has a grip you can see, and a wider catch.

v0.48.0
--------------------------------------
  - **Spine loops now actually loop, and particles stop flying backwards.**
    This was reported as particles "flying back to their original position and
    glitching or spasming out", fixed by hand one particle at a time.

    It was not a loop problem. In Spine a slot is a REUSED SEAT: when one
    particle dies, that seat is handed to a different particle somewhere else on
    screen — and the bone travelled in a straight line from where the first one
    died to where the second one begins. Measured across 41 exported skeletons:
    20,330 handovers, 3,226 of them smearing more than 4 pixels, the worst
    throwing a leaf 265 pixels back up the screen. It happened on one-shots too,
    not only on loops.

    Every animation now also carries a first and last key on everything, with
    the pair matching on a loop. Spine's own verdict: an effect declaring an 8
    second loop now imports and re-exports at 8.00s, where a 3.0s effect
    previously came back as 2.80s — six frames short, because a Spine animation
    ends at its last key and nothing was keyed on the final frames.

    **The honest cost: exported Spine files are 18.5% larger** (131.0 MB to
    155.2 MB across the whole set, 657,347 extra keys). That is what full
    first-and-last keying costs. If it matters more than the fix, say so — a
    smaller version that only fixes the short animations is measured and ready.

  - **A proper colour picker.** The old one was not ours: the Tint control was a
    plain browser colour box, which hands the whole job to the operating system,
    so on Windows you got its colour dialog — the grid of basic colours and the
    numeric code fields. Nothing here could improve it, because none of it was
    ours to change.

    Now it is: a saturation and brightness square, a hue strip, an alpha strip,
    a hex box and your recently used colours. It opens beside the swatch instead
    of in a dialog, and nothing scrolls. Gradient stops use the same one.

  - **Images can be removed from a project.** They never could — nothing in
    Ottomancer had ever been able to delete one, so a mistaken import stayed for
    good and travelled inside every saved copy. Right-click an image in the
    Images list: it tells you which layers use it, removes it from those layers
    too, and Ctrl+Z puts it all back.

  - **Importing an image no longer overwrites one.** If a file you added
    happened to share a name with an image already in the project, it silently
    replaced that image — under every layer using it. Imports are now purely
    additive; a clash arrives as "coin 2" and says so. To swap a picture on
    purpose, right-click it and choose Replace image.

v0.47.0
--------------------------------------
  - **Curve handles are visible again on straight segments.** A straight
    segment's two handles sit exactly ON the curve line, in the same colour as
    it, and were faded until you selected the key — so on the segments you most
    want to bend, there was nothing to see. They now get a dark surround
    whether or not the key is selected, and sit at half strength rather than a
    quarter. Measured: the knob now stands 87 to 123 levels clear of what is
    behind it, where before it was the same colour as the line it sat on.

  - **Emitter properties no longer show handles that do nothing.** Keyed
    particle settings — Start Size, Gravity, Tint and the rest — were drawing
    grabbable-looking knobs on the graph. The cursor changed over them and
    dragging one did nothing, because the simulation reads those values in a
    straight line between keys and there is nowhere to store an ease. The fake
    knobs are gone. Layer Position, Rotation, Scale and Opacity have real curves
    and keep them.

    Giving particle settings real easing needs a change inside the playback
    engine, not the editor, and is not done.

  - **Spine export, three fixes** (from the session working the exporter):
    a state set's animations are no longer baked from two different
    simulations; an animation that is a view of persistent content no longer
    opens on a one-frame blank; and a slot filled by one animation and never
    keyed by another is no longer left drawn at full opacity through it.
    `chain-frame` was shipping four glints doing exactly that.

v0.46.0
--------------------------------------
  - **Alt+C and Alt+V copy one property.** Point at any property — or click into
    its box — and Alt+C takes just that value. Alt+V drops it on the same
    property of another layer.

    Copying a single property has been possible since v0.37.0 by right-clicking
    it, which was the "easy" half of what was asked for. This is the fast half:
    moving one number was four gestures and is now two keys.

    It lands only on the property it came from — paste Start Lifetime onto Start
    Speed and it refuses and says why, rather than quietly putting a number
    somewhere it does not belong. With several layers selected, one Alt+V sets
    them all: verified on three layers at once. Ctrl+Z takes it back.

    Ctrl+C and Ctrl+V are unchanged — they still copy whole layers — and Alt was
    chosen so that copying the TEXT in a box still works normally while you are
    typing in it.

    The right-click menu now shows the shortcut beside each item, which is where
    anyone will find out it exists.

v0.45.0
--------------------------------------
  - **On a phone, the editor told you to widen your window.** Ottomancer needs a
    desktop — it is three columns of panels and a mouse — and on a narrow screen
    it already said something. But that message was written for a desktop window
    dragged too small: "widen it, or zoom out with Ctrl -". On a phone you can do
    neither. There is no window edge to drag and no Ctrl key.

    Measured on a 375-pixel phone: that message filled a fifth of the screen with
    two instructions nobody there could follow, the layer tree took 56% of the
    width, and the effect you came to look at got 14.7% of it.

    A phone now gets the truth — that this is a desktop tool — and a link to the
    effects gallery, which reads properly at that size. Both side panels fold
    away, so the effect gets 54% of the screen instead of 14.7%.

    This matters more than it sounds: every link to Ottomancer gets tapped on
    phones, so for a lot of people that screen was the whole first impression.

  - **Nothing changes on a desktop.** Verified at full width (three columns, no
    message) and at a narrow window (properties panel folds, same wording as
    before). The change applies below 700 pixels only.

v0.44.0
--------------------------------------
  - **The changelog and licence pages were unreadable on a phone.** Both were
    missing the one line that tells a phone to use the real screen width, so
    they were laid out as if the screen were 980 pixels wide and then shrunk to
    fit — the text arrived at about a third of its size.

    Measured on a 375-pixel phone: the changelog reported a 981-pixel window
    against the About page's 375. Fixed on both, and the publish checker now
    refuses to ship any page missing it.

  - These are the two pages a careful person reads BEFORE deciding to try
    something — what changed lately, and what the licence lets them do.

v0.43.0
--------------------------------------
  - **A line about import settings on the image tab.** If exported frames look
    soft once they are in a game engine, that is almost always the engine's
    import settings rather than the export — the frames themselves are sharp.
    The panel now says so, and says the two settings that fix it: texture filter
    set to Point (or Nearest), and compression off.

    It is the single most common thing that goes wrong AFTER a correct export,
    and a tool that writes frames and then says nothing about them is leaving
    you to find it out from a forum.

v0.42.0
--------------------------------------
  - **Estimate now tells you how big the export will actually be**, and what the
    same effect costs by the other routes. Before, it told you the frame count
    and stopped — so the format choice, which can cost a hundred times the file
    size, was made blind.

    It measures rather than guesses: it renders two real frames from partway
    through your effect and averages them. Checked against a real export of the
    same project — estimate 6.3 MB, actual 6.22 MB.

  - It also shows the Spine bundle and web bundle sizes beside it, because those
    play the effect live instead of storing every frame and are usually far
    smaller. It says why, and says when frames are still the right answer — a
    video edit, a store page, anyone who cannot run a runtime.

v0.41.0
--------------------------------------
  - **A heavy GIF or WebP now warns you before it starts.** Those two formats
    cannot write anything until every frame exists — the GIF palette is chosen by
    looking at all of them — so the whole sequence sits in memory uncompressed.
    A 90-frame export at the phone size (1080×1920) works out at about **712 MB**.

    That is not a number anyone would guess from "export a GIF", and on a machine
    without room for it the tab slows badly or stops responding. Now the export
    panel says the figure before you press the button, and tells you that halving
    the size quarters the memory.

  - The warning stays quiet where it does not apply. PNG sequences compress each
    frame as they go and WebM records as it plays, so neither holds frames this
    way and neither is warned about.

v0.40.0
--------------------------------------
  - **You can stop an export now.** A Cancel button appears while an export is
    running, and disappears when it is not. Nothing is written, and the project
    you were working on is untouched.

  - **There is a clock beside the progress bar.** A bar on its own cannot tell
    you whether something is slow or stuck — which is exactly the confusion the
    WebP problem caused last week. Now it says how long it has been going.

  - One honest note, which the button says too: the frame-by-frame exports stop
    within a fraction of a second. The GIF and animated WebP encoders do their
    work in one long uninterruptible push, so there Cancel takes effect at the
    end of that step, which can be tens of seconds. The button says "Stopping…"
    rather than pretending it already has.

  - Cancelling is reported as cancelling, not as a failure. It is not an error
    and it does not read like one.

v0.39.0
--------------------------------------
  - **Drag a saved project onto the page and it asks what you meant.** Drop a
    .ottomancer file anywhere on the editor and you get three choices:

      Add to this project — keeps what you have and brings the dropped effect in
      alongside it. This is how you build a big effect out of small ones: drop a
      fire, drop a smoke, drop some embers, and tidy up the result.

      Open it instead — replaces what is open. A snapshot of your current work
      goes into Recovery first, so choosing wrong is not the end of anything.

      Open in a new tab — leaves this one exactly as it is.

  - Adding is undoable. One Ctrl+Z takes the whole merge back out.

  - **Merging never breaks what it merges.** When two projects use the same
    layer name the incoming one is renamed — and everything pointing at that
    name is repointed with it. That matters most for sub-emitters, which find
    their target by name: without this, merging two copies of an effect would
    leave both of them driving the same sparks, and nothing would have looked
    wrong in the layer list. Images are matched by content, so merging effects
    built from the same library reuses the art instead of piling up copies.

  - If the dropped effect is longer than your timeline, the timeline grows so
    the whole thing can play. It never shrinks.

  - Dropping something that is not a project now says what you *can* drop,
    instead of "Those files were not images".

v0.38.0
--------------------------------------
  - **The Animated WebP export could hang for ever, and now it cannot.** Choosing
    Animated WebP on a large canvas — 1080x1920, the phone-shaped preset — made
    the progress bar stop at 2% and stay there. No error, no file, no end. The
    cause is in the browser rather than in Ottomancer: Chrome's WebP encoder
    simply never answers above a certain image size, and it does not fail, it
    goes quiet. Measured here: the same picture saves as a PNG in about a second
    and as a WebP at 360x640 in a few milliseconds.

    Ottomancer now stops waiting after a minute and tells you what happened, what
    the browser was asked to do, and what to use instead — a smaller size, or the
    PNG sequence or WebM. A failed export also empties its progress bar, so the
    bar and the message no longer say different things.

  - Every other export was checked the same way, by exporting a real project and
    opening what came out: Spine bundle, PNG sequence, GIF, WebM, MP4, SVG and
    the web bundle all write what they promise. The SVG export of an all-particle
    project correctly says so in capitals rather than handing you an empty file.

v0.37.0
--------------------------------------
  - **Copy one property from one layer to another.** Right-click any property in
    the panel — Start Lifetime, a colour, a speed — and choose Copy value, then
    right-click the same property on another layer and choose Paste value. It
    carries the whole setting, so a range copied onto a layer holding a single
    number becomes a range there too, and a gradient arrives with every stop.

  - Paste only ever lands on the property it was copied from. If the clipboard
    is holding something else the menu says so by name instead of offering a
    paste that would put a lifetime into a speed.

  - With several layers selected, the menu says how many the paste will reach —
    and it reaches the ones where that module is switched on, the same rule
    typing a value already follows.

  - **Reset to default** is in the same menu, for putting one property back
    without touching the rest of the layer.

  - The menu is on **every** property, including Position, Rotation, Scale and
    Opacity at the top of the panel. Copying a position onto another layer works
    the same way copying a lifetime does.

  - **A property your selected layers disagree about now shows EMPTY**, instead
    of showing one layer's number with a dot beside it. An empty box cannot be
    misread; a number can. Type into it and every selected layer takes the value,
    exactly as before. Checkboxes show the half-ticked state and dropdowns show
    nothing selected. A colour, a gradient, a burst list and a sprite list have
    no empty state, so those still use the dot.

  - **Ctrl+click in the layer list could add a layer to the selection but never
    remove one.** Clicking a selected layer again left it selected, which looks
    like the click was missed. Fixed. Shift+click to select a range was already
    working and now has tests so it stays that way.

v0.36.0
-------
  - **The gradient editor is no longer blurry.** It was being drawn at a fixed
    460 by 110 and then stretched to fill the dialog — nearly three times its
    real size — which is why every handle and the chequerboard behind the colours
    looked soft and blocky. It now draws at your screen's actual resolution and
    redraws when the window changes.

  - **New handles.** Round, larger, on a stem that points at the exact position
    they own, and they light up as you move over them so you can see what you
    are about to grab. The selected one gets a ring, which reads on any colour —
    the old outline vanished on an orange stop.

  - The colour bar has rounded corners and twice the colour resolution, so a
    smooth ramp no longer shows banding.

v0.35.0
--------
  - **Adding an emitter no longer makes the Check badge complain.** Every new
    layer arrived with loop-safe randomness switched off, and a looping layer
    without it does not close its loop — which the badge correctly reported. So
    the count went up by one every time you pressed + Emitter, about something
    you had not done and could not have avoided. A new emitter now gets the same
    setting the starter project has always had.

  - **Colour can now be keyed over the timeline.** Tint has a key button, so an
    effect can start warm and end cold, or flash a colour at a moment. It
    multiplies whatever your gradient does rather than replacing it, so the
    per-particle colour ramp is untouched and the whole system shifts together.

  - **Positions and directions can be keyed too.** Every X/Y setting — shape
    Position, Gravity Direction, Box Size, the speed ranges — now has a key
    button. Both channels key with one click, and right-clicking that button
    clears them again.

  - **Auto Key now covers emitter settings, not just layer movement.** With it
    on, changing Start Speed, Lifetime, Size, Tint or any other keyable setting
    lands a key at the playhead. It used to apply only to moving, rotating and
    scaling a layer, which its own message admitted but nothing else did.

  - Ctrl+Z takes back every one of these.

  **One thing that is still not possible:** keying a whole gradient. A gradient
  is a list of colour stops rather than a single value, and the player that runs
  your exported effects cannot blend one into another. Keying Tint is the way to
  move colour through time, and it works alongside the gradient.

v0.34.0
--------
  - **The properties panel marks settings that differ across your selection**,
    and says how many layers an edit will reach. Select several layers and any
    value they do not share carries a dot; hovering it says whose number is the
    one on screen, and the header reads "editing 3 layers" so the panel never
    quietly changes more than it names.

  - **Right-clicking a keyframe no longer deletes it.** It opens a menu — Delete,
    Cut, Copy, Reverse when several are selected, and six easings. The old
    behaviour removed the key on the spot, with nothing anywhere telling you
    that is what right-click did, and on a group it took the whole selection.

  - **Easing is now two clicks from the keyframe itself.** Linear, Stepped,
    Ease, Ease In, Ease Out and Ease In Out are in that menu. They used to live
    only inside the curve editor, which is a different window and a longer trip.
    The full set of twelve, with their drawn previews, is still there.

v0.33.0
--------
  - **Deleting a keyframe could delete another layer's keyframe.** If two layers
    had the same name — which Ottomancer allows — the timeline could not tell
    their keyframes apart. Selecting one selected both, and deleting one deleted
    both, silently. Keyframes are now identified by the layer itself rather than
    by its name, so two layers can share a name safely.

  - **Reverse (Shift+R).** Select two or more keyframes and mirror them in time,
    about their own span — a rise becomes a fall, a burst played backwards is a
    suck-in. The keys stay where they were as a group, so reversing a run in the
    middle of an animation does not fling it to one end. Each key keeps its own
    easing.

  - Behind the scenes: a setting that every project has been saving since the
    beginning, and that nothing ever read, is gone — the file format's published
    description never mentioned it either.

v0.32.0
--------
  - **Onion skin now lets you set how many ghosts and how strong.** Turning
    Onion on reveals four boxes: how many frames apart the ghosts are, how many
    to show before the playhead, how many after, and how solid they are. Before
    the playhead is drawn cool, after is warm, and nearer frames are always
    stronger. Only the spacing used to be adjustable.

  - **Cut (Ctrl+X) and Select All (Ctrl+A) now work.** Copy and paste already
    did; the other two thirds of the clipboard were missing. Both follow the
    same rule Copy does: if you have keyframes selected they act on the
    keyframes, otherwise on the layers.

    Ctrl+A in the sheet means "all the keys on the rows I am already working
    in", not every key in the whole project — so it cannot sweep in layers you
    had forgotten were animated. Cut always copies before it deletes, and one
    Ctrl+Z brings it all back.

v0.31.0
--------
  - **Changing a setting now changes every layer you have selected.** Select
    eight layers, set the opacity once, and all eight take it — the same for
    start size, speed, lifetime, colours and every module setting. It used to
    change only the one whose values were on screen, so eight layers meant
    eight visits. This is how Spine, After Effects and Animate all behave.

    Two things it deliberately will not do: it never writes into a module that
    is switched OFF on a layer (so changing Noise across a mixed selection
    leaves the layers without Noise alone), and one Ctrl+Z takes back the whole
    change rather than one layer of it.

v0.30.0
--------
  - **Saved curves were being stored under a broken name.** They worked, but by
    accident — the setting had no name of its own, so it went into a slot called
    "undefined". Anything you saved is moved to its proper place automatically
    when you open this version; nothing is lost.

  - **You can now save gradients, like you can save curves.** A colour ramp you
    spent ten minutes shaping is one pick next time, from the same Presets list
    as Fire and Smoke. It was the only one of the five libraries that could not
    grow.

  - **Moving something in Animate mode without Auto-key now says so.** It
    changed the base pose instead of making a keyframe — the layer moved, so it
    looked like it had worked, and nothing said otherwise until you played it
    back. It now tells you, and tells you to press K.

v0.29.0
--------
  - **"Preview export" said your art was missing when it wasn't.** Any effect
    built on an animated sprite sheet — the campfire, the torches, most of the
    fire and smoke — showed a wall of red "NOT FOUND, it will draw nothing"
    warnings, one per frame of the sheet, and the preview drew the effect
    without its flames. The export itself was always correct and complete; only
    the preview was looking for the art under the wrong name. It now previews
    what you will actually get.

  - **The export settings now match the format you picked.** Choosing WebM no
    longer offers you GIF colours; a PNG sequence no longer offers a video
    bitrate. And MP4 no longer offers a Transparent tick it cannot honour — it
    now says so, and points you at WebM or a PNG sequence if you need
    transparency.

  - **Picking a move, rotate or scale tool while the effect is playing now
    tells you to pause.** The handles are hidden during playback on purpose, but
    the status bar used to just say "Move tool" while nothing appeared and
    dragging did nothing.

v0.28.0
--------
  - **The gradient editor was unusable, and now works.** Clicking anywhere on a
    gradient added a new colour stop instead of selecting the one you aimed at —
    so every attempt to correct it added another, and another. You can now click
    a stop to select it and drag it to move it. Adding is a double-click on the
    bar, or the new **+ Add stop** button; removing is the new **Remove stop**
    button, or a right-click as before.

  - **The cause was worse than it looked, and it was fixed too.** The editor
    canvas is drawn at one size and displayed at another, and the pointer was
    being measured in the wrong one — so the editor could not tell where you had
    clicked. The curve editor had the identical fault, which is why grabbing
    points on a curve has been fiddly. Both now measure correctly.

  - **Ctrl+Z was dead whenever a box had focus.** After typing into any field —
    which is most of the time — undo silently did nothing, with no message. It
    now works everywhere. Typing keys still cannot trigger shortcuts by accident.

  - **Eight more things can now be undone.** Canvas width, canvas height, the
    canvas preset, frame rate, background mode, background colour, and setting
    or clearing the background image all skipped the undo history entirely.

  - Behind the scenes: four new checks, each one watched to fail before it was
    allowed to pass, so none of the above can come back unnoticed.

v0.27.0
--------
  - **The Ottomancer name in the top bar now has the flame beside it, and it is
    a proper link.** Middle-click it (the scroll wheel) and it opens Ottomancer
    in a new tab, exactly like a link on any other website. Ctrl-click does the
    same, and right-click gives you the usual "open in new tab" menu. A normal
    left-click reloads the editor, and it takes a recovery snapshot first, so
    nothing in progress is lost if you click it by accident.

v0.26.7
--------
  - **Ottomancer would not open at all without a connection.** The saved offline
    copy was being stored in a form the browser refuses to reopen, so every page
    — the editor included — came up as a blank white window with no error and
    nothing to click. It looked exactly like the site being down. Every page is
    now saved in a form that reopens, and the offline copy genuinely works
    again. If you ever saw a blank Ottomancer, this was why.

  - The blank-window note in v0.26.6 below only covered half of this. The other
    half is fixed here.

v0.26.6
--------
  - **The site could get stuck showing an error page.** When a page was loaded
    during the minute or so after an update goes out, the browser sometimes
    caught the update mid-flight and got an error back — and Ottomancer then
    stored that error and kept showing it, instead of throwing it away and
    asking again. It now only ever remembers a page that actually loaded.

  - **A blank tab on the /app.html address.** That address forwards to /app, and
    the forwarding step was being stored as if it were the page. This release
    stopped new ones being stored; the copies already saved were dealt with in
    v0.26.7 above.

  - Behind the scenes: updating the offline copy now also notices when the part
    of Ottomancer that manages it has itself changed, so a fix like the two
    above reaches people who already have the site saved. Both bugs have a test
    that was watched to fail before it was allowed to pass.

v0.26.5
--------
  - **Docking a panel no longer covers the panel underneath it.** If you docked
    the Curves window to the right-hand edge — the natural thing to do with it —
    it sat on top of the Properties panel and every control there stopped
    responding, with nothing to tell you why. A docked panel now takes its own
    room and the workspace makes space for it, on any of the four edges.

  - Behind the scenes: the animated WebP frame flag fixed in v0.26.0 now has a
    test of its own, so the smearing cannot come back unnoticed.

v0.26.4
--------------------------------------
  - **The light theme is properly readable now.** Ten colours had no light
    version at all, so they stayed dark while everything around them went light:
    the "Start here" panel a new user is pointed at was dark text on a dark
    block, and the Export button — the main action in the top bar — lost its
    orange and became cream text on near-white, which is very close to
    invisible. Measured before and after: the Export button went from 1.06 to
    4.68, the panel titles from 1.22 to 11.3, the Start-here label from 1.24 to
    12.2. Every colour pair in both themes is now comfortably readable, and the
    build refuses to publish if a colour is ever added to one theme and not the
    other.

v0.26.3
--------------------------------------
  - **The editor can be used with a keyboard.** The scene tree, the colour tags,
    the behaviour headers and every cell in the Effects and Sprites libraries
    could only ever be clicked with a mouse — there was no way to reach any of
    them by tabbing, so somebody using a keyboard could type into the effect
    search box and then had nothing they could pick, and could not even select a
    layer. All of them can now be tabbed to and used with Enter or Space, and
    they announce themselves as buttons to a screen reader.

v0.26.2
--------------------------------------
  - **Number boxes cannot be given nonsense any more.** Canvas width and height
    now sit between 8 and 8192 — typing a huge number used to be accepted and
    gave you a canvas the graphics card refuses to draw, and typing letters
    silently collapsed it to 8 pixels. Seventeen settings that are meant to be a
    fraction between 0 and 1 — Flip U, Flip V, Flip Rotation, Dampen and others —
    already said so internally and nothing was reading it; they are properly
    limited now.

  - **A box always shows the value it actually kept.** If a number gets adjusted
    to fit, the box updates to match instead of displaying what you typed while
    holding something else.

v0.26.1
--------------------------------------
  - **A layer put on a path stays on it after you save and reopen.** This was
    the oldest known bug in the list. The layer used to freeze wherever it
    happened to be, the Follow-path box read "missing path", and playback and
    every export quietly stopped moving it — with nothing to tell you. The link
    is now stored by the path's name, which survives being saved; and renaming a
    path takes everything following it along, so the rename you make is the one
    you meant.

v0.26.0
--------------------------------------
  This one came out of a full audit — five separate passes over the app, the
  site, the exports and the security. These are the things that were wrong.

  - **Animated WebP exports were smearing.** Every particle that faded out
    stayed on screen for the rest of the clip, so a long effect ended as a
    build-up of everything that had ever happened. One wrong byte in the file
    format told players to blend each frame over the last instead of replacing
    it. Every animated WebP you export from now on is clean.

  - **"New" could lose your work with no way back.** Starting a new project
    reset undo, and the first edit you made afterwards overwrote the autosave —
    so up to three minutes of work could exist in no copy at all, while the
    button's own tooltip promised the opposite. It now takes a recovery snapshot
    first, the same as Open always did. More ▾ → Recover will have it.

  - **The editor now really does work offline.** The file holding all 57 sprites
    was never being saved for offline use, so offline you got the editor and not
    one sprite or ready-made effect. It is included now.

  - **Renaming a layer can be undone**, and two layers can no longer end up with
    the same name — which mattered, because effects that trigger each other find
    each other by name.

  - **A hostile project file can no longer put code into an exported SVG.**
    Sprite sizes from a `.ottomancer` someone sends you are now treated strictly
    as numbers. Nothing you have made is affected; this closes a door.

  - **About and Help showed "Ottomancer v?"**, and five pages still said v0.18.3.
    Every page now shows the version you are actually running.

  - **The tab you pick when two panels share an edge is remembered properly.**
    It used to come back correctly once and then forget.

  - Corrected what the built-in help and the machine-readable reference say about
    the collision floor: particles that start below it are held there, they do
    not disappear.

v0.25.3
--------------------------------------
  - **A panel can no longer be lost off the edge of the screen.** If you had a
    floating panel near the right-hand side and then made the window smaller,
    the panel stayed where it was — off the edge, with its title bar gone. You
    could not click it and you could not drag it back, because the bar you drag
    it by was the part that had disappeared. Panels are now pulled back into
    reach whenever the window shrinks.

v0.25.2
--------------------------------------
  - **A keyframe's two curve handles now stay in line with each other.** Drag
    the handle on one side of a point and the one on the other side swings round
    to match, keeping its own length. That is what stops a curve kinking as it
    passes through a keyframe, and it is how Spine and every other animation
    tool behave. Until now the two moved completely independently.

    **Hold Alt** while you drag if you WANT a sharp corner at that point — the
    other handle stays put. **Hold Shift** to make a handle longer or shorter
    without changing the direction it points. Both are written under the graph
    so you do not have to remember them.

v0.25.1
--------------------------------------
  - **Sheet and Graph are buttons on the timeline again.** Switching the
    timeline between the keyframe sheet and the curve graph was hidden inside
    the "View" menu at the bottom right — at every window size, not just narrow
    ones. The two buttons had been built to sit on the bar next to "All layers"
    and "Markers", and something was quietly moving them into the menu. They are
    back where they belong, so you can see which one you are looking at and
    switch with one click.

v0.25.0
--------------------------------------
  - **Two panels can now share an edge, as tabs.** Dock the Curves panel and
    the Preview to the same side of the screen and they no longer sit on top of
    each other — the title bar becomes a row of tabs and you click between them.
    Before this, docking the second one simply hid the first, with nothing to
    tell you where it went. Whichever tab you leave selected is the one that
    comes back next time you open the editor, and dragging the edge resizes the
    whole strip rather than one panel inside it.

v0.24.1
--------------------------------------
  - **Delete now works while the Curves window is open.** It already worked in
    the timeline below, but with the Curves window up the key was being caught
    and thrown away before anything could act on it, so pressing Delete simply
    did nothing. Found by using the editor rather than by reading it. Ctrl+Z
    still brings the keyframes back.

v0.24.0
--------------------------------------
  - **Sprites can now point at the middle of the emitter, or straight away
    from it.** In the Renderer module, Alignment has two new settings: "inward"
    and "outward". Say you build rain out of a circle using a streak sprite —
    before, every streak sat at whatever angle it was drawn at. Now "inward"
    turns them all to face the centre, and they keep facing it however they
    move. "outward" does the opposite, for a burst or a sunburst.

    Worth knowing: if your particles are already TRAVELLING toward the middle,
    the existing "velocity" setting already aimed them there. The new settings
    are for when the sprite has to face somewhere it is NOT travelling — rain
    falling straight down whose streaks face a logo, or a ring of shards
    orbiting with all of them facing in.

    Start Rotation still works on top of all of them, so if your artwork is
    drawn pointing up instead of right, correct it there once and every
    Alignment setting aims properly from then on.

v0.23.1
--------------------------------------
  - **Delete removes the selected keyframes.** Select one or drag a box over
    several, press Delete or Backspace, and they go — and Ctrl+Z brings them
    back. You could already do it by right-clicking, which is not where anybody
    looks. Typing in a box is left alone.

v0.23.0
--------------------------------------
  - **New keyframes now ease.** A keyframe you make starts gently, runs, and
    arrives gently, instead of moving at one flat speed and stopping dead.
    Constant speed is what makes animation look mechanical, and every other
    tool eases by default. **Nothing you have already made changes** — this is
    only what a NEW keyframe starts as, and you can still make any keyframe
    straight by hand.

  - **Old projects get their names tidied when you open them.** A project saved
    a while ago could have a layer called "Emitter 1" while the thing inside it
    was called "Sparks" — two names for one thing. Since effects that trigger
    each other do so BY NAME, that could make one quietly miss. Opening such a
    file now makes the two agree, keeping the name the effects actually use.

  - **Ctrl+Z takes back curve edits.** Reshaping a curve changed your effect
    immediately but was invisible to undo — the only way back was Cancel. It is
    a normal undo step now.

  - **Undo no longer collapses the layer you were working on.** Pressing Ctrl+Z
    folded the layer shut in the timeline and its keyframes looked like they had
    been lost. They were always there; the row had closed.

v0.22.7
--------------------------------------
  - **The timeline now names both its views: Sheet and Graph.** They were one
    button labelled "Graph", which never told you what turning it off gave you
    — so the dope sheet was a view you had to already know about. Same rows,
    same selection, same zoom; only how they are drawn changes. Graph has
    draggable curve handles built in.

v0.22.6
--------------------------------------
  - **Dragging a curve point straight up or down no longer moves it in time.**
    Before, any sideways drift of the mouse — and there is always some — also
    retimed the point, so a curve's timing crept every time you adjusted its
    shape. Drag mostly up or down and the timing is held; mostly sideways and
    the value is held; diagonally and you get both, as you asked for.

v0.22.5
--------------------------------------
  - **Zoom the timeline to your selected keyframes.** Select some keys and press
    **Shift+F**, or use **Frame keys** in the timeline's View menu. Three keys
    four frames apart on a six-second effect used to be an unreadable smudge,
    and the only way in was to spin the wheel and then pan by hand. **Fit time**
    is in the same menu to go back to the whole effect.

v0.22.4
--------------------------------------
  - **Arrow keys move selected keyframes.** Select keys in the timeline — drag
    a box over them, or click one — and left/right shifts them a frame at a
    time, Shift for ten. It is the quickest way to fix timing that is out by a
    frame or two. With nothing selected the arrows still nudge the layer, as
    before.

v0.22.3
--------------------------------------
  - **Fixed an error that fired every time you shaped a curve.** Dragging one of
    the little square handles in the Curves window threw an error on every
    mouse movement, because two different parts of the timeline were using the
    same place to remember "which handle is being dragged" — and each expected
    a different thing to be in it. Nothing visibly broke, which is why it went
    unnoticed; it just filled the browser's error log while you worked.

v0.22.2
--------------------------------------
  - **The keyboard works on curves now.** Pick a point and the up and down
    arrows nudge it; hold Shift for bigger steps. Delete removes the point
    (except the first and last, which set where the move starts and ends), and
    Escape lets go of it. Typing in any box is left alone.

v0.22.1
--------------------------------------
  - **Fixed a hang.** The curve graph could lock the whole browser tab solid —
    no error, nothing to click, only closing the tab. The time ruler along the
    bottom of the graph was drawing its marks one at a time with no upper
    limit, and if the view got into a wide enough state it tried to draw
    millions of them, sixty times a second. It now works out the spacing from
    what is on screen, and refuses any view that does not make sense.

  - **Panels resize from any edge.** Before, only the little corner grip
    worked, and it disappeared entirely once a panel was docked — so a panel
    docked down the side could not be made wider, which is the one resize you
    actually want. Grab any edge now; a docked panel resizes by the edge facing
    your work.

v0.22.0
--------------------------------------
  - **The Curves panel is editable at last.** There were two of them: a
    "Curves…" window you could edit but not dock, and a **Curves** panel from
    the top bar that docks to the edges of the workspace but was a picture you
    could only look at. That panel now has everything the window has — click a
    point to select it, drag it, drag its square handles to shape the ease.

  - **The curve graph has a proper time axis.** Wheel to zoom around the
    pointer, shift+wheel or middle-drag to pan, double-click or **Fit** to see
    the whole effect again, and **−** / **+** buttons if you would rather not
    use the wheel. The tick marks get finer as you zoom in.

  - **A readout above the graph shows the selected key, with its time and value
    in boxes you can type into.** Dragging is the quick way; typing is the way
    that cannot miss by a pixel.

  - **Panels and windows roll up** to just their title bar, so you can park one
    without closing it and losing your place.

v0.21.2
--------------------------------------
  - **The Curve editor works properly now** — the one behind the "Curve" button
    on Size, Start Size and the rest. Four things were wrong with it:

    **Clicking a point added a new point instead of selecting it.** If your
    click missed the point by a few pixels — and the points were small — you
    got a new one where you were aiming. So every attempt to grab a point made
    the curve messier. Clicking on or near a point now always selects it. You
    can still add one by clicking in clear space.

    **Nothing you did applied until you pressed OK.** Drag a curve, look at
    your effect, see no change. It updates live now, as you drag, and Cancel
    puts it back exactly as it was.

    **The graph was tiny and would not grow.** It now fills its window, and the
    window resizes.

    **Nothing showed a point could be grabbed.** The cursor now changes over a
    point and over a handle.

v0.21.1
--------------------------------------
  - **The curve window is a real window now.** It used to be a popup that
    dimmed everything and took every click, so you could look at a curve OR
    work, never both. It now floats: the timeline, the viewport and the panels
    all stay live while it is open, so you can scrub and watch the curve at the
    same time. Press Curves again, or Escape, to close it.

  - **The points and handles are much easier to hit**, and the cursor now
    changes when you are over one — a hand over a point, a pointer over a
    handle. They were small enough to miss on a large screen, and nothing told
    you they could be grabbed.

  - **Window edges are easier to grab too**, and they light up under the
    pointer.

v0.21.0
--------------------------------------
  - **Applying an animation now shows its keyframes.** They were always being
    created, but the layer stayed folded shut in the timeline, so you got one
    summary row and no properties — which looks exactly like nothing happened.
    Anything that makes a keyframe now opens the layer that got it.

  - **The curve window has a playhead.** A vertical line that moves with the
    transport, just like the one in the timeline, so the shape of a curve is
    tied to the moment you are looking at.

  - **Curve handles show you which key you are working on.** They sit faint
    until you click a point; that point's handles then go full colour on a
    dotted arm, and the one you are dragging fills in. Click a handle to grab
    it directly.

  - **Every window resizes from any edge, moves, and snaps.** Not just the
    bottom-right corner. Drag any edge or corner, drag the title bar to move
    it, and it snaps to the screen edges and to the panels behind it, with a
    line showing where it will land. Each window remembers its own size and
    place. The curve graph now fills its window too — before, a taller window
    just gave you more grey.

v0.20.3
--------------------------------------
  - **Spine cost estimates were counting layers you had switched off.** Both of
    them. So an export looked more expensive than it actually was, and the
    numbers you use to decide what to ship were high. Fixed — a disabled layer
    now costs nothing, which is what it does.

  - Behind the scenes, two new checks run before anything is published: one
    that catches a setting written to a name that does not exist (which used to
    do nothing at all, quietly), and one that re-measures how the engine
    actually behaves against what the guides claim. The first found the bug
    above the moment it was switched on.

v0.20.2
--------------------------------------
  - **The curve editor has handles now.** Every keyframe already carried an
    ease — it was in the file, in the playback and in the Spine export — and
    there was no way to reach it. Open **Curves** and each segment now shows
    two square handles on top of the round points: drag a round one to change
    the value, a square one to shape how the value gets there. A hold key has
    no ease, so it shows none.

  - **Canvas size says which box is which.** It was two bare numbers stacked
    on top of each other. They are now marked W and H.

  - **A fix for anyone writing a project file by hand or by script.** The
    format guide described a layer's keyframes with the wrong shape, and a file
    written to it loaded with every keyframe blank — no error, the layer
    present, the animation simply gone. The guide is corrected, and the reader
    now accepts both shapes and refuses a keyframe it cannot read instead of
    loading a broken one.

v0.20.1
--------------------------------------
  - **Onion skin now has its dials.** It could always show ghost frames before
    and after the playhead, tinted cool for the past and warm for the future —
    but only the spacing could be changed. How many ghosts to show behind, how
    many ahead, and how strong they are now sit beside it in the View menu.

  - **A first visit says where to start.** One line above the ready-made
    effects, once, and it goes away as soon as you pick one. If you arrive on a
    link that already opens an effect, you still get it.

  - **The editor can be used with a screen reader.** Most of the boxes in the
    properties panel had no name a screen reader could read — the label was on
    screen but not joined to the field, so it announced them as blank. All of
    them are named now, and the status line at the bottom is read out, so
    "Added Festival Fireworks" or "Could not save, storage is full" is heard
    rather than only shown. A canvas editor will never be fully navigable this
    way, but nothing should be silent.

v0.20.0
--------------------------------------
  - **The looping effects now actually loop.** Almost none of them did. An
    effect set to loop was drawing different random numbers every time round,
    so the last frame never matched the frame before the first — in a game that
    reads as a small pop, once per cycle. Measured across the whole library:
    4 of the 94 looping effects closed cleanly before, 92 do now. Eleven of them
    also needed their rate, their cycle length or their particle limit adjusted
    so the numbers divide.

    If you liked the old endless variation for a live background, turn
    **Loop-safe random** off in Main — it is a switch, not a rule.

  - **A new "Check" button in the top bar**, next to the Spine one. It looks for
    the faults that do not look like faults: a loop that will not close, an
    emitter quietly hitting its particle limit so half the burst is never born,
    a sub-emitter pointing at a name that no longer exists, particles born at
    zero size. Where the repair is arithmetic it offers to do it — **Fix this** —
    and where it is a matter of taste it tells you what to change and leaves it
    alone.

  - **The properties panel only shows what the emitter is using.** There are 19
    modules and a typical emitter uses six, so the panel used to spend thirteen
    headers saying nothing is happening here. The rest now sit under **Add
    behaviour**, grouped by what they do — "how they move", "how they change as
    they age" — rather than by their engine names. Searching still looks through
    all nineteen.

  - **A link that opens an effect.** `ottomancer.com/?fx=Fire+Tornado` starts the
    editor with that effect already loaded. Any name from the effects list works.

  - Undo now updates the Spine and Check readouts. They could previously sit on a
    verdict about a project you had just undone.

  - **The site was telling people there are 118 effects.** There are 119, and one
    button said 117. Fixed everywhere, and the deploy now counts the library and
    refuses to publish if any of that copy disagrees with it.

  - **Every setting now explains itself.** Hover any field name and it tells you
    what it does in plain words — all 112 of them, where before only a quarter
    had any explanation. The ones with a trap in them say so: pulling inward
    needs a negative number, a collision floor is solid underneath, and a
    sub-emitter stops working if you rename what it points at.

  - **The first layer is called what it says it is.** A new project's layer read
    "Emitter 1" in the list while the effect inside it was called "Sparks" — and
    "Sparks" was the name that actually did the work.

  - **"Start here."** The ready-made shelf in the bottom-left is where you
    actually begin, and it used to look like the quietest thing on screen. It is
    now a proper block that says what it is for. It has not moved.

  - **Effects with an opening burst no longer lose it.** If a burst was set to
    go off in the first fraction of a second, it could quietly stop firing after
    a few loops and never come back — Volcano Eruption lost its opening blast
    that way. Every looping effect in the library now repeats exactly, forever,
    with no drift at all.

  - **The Check button takes you to the problem.** Every emitter it names is
    now a link — click it and that layer is selected, ready to fix. Naming a
    layer was only half an answer in a scene with nine of them.

  - **You can now tell the panels apart.** The greys the editor was built from
    were so close together that the whole app read as one flat sheet — the
    darkest and lightest surfaces were within a whisker of each other, and
    neighbouring ones were closer still. They have been spread out. Same dark
    tool, same colours, but the panels, the bars and the stage are now visibly
    different surfaces instead of one.

  - **Small grey labels are readable.** They were below the contrast a person
    needs to read comfortably; they are not any more.

  - **Ottomancer now looks the same for everyone.** It used to ask for Segoe UI
    and Consolas, which only exist on Windows — so anyone on a Mac or Linux was
    quietly getting different fonts, and a different-looking app. It now brings
    its own (IBM Plex Sans and IBM Plex Mono, 59 KB once, then cached and
    available offline). If they ever fail to load the editor still reads
    correctly in whatever the machine has.

  - **More room to work.** Property rows, module headers, the layer list and
    every input got a little taller and a little wider inside. It reads calmer
    and is easier to hit; the cost is about three fewer property rows on screen
    at once.

  - **The Spine and Check readouts look like readouts now**, not like two more
    buttons. They are pills in plain colours — green when everything is fine,
    sand when something is worth a look, red when something is wrong.

  - **Corners agree with each other.** There were eleven different rounded
    corners on screen; now there are three, and each one means something:
    controls, panels, and the two status pills.

  - **The smallest text in the editor got bigger.** Some labels were 8 and 9
    pixels tall; nothing is under 10 now. Along with it, the editor's colours
    and sizes are on a proper system rather than being chosen a rule at a time —
    invisible today, but it is what lets the interface actually improve.

  - **The effect you start with now loops properly too.** The starter project
    was built by hand rather than from the effects library, so the loop fix
    missed it — which meant the new Check button greeted you with a problem
    about the project Ottomancer had just made for you. Fixed, and checked on
    every publish from now on.

  - **Keyboard focus is visible.** Tabbing through the editor used to leave you
    guessing which button you were on, because buttons drew no focus at all.
    They now show an amber ring. Clicking with the mouse still shows nothing,
    which is how it should be.

  - The Check button no longer warns about things that are fine. Projects store
    numbers to five decimal places, and three of its rules were stricter than
    that — so a correct effect could come back from a save looking broken. All
    three now allow for it, and every real fault is still caught.

v0.19.18 — earlier
------------------
  - **The Project panel now shows how big your project is**, and how much of
    that is images. A project keeps its own artwork inside it, so one imported
    sheet can turn a 20 KB file into a 5 MB one — worth being able to see
    rather than discover later.

  - Your projects stay **one plain file that carries its own art**. It opens
    anywhere, nothing goes missing, and a script or a text editor can read it.

v0.19.17 — earlier
------------------
The SETUP preview is live now — move something and it follows.

  - **Move an emitter, drag a folder, change anything, and the playing preview
    updates as you do it**, the way Spine does. It was being fed nothing about
    where things are, so moving an object changed the stage and left the preview
    showing the old arrangement.

  - Everything else was always live — rate, size, colour, lifetime — because the
    simulation reads those as it runs. It was only ever the positions that were
    missing.

  - **Adding or deleting an emitter shows up too**, instead of the preview
    quietly carrying on with the old list.

  - The stage stays exactly where you left it while the preview plays. The two
    run on separate clocks on purpose, so nothing you watch can move your
    playhead or key anything.

v0.19.16 — earlier
------------------
A proper layout pass — the tools, the modes, and where everything lives.

  - **The move / rotate / scale buttons were drawn on top of the transform
    panel.** They were both pinned to the same corner, so the panel's title read
    as "sform" and its X and Y labels sat behind the icons. The tools now have
    their own column and the panel sits beside them, readable.

  - **SETUP and ANIMATE moved onto the stage**, centred at the top, where the
    thing they change actually is. They were sitting in the menu bar next to New
    and Open, which made them look like ordinary buttons.

  - **SETUP now splits the screen.** The timeline goes away — it is no use while
    you are posing — and the stage divides: your work on the left, the effect
    playing on the right, almost as large. The earlier version put the preview
    along the bottom where the timeline had been, which was not the same thing.

  - **The preview never stops, and never touches your keys.** It runs its own
    clock and loops forever, so you can change something and watch what it did
    without the playhead moving and without keying anything by accident.

  - **"Spine: safe" is always on the top bar now**, instead of hidden inside the
    More menu. It tells you whether your project can be exported at all, which
    is not something to go looking for.

  - **The left column is organised the way other software does it.** Buttons
    that add to the scene sit under the scene. Adding an image sits with the
    images, as **+ Add** on the Images list. The ready-made shelf — Effects,
    Sprites, Animations — moved to the bottom, because picking one is something
    you do once at the start.

  - **Two duplicate buttons removed.** "Add Images" and "Library" in the top bar
    opened the same dialogs as the buttons in the panels below them.

v0.19.15 — earlier
------------------
The Export window now tells you what each emitter costs, before you export.

  - **A "Spine cost" line, and a breakdown per emitter.** It says roughly how
    many slots your effect will use in Spine, which emitter is responsible for
    them, and what share each one is — sorted by the expensive one first.

  - **It names the reason.** If trails are what is multiplying an emitter, it
    says so: *"trails are 7 samples, so each particle costs 8x"*. If Max
    Particles is the only thing holding one down, it says that too.

  - **It updates as you change things**, so you can see the number move rather
    than exporting to find out.

  - **It warns when Spine will struggle.** Spine's editor gets slow long before
    the file gets big, so the number that matters for Spine is slots, not
    megabytes.

  The figure is deliberately on the high side — it is checked against real
  exports and always comes out at or above what the file actually contains, so
  it is safe to plan against.

v0.19.14 — earlier
------------------
Every export that can have a transparent background now does.

  - **SVG was ignoring the Transparent tick.** You could tick the box, export,
    and still get a solid rectangle behind everything. It now does what the box
    says.

  - **The web bundle was always dark.** Drop it into a page or an iframe and it
    brought a black rectangle with it. With Transparent ticked, the page is now
    see-through, so the effect sits on whatever is behind it.

  - **Transparent GIFs were losing almost the whole effect.** A GIF can only do
    "fully there" or "fully gone" — no in-between — and a glow is almost entirely
    in-between, so nearly all of it was being thrown away. Measured on one frame:
    2,902 visible pixels became 49.

    Now the visible part is blended onto a colour first and only the truly empty
    area is left transparent, which is how GIF exporters have always done it.
    **93% of what you can see survives**, instead of 2%. The export tells you the
    number each time.

  - **WebM keeps transparency, and the note now says so.** It used to advise
    turning Transparent off for video, which sent you away from the one video
    format here that keeps it.

  Where each format stands, all measured on real exported files:

    PNG sequence   full soft transparency
    Animated WebP  full soft transparency — same as the PNG, pixel for pixel
    Spine          full soft transparency
    WebM           keeps transparency
    SVG            no background
    Web bundle     see-through page
    Animated GIF   hard-edged only, keeps 93% of what you see
    MP4            cannot — the format has no transparency at all, and says so

v0.19.13 — earlier
------------------
Safety net: nothing broken gets out quietly.

  - **An export is now checked by reading it back**, the same way saving already
    was. Ottomancer opens the file it just made, plays it, and confirms every
    image it asks for is actually in the zip. If something is missing it
    **refuses to save the file and tells you which image**, instead of handing
    you a zip that imports into Spine with pieces missing.

  - **It knows where the export is going.** Sending it to a game runtime and
    sending it to the Spine editor need different files, so a problem that would
    break one and not the other is reported accordingly — no false alarms.

  - **If anything goes wrong while you are working, a bar now appears with a
    "Save my work now" button.** It writes your project straight to your
    Downloads folder. Before this, any error covered the whole screen with
    "Ottomancer could not start" — which was untrue an hour into a session, and
    gave you no way to rescue what you had done.

  - **An image that fails to save is now reported.** It used to be skipped in
    silence, which is how an export ends up quietly missing a piece.

  - Under the hood: the feedback board now has an automatic check that nothing
    anyone posts can ever run as code, and the markers that prove this is the
    original Ottomancer are all verified on every build.

v0.19.12 — earlier
------------------
Every looping effect now closes exactly — including the ones we used to warn you about.

  - **Swirling, drifting noise no longer breaks a loop.** Fire Tornado had 628
    flames landing in the wrong place at the wrap. It now has none. The noise
    pattern repeats with the loop instead of drifting on forever, so a flame
    coming round again follows exactly the path the last one did.

  - **Two warnings in the Export window are gone, because they are no longer
    true.** One told you to turn Noise Scroll Speed down to zero. The other told
    you to shorten a particle lifetime that outlived the loop. Both would have
    cost you the look of your effect to fix something that no longer happens.

  - **Measured across the whole library**: every looping effect closes at zero
    pixels — Fire Tornado over 386 particles on screen at the seam, Falling Snow
    over 214, Portal Vortex 130, Magic Aura 91. It still closes with the noise
    scroll pushed to three times what any effect uses, and with a lifetime twice
    the length of the loop.

  Nothing about how your effects look has changed. The noise only repeats once
  the loop comes round, which is what asking for a loop means.

v0.19.11 — earlier
------------------
See what your export will actually do, before you export it.

  - **A "Preview export" button in the Export window** (on the Spine tab). It
    bakes the file and then PLAYS it — not the effect running in the editor, but
    the finished JSON, read back the same way a game engine reads it. If it
    plays here, the file is sound.

  - **It tells you what the file needs.** Every image it references, at the size
    it expects — and says plainly if one of them is missing, which is the thing
    that leaves you with an invisible effect in your game.

  - **It tells you what the file costs.** Frames, duration, bones, slots, keys,
    JSON size, and whether it loops. Then it measures the drawing as it plays:
    average and worst frame time against the budget your frame rate allows, and
    how many frames went over.

  - **Play, pause and scrub** through it, and anything the preview cannot draw
    is listed rather than quietly skipped.

  This was asked for on the feedback board: "i need a way to see if a json i
  will export, how it will play in a basic html game, what info it has...like
  assets, frame rate, frame drop, etc. so i know the export will work before i
  add it to an existing project."

v0.19.10 — earlier
------------------
Falling Snow loops properly now — and so does everything else.

  - **A looping effect no longer hitches at the wrap.** Falling Snow had a
    flake jumping most of the width of the screen every time the loop came
    round. It is gone: all 214 snowflakes on screen at the seam now land in
    exactly the same place at the end as they do at the start.

  - The cause was a rounding error, not the snow. An effect that loops restarts
    its random numbers each time round, so every cycle looks the same — but the
    restart was landing one frame late, and after a while it started landing on
    time instead. That one frame is two snowflakes, which was enough to pair
    every flake with the wrong twin on the far side of the loop.

  - **This affected any looping effect**, not just snow. Snow was simply the
    only one whose flakes live longer than the loop, so it was the only one
    where you could see it happen. The same fix is in the web player, so
    exported web builds loop cleanly too.

v0.19.9 — earlier
-----------------
Curve handles on every point.

  - **Every point on a curve now has its two handles showing** — one reaching
    back, one reaching forward — instead of only the point you had clicked.
    Grab either one and drag it to bend the curve into that point or out of it.

  - **Grabbing a handle picks up its own point.** You no longer have to select
    a point first and then find its handles; just take hold of the handle you
    want. The point you are working on is drawn brighter than the rest, so you
    can still tell them apart at a glance.

  - The first point has no backward handle and the last has no forward one,
    because there is no curve on that side of them to shape.

v0.19.8 — earlier
-----------------
A Windows menu, and panels you can put where you want them.

  - **Windows ▾ in the top bar**, where every other program keeps it. It lists
    the panels: **Curves** and **Preview**, with a tick beside the ones that
    are open.

  - **Drag a panel by its title bar and drop it where you like.** Near an edge
    it snaps and fills it — left, right or bottom — and an outline shows you
    where it will land before you let go. Drop it anywhere else and it floats.
    Drag the corner to resize. Where you put them is remembered.

  - **They follow the selection and keep playing.** Curves shows the selected
    layer's animation live; Preview shows the effect running, framed the way an
    export will frame it, not the way the stage happens to be panned.

  - **SETUP mode puts the preview where the timeline was.** The timeline only
    appears in ANIMATE now, the way Spine does it — a dope sheet is no use
    while you are posing, and it is the tallest thing on screen. The stage grows
    from 414 to 631 pixels tall in the swap.

    If you had the preview open somewhere else, that is left exactly as it was
    and put back when you return to ANIMATE. Only a preview that SETUP opened
    gets closed again.

v0.19.7 — earlier
-----------------
Spine exports now say what every slot is doing on the first frame.

  - **Every slot is switched on or off explicitly at frame 0.** Before, a slot
    whose particle appears later said nothing at all until then — and what a
    slot shows when it says nothing is somebody else's software's decision. On
    one firework, **158 slots were still holding artwork from the end of the
    loop at the start of it**, and 2507 of 2783 slots were silent on frame 0.

    That is the "bits of the end playing at the beginning" problem, and the
    "stars frozen on screen during other animations" one. Both come from the
    same silence. It costs about one key per slot — under 2% of the file.

  - **A scrolling noise field cannot close a loop, and the export now says so.**
    Measured rather than guessed: one effect goes from 366 slots jumping at the
    loop point to zero when Noise > Scroll Speed is set to 0, and loop-safe
    randomness makes no difference to it whatsoever. The warning names the
    emitters and tells you the choice — set the scroll to zero for an exact
    loop, or keep it and accept a few pixels of pop.

v0.19.6 — earlier
-----------------
Tools you can press.

  - **Move, Rotate and Scale are buttons now**, in a rail on the left of the
    stage, one of them always lit so it is never a guess which is active. Or
    press W, E, R — the same keys Spine, Unity and Maya use.

    The handles were always there. Nothing on screen said they were tools, so
    "we need translate and rotate tools" got reported twice by someone looking
    straight at them. That is a UI failure, not a missing feature.

  - **The stage shows only the tool you chose.** Move draws arrows out of the
    pivot, rotate draws the ring, scale draws its handle — instead of all five
    grab targets stacked around one small object, where reaching for the X
    arrow got you the rotate ring.

  - **A selected layer is always marked**, whichever tool is up: the pivot
    square, and a faint dashed circle when the tool draws nothing near it.

  - **SETUP and ANIMATE moved to the centre of the top bar.** They decide what
    half the app does, and they were sitting in the run of ordinary buttons
    with nothing marking them as different in kind.

  - **Fixed: the Local / Parent / World buttons stopped lighting up when
    clicked.** They had been broken for two releases — the space really did
    change, only the highlight did not follow, so the panel showed one thing
    and did another.

v0.19.5 — earlier
-----------------
Eight defects from an outside bug report, and a new firework.

  - **FIXED, and the worst of them: a burst on the very first frame never
    reached a Spine export.** The file came out valid, complete-looking, and
    missing that whole part of the effect — no error, no warning. The editor
    showed it firing perfectly, because only the export warms the simulation up
    first, and the warm-up swallowed it. Anyone hitting this had to move their
    burst a frame or two later and never know why.

  - **The export now refuses rather than quietly losing an emitter.** If
    something emits in the editor and puts nothing in the file, the export stops
    and says which emitter. That is the general net: it does not need to know
    why, so the next cause of this gets caught too.

  - **"export blocked: [object Object]"** — every blocked export said exactly
    that, and nothing else. The one sentence written to explain the refusal was
    the one thing thrown away. Blocked exports now say what is wrong, all of
    them, not just the first.

  - **An empty first frame no longer refuses the export.** A shell that opens a
    frame or two in legitimately has nothing on frame 0; that used to be a hard
    block with no way forward. It is a note now, saying it opens blank and which
    box to untick.

  - **The setup-pose control says what it does.** It fills the slots holding a
    particle on frame 0 — not all of them, deliberately, because filling the
    rest would leave particles frozen on screen in other animations. It is
    called "Show frame 0 in Spine's setup pose" now and reports "74 of 400" so
    the number makes sense.

  - **The size estimate was nine times under on effects with trails.** Every
    trail sample is its own slot in a Spine export, and the estimate counted one
    per particle. It counts them properly now and is deliberately generous —
    real exports come in at or under it.

  - **Projects saved by older builds open again.** Files ending `.ottopia` were
    not selectable in the Open dialog even though they load perfectly.

  - A library sprite with no image data is refused instead of silently
    producing an emitter that draws nothing.

  - **New effect — Festival Fireworks** (Scenes). A peony shell that opens
    straight into gold star-streaks with drooping tips and lingering embers.
    Contributed as a finished, measured recipe. Duplicate the folder for a
    second shell and change its colour and position. It opens on the very first
    frame, which is only possible because of the fix at the top of this list.

v0.19.4 — earlier
-----------------
The effects library shows you the effects.

  - **Every effect now has a picture.** 118 of them, previously offered as a
    name and a sentence in a tool whose whole subject is how things look. Each
    thumbnail is the real recipe, simulated and drawn by the real renderer — the
    same road the effect takes when you click it — so what you see is what you
    get, not an illustration of it.

  - **It picks the moment worth showing.** Not the first frame (a slow build has
    not started), not the last (a burst is over), and not the busiest either: an
    effect that grows its particles peaks its count when everything is still too
    small to see. It measures how much is actually on the frame and shows you
    that moment.

  - **Only what you are looking at is drawn**, one at a time, and kept for the
    rest of the session — so scrolling back is instant and opening the library
    never makes you wait for 118 simulations.

  - 111 of the 118 produce a picture. Seven are too thin or too sparse to read
    at this size and keep the name and description they always had.

v0.19.3 — earlier
-----------------
The editor opens in roughly half the download it used to need.

  - **569 KB down to 322 KB.** The built-in sprite art was 45% of everything a
    visitor downloaded, and none of it is needed to open the editor. It now
    lives in its own file, fetched the moment the editor is on screen and
    before you could ask for it.

  - **Nothing about using it changes.** Every sprite's name, size and category
    is still in the page, so the library lists instantly. If you open the sprite
    library or add a ready-made effect in the first half-second, it waits for
    the art rather than showing you empty boxes, and says so if it is taking a
    moment.

  - Your own projects are untouched: art you have added lives in your project
    file exactly as before. The starter sprites are drawn by the editor itself,
    so it opens with something on screen whatever the network is doing.

  - Offline still works — the new file is cached with everything else on your
    first visit.

v0.19.2 — earlier
-----------------
See what your effect actually costs to draw.

  - **Overdraw view.** One button in the View menu, and the stage shows how many
    times each pixel gets painted: dark where nothing overlaps, bright where a
    lot does. That number is what decides whether an effect runs on a phone, and
    until now nothing in any editor would tell you — two effects that look
    identical can cost four times as much, and you find out on the device.

    In Unity and Unreal artists get this by hand: switch the blend mode to Add,
    set the particle colour to a dim grey, put a black card behind the effect,
    read the brightness, then undo all of it. This is that, built in, with the
    reading done for you.

  - **The reading, in the corner:** average overdraw, the worst spot, and how
    much of the frame is covered at all. Average is the one that matters — a few
    hot pixels are cheap, a whole screen painted three times over is not.

  - **A particle budget you pick by device.** Phone (300), Tablet or Switch
    (600), Desktop (1500), or no opinion. The counter turns amber when the peak
    goes past it. The budget already existed in the file format and nothing ever
    set it, so it could never actually fire.

  - **It cannot change anything.** The view measures by running the real
    renderer against a counting surface, so what it reports is what you see —
    but it touches no part of your project, the simulation, or any export.
    Checked by baking a Spine export with the view on and off and comparing.

  - It costs about 4ms a frame on a heavy scene. Getting there took three
    rewrites: the first was 80ms, and the cause was not what it looked like.

v0.19.1 — earlier
-----------------
Stretch or squash the timing of a whole action.

  - **Select some keys and a bracket appears across the top of the sheet**, with
    a grab at each end. Pull one and the selection stretches or squashes in
    time; the other end stays put. The spacing inside keeps its proportions, so
    "make this whole thing thirty percent slower" is one drag instead of moving
    every key by hand and hoping the rhythm survived.

    Dragging a key still slides the selection about as it always did. This is
    the other half of timing work: the length of an action rather than where it
    sits.

  - Keys land on frames while you drag, like everything else in the timeline.
    Hold Alt for the exact time.

  - **It will not let you destroy the action you are editing.** Squash it as far
    as you like and it stops at one frame between keys instead of merging them
    into each other; pull it left past the start of the timeline and it stops at
    zero instead of piling every early key onto the same moment. Both of those
    lost keys in testing before the limits went in, which is why they are there.

v0.19.0 — earlier
-----------------
Copy and paste keyframes — the thing Spine users reach for most.

  - **Select keys, Ctrl+C, move the playhead, Ctrl+V.** The spacing between them
    comes with them, so a whole action lands intact wherever you put it. There
    are "Copy keys" and "Paste keys" buttons in the View menu too, because a
    shortcut nothing mentions is a shortcut most people never find.

  - **Paste onto a different layer.** Select one layer before pasting and the
    keys land on that layer instead, creating the property track if it does not
    have one. Build a bounce once and give it to everything.

  - **Paste mirrored** with Ctrl+Shift+V, or shift-click the Paste keys button.
    Every value is negated, so a move to the right becomes a move to the left
    and a turn one way becomes a turn the other. Meant for position and
    rotation; it will do nothing sensible to Opacity, which is why it is a
    separate command rather than the default.

  - **Fixed on the way: Ctrl+C copied the LAYER even when you had just
    box-selected a run of keyframes.** The obvious gesture did something
    confidently wrong. Keys win when keys are selected; layers when they are
    not; and the clipboard remembers which kind it holds, so paste never has to
    guess from where you last clicked.

  - Easing comes with the keys. Copy a run with an ease-out on it and the
    ease-out is there when you paste.

v0.18.9 — earlier
-----------------
Housekeeping you will not see, except for one line on this page that was wrong.

  - **This page used to say the developer notes live in "VERIFY.md".** No such
    file exists, and as far as the history goes it never did. Anyone who went
    looking found nothing. Fixed, and there is now a check that fails the
    publish if any document names a file that is not there.

  - **The project got a front door.** Nine developer documents and nothing
    saying where to start. There is now a README, a single RULES file holding
    every invariant in one place instead of scattered through comments, and a
    guide for AI assistants picking the project up cold. None of this changes
    the editor; all of it makes the next change safer.

  - **A licence file now sits with the source**, carrying the same nine clauses
    published here. If the two ever drift apart, the publish stops.

v0.18.8 — earlier
-----------------
A cleaning and safety pass. Almost nothing here changes what you see, which is
the point of it — this is the release that makes the next ten safer.

  - **The publish button now runs a safety audit before it uploads anything.**
    It refuses to publish if a file about to go live contains a password, a key
    or a personal email address; if a developer-only file has strayed into the
    website folder; if the marker that identifies this code as ours has gone
    missing; if the security headers have weakened; if a link points somewhere
    unexpected; or — the one with teeth — if any licensed artwork has ended up
    in a shipped file. Every one of those rules existed already, written down
    somewhere. Now they stop a publish instead of being remembered.

  - **Dead code removed.** Three definitions nobody used: a table of value types
    that nothing consulted, a function whose only caller had been deleted, and a
    list of align modes that sat unread while the buttons passed their own text.
    That last one is now actually read, so a typo in an align button says so
    instead of quietly doing nothing.

  - **Nothing was slow.** Measured before changing anything: drawing the
    viewport is 9% of a frame's budget and everything else — visibility keys,
    path following, the transform bar — is under a fifth of one percent, and all
    of it scales linearly to a thousand layers. No optimization was needed, so
    none was invented.

  - The download is 569 KB compressed, and 45% of that is the built-in sprite
    art. Loading it on demand instead would cut the first visit nearly in half.
    That is a real change to how the app loads, so it is written up properly and
    scheduled rather than rushed in at the end of a long day.

v0.18.7 — earlier
-----------------
I built a whole effect by hand and it broke in four places. All four are fixed.

The effect: a rocket that climbs a path with a flame trail, sparks and smoke on
it, hands over at 1.15s to an explosion with a shell burst, glitter and a shock
ring, using every one of the nineteen modules. Nothing below was visible in the
parts. All of it showed up the moment they were assembled.

  - **FIXED, and the worst of them: one-shot emitters were silently missing from
    a looping Spine export.** A looping bake warms up for four cycles before it
    records anything, so an emitter set to fire once fired during the warm-up and
    was finished long before recording started. On this firework the entire
    explosion — three emitters, 1271 bones' worth — was absent from the .json,
    while the warning list talked about trail slots. One-shots now restart at the
    top of the recorded loop, and the export says so.

  - **FIXED: hiding a layer now stops its emitters.** A Visible key hid the
    drawing but the emitter kept running, so an explosion keyed on at 1.15s had
    already fired at 0s, unseen, and was over before it appeared. Hiding a folder
    stops everything inside it, and switching one on starts it from its own
    beginning — so a burst fires when it appears, which is the point.

  - **FIXED: a Visible key could empty the whole Spine export.** 1521 bones and
    1512 slots became 9 and 0, with no error, because a branch that happened to
    be hidden on the last frame was dropped from the bake. Bakes are a replay of
    the project now: every layer is on throughout, whatever the playhead is
    doing when you press Export, and the export panel says exactly that.

  - **FIXED: renaming a path silently unhooked everything following it.** Paths
    were referenced by name, so "Path 1" → "Launch Arc" left every layer on it
    frozen where it stood, with no error and a Follow-path box gone blank. Two
    paths sharing a name was worse — the layer jumped to the wrong one. They are
    referenced by identity now, so a rename is just a rename. Projects saved
    before this go on working. Deleting a path shows "⚠ missing path" on the
    layers that were using it instead of quietly showing nothing.

  - **Search in the Effects library.** 118 effects behind nine tabs, and no way
    to find one you had heard of except reading every card. Type and it searches
    all of them, by name and by description, telling you which category each
    result came from.

  - **Buttons that were cut off.** "Effects list" was losing 18 pixels of itself
    and Help 7, both squeezed into a 24-pixel square meant for one-character
    buttons. Help is "?" now, next to the "i". The hint on the Scene panel —
    "drag to reorder · drop onto a folder to nest", the one line that teaches
    that layers nest — was getting 28 pixels and ellipsising to a single letter;
    it wraps to its own line now.

v0.18.6 — earlier
-----------------
The curve editor, the way Spine does it: shapes you can see, one click away.

  - **Presets are pictures now.** Twelve tiles, each drawing its own curve, so
    you pick a shape instead of guessing what "Back In" means. Every tile is
    drawn by the same function that plays the animation, so a tile cannot show
    you one thing and apply another.

  - **The one you are using lights up.** Open a curve and the tile matching it
    is highlighted. Before, all of them looked the same whatever the segment was
    actually set to — the panel could tell you where you could go, never where
    you were.

  - **Three new shapes.** Slow Out (a long, soft landing), Strong In (almost
    nothing, then a rush) and Elastic Out (overshoots a long way and springs
    back), joining Ease, Back and Bounce.

  - **Type the numbers.** Four boxes under the presets hold the bezier values,
    for a curve copied from somewhere else or a value the mouse cannot land on.
    Greyed out on Linear and Stepped, which have no handles to type.

  - **One curve, many keys.** Select a stretch of keys in the timeline, pick a
    shape, and it lands on all of them. The button says how many. A twelve-key
    bounce used to mean opening this window eleven times.

  - **A "Curve…" button in the View menu.** Reaching the editor used to mean
    double-clicking the gap BETWEEN two keys, on the right row, in a sheet where
    that gap can be four pixels wide. Everything the editor could do was already
    there and most of it was unreachable in practice.

  - **Fixed: the editor leaked two handlers every time you opened it.** Nothing
    ever removed them, so a session with fifty curve edits carried a hundred
    dead listeners running on every mouse move. The knobs, the graph handles and
    the numbers all still work; there is just less rubbish behind them.

v0.18.5 — earlier
-----------------
Spine's transform bar, over the stage, with Local / Parent / World.

  - **A transform bar on the viewport.** Translate, Rotate and Scale in a compact
    strip in the top-left corner of the stage, showing whichever layer is
    selected. Type into it and the layer moves. Drag a handle and the numbers
    follow. It is a second way in to the same values the properties panel has
    always had, so Auto Key, undo, the dope sheet and the curve editor all
    behave exactly as they did.

    Fold it away by clicking its title, or turn it off entirely in the View menu.

  - **Local / Parent / World.** These pick which axes the X and Y arrows run
    along:

      Local  — the layer's own axes. A layer rotated 40° travels the way it
               faces.
      Parent — its parent's axes. This is the space the numbers are stored in,
               so dragging X changes the stored X and nothing else.
      World  — the stage's axes, flat across and up. The numbers become
               absolute stage values: where the layer really is, whatever every
               parent above it is doing to it.

  - **A real bug this uncovered.** The X and Y arrows were DRAWN along the
    layer's own axes but the drag was constrained in its parent's space. On any
    rotated layer the arrow pointed one way and the layer went another. Both now
    come from the same place, so the layer travels along the arrow you grabbed —
    in every space.

  - **Shear is shown greyed out, on purpose.** Spine has it; Ottomancer's
    transform is position, rotation and two scales, with no shear component to
    write to. A box that quietly swallowed what you typed would be worse than a
    box that says why it is off.

v0.18.4 — earlier
-----------------
You can key a layer on and off, and it was asked for on the feedback board.

  - **Visible is now an animatable property.** Select any layer — an emitter, an
    image, a folder — and the transform panel has a Visible row next to Position
    and Scale. Key it 1 to show, 0 to hide. It switches, it does not fade: a
    layer is either there on a frame or it is not.

    That means one project can hold several passes of an effect and turn each on
    at its own moment, instead of a separate project per pass. Hiding a folder
    hides everything under it.

    From the board: "id love if i could key switches of assets or particles in
    the hierarchy." Thank you — that is exactly the kind of thing worth asking
    for.

  - **The dope sheet calls rows what the panel calls them.** Rows read "Visible"
    and "Progress" now, not the internal names.

  - Honest limit, stated in the export panel where it matters: PNG sequence, GIF,
    WebP, MP4 and the sprite sheet all carry visibility keys, because they render
    frames. The Spine export does not — the layer bakes as if it were visible
    throughout. Fix planned; until then the warning tells you before you export,
    not after.

v0.18.3 — earlier
-----------------
The graph view has real curve handles now.

  - **Bezier handles on the timeline graph.** Switch the timeline to graph view
    (View menu), select a key, and the segments either side of it show their two
    control points joined by dashed lines — the same way Spine draws them. Drag
    one and the easing changes under your hand.

    The curve dialog got handles two releases ago; the GRAPH did not, and the
    graph is where you actually work. That was the gap.

  - **Double-click adds and removes keys.** In graph view, double-click empty
    track to drop a key exactly where you clicked, or double-click a key to
    remove it. The diamond view keeps what it always did — double-click to type
    an exact value, or double-click between two keys for the easing editor.

  - Handles only appear on segments touching a selected key. Every segment at
    once is an unreadable thicket on a busy sheet.

v0.18.2 — earlier
-----------------
A campfire built the way a fire actually is: four layers, not one.

  - **New scene: Campfire.** Lit ground breathing underneath, a body of flame on
    the sixteen-frame sheet so every particle burns rather than drifts, embers
    leaving the top with trails, and smoke drawn over the lot. Four emitters at
    four speeds, in that draw order.

  - It is there as the standard, not just as another effect. A single emitter
    cannot be a fire, and most of the fire entries in this library still are
    one. This is what the rest are being measured against.

v0.18.1 — earlier
-----------------
The animated fire sheet is redrawn, with sixteen real frames.

  - **"Flame Sheet 4x4" rebuilt.** The old one animated, but every pixel in it
    was at full brightness — a flat silhouette flipping between poses. It was
    the smallest sheet in the library by a wide margin, which is what a flat
    silhouette costs.

    The new one has the shading fire actually has: a white-hot core low down,
    a bright inner flame inside the outer one, orange body, deep red at the tip
    where it thins out. Three travelling waves at different speeds make tongues
    that rise and lick across the sixteen frames.

  - **It loops properly.** Every wobble is built from the frame number, so frame
    sixteen flows back into frame one. Measured: the wrap is a SMALLER step than
    an ordinary frame-to-frame one, so there is no pop once per cycle.

  - Flipbook Fire, Blue Flame and Flamethrower all use it.

v0.18.0 — earlier
-----------------
Eleven more effects, aimed at the things casual games actually need.

  - **117 effects now, up from 106.** The new ones are the beats a game asks for
    over and over and the library had no answer to:

      Damage Spark      the jolt when something takes a hit
      Landing Puff      dust lifting where something lands
      Freeze Crack      ice locking on, shards settling where they stop
      Splash Ring       something hitting water
      Poison Bubbles    fat sickly bubbles rising and bursting
      Electric Shock    current flickering around a point
      Heal Burst        green motes lifting off
      Wind Gust         a gust crossing frame with leaves in it
      Coin Pop          coins bursting up and falling back
      Star Rating Pop   one star landing with a flash
      Combo Flash       a hard radial flash for a crit

  - They are built on the sprites fixed in the last two releases, which is why
    they were worth doing now rather than earlier: a spark effect made of
    two-pixel dots is a spark effect nobody wants.

  - The effects page lists all 117: ottomancer.com/effects

v0.17.5 — earlier
-----------------
Sparks look like sparks, and the site finally lists what is in the box.

  - **"Hard Spark" redrawn.** It was a two-pixel rectangle — a dot pretending to
    be a spark. It is now a streak with a white-hot head and a tail that fades
    out behind it, which is what a spark in flight actually looks like and what
    the effects that align particles to their direction of travel need. It is
    the most-used sprite in the library after the flame, so Sparkler, Forge
    Sparks, Celebration Burst, Rank Up Beam, Fireworks Show and Summoning Circle
    all change with it.

  - **"Splash Shard" redrawn** from a symmetrical diamond into a bent sliver.

  - **A new page listing every effect**: ottomancer.com/effects — all 106 by
    name, in their nine categories, with what each one does, and the 57 sprites
    underneath. It is generated from the library itself, so it cannot drift from
    what the editor actually contains. There is a link to it in the top bar.

v0.17.4 — earlier
-----------------
The fire sprites are redrawn. They look like fire now.

  - **"Flame Body" and "Cartoon Flame" have been redrawn from scratch.** The old
    ones were smooth, symmetrical teardrops — widest at the very bottom, soft
    all the way round. That is a gradient blob, not a flame, and stacking a
    hundred of them gave a fire that read as orange fog.

    The new ones are shaped the way fire actually is: pinched at the root,
    widest low down, tapering to a wisp that leans, with a white-hot core near
    the base and edges bitten away so the outline is ragged rather than round.

  - **Every fire effect improves at once** — Torch Flame, Flamethrower, Ghost
    Fire, Lava Spurts, Cartoon Fire, Fire Tornado, Backdraft Roll, Dragon
    Breath and the Volcano scene all use those two sprites.

  - **Your existing projects improve too.** The sprites kept their names, so
    anything you have already made picks up the new artwork with nothing to
    re-do and nothing to re-link.

v0.17.3 — earlier
-----------------
A security pass, and a quiet mark of where this came from.

  - **Checked, not assumed.** Every place the app writes HTML was traced: there
    is exactly one, and it draws an icon from a fixed set, never anything typed
    by anyone. The feedback board escapes every field it shows. There is no
    eval, no new Function, no document.write and no injected frame anywhere in
    the build. The server side caps the size of a post before reading it, checks
    the type of every field, trims whitespace and cuts each to a maximum length.

  - **Nothing here is "unhackable"** and it would be dishonest to say so. What is
    true: the pages carry a strict content policy with a hash for every script,
    the editor uploads nothing, and the one page that does send anything says so
    on itself.

  - The build carries a small origin mark. It does nothing, it holds no personal
    information, and it exists so a copy of this code can be traced back here if
    it ever appears under someone else's name.

v0.17.2 — earlier
-----------------
A dead copy of a function removed, and a guard so it cannot happen again.

  - Nothing you can see changed. `isAncestor` existed TWICE with two different
    meanings, and the second silently replaced the first for every caller. The
    one that ran is the one that stops a layer being dropped inside itself; the
    dead copy would not have. Reordering the file would have turned that into
    scene corruption with no error anywhere. The dead copy is gone.

  - The build now refuses to publish if any two top-level functions share a
    name. A comment in the code claimed a tool already did this. There was no
    such tool.

v0.17.1 — earlier
-----------------
Shape a path where it lives, and the handles work when paused.

  - **Drag a path's points in the viewport.** Select the path and its points
    appear — green at the start, red at the end. Drag one to reshape the path.
    **Alt-click a point removes it; Alt-click the line adds one there** — the
    same two gestures the curve editor uses. It never drops below two points,
    because one point is not a path.

  - **Fixed: the move/rotate/scale handles were visible but dead while paused.**
    v0.16.2 made them draw whenever playback is paused, but the click handler
    still asked "is this SETUP mode?" before starting a drag — so outside SETUP
    you could see them, hover them, and nothing happened when you pulled. They
    drag now wherever they are drawn.

v0.17.0 — earlier
-----------------
Paths: put a layer on a line and animate it along.

  - **+ Path** adds a path to the scene — a dashed line with a green start and a
    red end. It draws nothing and exports nothing by itself; it is there to be
    followed.

  - **Put a layer on it.** Select the layer, set "Follow path" in the properties
    panel, and a **Progress** row appears: 0 is the start of the path, 1 is the
    end. Key Progress and the layer travels — a rocket arcing, a coin flying to
    a counter, a leaf crossing the screen.

  - Progress is an ordinary keyable property, so the timeline, the dope sheet
    and the curve editor with its new tangent handles all work on a path move
    with nothing new to learn. Ease it out of the start and into the end exactly
    as you would ease anything else.

  - Movement is by **distance, not by point**: a path with one short leg and one
    long one is crossed at a steady speed rather than dawdling on the short one.

  - It comes out the other end as real animation. A layer following an arc
    exports to Spine as ordinary position keys, so any runtime plays it with no
    special support — and the same is true of GIF, MP4, WebM and the rest.

v0.16.5 — earlier
-----------------
Curves can be shaped by hand.

  - **Tangent handles.** Select a key in any curve editor and two blue handles
    appear. Drag one to pull the curve through that key — a slow start, a hard
    snap, a long settle. Both sides move together so the curve stays smooth;
    **hold Shift to bend one side only**, which is how an ease-in differs from
    the ease-out beside it.

  - **Hand-shaped keys keep their shape.** Tangents used to be recalculated
    every time anything moved, so any shape you pulled was wiped the moment you
    nudged a key. Keys you have shaped are marked with a small dot and are left
    alone; everything else still auto-smooths as before.

  - Adding a key (click empty space) and removing one (right-click) worked
    already and are unchanged.

v0.16.4 — earlier
-----------------
A Spine import now arrives with the hierarchy you built, not one flat heap.

  - **The exported bone tree mirrors your scene.** A firework used to land in
    Spine as 2,724 bones hanging directly off root, with nothing to say which
    belonged to the lift-off and which to the burst. It now arrives as the tree
    you made:

        root
          Fireworks Show
            Red
              Comet Red      -> its particles
              Burst Red      -> its particles
              Glitter Red    -> its particles

    Every folder and every emitter becomes a named parent. Volcano Eruption,
    Summoning Circle and the rest all changed the same way.

  - The cause was world-space emitters. Their particles hold absolute positions,
    so they cannot hang off a bone that moves — they were parented to root
    instead, which is correct arithmetic and an unusable tree. The new parents
    are STATIC bones with no transform and no keys, so they are identity: the
    animation is byte-for-byte what it was, only organised.

  - Six new checks keep it that way, including one that fails if an organiser
    bone ever gains a transform or a keyframe.

v0.16.3 — earlier
-----------------
Drag a sprite onto the canvas, and Help stops hiding in a menu.

  - **Drag an image from the list straight onto the canvas** and it is placed
    where you drop it. The canvas lights up while you drag over it. Clicking
    still gives the sprite to the selected emitter and double-clicking still
    drops it in the middle, so nothing you already do has changed. Dragging was
    the obvious thing to try and it used to do nothing at all.

  - **The ? Help button is on the toolbar now**, not inside the More menu. It
    opens 37 keyboard shortcuts and a short guide to how the app works — the
    one thing that explains everything else, and it was behind a menu called
    "More". F1 opens it too.

  - **Ready-made things and empty things are now in separate boxes** under the
    scene. "Effects", "Sprites" and "Animations" hand you finished content;
    "+ Emitter", "+ Folder" and "+ Images" make new empty ones. They were mixed
    together under a single heading, which made a 106-effect library look like
    just another button.

v0.16.2 — earlier
-----------------
The move / rotate / scale handles were always there. Now you can see them.

  - **Transform handles show whenever playback is paused.** Select a layer and
    press Space: a square in the middle to drag it anywhere, an X and a Y arrow
    to slide along one axis, a small square to scale, and the ring around it all
    to rotate. Turn Auto Key on and posing sets a keyframe as you go.

    None of this is new — it has been in the app the whole time. It only ever
    drew in SETUP mode, and the app opens in ANIMATE, so unless you happened to
    press a mode button you never saw a single handle and there was nothing to
    suggest one existed. It still stays hidden while the effect is playing,
    where it would just be clutter over moving particles.

  - The SETUP and ANIMATE buttons now say what they actually give you.

v0.16.1 — earlier
-----------------
Exported loops actually loop.

  - **A baked Spine loop now closes.** If you exported a looping effect and
    found particles cutting short or snapping back at the wrap, that was real
    and it is fixed. Two things were wrong, and both had to go:

    Loop-safe Randomness was off by default, so the simulation never repeated
    at all — measured, the particles one cycle later matched the start in 0
    cases out of 36. An export set to Loop now switches it on for itself while
    baking, warms four cycles, and says so. Your project is left as it was.

    Spine slots were also handed to a new particle as soon as the old one died,
    so a particle arriving one cycle later found its slot taken by a stranger —
    and Spine then interpolated between the two across the loop point. That is
    the snap. A looping bake now keeps each particle's slot for the whole
    animation.

    Measured on four effects: every slot that is on screen at both ends now
    holds exactly the same value at both ends. Portal Vortex was jumping by
    1261 pixels; it is now zero. There is a test so it stays that way.

  - A looping bake uses more slots than before (Fireflies 55 to 64) and the
    .json is usually SMALLER, because a loop only has to cover one cycle.

v0.16.0 — earlier
-----------------
Thirty more effects, and the timeline now tells you where a loop closes.

  - **106 ready-made effects, up from 76.** Thirty new ones across every
    category: Fire Tornado, Dragon Breath, Forge Sparks, Geyser, Ocean
    Spray, Bubble Column, Black Hole, Time Rewind, Soul Ascend, Necrotic
    Miasma, Falling Star Wish, Aurora Veil, Cherry Blossom Drift,
    Hyperspace Jump, Frost Nova, Glass Shatter, Ground Slam Dust, Slash
    Arc, Anime Impact Flash, Incense Curl, Smoke Rings, Locomotive Chuff,
    Backdraft Roll, Ripple Rings, Anger Steam, Dizzy Stars, Coin Magnet,
    Rank Up Beam — plus two multi-emitter scenes, **Volcano Eruption** and
    **Summoning Circle**.

  - **A pin for where the effect repeats.** The ruler already marked each
    emitter's own cycle. With more than one emitter that is not the same
    thing: emitters of 1s and 1.5s only line up again at 3s, and 3s is the
    number you need to cut a PNG sequence or a Spine clip that loops. The
    new teal dashed pin marks it, and says the period in seconds and
    frames. It stays away entirely if any enabled emitter plays once and
    stops, because then the effect never does come back round.

  - **The export dialog says when the first frame will be empty.** On a
    one-shot render nothing has been emitted at time zero, so frame one is
    blank. That was always true and never mentioned.

Under the bonnet, and only worth knowing if something looks wrong: the
export container writers (GIF, zip, animated WebP, MP4) now have their own
tests, and every one of the eight export formats was run end to end and
checked byte by byte. Four of the new effects were built with an inverted
force direction — a "black hole" that was really a fountain — and were
caught by measuring what they produced rather than trusting the settings.

v0.15.1 — earlier
-----------------
Security hardening, an honest privacy note, and one more button.

  - **Reset a module.** Next to the copy arrow on each module header there
    is now a ↺. It puts that one module back exactly as a new emitter
    would have it — and removes its keyframes with it, because defaults
    with old keys still driving them is not "back to how it started", it
    is a third state that never existed. It asks first, and tells you how
    many keyed properties it is about to remove.
  - **Three security headers added**: HSTS (so the first request of a
    session cannot happen in the clear on a hostile network),
    Permissions-Policy (this tool needs no camera, microphone, location or
    payment access, so all of it is now denied outright), and
    Cross-Origin-Opener-Policy.
  - **The feedback board can never be cached by the offline worker.** It
    was not being cached, but only because nothing had happened to put it
    there — and the lookup ignored query strings, which is how one
    visitor eventually gets served another visitor's response. It is now
    excluded explicitly.
  - **The privacy claim now says what actually happens.** The licence said
    the software transmits nothing anywhere — true of the editor, and not
    true of the feedback board, which is a public page you can post to.
    Section 7 now spells out exactly what a post sends, what the server
    keeps to stop one person flooding the board (a one-way salted hash of
    your address, never shown, never reversible), and that posting is
    optional. The feedback page says the same thing in a line.

v0.15 — earlier
---------------
Three things for the person using it, and one for anyone who wants to
script it.

  - **Send one module to another emitter.** Hover any module header in the
    Properties panel and a small → appears. It copies just that module
    — Velocity, or Colour over Lifetime, or whichever — to another emitter,
    or to all of them at once. Duplicating a whole emitter was the only
    way to reuse anything before, which is no help when the two emitters
    differ in every other respect.
    It copies the keyframes in that module too. Copying the numbers alone
    would leave the target's old keys driving your new values: the panel
    would show what you sent and the animation would do something else,
    with nothing to tell you. Anything the target had keyed in that module
    is replaced, not merged.
  - **Importing a flipbook sheet now shows you the slice.** Bring in a
    square sheet and you get a preview with the grid drawn over it, and a
    button for each division that actually fits — 2×2, 4×4,
    8×8. Pick the one that lands between the drawings instead of
    across them, press the button, and Texture Sheet Animation is switched
    on and set up for you, with the sheet moved to the front of the sprite
    list where the tile grid applies.
    Before this you got a sentence in the status bar naming the candidate
    grids, then went looking for the module and typed the numbers in
    yourself, and found out whether you were right by pressing play.
    Importing an ordinary sprite is unchanged — no dialog appears.
  - **A filter for the Properties panel.** There are 112 rows across
    nineteen modules. Type in the box next to "Properties" and only the
    matching ones stay: it looks at each property's name, its unit and its
    description, as well as the module it lives in, so "speed" finds Start
    Speed and Stretch by Speed, and "flip" finds all three flips wherever
    they live. Modules with nothing matching disappear rather than sitting
    there empty. Clearing the box puts the panel back exactly as it was,
    including which modules you had collapsed.
  - **Ottomancer from the command line, and a written-down file format.**
    `node export.mjs project.ottomancer --info` summarises a project;
    `--validate` checks it bakes to a sound Spine skeleton; `--spine`
    writes that skeleton, for 3.8, 4.0, 4.1 or 4.2. `FORMAT.md` documents
    the `.ottomancer` JSON — every module, the four value types, how
    keyframes are stored, and the rules a reader should follow.
    Why bother: the project file is open JSON, so a script can generate
    twenty variations of an effect, retint a whole scene, or check exports
    in a build without the editor being involved. The command loads the
    engine out of the shipped page rather than reimplementing it, so it
    cannot disagree with what you see on screen.
    Honest limit: `--spine` writes the skeleton only. The atlas and its
    page image need pixels packed into a sheet, which needs the browser.
    Use Export > Spine for those.

v0.14.3 — earlier
-----------------
Three things, none of them requested by anybody: a lock on the front
door, a test that runs itself, and an apology to anyone using Spine 4.

  - **Only the scripts in this build can run.** The site now sends a
    policy listing the exact fingerprint of every piece of code it
    contains. Anything else — a script injected into the file, appended to
    it, or slipped in by a compromised tool — is refused by the browser
    before it executes. This project has actually shipped a build with an
    injected script in it once: it uploaded cleanly and left the editor
    dead. That specific thing cannot happen quietly again. The
    fingerprints are regenerated on every build, because a stale one would
    mean a blank page.
    Also blocked by the same policy: loading code from another website,
    and sending your data to one.
  - **The editor is now tested by a command, not by hand.** `tests\engine.mjs`
    runs the real particle simulation and checks 28 things: emitter scale,
    Flip U and V and their independence, all three alignment modes, that
    rotation still works under one and is suppressed under another, curve
    tangents, save-and-reload including projects saved before these
    features existed, and all 76 shipped effects building, emitting and
    staying numerically sane. Publishing runs it and refuses to upload if
    anything fails.
  - **Spine 4 users were being sent the long way round.** The export has
    been able to write 3.8, 4.0, 4.1 and 4.2 for a while — it changes the
    format, not just the label — but the /spine page still said you had to
    import with 3.8 and described a detour through an old install. That
    page now says what the software actually does. The genuine caveat is
    stated plainly instead: the output is verified against the format on
    every build, but nobody has yet opened it in a running Spine editor.
  - Offline mode was missing three files it should have been keeping,
    including the one that makes the Back link work. Generated from the
    file list now, so it cannot fall behind again.

v0.14.2 — earlier
-----------------
Findings from an audit of the whole thing, not from the to-do list.

  - The feedback board could look four hours out of date. Post a bug
    report, reload, and it might not be there — and neither would anyone
    else's. The board is cached for half a minute so that heavy traffic
    cannot exhaust the database, which is right, but Cloudflare was
    writing its own four-hour figure into the instruction sent to your
    browser. The half-minute cache stays; your browser is now told, every
    time, not to keep a copy.
  - The sitemap named a namespace that does not exist — sitemap.org
    instead of sitemaps.org. Nothing on the site showed it, and it is the
    file a search engine is handed first.
  - The /api/ responses were missing two security headers that every page
    on the site already had, because the file that sets them only applies
    to pages.
  - A dialog whose cleanup step failed used to fail in complete silence,
    which left window listeners attached and showed up later as a control
    that responded twice. It still cannot trap you in a dialog, but it now
    says what happened.

Also checked and found correct, so nobody has to wonder again: the
advertised counts (75 effects, 57 sprites, nine categories) are exact;
every page, asset and internal link resolves; the database is empty of
test rows; the rate limit, the honeypot and the input validation all
behave; and an exported web bundle now carries the corrected player.

v0.14.1 — earlier
-----------------
New: Alignment "birth", and an explanation of the one next to it.

  - Renderer > Alignment has a third option. "birth" points the sprite the
    way the particle launched, once, and then lets it rotate normally from
    there. That is what debris wants: it leaves the blast pointing outward
    and then tumbles. "velocity" re-aims it every single frame, which is
    what a streak or a raindrop wants.
  - The existing "velocity" option had a trap worth naming: because it
    re-aims every frame, it overwrites rotation entirely, so setting an
    angular velocity alongside it silently does nothing. It still behaves
    exactly as it always did — but the control now says so, and "birth" is
    the option for people who wanted both.

v0.14 — earlier
---------------
New: Flip U and Flip V.

  - Two new controls in the Main module, under Flip Rotation. Each is the
    fraction of particles to mirror: Flip U left-to-right, Flip V
    top-to-bottom, decided independently per particle.
    This is the cheapest variety there is. One asymmetric sprite — a leaf,
    a shard, a splash, a scrap of debris — becomes two or four without
    drawing anything new, and a spray of them stops looking like the same
    stamp repeated.
  - Works everywhere the particle does: the viewport, PNG sequences, MP4,
    WebM, GIF, WebP, the Spine export, and an exported web bundle. Checked
    in each rather than assumed, because a mirror that appears in the
    editor and not in your engine is worse than no mirror at all.
  - Nothing you have already made changes. Both default to 0, and the
    feature deliberately does not draw from the per-particle random
    sequence — doing so would have reshuffled every existing effect while
    changing nothing about what any of them does.

v0.13.3 — earlier
-----------------
Exported web bundles now match the editor.

  - A web bundle played a scaled world-space emitter at the wrong
    particle size. The fix that made emitter scale affect particle size
    went into the editor in v0.12.3; the little runtime that ships inside
    an exported bundle never got it. So the same project drew one picture
    in the editor and another in the bundle you handed someone: particles
    spread out and moving correctly, each one the wrong size. Scale 2 drew
    them at 1, scale 0.5 drew them at 1.
    Only world simulation space was affected, and only at a scale other
    than 1 — which is everything unless you changed it.
  - Checked the rest of that runtime the same way rather than waiting to
    trip over the next one: of the 125 functions it shares with the
    editor, this was the only one that had fallen behind. The pre-flight
    check now compares all 125 before any release, so a bundle that would
    not match the editor cannot be published again.

v0.13.2 — earlier
-----------------
Autosave stops re-copying your images.

  - A project's pictures used to be written into every autosave and every
    recovery snapshot. On a 2048x2048 sheet of the kind that does not
    compress, that is 21.35 MB written each time — and 99.9% of it was the
    one image. The settings, meaning every emitter, curve, gradient, key
    and animation you have made, come to 22.6 KB.
    Images are now stored once, on their own, and rewritten only when you
    actually add or remove one. An autosave went from about 75
    milliseconds of frozen editor to under half a millisecond; the
    snapshot went from 21.35 MB to 12 KB.
  - Which means the recovery history works on real projects. Its 3.5 MB
    allowance used to be swallowed by duplicate copies of the same
    picture, so a project with one large sheet in it kept no recovery
    points at all. It now keeps the last twelve.
  - Your .ottomancer files are unchanged and still carry their own art —
    a project file that needed this browser's storage to open would not
    be a file you could send anyone. Projects saved by older versions
    still open exactly as before, and an autosave left by an older version
    is still restored with its images.

v0.13.1 — earlier
-----------------
Buttons that looked normal and did nothing. Every one of these was a
control you could see, point at, click, and get no response from — which
is the most annoying kind of bug there is, because it looks like you did
it wrong. Checked at 800x600, 911x512, 1024x768, 1093x614, 1280x720,
1366x768 and 1920x1080, which covers the common laptop sizes and the
browser zoom levels people actually use: zero unreachable controls left.

  - The "View" menu on the timeline was almost empty and is now full.
    Onion skin and its frame count, the graph reading, Curves…, Guides
    and A/B were all supposed to live in it. They were being built a
    moment after the menu was assembled, so the menu quietly took the one
    button that existed yet and left the other six crowding the timeline
    bar — which is why that bar was nearly three times wider than the
    space it had.
  - The "More" and "View" menus open properly. Their entries could not
    be clicked at all below 1200px wide: the menus drop below their
    button, and the bar had been told to scroll sideways, which silently
    clips anything hanging outside it. Both bars wrap to a second row
    instead, as they were originally written to.
  - The "View" menu now opens upward when it is near the bottom of the
    window, instead of running its last entry off the bottom edge.
  - Controls at the bottom of the properties panel are clickable again.
    The floating "Buy me a coffee" pill was pinned to the bottom-right
    corner on top of everything else, and the editor fills the whole
    window — so it sat over whichever controls happened to be there. It
    is gone; the support button on the top bar was always the more
    visible of the two anyway.
  - The support button no longer falls off the right-hand edge on a narrow
    window. Below 1200px the two right-hand labels shorten to
    "Support" and "Bugs" — the full wording is still in the tooltip.
  - Below 950px, where the properties panel folds away to make room, the
    editor now says so and tells you how to get it back. There has been a
    line of styling waiting to show that message since the narrow layout
    was written; the message itself had never been added.
  - The timeline bar fits its controls on two rows rather than three on a
    narrow window, which gives the dope sheet back 30 of its 210 pixels.

v0.13 — earlier the same day
----------------------------
Everything below from 0.12.1 to 0.12.3 shipped on the same day and was
never released separately, so it is all collected here as 0.13. The
detailed entries are kept because they say what actually changed.

It earns a version of its own rather than another patch number for one
reason: **effects that use a scaled emitter in world simulation space
now draw differently**, because their particles finally scale with the
emitter. That is a change you can see in work you already saved, and a
version number that claimed nothing had changed would be lying to you.

Alongside that, three ways of losing work were closed:
  - a dragged loop region made a project impossible to save at all;
  - autosave could stop and never say so;
  - and the recovery snapshot re-serialised the whole project on every
    edit once storage filled, which is what made large projects freeze.

Also new: a "Bugs & ideas" button on the top bar, a warning that appears
if autosave ever stops, and the editor tab finally has an icon.

v0.12.3 — fixes
---------------
  - Scaling an emitter now scales its particles too when the emitter is
    set to world simulation space. It already worked in local space, so
    the same emitter at the same scale drew two different pictures
    depending on that dropdown: in world space the particles spread out
    and moved faster but each one stayed its original size.
    If you have a saved project with a world-space emitter scaled to
    anything other than 1, it will look different — larger or smaller,
    and correct. Projects at scale 1, which is everything unless you
    changed it, are untouched.

v0.12.2 — fixes
---------------
  - Dragging the loop region no longer makes a project impossible to save.
    Opening a file overwrote the loop region with the full animation
    length, so a project whose loop had been dragged never read back as
    itself — and the save check, correctly, refused to write a file that
    would not reload. Two bugs in one: the loop region is now kept as you
    set it and survives saving and reopening.
  - The "More" menu on the top bar sat to the right of the support
    button and got pushed off the edge, showing as a stray fragment of its
    own label. It now sits with the buttons it holds.
  - A "Bugs & ideas" link now sits on the top bar next to the
    support button. A clear bug report is worth more than a coffee, and it
    was two clicks further away than the donate button.

v0.12.1 — fixes
---------------
  - MP4 export works again at 1080p and above. It had been asking the
    browser for an H.264 level that cannot encode anything larger than
    720p, so a normal 1920x1080 export was refused and reported as
    "H.264 not available" on machines that encode H.264 perfectly well.
    The exporter now picks a profile that fits the size you asked for.
  - Texture sheet animation no longer slices sprites that are not
    sheets. The tile grid was being applied to every sprite in an
    emitter, so an ordinary sprite sharing an emitter with a flipbook
    was drawn at a sixteenth of itself. The grid now describes the
    first sprite only. This also affected the Spine export and the
    exported web player, and is fixed in all of them.
    (Visible in the shipped Flamethrower effect, whose Heat Puff was
    being quartered.)

v0.12 — first public release
----------------------------
A little history: this software was originally developed under the name
"Ottopia Particles" before becoming Ottomancer for its public debut.
The editor:
  - professional dope-sheet timeline: dope sheet, frame ruler over the key lane,
    transport cluster, loop region you can drag, animation variants with
    their own menu, and a curve editor in its own window.
  - Properties panel rows now wrap instead of pushing buttons out of
    reach; every label stays inside its button; small controls got
    proper click sizes.
  - flat professional dark look: flat panels, orange accent, matching light
    theme.

The library:
  - 118 ready-made effects in nine categories — including animated
    flipbook effects (Toon Explosion, Flipbook Fire, Electric Zap),
    seamless loop overlays for games (Win Rays, Pulse Glow, Shine
    Sweep, Big Win, Idle Shimmer), Matrix Code Rain, a Comet, Cartoon
    Fire, and many variants.
  - 57 built-in sprites, with animated 4x4 sheets drawn frame by frame.
  - Every effect is an ordinary emitter after you apply it — recolor,
    resize, pull apart, make it yours.

Around the app:
  - Exports, all verified from disk by the test pipeline: Spine-compatible
    JSON + atlas + PNG (engine-ready), PNG sequence, WebM and MP4 video,
    animated WebP and GIF, SVG (transforms; warns rather than writing an
    empty file), and a compact web bundle with its own player.
  - A website version: same editor, nothing installed, works offline
    after the first visit, installable as an app.
  - A license in plain language: free for everyone, everything you make
    is yours to sell; just don't sell or repackage the tool itself.
  - Version number in the title bar, so reports can say which build.

Known rough edges:
  - This is a one-person, free-time project. Things will be imperfect;
    reports are welcome and read. Thank you for your patience.