{
 "version": 1,
 "easing": {
  "out": "cubic-bezier(.2,.8,.2,1)",
  "in": "cubic-bezier(.6,0,.9,.4)",
  "inOut": "cubic-bezier(.7,0,.2,1)"
 },
 "presets": [
  {
   "id": "T01",
   "kind": "text",
   "name": "Blur rise",
   "group": "Reveal",
   "use": "House default for narration lines. Words arrive grey and settle to ink.",
   "avoid": "Very long paragraphs: switch to line reveal.",
   "split": "word",
   "stagger": 0.13,
   "animation": "m-blurRise .75s cubic-bezier(.2,.75,.2,1) both",
   "keyframes": "@keyframes m-blurRise{0%{opacity:0;filter:blur(12px);transform:translateY(26px);color:var(--mute)}45%{opacity:1;filter:none;transform:none;color:var(--mute)}100%{opacity:1;color:var(--ink)}}",
   "preview": "index.html#m/T01"
  },
  {
   "id": "T02",
   "kind": "text",
   "name": "Fade up",
   "group": "Reveal",
   "use": "Calm, neutral captions and sub-lines.",
   "avoid": "Hooks: too quiet to stop the scroll.",
   "split": "word",
   "stagger": 0.08,
   "animation": "m-fadeUp .6s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-fadeUp{from{opacity:0;transform:translateY(40px)}to{opacity:1;transform:none}}",
   "preview": "index.html#m/T02"
  },
  {
   "id": "T03",
   "kind": "text",
   "name": "Character cascade",
   "group": "Reveal",
   "use": "Short product names and one-word titles.",
   "avoid": "Lines over ~20 characters: it drags.",
   "split": "char",
   "stagger": 0.03,
   "animation": "m-charUp .5s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-charUp{from{opacity:0;transform:translateY(.6em) rotate(8deg)}to{opacity:1;transform:none}}",
   "preview": "index.html#m/T03"
  },
  {
   "id": "T04",
   "kind": "text",
   "name": "Typewriter",
   "group": "Reveal",
   "use": "Prompts, search boxes, AI input, code.",
   "avoid": "Emotional hooks.",
   "split": "char",
   "stagger": 0.055,
   "animation": "m-type .01s steps(1) both",
   "keyframes": "@keyframes m-type{from{opacity:0}to{opacity:1}}",
   "preview": "index.html#m/T04"
  },
  {
   "id": "T05",
   "kind": "text",
   "name": "Decode scramble",
   "group": "Reveal",
   "use": "Dev, security, AI and data topics.",
   "avoid": "Friendly consumer tone.",
   "split": "scramble",
   "animation": "script",
   "keyframes": "/* JS: every frame, reveal N = progress * length characters; fill the rest with random glyphs from A-Z0-9#%&. 1.4s linear. */",
   "preview": "index.html#m/T05"
  },
  {
   "id": "T06",
   "kind": "text",
   "name": "Line mask reveal",
   "group": "Reveal",
   "use": "Premium, editorial titles. Works for long lines.",
   "avoid": "Tiny text: the motion is invisible.",
   "split": "line",
   "stagger": 0.15,
   "animation": "m-maskUp .8s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-maskUp{from{transform:translateY(105%)}to{transform:none}}\n/* wrapper per line: overflow:hidden */",
   "preview": "index.html#m/T06"
  },
  {
   "id": "T07",
   "kind": "text",
   "name": "Line split sides",
   "group": "Reveal",
   "use": "Two-line contrasts: \"Less busywork / more building\".",
   "avoid": "Single lines.",
   "split": "line",
   "stagger": 0.12,
   "animation": "m-fromL .8s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-fromL{from{opacity:0;transform:translateX(-160px)}to{opacity:1;transform:none}}\n@keyframes m-fromR{from{opacity:0;transform:translateX(160px)}to{opacity:1;transform:none}}",
   "preview": "index.html#m/T07"
  },
  {
   "id": "T08",
   "kind": "text",
   "name": "Flip up 3D",
   "group": "Reveal",
   "use": "Energetic lists and feature names.",
   "avoid": "Serious finance or security claims.",
   "split": "word",
   "stagger": 0.1,
   "animation": "m-flipUp .7s cubic-bezier(.2,.8,.2,1) both",
   "transformOrigin": "50% 100%",
   "keyframes": "@keyframes m-flipUp{from{opacity:0;transform:perspective(600px) rotateX(-90deg)}to{opacity:1;transform:perspective(600px) rotateX(0)}}",
   "preview": "index.html#m/T08"
  },
  {
   "id": "T09",
   "kind": "text",
   "name": "Skew slide",
   "group": "Reveal",
   "use": "Speed claims: \"faster\", \"instant\".",
   "avoid": "Calm explainer passages.",
   "split": "word",
   "stagger": 0.08,
   "animation": "m-skew .6s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-skew{from{opacity:0;transform:translateX(-60px) skewX(20deg)}to{opacity:1;transform:none}}",
   "preview": "index.html#m/T09"
  },
  {
   "id": "T10",
   "kind": "text",
   "name": "Depth rise",
   "group": "Reveal",
   "use": "Reveals that should feel like they come toward the viewer.",
   "avoid": "Stacked small text.",
   "split": "word",
   "stagger": 0.1,
   "animation": "m-depth .8s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-depth{from{opacity:0;transform:perspective(800px) translateZ(-600px)}to{opacity:1;transform:perspective(800px) translateZ(0)}}",
   "preview": "index.html#m/T10"
  },
  {
   "id": "T11",
   "kind": "text",
   "name": "Letters converge",
   "group": "Reveal",
   "use": "\"Everything in one place\" moments.",
   "avoid": "Long sentences.",
   "split": "char",
   "stagger": 0.02,
   "animation": "m-conv .9s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-conv{from{opacity:0;transform:translate(var(--x),var(--y)) rotate(var(--r))}to{opacity:1;transform:none}}\n/* each char gets random --x --y (+-300px) and --r (+-90deg) */",
   "preview": "index.html#m/T11"
  },
  {
   "id": "T12",
   "kind": "text",
   "name": "Focus pull",
   "group": "Reveal",
   "use": "Cinematic openers and quotes.",
   "avoid": "Fast-cut shorts: too slow.",
   "split": "whole",
   "animation": "m-focus 1.2s ease both",
   "keyframes": "@keyframes m-focus{from{opacity:0;filter:blur(24px);transform:scale(1.08)}to{opacity:1;filter:none;transform:none}}",
   "preview": "index.html#m/T12"
  },
  {
   "id": "T13",
   "kind": "text",
   "name": "Tracking in",
   "group": "Reveal",
   "use": "Brand names, launch titles, chapter cards.",
   "avoid": "Sentences.",
   "split": "whole",
   "animation": "m-track 1.1s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-track{from{opacity:0;letter-spacing:.6em;filter:blur(6px)}to{opacity:1;letter-spacing:-.02em;filter:none}}",
   "preview": "index.html#m/T13"
  },
  {
   "id": "T14",
   "kind": "text",
   "name": "Outline to fill",
   "group": "Reveal",
   "use": "Poster-style hero words, xl sizes only.",
   "avoid": "Body copy.",
   "split": "whole",
   "animation": "m-fill 1.4s ease both",
   "keyframes": "@keyframes m-fill{0%{opacity:0;color:transparent}30%{opacity:1;color:transparent}100%{opacity:1;color:var(--ink)}}\n/* element: -webkit-text-stroke: 3px var(--ink) */",
   "preview": "index.html#m/T14"
  },
  {
   "id": "T15",
   "kind": "text",
   "name": "Block reveal",
   "group": "Reveal",
   "use": "Agency-style title cards and chapter breaks.",
   "avoid": "More than 3 lines.",
   "split": "block",
   "stagger": 0.25,
   "animation": "m-box 1s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-box{0%{transform:scaleX(0);transform-origin:0 50%}50%{transform:scaleX(1);transform-origin:0 50%}51%{transform-origin:100% 50%}100%{transform:scaleX(0);transform-origin:100% 50%}}\n@keyframes m-boxText{0%,49%{opacity:0}50%,100%{opacity:1}}\n/* ::after is the accent block (m-box); text uses m-boxText */",
   "preview": "index.html#m/T15"
  },
  {
   "id": "T16",
   "kind": "text",
   "name": "Pop overshoot",
   "group": "Kinetic",
   "use": "Playful, upbeat lines.",
   "avoid": "Enterprise tone.",
   "split": "word",
   "stagger": 0.1,
   "animation": "m-pop .5s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-pop{0%{opacity:0;transform:scale(.3)}60%{opacity:1;transform:scale(1.15)}100%{opacity:1;transform:none}}",
   "preview": "index.html#m/T16"
  },
  {
   "id": "T17",
   "kind": "text",
   "name": "Slam",
   "group": "Kinetic",
   "use": "The one number or claim of the video.",
   "avoid": "Using it twice in one short.",
   "split": "whole",
   "animation": "m-slam .6s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-slam{0%{opacity:0;transform:scale(3);filter:blur(10px)}60%{opacity:1;transform:scale(.94);filter:none}100%{opacity:1;transform:none}}",
   "preview": "index.html#m/T17"
  },
  {
   "id": "T18",
   "kind": "text",
   "name": "Drop bounce",
   "group": "Kinetic",
   "use": "Lists of short items, fun reveals.",
   "avoid": "Serious claims.",
   "split": "word",
   "stagger": 0.1,
   "animation": "m-drop .7s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-drop{0%{opacity:0;transform:translateY(-120px)}60%{opacity:1;transform:translateY(12px)}80%{transform:translateY(-4px)}100%{opacity:1;transform:none}}",
   "preview": "index.html#m/T18"
  },
  {
   "id": "T19",
   "kind": "text",
   "name": "Stacked words",
   "group": "Kinetic",
   "use": "Rhythm lines read like a beat.",
   "avoid": "More than 6 words.",
   "split": "stack",
   "stagger": 0.28,
   "animation": "m-pop .5s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-pop{0%{opacity:0;transform:scale(.3)}60%{opacity:1;transform:scale(1.15)}100%{opacity:1;transform:none}}\n/* one word per line, sizes alternate m / xl */",
   "preview": "index.html#m/T19"
  },
  {
   "id": "T20",
   "kind": "text",
   "name": "Wave",
   "group": "Kinetic",
   "use": "Loading, waiting, \"thinking\" states.",
   "avoid": "Anything that needs to be read calmly.",
   "split": "char",
   "stagger": 0.05,
   "animation": "m-wave 1.2s ease-in-out infinite both",
   "keyframes": "@keyframes m-wave{0%,100%{transform:none}50%{transform:translateY(-.25em)}}",
   "preview": "index.html#m/T20"
  },
  {
   "id": "T21",
   "kind": "text",
   "name": "Vertical word swap",
   "group": "Kinetic",
   "use": "One product, many audiences or use cases.",
   "avoid": "More than 5 words in the cycle.",
   "split": "swap",
   "animation": "m-swap3 4s cubic-bezier(.7,0,.2,1) infinite",
   "keyframes": "@keyframes m-swap3{0%,25%{transform:translateY(0)}33%,58%{transform:translateY(-100%)}66%,91%{transform:translateY(-200%)}100%{transform:translateY(-300%)}}\n/* column of words + first word repeated; parent height 1.15em, overflow hidden */",
   "preview": "index.html#m/T21"
  },
  {
   "id": "T22",
   "kind": "text",
   "name": "Number roll",
   "group": "Kinetic",
   "use": "Big metrics: revenue, users, hours saved.",
   "avoid": "Numbers with more than 7 digits.",
   "split": "roll",
   "animation": "m-roll 1.6s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-roll{from{transform:translateY(0)}to{transform:translateY(var(--y))}}\n/* each digit is a 0-9 column; --y = -digit * 10% (plus 1 extra spin) */",
   "preview": "index.html#m/T22"
  },
  {
   "id": "T23",
   "kind": "text",
   "name": "Marker highlight",
   "group": "Emphasis",
   "use": "Pull one phrase out of a sentence.",
   "avoid": "Highlighting more than one phrase per line.",
   "split": "word",
   "stagger": 0.1,
   "animation": "m-fadeUp .6s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-fadeUp{from{opacity:0;transform:translateY(40px)}to{opacity:1;transform:none}}\n@keyframes m-mark{from{background-size:0% 42%}to{background-size:100% 42%}}\n/* emphasis: background:linear-gradient(var(--ac2),var(--ac2)) no-repeat 0 88% */",
   "preview": "index.html#m/T23"
  },
  {
   "id": "T24",
   "kind": "text",
   "name": "Underline draw",
   "group": "Emphasis",
   "use": "Correcting a belief: \"the right way\".",
   "avoid": "Stacking with highlight.",
   "split": "word",
   "stagger": 0.1,
   "animation": "m-fadeUp .6s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-fadeUp{from{opacity:0;transform:translateY(40px)}to{opacity:1;transform:none}}\n@keyframes m-grow{from{transform:scaleX(0)}to{transform:scaleX(1)}}\n/* emphasis ::after: 0.1em accent bar, transform-origin left, delay +0.4s */",
   "preview": "index.html#m/T24"
  },
  {
   "id": "T25",
   "kind": "text",
   "name": "Strike and replace",
   "group": "Emphasis",
   "use": "Before/after claims and price drops.",
   "avoid": "When the old value is not obvious.",
   "split": "strike",
   "animation": "m-fadeUp .6s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-fadeUp{from{opacity:0;transform:translateY(40px)}to{opacity:1;transform:none}}\n@keyframes m-grow{from{transform:scaleX(0)}to{transform:scaleX(1)}}\n@keyframes m-pop{0%{opacity:0;transform:scale(.3)}60%{opacity:1;transform:scale(1.15)}100%{opacity:1;transform:none}}\n/* old word ::after red bar grows; new word pops after */",
   "preview": "index.html#m/T25"
  },
  {
   "id": "T26",
   "kind": "text",
   "name": "Emphasis shake",
   "group": "Emphasis",
   "use": "Pain points, warnings, errors.",
   "avoid": "Positive news.",
   "split": "word",
   "stagger": 0.1,
   "animation": "m-fadeUp .6s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-fadeUp{from{opacity:0;transform:translateY(40px)}to{opacity:1;transform:none}}\n@keyframes m-shake{0%,100%{transform:none}20%{transform:translateX(-10px) rotate(-2deg)}40%{transform:translateX(10px) rotate(2deg)}60%{transform:translateX(-6px)}80%{transform:translateX(6px)}}",
   "preview": "index.html#m/T26"
  },
  {
   "id": "T27",
   "kind": "text",
   "name": "Grey to ink settle",
   "group": "Emphasis",
   "use": "Subtle build on text-only scenes, no movement.",
   "avoid": "Busy scenes where nothing else moves slowly.",
   "split": "word",
   "stagger": 0.12,
   "animation": "m-settle .9s ease both",
   "keyframes": "@keyframes m-settle{0%{opacity:0;color:var(--line)}30%{opacity:1;color:var(--mute)}100%{opacity:1;color:var(--ink)}}",
   "preview": "index.html#m/T27"
  },
  {
   "id": "T28",
   "kind": "text",
   "name": "Glitch in",
   "group": "Emphasis",
   "use": "Bugs, outages, hacks, \"broken\" moments.",
   "avoid": "Happy endings.",
   "split": "whole",
   "animation": "m-glitch .8s linear both",
   "keyframes": "@keyframes m-glitch{0%{opacity:0}10%{opacity:1;clip-path:inset(40% 0 30% 0);transform:translateX(-12px)}20%{clip-path:inset(10% 0 60% 0);transform:translateX(10px)}30%{clip-path:inset(70% 0 5% 0);transform:translateX(-6px)}40%,100%{opacity:1;clip-path:inset(0);transform:none}}",
   "preview": "index.html#m/T28"
  },
  {
   "id": "T29",
   "kind": "text",
   "name": "Inline icon pop",
   "group": "Emphasis",
   "use": "Replace a noun with its icon: \"connect [Stripe] in one click\".",
   "avoid": "More than one icon per line.",
   "split": "icon",
   "stagger": 0.12,
   "animation": "m-fadeUp .6s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-fadeUp{from{opacity:0;transform:translateY(40px)}to{opacity:1;transform:none}}\n@keyframes m-pop{0%{opacity:0;transform:scale(.3)}60%{opacity:1;transform:scale(1.15)}100%{opacity:1;transform:none}}\n/* icon chip (accent square + Lucide icon) placed inline, pops in its word slot */",
   "preview": "index.html#m/T29"
  },
  {
   "id": "T30",
   "kind": "text",
   "name": "Karaoke fill",
   "group": "Captions",
   "use": "Voice-over captions synced to speech.",
   "avoid": "No voice-over.",
   "split": "word",
   "stagger": 0.32,
   "animation": "m-kara .25s ease both",
   "keyframes": "@keyframes m-kara{from{color:var(--line)}to{color:var(--ink)}}\n/* all words visible in light grey; each fills at its spoken timestamp */",
   "preview": "index.html#m/T30"
  },
  {
   "id": "T31",
   "kind": "text",
   "name": "Caption box",
   "group": "Captions",
   "use": "Talking-head shorts, subtitle track.",
   "avoid": "Scenes that already have heavy text.",
   "split": "word",
   "stagger": 0.38,
   "animation": "m-cap .38s steps(1) both",
   "keyframes": "@keyframes m-cap{0%{background:transparent;color:var(--ink)}1%,99%{background:var(--ac);color:#fff}100%{background:transparent;color:var(--ink)}}\n/* each word is active (accent box) for exactly one stagger interval */",
   "preview": "index.html#m/T31"
  },
  {
   "id": "T32",
   "kind": "text",
   "name": "Split horizon",
   "group": "Kinetic",
   "use": "\"Two things join\" moments, integrations.",
   "avoid": "Multi-line text.",
   "split": "horizon",
   "animation": "m-fromL .9s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-fromL{from{opacity:0;transform:translateX(-160px)}to{opacity:1;transform:none}}\n@keyframes m-fromR{from{opacity:0;transform:translateX(160px)}to{opacity:1;transform:none}}\n/* two copies of the text: top half clip-path inset(0 0 50% 0) from left, bottom half inset(50% 0 0 0) from right */",
   "preview": "index.html#m/T32"
  },
  {
   "id": "T33",
   "kind": "text",
   "name": "Blur out",
   "group": "Exit",
   "use": "Default text exit before a new line.",
   "avoid": "Hard cuts to a new scene (just cut).",
   "split": "word",
   "stagger": 0.06,
   "animation": "m-blurOut .5s ease-in both",
   "keyframes": "@keyframes m-blurOut{to{opacity:0;filter:blur(12px);transform:translateY(-20px)}}",
   "preview": "index.html#m/T33"
  },
  {
   "id": "T34",
   "kind": "text",
   "name": "Mask out",
   "group": "Exit",
   "use": "Pair with Line mask reveal.",
   "avoid": "Mixed with blur styles in the same scene.",
   "split": "line",
   "stagger": 0.1,
   "animation": "m-maskOut .6s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-maskOut{to{transform:translateY(-105%)}}\n/* wrapper per line: overflow:hidden */",
   "preview": "index.html#m/T34"
  },
  {
   "id": "X01",
   "kind": "trans",
   "name": "Blur dissolve",
   "group": "Dissolve",
   "use": "House default between scenes of the same topic.",
   "avoid": "Topic changes: use a stronger move.",
   "sceneA": "m-xBlurOut .5s ease-in both",
   "sceneB": "m-xBlurIn .6s ease-out both",
   "sceneBDelay": 0.35,
   "keyframes": "@keyframes m-xBlurOut{to{opacity:0;filter:blur(24px)}}\n@keyframes m-xBlurIn{from{opacity:0;filter:blur(24px)}to{opacity:1;filter:none}}",
   "preview": "index.html#m/X01"
  },
  {
   "id": "X02",
   "kind": "trans",
   "name": "Crossfade",
   "group": "Dissolve",
   "use": "Calm long-form, testimonials.",
   "avoid": "Shorts hooks.",
   "sceneA": "m-xFadeOut .6s ease both",
   "sceneB": "m-xFadeIn .6s ease both",
   "keyframes": "@keyframes m-xFadeOut{to{opacity:0}}\n@keyframes m-xFadeIn{from{opacity:0}to{opacity:1}}",
   "preview": "index.html#m/X02"
  },
  {
   "id": "X03",
   "kind": "trans",
   "name": "Dip to colour",
   "group": "Dissolve",
   "use": "Chapter changes, brand moments.",
   "avoid": "Back-to-back use.",
   "sceneB": "m-xAppear 1s linear both",
   "overlay": "dip",
   "keyframes": "@keyframes m-xDip{0%{opacity:0}45%,55%{opacity:1}100%{opacity:0}}\n@keyframes m-xAppear{0%,49%{opacity:0}50%,100%{opacity:1}}\n/* overlay: full-stage accent panel, 1s ease-in-out */",
   "preview": "index.html#m/X03"
  },
  {
   "id": "X04",
   "kind": "trans",
   "name": "Push left",
   "group": "Move",
   "use": "Next step in a sequence, carousels.",
   "avoid": "Going back in time (use push right).",
   "sceneA": "m-xOutL .7s cubic-bezier(.7,0,.2,1) both",
   "sceneB": "m-xInR .7s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-xOutL{to{transform:translateX(-100%)}}\n@keyframes m-xInR{from{transform:translateX(100%)}to{transform:none}}",
   "preview": "index.html#m/X04"
  },
  {
   "id": "X05",
   "kind": "trans",
   "name": "Push up",
   "group": "Move",
   "use": "Feed-like shorts, \"next\" beats.",
   "avoid": "Landscape long form (feels like scrolling).",
   "sceneA": "m-xOutU .7s cubic-bezier(.7,0,.2,1) both",
   "sceneB": "m-xInD .7s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-xOutU{to{transform:translateY(-100%)}}\n@keyframes m-xInD{from{transform:translateY(100%)}to{transform:none}}",
   "preview": "index.html#m/X05"
  },
  {
   "id": "X06",
   "kind": "trans",
   "name": "Slide over",
   "group": "Move",
   "use": "Drilling into detail.",
   "avoid": "Returning to overview.",
   "sceneA": "m-xRecede .8s cubic-bezier(.7,0,.2,1) both",
   "sceneB": "m-xInR .8s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-xRecede{to{transform:scale(.9);filter:brightness(.6)}}\n@keyframes m-xInR{from{transform:translateX(100%)}to{transform:none}}",
   "preview": "index.html#m/X06"
  },
  {
   "id": "X07",
   "kind": "trans",
   "name": "Whip pan",
   "group": "Move",
   "use": "High-energy cuts, \"meanwhile\" moments.",
   "avoid": "Calm explainers.",
   "sceneA": "m-xWhipOut .35s ease-in both",
   "sceneB": "m-xWhipIn .45s ease-out both",
   "sceneBDelay": 0.3,
   "keyframes": "@keyframes m-xWhipOut{to{transform:translateX(-60%);filter:blur(30px);opacity:0}}\n@keyframes m-xWhipIn{from{transform:translateX(60%);filter:blur(30px);opacity:0}to{transform:none;filter:none;opacity:1}}",
   "preview": "index.html#m/X07"
  },
  {
   "id": "X08",
   "kind": "trans",
   "name": "Zoom through",
   "group": "Scale",
   "use": "Going deeper: \"let us look inside\".",
   "avoid": "Every cut: it tires fast.",
   "sceneA": "m-xZoomOut .6s ease-in both",
   "sceneB": "m-xZoomIn .7s cubic-bezier(.2,.8,.2,1) both",
   "sceneBDelay": 0.3,
   "keyframes": "@keyframes m-xZoomOut{to{transform:scale(2.5);opacity:0;filter:blur(10px)}}\n@keyframes m-xZoomIn{from{transform:scale(.6);opacity:0}to{transform:none;opacity:1}}",
   "preview": "index.html#m/X08"
  },
  {
   "id": "X09",
   "kind": "trans",
   "name": "Zoom out reveal",
   "group": "Scale",
   "use": "Big-picture moments: \"and that is just one team\".",
   "avoid": "Detail scenes.",
   "sceneA": "m-xShrink .6s ease-in both",
   "sceneB": "m-xSettle .7s cubic-bezier(.2,.8,.2,1) both",
   "sceneBDelay": 0.25,
   "keyframes": "@keyframes m-xShrink{to{transform:scale(.3);opacity:0}}\n@keyframes m-xSettle{from{transform:scale(1.2);opacity:0}to{transform:none;opacity:1}}",
   "preview": "index.html#m/X09"
  },
  {
   "id": "X10",
   "kind": "trans",
   "name": "Spin zoom",
   "group": "Scale",
   "use": "Playful brands, \"plot twist\".",
   "avoid": "B2B enterprise.",
   "sceneA": "m-xSpinOut .6s ease-in both",
   "sceneB": "m-xSpinIn .7s cubic-bezier(.2,.8,.2,1) both",
   "sceneBDelay": 0.3,
   "keyframes": "@keyframes m-xSpinOut{to{transform:rotate(90deg) scale(.2);opacity:0}}\n@keyframes m-xSpinIn{from{transform:rotate(-90deg) scale(.2);opacity:0}to{transform:none;opacity:1}}",
   "preview": "index.html#m/X10"
  },
  {
   "id": "X11",
   "kind": "trans",
   "name": "Linear wipe",
   "group": "Wipe",
   "use": "Before/after, clean handoffs.",
   "avoid": "Two very similar scenes (looks like a glitch).",
   "sceneB": "m-xWipe .8s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-xWipe{from{clip-path:inset(0 0 0 100%)}to{clip-path:inset(0)}}",
   "preview": "index.html#m/X11"
  },
  {
   "id": "X12",
   "kind": "trans",
   "name": "Diagonal wipe",
   "group": "Wipe",
   "use": "Dynamic sports-like energy.",
   "avoid": "Text-heavy scenes.",
   "sceneB": "m-xDiag .9s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-xDiag{from{clip-path:polygon(0 0,0 0,0 0)}to{clip-path:polygon(0 0,200% 0,0 200%)}}",
   "preview": "index.html#m/X12"
  },
  {
   "id": "X13",
   "kind": "trans",
   "name": "Circle iris",
   "group": "Wipe",
   "use": "Focus on one idea, reveal.",
   "avoid": "Many times in one video.",
   "sceneB": "m-xIris .9s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-xIris{from{clip-path:circle(0% at 50% 50%)}to{clip-path:circle(150% at 50% 50%)}}",
   "preview": "index.html#m/X13"
  },
  {
   "id": "X14",
   "kind": "trans",
   "name": "Click iris",
   "group": "Wipe",
   "use": "After a button click in a UI demo.",
   "avoid": "No cursor in the previous scene.",
   "sceneB": "m-xIrisClick .9s cubic-bezier(.7,0,.2,1) both",
   "overlay": "click",
   "keyframes": "@keyframes m-xIrisClick{from{clip-path:circle(0% at 70% 72%)}to{clip-path:circle(160% at 70% 72%)}}\n/* starts where the cursor clicks; pair with a ripple */",
   "preview": "index.html#m/X14"
  },
  {
   "id": "X15",
   "kind": "trans",
   "name": "Colour panel sweep",
   "group": "Wipe",
   "use": "Section breaks with brand colour.",
   "avoid": "When the accent equals the next scene bg.",
   "sceneB": "m-xAppear 1.1s linear both",
   "overlay": "panel",
   "keyframes": "@keyframes m-xPanel{0%{transform:translateX(-101%)}45%,55%{transform:none}100%{transform:translateX(101%)}}\n@keyframes m-xAppear{0%,49%{opacity:0}50%,100%{opacity:1}}\n/* overlay: accent panel, 1.1s cubic-bezier(.7,0,.3,1) */",
   "preview": "index.html#m/X15"
  },
  {
   "id": "X16",
   "kind": "trans",
   "name": "Stripe wipe",
   "group": "Wipe",
   "use": "Energetic lists, intros.",
   "avoid": "Slow long form.",
   "sceneB": "m-xAppear 1.2s linear both",
   "overlay": "stripes",
   "keyframes": "@keyframes m-xBar{0%{transform:scaleY(0);transform-origin:50% 0}45%{transform:scaleY(1);transform-origin:50% 0}55%{transform:scaleY(1);transform-origin:50% 100%}100%{transform:scaleY(0);transform-origin:50% 100%}}\n@keyframes m-xAppear{0%,49%{opacity:0}50%,100%{opacity:1}}\n/* 5 vertical bars, 0.06s stagger, alternating accent / ink */",
   "preview": "index.html#m/X16"
  },
  {
   "id": "X17",
   "kind": "trans",
   "name": "Mosaic",
   "group": "Wipe",
   "use": "Data, pixels, \"building blocks\" themes.",
   "avoid": "Minimal premium tone.",
   "sceneB": "m-xAppear 1.2s linear both",
   "overlay": "mosaic",
   "keyframes": "@keyframes m-xTile{0%{transform:scale(0)}45%,55%{transform:scale(1.02)}100%{transform:scale(0)}}\n@keyframes m-xAppear{0%,49%{opacity:0}50%,100%{opacity:1}}\n/* grid of squares, random delays 0-0.3s */",
   "preview": "index.html#m/X17"
  },
  {
   "id": "X18",
   "kind": "trans",
   "name": "Card flip",
   "group": "3D",
   "use": "\"Flip side\": pros/cons, front/back.",
   "avoid": "Dense UI (unreadable mid-flip).",
   "sceneA": "m-xFlipA .45s ease-in both",
   "sceneB": "m-xFlipB .45s ease-out both",
   "sceneBDelay": 0.45,
   "keyframes": "@keyframes m-xFlipA{to{transform:perspective(2400px) rotateY(90deg)}}\n@keyframes m-xFlipB{from{transform:perspective(2400px) rotateY(-90deg)}to{transform:perspective(2400px) rotateY(0)}}",
   "preview": "index.html#m/X18"
  },
  {
   "id": "X19",
   "kind": "trans",
   "name": "Cube turn",
   "group": "3D",
   "use": "Switching between two products or personas.",
   "avoid": "Overuse: once per video.",
   "sceneA": "m-xCubeA .8s cubic-bezier(.7,0,.2,1) both",
   "sceneB": "m-xCubeB .8s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-xCubeA{to{transform:perspective(2400px) translateX(-100%) rotateY(-90deg)}}\n@keyframes m-xCubeB{from{transform:perspective(2400px) translateX(100%) rotateY(90deg)}to{transform:perspective(2400px)}}\n/* A origin right, B origin left */",
   "preview": "index.html#m/X19"
  },
  {
   "id": "X20",
   "kind": "trans",
   "name": "Door split",
   "group": "3D",
   "use": "Grand reveals: \"introducing\".",
   "avoid": "Minor beats.",
   "sceneB": "m-xSettle .8s cubic-bezier(.2,.8,.2,1) both",
   "sceneBDelay": 0.2,
   "overlay": "doors",
   "keyframes": "@keyframes m-xDoorL{to{transform:translateX(-100%)}}\n@keyframes m-xDoorR{to{transform:translateX(100%)}}\n@keyframes m-xSettle{from{transform:scale(1.2);opacity:0}to{transform:none;opacity:1}}\n/* A duplicated: left half clip inset(0 50% 0 0), right half inset(0 0 0 50%) */",
   "preview": "index.html#m/X20"
  },
  {
   "id": "X21",
   "kind": "trans",
   "name": "Shared element expand",
   "group": "Morph",
   "use": "Tap a card, it opens: app-like continuity.",
   "avoid": "When A has no card.",
   "sceneB": "m-xFadeIn .3s ease both",
   "sceneBDelay": 0.75,
   "overlay": "expand",
   "keyframes": "@keyframes m-xExpand{from{left:20%;top:52%;width:60%;height:14%;border-radius:30px}to{left:0;top:0;width:100%;height:100%;border-radius:0}}\n@keyframes m-xFadeIn{from{opacity:0}to{opacity:1}}\n/* a card in scene A grows to fill the frame and becomes scene B background */",
   "preview": "index.html#m/X21"
  },
  {
   "id": "X22",
   "kind": "trans",
   "name": "Glitch cut",
   "group": "Cut",
   "use": "Tech, bugs, \"but something broke\".",
   "avoid": "Calm tone.",
   "sceneA": "m-xGlitchOut .4s steps(4) both",
   "sceneB": "m-xGlitchIn .4s steps(4) both",
   "sceneBDelay": 0.35,
   "keyframes": "@keyframes m-xGlitchOut{0%{clip-path:inset(0)}25%{clip-path:inset(20% 0 50% 0);transform:translateX(20px)}50%{clip-path:inset(60% 0 10% 0);transform:translateX(-20px)}100%{clip-path:inset(50% 0 50% 0);opacity:0}}\n@keyframes m-xGlitchIn{0%{clip-path:inset(50% 0 50% 0)}50%{clip-path:inset(10% 0 30% 0);transform:translateX(16px)}100%{clip-path:inset(0);transform:none}}",
   "preview": "index.html#m/X22"
  },
  {
   "id": "E01",
   "kind": "enter",
   "name": "Rise blur",
   "group": "Move",
   "use": "House default for cards and screenshots.",
   "animation": "m-eRise .9s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-eRise{from{opacity:0;transform:translateY(140px);filter:blur(10px)}to{opacity:1;transform:none;filter:none}}",
   "preview": "index.html#m/E01"
  },
  {
   "id": "E02",
   "kind": "enter",
   "name": "Fade scale",
   "group": "Fade",
   "use": "Small UI details, tooltips, badges.",
   "avoid": "Hero visuals (too subtle).",
   "animation": "m-eFadeScale .5s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-eFadeScale{from{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}",
   "preview": "index.html#m/E02"
  },
  {
   "id": "E03",
   "kind": "enter",
   "name": "Blur focus",
   "group": "Fade",
   "use": "Photos, backgrounds, calm reveals.",
   "avoid": "Text-heavy cards (blurry text looks broken).",
   "animation": "m-eFocus 1s ease both",
   "keyframes": "@keyframes m-eFocus{from{opacity:0;filter:blur(30px)}to{opacity:1;filter:none}}",
   "preview": "index.html#m/E03"
  },
  {
   "id": "E04",
   "kind": "enter",
   "name": "Pop overshoot",
   "group": "Scale",
   "use": "Icons, stickers, mascots, badges.",
   "avoid": "Large screenshots.",
   "animation": "m-ePop .6s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-ePop{0%{opacity:0;transform:scale(.6)}60%{opacity:1;transform:scale(1.05)}100%{opacity:1;transform:none}}",
   "preview": "index.html#m/E04"
  },
  {
   "id": "E05",
   "kind": "enter",
   "name": "Zoom blur in",
   "group": "Scale",
   "use": "Impact visuals, big numbers.",
   "avoid": "Many at once.",
   "animation": "m-eZoom .8s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-eZoom{from{opacity:0;transform:scale(1.6);filter:blur(16px)}to{opacity:1;transform:none;filter:none}}",
   "preview": "index.html#m/E05"
  },
  {
   "id": "E06",
   "kind": "enter",
   "name": "Drop bounce",
   "group": "Move",
   "use": "Notifications, stickers, fun beats.",
   "avoid": "Enterprise dashboards.",
   "animation": "m-eDrop .8s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-eDrop{0%{opacity:0;transform:translateY(-500px)}60%{opacity:1;transform:translateY(20px)}80%{transform:translateY(-8px)}100%{opacity:1;transform:none}}",
   "preview": "index.html#m/E06"
  },
  {
   "id": "E07",
   "kind": "enter",
   "name": "Slide from left",
   "group": "Move",
   "use": "Left column items, \"before\" states.",
   "animation": "m-eLeft .8s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-eLeft{from{opacity:0;transform:translateX(-400px)}to{opacity:1;transform:none}}",
   "preview": "index.html#m/E07"
  },
  {
   "id": "E08",
   "kind": "enter",
   "name": "Slide from right",
   "group": "Move",
   "use": "Right column items, \"after\" states, chat replies.",
   "animation": "m-eRight .8s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-eRight{from{opacity:0;transform:translateX(400px)}to{opacity:1;transform:none}}",
   "preview": "index.html#m/E08"
  },
  {
   "id": "E09",
   "kind": "enter",
   "name": "Arc path",
   "group": "Move",
   "use": "Thrown-in objects, \"added to cart\".",
   "avoid": "Rigid UI.",
   "animation": "m-eArc 1s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-eArc{0%{opacity:0;transform:translate(-420px,300px) rotate(-12deg)}50%{opacity:1;transform:translate(-120px,-80px) rotate(-4deg)}100%{opacity:1;transform:none}}",
   "preview": "index.html#m/E09"
  },
  {
   "id": "E10",
   "kind": "enter",
   "name": "Toss in",
   "group": "Move",
   "use": "Cards dealt onto a table, photos.",
   "avoid": "Serious data.",
   "animation": "m-eToss .9s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-eToss{from{opacity:0;transform:translate(300px,500px) rotate(25deg)}to{opacity:1;transform:none}}",
   "preview": "index.html#m/E10"
  },
  {
   "id": "E11",
   "kind": "enter",
   "name": "Flip up",
   "group": "3D",
   "use": "Screens rising off a desk, dashboards.",
   "animation": "m-eFlipUp .9s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-eFlipUp{from{opacity:0;transform:perspective(1600px) rotateX(55deg) translateY(120px)}to{opacity:1;transform:none}}",
   "preview": "index.html#m/E11"
  },
  {
   "id": "E12",
   "kind": "enter",
   "name": "Flip side",
   "group": "3D",
   "use": "Cards turning over, reveals of a result.",
   "animation": "m-eFlipSide .9s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-eFlipSide{from{opacity:0;transform:perspective(1600px) rotateY(-90deg)}to{opacity:1;transform:perspective(1600px) rotateY(0)}}",
   "preview": "index.html#m/E12"
  },
  {
   "id": "E13",
   "kind": "enter",
   "name": "Tilt settle",
   "group": "3D",
   "use": "Premium product shots.",
   "avoid": "Fast cuts.",
   "animation": "m-eTilt 1.2s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-eTilt{from{opacity:0;transform:perspective(2000px) rotateY(28deg) rotateX(12deg) translateY(80px)}to{opacity:1;transform:perspective(2000px)}}",
   "preview": "index.html#m/E13"
  },
  {
   "id": "E14",
   "kind": "enter",
   "name": "Swing in",
   "group": "3D",
   "use": "Hanging signs, banners, price tags.",
   "animation": "m-eSwing 1s cubic-bezier(.2,.8,.2,1) both",
   "transformOrigin": "50% 0",
   "keyframes": "@keyframes m-eSwing{0%{opacity:0;transform:perspective(1600px) rotateX(-90deg)}60%{opacity:1;transform:perspective(1600px) rotateX(12deg)}80%{transform:perspective(1600px) rotateX(-5deg)}100%{opacity:1;transform:perspective(1600px)}}\n/* transform-origin: top */",
   "preview": "index.html#m/E14"
  },
  {
   "id": "E15",
   "kind": "enter",
   "name": "Spin in",
   "group": "Scale",
   "use": "Logos, badges, awards.",
   "avoid": "Rectangular screenshots.",
   "animation": "m-eSpin .9s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-eSpin{from{opacity:0;transform:rotate(-180deg) scale(.3)}to{opacity:1;transform:none}}",
   "preview": "index.html#m/E15"
  },
  {
   "id": "E16",
   "kind": "enter",
   "name": "Unfold down",
   "group": "Mask",
   "use": "Menus, dropdowns, receipts printing.",
   "animation": "m-eUnfold .8s cubic-bezier(.7,0,.2,1) both",
   "transformOrigin": "50% 0",
   "keyframes": "@keyframes m-eUnfold{from{transform:scaleY(0)}to{transform:none}}\n/* transform-origin: top */",
   "preview": "index.html#m/E16"
  },
  {
   "id": "E17",
   "kind": "enter",
   "name": "Curtain open",
   "group": "Mask",
   "use": "Banners, horizontal bars, dividers.",
   "avoid": "Text-first cards (squished text).",
   "animation": "m-eCurtain .8s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-eCurtain{from{transform:scaleX(0)}to{transform:none}}",
   "preview": "index.html#m/E17"
  },
  {
   "id": "E18",
   "kind": "enter",
   "name": "Mask wipe in",
   "group": "Mask",
   "use": "Images and screenshots, editorial feel.",
   "animation": "m-eWipe .9s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-eWipe{from{clip-path:inset(0 100% 0 0 round 30px)}to{clip-path:inset(0 0 0 0 round 30px)}}",
   "preview": "index.html#m/E18"
  },
  {
   "id": "E19",
   "kind": "enter",
   "name": "Iris in",
   "group": "Mask",
   "use": "Avatars, photos, round visuals.",
   "animation": "m-eIris .9s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-eIris{from{clip-path:circle(0% at 50% 50%)}to{clip-path:circle(75% at 50% 50%)}}",
   "preview": "index.html#m/E19"
  },
  {
   "id": "E20",
   "kind": "enter",
   "name": "Elastic stretch",
   "group": "Physics",
   "use": "Buttons, mascots, jelly UI.",
   "avoid": "Serious finance.",
   "animation": "m-eElastic 1s linear both",
   "keyframes": "@keyframes m-eElastic{0%{opacity:0;transform:scale(.2,.2)}30%{opacity:1;transform:scale(1.25,.8)}45%{transform:scale(.85,1.15)}60%{transform:scale(1.08,.94)}75%{transform:scale(.97,1.03)}100%{opacity:1;transform:none}}",
   "preview": "index.html#m/E20"
  },
  {
   "id": "E21",
   "kind": "enter",
   "name": "Squash land",
   "group": "Physics",
   "use": "Mascots and objects landing.",
   "avoid": "Screenshots.",
   "animation": "m-eSquash .9s linear both",
   "transformOrigin": "50% 100%",
   "keyframes": "@keyframes m-eSquash{0%{opacity:0;transform:translateY(-600px) scale(.9,1.1)}55%{opacity:1;transform:translateY(0) scale(.9,1.1)}65%{transform:scale(1.2,.8)}80%{transform:scale(.95,1.05)}100%{opacity:1;transform:none}}\n/* transform-origin: bottom */",
   "preview": "index.html#m/E21"
  },
  {
   "id": "E22",
   "kind": "enter",
   "name": "Float in + idle",
   "group": "Physics",
   "use": "Hero product shots that stay on screen 3s+.",
   "avoid": "Dense UI people need to read.",
   "animation": "m-eRise .9s cubic-bezier(.2,.8,.2,1) both",
   "idle": "m-float 5s ease-in-out infinite",
   "keyframes": "@keyframes m-eRise{from{opacity:0;transform:translateY(140px);filter:blur(10px)}to{opacity:1;transform:none;filter:none}}\n@keyframes m-float{0%,100%{translate:0 0}50%{translate:0 -18px}}\n/* second animation keeps the element alive while held */",
   "preview": "index.html#m/E22"
  },
  {
   "id": "E23",
   "kind": "enter",
   "name": "Draw on",
   "group": "Illustration",
   "use": "Line illustrations, signatures, charts, arrows.",
   "avoid": "Filled icons.",
   "animation": "m-draw 1.8s ease-in-out both",
   "keyframes": "@keyframes m-draw{from{stroke-dashoffset:var(--len)}to{stroke-dashoffset:0}}\n/* SVG path: stroke-dasharray = --len = path length */",
   "preview": "index.html#m/E23"
  },
  {
   "id": "E24",
   "kind": "enter",
   "name": "Draw and fill",
   "group": "Illustration",
   "use": "Logos and icons built from outlines.",
   "avoid": "Photos.",
   "animation": "m-draw 1.4s ease-in-out both",
   "keyframes": "@keyframes m-draw{from{stroke-dashoffset:var(--len)}to{stroke-dashoffset:0}}\n@keyframes m-fillIn{from{fill-opacity:0}to{fill-opacity:1}}\n/* fill starts when the stroke finishes */",
   "preview": "index.html#m/E24"
  },
  {
   "id": "E25",
   "kind": "enter",
   "name": "Stagger grid",
   "group": "Group",
   "use": "Integration walls, app grids, galleries.",
   "avoid": "Grids over ~24 items (too long).",
   "stagger": 0.07,
   "animation": "m-ePop .5s cubic-bezier(.2,.8,.2,1) both",
   "keyframes": "@keyframes m-ePop{0%{opacity:0;transform:scale(.6)}60%{opacity:1;transform:scale(1.05)}100%{opacity:1;transform:none}}\n/* delay = index * 0.07s, row-major */",
   "preview": "index.html#m/E25"
  },
  {
   "id": "E26",
   "kind": "enter",
   "name": "Assemble parts",
   "group": "Group",
   "use": "Explaining what a UI is made of.",
   "avoid": "Quick cuts.",
   "animation": "multiple",
   "keyframes": "@keyframes m-eLeft{from{opacity:0;transform:translateX(-400px)}to{opacity:1;transform:none}}\n@keyframes m-eRight{from{opacity:0;transform:translateX(400px)}to{opacity:1;transform:none}}\n@keyframes m-ePop{0%{opacity:0;transform:scale(.6)}60%{opacity:1;transform:scale(1.05)}100%{opacity:1;transform:none}}\n/* card shell fades, header slides from left, rows from right, button pops */",
   "preview": "index.html#m/E26"
  },
  {
   "id": "O01",
   "kind": "exit",
   "name": "Blur out",
   "group": "Fade",
   "use": "House default exit.",
   "animation": "m-oBlur .5s ease-in both",
   "keyframes": "@keyframes m-oBlur{to{opacity:0;filter:blur(20px)}}",
   "preview": "index.html#m/O01"
  },
  {
   "id": "O02",
   "kind": "exit",
   "name": "Fade down",
   "group": "Fade",
   "use": "Calm exits in long form.",
   "animation": "m-oFadeDown .5s ease-in both",
   "keyframes": "@keyframes m-oFadeDown{to{opacity:0;transform:translateY(80px)}}",
   "preview": "index.html#m/O02"
  },
  {
   "id": "O03",
   "kind": "exit",
   "name": "Blur up",
   "group": "Fade",
   "use": "Mirror of Rise blur entrance.",
   "animation": "m-oBlurUp .6s ease-in both",
   "keyframes": "@keyframes m-oBlurUp{to{opacity:0;transform:translateY(-120px);filter:blur(14px)}}",
   "preview": "index.html#m/O03"
  },
  {
   "id": "O04",
   "kind": "exit",
   "name": "Pop out",
   "group": "Scale",
   "use": "Icons, badges, stickers leaving.",
   "avoid": "Big screenshots.",
   "animation": "m-oPop .4s ease-in both",
   "keyframes": "@keyframes m-oPop{30%{transform:scale(1.06)}100%{opacity:0;transform:scale(.4)}}",
   "preview": "index.html#m/O04"
  },
  {
   "id": "O05",
   "kind": "exit",
   "name": "Zoom past camera",
   "group": "Scale",
   "use": "Punchy exit into the next idea.",
   "animation": "m-oZoom .6s ease-in both",
   "keyframes": "@keyframes m-oZoom{to{opacity:0;transform:scale(2.6);filter:blur(12px)}}",
   "preview": "index.html#m/O05"
  },
  {
   "id": "O06",
   "kind": "exit",
   "name": "Shrink to point",
   "group": "Scale",
   "use": "Minimise, save to library, close.",
   "animation": "m-oShrink .6s ease-in both",
   "transformOrigin": "100% 0",
   "keyframes": "@keyframes m-oShrink{to{opacity:0;transform:scale(0)}}\n/* transform-origin: top right (or wherever it \"goes\") */",
   "preview": "index.html#m/O06"
  },
  {
   "id": "O07",
   "kind": "exit",
   "name": "Spin out",
   "group": "Scale",
   "use": "Playful removal.",
   "avoid": "Enterprise tone.",
   "animation": "m-oSpin .6s ease-in both",
   "keyframes": "@keyframes m-oSpin{to{opacity:0;transform:rotate(180deg) scale(.2)}}",
   "preview": "index.html#m/O07"
  },
  {
   "id": "O08",
   "kind": "exit",
   "name": "Fall away",
   "group": "Move",
   "use": "Discarded tools, \"drop the old way\".",
   "animation": "m-oFall .8s cubic-bezier(.5,0,.9,.5) both",
   "keyframes": "@keyframes m-oFall{to{opacity:0;transform:translateY(900px) rotate(14deg)}}",
   "preview": "index.html#m/O08"
  },
  {
   "id": "O09",
   "kind": "exit",
   "name": "Slide out left",
   "group": "Move",
   "use": "Previous item in a carousel.",
   "animation": "m-oLeft .6s ease-in both",
   "keyframes": "@keyframes m-oLeft{to{opacity:0;transform:translateX(-500px)}}",
   "preview": "index.html#m/O09"
  },
  {
   "id": "O10",
   "kind": "exit",
   "name": "Slide out right",
   "group": "Move",
   "use": "Dismiss, swipe away.",
   "animation": "m-oRight .6s ease-in both",
   "keyframes": "@keyframes m-oRight{to{opacity:0;transform:translateX(500px)}}",
   "preview": "index.html#m/O10"
  },
  {
   "id": "O11",
   "kind": "exit",
   "name": "Toss away",
   "group": "Move",
   "use": "Throw away the old way / spreadsheet.",
   "animation": "m-oToss .7s ease-in both",
   "keyframes": "@keyframes m-oToss{to{opacity:0;transform:translate(600px,-700px) rotate(35deg)}}",
   "preview": "index.html#m/O11"
  },
  {
   "id": "O12",
   "kind": "exit",
   "name": "Fly to target",
   "group": "Move",
   "use": "Save, add to cart, send to inbox.",
   "avoid": "No visible target.",
   "animation": "m-oFly .8s cubic-bezier(.6,0,.3,1) both",
   "keyframes": "@keyframes m-oFly{to{opacity:.2;transform:translate(300px,-640px) scale(.08)}}\n@keyframes m-bump{0%,100%{transform:none}50%{transform:scale(1.3)}}\n/* target icon bumps when the element arrives */",
   "preview": "index.html#m/O12"
  },
  {
   "id": "O13",
   "kind": "exit",
   "name": "Collapse up",
   "group": "Mask",
   "use": "Dropdowns, accordions, receipts.",
   "animation": "m-oCollapse .5s ease-in both",
   "transformOrigin": "50% 0",
   "keyframes": "@keyframes m-oCollapse{to{transform:scaleY(0)}}\n/* transform-origin: top */",
   "preview": "index.html#m/O13"
  },
  {
   "id": "O14",
   "kind": "exit",
   "name": "Curtain close",
   "group": "Mask",
   "use": "Banners, bars.",
   "animation": "m-oCurtain .5s ease-in both",
   "keyframes": "@keyframes m-oCurtain{to{transform:scaleX(0)}}",
   "preview": "index.html#m/O14"
  },
  {
   "id": "O15",
   "kind": "exit",
   "name": "Mask wipe out",
   "group": "Mask",
   "use": "Screenshots leaving to the right.",
   "animation": "m-oWipe .7s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-oWipe{to{clip-path:inset(0 0 0 100% round 30px)}}",
   "preview": "index.html#m/O15"
  },
  {
   "id": "O16",
   "kind": "exit",
   "name": "Iris out",
   "group": "Mask",
   "use": "Classic ending on one element.",
   "animation": "m-oIris .7s cubic-bezier(.7,0,.2,1) both",
   "keyframes": "@keyframes m-oIris{from{clip-path:circle(75% at 50% 50%)}to{clip-path:circle(0% at 50% 50%)}}",
   "preview": "index.html#m/O16"
  },
  {
   "id": "O17",
   "kind": "exit",
   "name": "Flip away",
   "group": "3D",
   "use": "Cards turning to the next topic.",
   "animation": "m-oFlip .6s ease-in both",
   "keyframes": "@keyframes m-oFlip{to{opacity:0;transform:perspective(1600px) rotateX(90deg)}}",
   "preview": "index.html#m/O17"
  },
  {
   "id": "O18",
   "kind": "exit",
   "name": "Stagger grid out",
   "group": "Group",
   "use": "Clearing a grid before the next beat.",
   "stagger": 0.05,
   "animation": "m-oPop .4s ease-in both",
   "keyframes": "@keyframes m-oPop{30%{transform:scale(1.06)}100%{opacity:0;transform:scale(.4)}}\n/* delay = index * 0.05s, reverse order optional */",
   "preview": "index.html#m/O18"
  }
 ]
}