animot-presenter 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -472,7 +472,7 @@ animot-presenter .animot-controls { display: none; }
472
472
 
473
473
  ## Features
474
474
 
475
- - **Morphing animations** — Elements with the same ID across slides smoothly morph position, size, rotation, color, opacity, and border radius
475
+ - **Morphing animations** — Elements with the same ID across slides smoothly morph position, size, rotation, color, opacity, border radius, and CSS filters (blur, brightness, contrast, saturate, grayscale)
476
476
  - **Code highlighting** — Syntax highlighting via Shiki with typewriter, highlight-changes, and instant animation modes
477
477
  - **Shape morphing** — Rectangles, circles, triangles, stars, hexagons with smooth transitions
478
478
  - **Charts** — Animated bar, line, area, pie, and donut charts
@@ -483,7 +483,8 @@ animot-presenter .animot-controls { display: none; }
483
483
  - **Transitions** — Fade, slide, zoom, flip, and morphing (none) transition types
484
484
  - **Responsive** — Automatically scales to fit any container size
485
485
  - **Keyboard navigation** — Arrow keys, spacebar, Home/End
486
- - **Property sequencing** — Fine-grained control over which properties animate first
486
+ - **CSS filters** — Blur, brightness, contrast, saturate, and grayscale on any element, animated across slides
487
+ - **Property sequencing** — Fine-grained control over which properties animate first (including filters via the `blur` property sequence)
487
488
 
488
489
  ## JSON Schema
489
490
 
@@ -517,7 +518,12 @@ Animot JSON files follow this structure:
517
518
  "color": "#ffffff",
518
519
  "rotation": 0,
519
520
  "visible": true,
520
- "zIndex": 1
521
+ "zIndex": 1,
522
+ "blur": 0,
523
+ "brightness": 100,
524
+ "contrast": 100,
525
+ "saturate": 100,
526
+ "grayscale": 0
521
527
  }
522
528
  ]
523
529
  },
@@ -563,6 +569,32 @@ You can replace the base64 data URL with a remote or local URL:
563
569
 
564
570
  This lets you keep your JSON files lightweight by hosting images separately instead of embedding them as base64. The same applies to text elements with `backgroundImage` and background `image` fields.
565
571
 
572
+ ### CSS Filters
573
+
574
+ All element types support CSS filter properties that animate smoothly between slides:
575
+
576
+ ```json
577
+ {
578
+ "id": "hero-image",
579
+ "type": "image",
580
+ "blur": 5,
581
+ "brightness": 120,
582
+ "contrast": 110,
583
+ "saturate": 80,
584
+ "grayscale": 0
585
+ }
586
+ ```
587
+
588
+ | Property | Range | Default | Description |
589
+ |--------------|---------|---------|----------------------------------|
590
+ | `blur` | 0–20 | 0 | Gaussian blur in pixels |
591
+ | `brightness` | 0–200 | 100 | Brightness percentage (100 = normal) |
592
+ | `contrast` | 0–200 | 100 | Contrast percentage (100 = normal) |
593
+ | `saturate` | 0–200 | 100 | Saturation percentage (100 = normal) |
594
+ | `grayscale` | 0–100 | 0 | Grayscale percentage (0 = none) |
595
+
596
+ Set different filter values on the same element across slides to create smooth animated transitions (e.g., blur 10 on slide 1 to blur 0 on slide 2 for a reveal effect). Use the `blur` property sequence in `animationConfig.propertySequences` to control filter animation timing independently.
597
+
566
598
  > **Note:** Remote URLs must allow cross-origin requests (CORS) if served from a different domain.
567
599
 
568
600
  ## Bundle Size
@@ -30,6 +30,11 @@
30
30
  strokeWidth: TweenValue | null;
31
31
  shapeMorph: TweenValue | null;
32
32
  motionPathProgress: TweenValue | null;
33
+ blur: TweenValue;
34
+ brightness: TweenValue;
35
+ contrast: TweenValue;
36
+ saturate: TweenValue;
37
+ grayscale: TweenValue;
33
38
  }
34
39
 
35
40
  interface ShapeMorphState { fromType: string; toType: string; }
@@ -205,8 +210,26 @@
205
210
  textTypewriterState = new Map(textTypewriterState);
206
211
  }
207
212
 
208
- // Arrow draw animation action
209
- function animateStyledArrowDraw(node: SVGPathElement, params: { enabled: boolean; duration: number; dashPattern: string; startX: number; endX: number; slideIndex: number }) {
213
+ // Build SVG path for 3+ control points using Catmull-Rom spline
214
+ function buildCatmullRomPath(start: {x:number,y:number}, cps: {x:number,y:number}[], end: {x:number,y:number}): string {
215
+ const pts = [start, ...cps, end];
216
+ let d = `M ${pts[0].x} ${pts[0].y}`;
217
+ for (let i = 0; i < pts.length - 1; i++) {
218
+ const p0 = pts[i === 0 ? 0 : i - 1];
219
+ const p1 = pts[i];
220
+ const p2 = pts[i + 1];
221
+ const p3 = pts[i + 2 < pts.length ? i + 2 : pts.length - 1];
222
+ const c1x = p1.x + (p2.x - p0.x) / 6;
223
+ const c1y = p1.y + (p2.y - p0.y) / 6;
224
+ const c2x = p2.x - (p3.x - p1.x) / 6;
225
+ const c2y = p2.y - (p3.y - p1.y) / 6;
226
+ d += ` C ${c1x} ${c1y} ${c2x} ${c2y} ${p2.x} ${p2.y}`;
227
+ }
228
+ return d;
229
+ }
230
+
231
+ // Arrow draw/undraw/draw-undraw animation action
232
+ function animateStyledArrowDraw(node: SVGPathElement, params: { enabled: boolean; mode: string; duration: number; dashPattern: string; startX: number; endX: number; slideIndex: number }) {
210
233
  let lastSlideIndex = params.slideIndex;
211
234
  let animationId: number | null = null;
212
235
  function runAnimation() {
@@ -215,24 +238,63 @@
215
238
  const svg = node.closest('svg') as SVGSVGElement | null;
216
239
  if (!svg) return;
217
240
  const goesLeftToRight = params.endX >= params.startX;
218
- svg.style.clipPath = goesLeftToRight ? 'inset(0 100% 0 0)' : 'inset(0 0 0 100%)';
219
- const startTime = performance.now();
241
+ const mode = params.mode;
220
242
  const dur = params.duration;
243
+ const startTime = performance.now();
244
+ if (mode === 'draw' || mode === 'draw-undraw') {
245
+ svg.style.clipPath = goesLeftToRight ? 'inset(0 100% 0 0)' : 'inset(0 0 0 100%)';
246
+ } else if (mode === 'undraw') {
247
+ svg.style.clipPath = 'none';
248
+ }
221
249
  function animate(currentTime: number) {
222
250
  const elapsed = currentTime - startTime;
223
- const progress = Math.min(elapsed / dur, 1);
224
- const eased = 1 - Math.pow(1 - progress, 3);
225
- const inset = 100 * (1 - eased);
226
- svg!.style.clipPath = goesLeftToRight ? `inset(0 ${inset}% 0 0)` : `inset(0 0 0 ${inset}%)`;
227
- if (progress < 1) animationId = requestAnimationFrame(animate);
228
- else { svg!.style.clipPath = 'none'; animationId = null; }
251
+ if (mode === 'draw') {
252
+ const progress = Math.min(elapsed / dur, 1);
253
+ const eased = 1 - Math.pow(1 - progress, 3);
254
+ const inset = 100 * (1 - eased);
255
+ svg!.style.clipPath = goesLeftToRight ? `inset(0 ${inset}% 0 0)` : `inset(0 0 0 ${inset}%)`;
256
+ if (progress < 1) { animationId = requestAnimationFrame(animate); }
257
+ else { svg!.style.clipPath = 'none'; animationId = null; }
258
+ } else if (mode === 'undraw') {
259
+ const progress = Math.min(elapsed / dur, 1);
260
+ const eased = 1 - Math.pow(1 - progress, 3);
261
+ const inset = 100 * eased;
262
+ svg!.style.clipPath = goesLeftToRight ? `inset(0 0 0 ${inset}%)` : `inset(0 ${inset}% 0 0)`;
263
+ if (progress < 1) { animationId = requestAnimationFrame(animate); }
264
+ else { svg!.style.clipPath = 'inset(0 0 0 100%)'; animationId = null; }
265
+ } else if (mode === 'draw-undraw') {
266
+ const halfDur = dur / 2;
267
+ if (elapsed < halfDur) {
268
+ const progress = Math.min(elapsed / halfDur, 1);
269
+ const eased = 1 - Math.pow(1 - progress, 3);
270
+ const inset = 100 * (1 - eased);
271
+ svg!.style.clipPath = goesLeftToRight ? `inset(0 ${inset}% 0 0)` : `inset(0 0 0 ${inset}%)`;
272
+ animationId = requestAnimationFrame(animate);
273
+ } else {
274
+ const progress = Math.min((elapsed - halfDur) / halfDur, 1);
275
+ const eased = 1 - Math.pow(1 - progress, 3);
276
+ const inset = 100 * eased;
277
+ svg!.style.clipPath = goesLeftToRight ? `inset(0 0 0 ${inset}%)` : `inset(0 ${inset}% 0 0)`;
278
+ if (progress < 1) { animationId = requestAnimationFrame(animate); }
279
+ else { svg!.style.clipPath = 'inset(0 0 0 100%)'; animationId = null; }
280
+ }
281
+ }
229
282
  }
230
283
  animationId = requestAnimationFrame(animate);
231
284
  }
232
285
  runAnimation();
233
286
  return {
234
287
  update(newParams: typeof params) {
235
- if (newParams.slideIndex !== lastSlideIndex) { lastSlideIndex = newParams.slideIndex; params = newParams; runAnimation(); }
288
+ const slideChanged = newParams.slideIndex !== lastSlideIndex;
289
+ params = newParams;
290
+ if (!params.enabled) {
291
+ if (animationId) { cancelAnimationFrame(animationId); animationId = null; }
292
+ const svg = node.closest('svg') as SVGSVGElement | null;
293
+ if (svg) svg.style.clipPath = '';
294
+ lastSlideIndex = newParams.slideIndex;
295
+ return;
296
+ }
297
+ if (slideChanged) { lastSlideIndex = newParams.slideIndex; runAnimation(); }
236
298
  },
237
299
  destroy() { if (animationId) cancelAnimationFrame(animationId); }
238
300
  };
@@ -278,7 +340,12 @@
278
340
  strokeColor: shapeEl ? tween(shapeEl.strokeColor, { duration: 500 }) : null,
279
341
  strokeWidth: shapeEl ? tween(shapeEl.strokeWidth, { duration: 500 }) : null,
280
342
  shapeMorph: shapeEl ? tween(1, { duration: 500 }) : null,
281
- motionPathProgress: element.motionPathConfig ? tween(0, { duration: 500 }) : null
343
+ motionPathProgress: element.motionPathConfig ? tween(0, { duration: 500 }) : null,
344
+ blur: tween(element.blur ?? 0, { duration: 500 }),
345
+ brightness: tween(element.brightness ?? 100, { duration: 500 }),
346
+ contrast: tween(element.contrast ?? 100, { duration: 500 }),
347
+ saturate: tween(element.saturate ?? 100, { duration: 500 }),
348
+ grayscale: tween(element.grayscale ?? 0, { duration: 500 })
282
349
  });
283
350
  const currentSlideEl = getElementInSlide(currentSlide, element.id);
284
351
  elementContent.set(element.id, JSON.parse(JSON.stringify(currentSlideEl || element)));
@@ -370,6 +437,11 @@
370
437
  animated.perspective.to(targetEl.perspective ?? 1000, { duration: 0 });
371
438
  animated.opacity.to(1, { duration: 0 });
372
439
  animated.borderRadius.to((targetEl as any).borderRadius ?? 0, { duration: 0 });
440
+ animated.blur.to(targetEl.blur ?? 0, { duration: 0 });
441
+ animated.brightness.to(targetEl.brightness ?? 100, { duration: 0 });
442
+ animated.contrast.to(targetEl.contrast ?? 100, { duration: 0 });
443
+ animated.saturate.to(targetEl.saturate ?? 100, { duration: 0 });
444
+ animated.grayscale.to(targetEl.grayscale ?? 0, { duration: 0 });
373
445
  if (targetEl.type === 'text') animated.fontSize?.to((targetEl as TextElement).fontSize, { duration: 0 });
374
446
  if (targetEl.type === 'shape') {
375
447
  const s = targetEl as ShapeElement;
@@ -433,6 +505,11 @@
433
505
  await animated.tiltY.to(currentEl.tiltY ?? 0, { duration: 0 });
434
506
  await animated.perspective.to(currentEl.perspective ?? 1000, { duration: 0 });
435
507
  await animated.borderRadius.to((currentEl as any).borderRadius ?? 0, { duration: 0 });
508
+ await animated.blur.to(currentEl.blur ?? 0, { duration: 0 });
509
+ await animated.brightness.to(currentEl.brightness ?? 100, { duration: 0 });
510
+ await animated.contrast.to(currentEl.contrast ?? 100, { duration: 0 });
511
+ await animated.saturate.to(currentEl.saturate ?? 100, { duration: 0 });
512
+ await animated.grayscale.to(currentEl.grayscale ?? 0, { duration: 0 });
436
513
  await animated.opacity.to(1, { duration: 0 });
437
514
  if (currentEl.type === 'text' && animated.fontSize) await animated.fontSize.to((currentEl as TextElement).fontSize, { duration: 0 });
438
515
  if (currentEl.type === 'shape') {
@@ -493,6 +570,13 @@
493
570
  if (!sequencedProps.has('skew')) { anims.push(animated.skewX.to(targetEl.skewX ?? 0, { duration: elementDuration, easing })); anims.push(animated.skewY.to(targetEl.skewY ?? 0, { duration: elementDuration, easing })); }
494
571
  if (!sequencedProps.has('size')) { anims.push(animated.width.to(targetEl.size.width, { duration: elementDuration, easing })); anims.push(animated.height.to(targetEl.size.height, { duration: elementDuration, easing })); }
495
572
  if (!sequencedProps.has('borderRadius')) anims.push(animated.borderRadius.to((targetEl as any).borderRadius ?? 0, { duration: elementDuration, easing }));
573
+ if (!sequencedProps.has('blur')) {
574
+ animated.blur.to(targetEl.blur ?? 0, { duration: elementDuration, easing });
575
+ animated.brightness.to(targetEl.brightness ?? 100, { duration: elementDuration, easing });
576
+ animated.contrast.to(targetEl.contrast ?? 100, { duration: elementDuration, easing });
577
+ animated.saturate.to(targetEl.saturate ?? 100, { duration: elementDuration, easing });
578
+ animated.grayscale.to(targetEl.grayscale ?? 0, { duration: elementDuration, easing });
579
+ }
496
580
  if (!sequencedProps.has('perspective')) anims.push(animated.perspective.to(targetEl.perspective ?? 1000, { duration: elementDuration, easing }));
497
581
  const sortedSeqs = [...propertySequences].sort((a, b) => a.order - b.order);
498
582
  let cumulativeDelay = 0;
@@ -506,6 +590,13 @@
506
590
  else if (seq.property === 'skew') { animated.skewX.to(targetEl.skewX ?? 0, { duration: seqDuration, easing }); animated.skewY.to(targetEl.skewY ?? 0, { duration: seqDuration, easing }); }
507
591
  else if (seq.property === 'size') { animated.width.to(targetEl.size.width, { duration: seqDuration, easing }); animated.height.to(targetEl.size.height, { duration: seqDuration, easing }); }
508
592
  else if (seq.property === 'borderRadius') animated.borderRadius.to((targetEl as any).borderRadius ?? 0, { duration: seqDuration, easing });
593
+ else if (seq.property === 'blur') {
594
+ animated.blur.to(targetEl.blur ?? 0, { duration: seqDuration, easing });
595
+ animated.brightness.to(targetEl.brightness ?? 100, { duration: seqDuration, easing });
596
+ animated.contrast.to(targetEl.contrast ?? 100, { duration: seqDuration, easing });
597
+ animated.saturate.to(targetEl.saturate ?? 100, { duration: seqDuration, easing });
598
+ animated.grayscale.to(targetEl.grayscale ?? 0, { duration: seqDuration, easing });
599
+ }
509
600
  else if (seq.property === 'color' && targetEl.type === 'shape') {
510
601
  const s = targetEl as ShapeElement;
511
602
  animated.fillColor?.to(s.fillColor, { duration: seqDuration, easing });
@@ -529,6 +620,11 @@
529
620
  anims.push(animated.tiltY.to(targetEl.tiltY ?? 0, { duration: elementDuration, easing }));
530
621
  anims.push(animated.perspective.to(targetEl.perspective ?? 1000, { duration: elementDuration, easing }));
531
622
  anims.push(animated.borderRadius.to((targetEl as any).borderRadius ?? 0, { duration: elementDuration, easing }));
623
+ anims.push(animated.blur.to(targetEl.blur ?? 0, { duration: elementDuration, easing }));
624
+ anims.push(animated.brightness.to(targetEl.brightness ?? 100, { duration: elementDuration, easing }));
625
+ anims.push(animated.contrast.to(targetEl.contrast ?? 100, { duration: elementDuration, easing }));
626
+ anims.push(animated.saturate.to(targetEl.saturate ?? 100, { duration: elementDuration, easing }));
627
+ anims.push(animated.grayscale.to(targetEl.grayscale ?? 0, { duration: elementDuration, easing }));
532
628
  }
533
629
  // Motion path progress — await reset, then animate forward
534
630
  if (animated.motionPathProgress && targetEl.motionPathConfig) {
@@ -575,6 +671,11 @@
575
671
  anims.push(animated.tiltY.to(targetEl.tiltY ?? 0, { duration: 0 }));
576
672
  anims.push(animated.perspective.to(targetEl.perspective ?? 1000, { duration: 0 }));
577
673
  anims.push(animated.borderRadius.to((targetEl as any).borderRadius ?? 0, { duration: 0 }));
674
+ anims.push(animated.blur.to(targetEl.blur ?? 0, { duration: 0 }));
675
+ anims.push(animated.brightness.to(targetEl.brightness ?? 100, { duration: 0 }));
676
+ anims.push(animated.contrast.to(targetEl.contrast ?? 100, { duration: 0 }));
677
+ anims.push(animated.saturate.to(targetEl.saturate ?? 100, { duration: 0 }));
678
+ anims.push(animated.grayscale.to(targetEl.grayscale ?? 0, { duration: 0 }));
578
679
  if (targetEl.type === 'text' && animated.fontSize) {
579
680
  anims.push(animated.fontSize.to((targetEl as TextElement).fontSize, { duration: 0 }));
580
681
  }
@@ -659,6 +760,13 @@
659
760
  elementContent = newElementContent;
660
761
  currentSlideIndex = targetIndex;
661
762
  isTransitioning = false;
763
+ // Ensure elements not on the new slide are fully hidden
764
+ const newSlide = slides[targetIndex];
765
+ for (const elementId of allElementIds) {
766
+ const onSlide = getElementInSlide(newSlide, elementId);
767
+ const animated = animatedElements.get(elementId);
768
+ if (!onSlide && animated) { animated.opacity.to(0, { duration: 0 }); }
769
+ }
662
770
  animateMotionPaths(slides[targetIndex]);
663
771
  onslidechange?.(targetIndex, slides.length);
664
772
  if (targetIndex === slides.length - 1 && !loop) oncomplete?.();
@@ -899,22 +1007,52 @@
899
1007
  style:--float-speed="{hasFloat ? computeFloatSpeed(floatCfg, floatGroupId || elementId) : 3}s"
900
1008
  style:--float-delay="{hashFraction(floatGroupId || elementId, 3) * 2}s"
901
1009
  style:animation-name={hasFloat ? getFloatAnimName(floatCfg!.direction, floatGroupId || elementId) : 'none'}
1010
+ style:filter={(() => { const parts: string[] = []; const b = animated.blur.current; const br2 = animated.brightness.current; const c = animated.contrast.current; const s = animated.saturate.current; const g = animated.grayscale.current; if (b) parts.push(`blur(${b}px)`); if (br2 !== 100) parts.push(`brightness(${br2}%)`); if (c !== 100) parts.push(`contrast(${c}%)`); if (s !== 100) parts.push(`saturate(${s}%)`); if (g) parts.push(`grayscale(${g}%)`); return parts.length ? parts.join(' ') : 'none'; })()}
902
1011
  >
903
1012
  {#if element.type === 'code'}
904
1013
  {@const codeEl = element as CodeElement}
905
1014
  {@const morphState = codeMorphState.get(codeEl.id)}
906
- <div class="animot-code-block" class:transparent-bg={codeEl.transparentBackground} style:font-size="{codeEl.fontSize}px" style:font-weight={codeEl.fontWeight || 400} style:padding="{codeEl.padding}px" style:border-radius="{animated.borderRadius.current}px">
1015
+ <div class="animot-code-block" class:transparent-bg={codeEl.transparentBackground} style:font-size="{codeEl.fontSize}px" style:font-weight={codeEl.fontWeight || 400} style:padding="{codeEl.padding}px" style:border-radius="{animated.borderRadius.current}px" style:background={codeEl.bgColor ?? '#0d1117'}>
907
1016
  {#if codeEl.showHeader}
908
- <div class="animot-code-header" class:macos={codeEl.headerStyle === 'macos'}>
1017
+ <div class="animot-code-header" class:macos={codeEl.headerStyle === 'macos'} class:windows={codeEl.headerStyle === 'windows'} style:border-radius="{codeEl.headerRadius ?? animated.borderRadius.current}px {codeEl.headerRadius ?? animated.borderRadius.current}px 0 0">
909
1018
  {#if codeEl.headerStyle === 'macos'}
910
1019
  <div class="animot-window-controls">
911
1020
  <span class="animot-control close"></span>
912
1021
  <span class="animot-control minimize"></span>
913
1022
  <span class="animot-control maximize"></span>
914
1023
  </div>
1024
+ {:else if codeEl.headerStyle === 'windows'}
1025
+ <div class="animot-window-controls">
1026
+ <span class="animot-control win-minimize">
1027
+ <svg width="10" height="10" viewBox="0 0 10 10"><path d="M2 5h6" stroke="currentColor" stroke-width="1.2"/></svg>
1028
+ </span>
1029
+ <span class="animot-control win-maximize">
1030
+ <svg width="10" height="10" viewBox="0 0 10 10"><rect x="1.5" y="1.5" width="7" height="7" rx="0.5" fill="none" stroke="currentColor" stroke-width="1.2"/></svg>
1031
+ </span>
1032
+ <span class="animot-control win-close">
1033
+ <svg width="10" height="10" viewBox="0 0 10 10"><path d="M2 2l6 6M8 2l-6 6" stroke="currentColor" stroke-width="1.2"/></svg>
1034
+ </span>
1035
+ </div>
915
1036
  {/if}
916
- <span class="animot-filename">{codeEl.filename}</span>
1037
+ <div class="animot-filename-tab" style:border-radius="{codeEl.tabRadius ?? 6}px">
1038
+ <svg class="animot-file-icon" width="14" height="14" viewBox="0 0 16 16" fill="none">
1039
+ <path d="M4 1h5.5L13 4.5V14a1 1 0 01-1 1H4a1 1 0 01-1-1V2a1 1 0 011-1z" stroke="currentColor" stroke-width="1.2" opacity="0.5"/>
1040
+ <path d="M9.5 1v3.5H13" stroke="currentColor" stroke-width="1.2" opacity="0.5"/>
1041
+ </svg>
1042
+ <span class="animot-filename">{codeEl.filename}</span>
1043
+ </div>
1044
+ <button class="animot-copy-code-btn" onclick={(e) => { e.stopPropagation(); navigator.clipboard.writeText(codeEl.code); const btn = e.currentTarget as HTMLElement; btn.classList.add('copied'); setTimeout(() => btn.classList.remove('copied'), 1500); }}>
1045
+ <span class="animot-copy-label">Copy</span><span class="animot-copied-label">Copied!</span>
1046
+ <svg class="animot-copy-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>
1047
+ <svg class="animot-check-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
1048
+ </button>
917
1049
  </div>
1050
+ {:else}
1051
+ <button class="animot-copy-code-btn animot-floating" onclick={(e) => { e.stopPropagation(); navigator.clipboard.writeText(codeEl.code); const btn = e.currentTarget as HTMLElement; btn.classList.add('copied'); setTimeout(() => btn.classList.remove('copied'), 1500); }}>
1052
+ <span class="animot-copy-label">Copy</span><span class="animot-copied-label">Copied!</span>
1053
+ <svg class="animot-copy-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>
1054
+ <svg class="animot-check-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
1055
+ </button>
918
1056
  {/if}
919
1057
  <div class="animot-code-content">
920
1058
  <div class="animot-highlighted-code">
@@ -960,25 +1098,27 @@
960
1098
  {:else if element.type === 'arrow'}
961
1099
  {@const arrowEl = element as ArrowElement}
962
1100
  {@const cp = arrowEl.controlPoints || []}
963
- {@const pathD = cp.length === 0 ? `M ${arrowEl.startPoint.x} ${arrowEl.startPoint.y} L ${arrowEl.endPoint.x} ${arrowEl.endPoint.y}` : cp.length === 1 ? `M ${arrowEl.startPoint.x} ${arrowEl.startPoint.y} Q ${cp[0].x} ${cp[0].y} ${arrowEl.endPoint.x} ${arrowEl.endPoint.y}` : `M ${arrowEl.startPoint.x} ${arrowEl.startPoint.y} C ${cp[0].x} ${cp[0].y} ${cp[1].x} ${cp[1].y} ${arrowEl.endPoint.x} ${arrowEl.endPoint.y}`}
964
- {@const endAngle = cp.length === 0 ? Math.atan2(arrowEl.endPoint.y - arrowEl.startPoint.y, arrowEl.endPoint.x - arrowEl.startPoint.x) : cp.length === 1 ? Math.atan2(arrowEl.endPoint.y - cp[0].y, arrowEl.endPoint.x - cp[0].x) : Math.atan2(arrowEl.endPoint.y - cp[1].y, arrowEl.endPoint.x - cp[1].x)}
1101
+ {@const pathD = cp.length === 0 ? `M ${arrowEl.startPoint.x} ${arrowEl.startPoint.y} L ${arrowEl.endPoint.x} ${arrowEl.endPoint.y}` : cp.length === 1 ? `M ${arrowEl.startPoint.x} ${arrowEl.startPoint.y} Q ${cp[0].x} ${cp[0].y} ${arrowEl.endPoint.x} ${arrowEl.endPoint.y}` : cp.length === 2 ? `M ${arrowEl.startPoint.x} ${arrowEl.startPoint.y} C ${cp[0].x} ${cp[0].y} ${cp[1].x} ${cp[1].y} ${arrowEl.endPoint.x} ${arrowEl.endPoint.y}` : buildCatmullRomPath(arrowEl.startPoint, cp, arrowEl.endPoint)}
1102
+ {@const lastCp = cp.length > 0 ? cp[cp.length - 1] : arrowEl.startPoint}
1103
+ {@const endAngle = Math.atan2(arrowEl.endPoint.y - lastCp.y, arrowEl.endPoint.x - lastCp.x)}
965
1104
  {@const headAngle = Math.PI / 6}
966
1105
  {@const headSize = arrowEl.headSize}
967
1106
  {@const arrowHeadPath = `M ${arrowEl.endPoint.x - headSize * Math.cos(endAngle - headAngle)} ${arrowEl.endPoint.y - headSize * Math.sin(endAngle - headAngle)} L ${arrowEl.endPoint.x} ${arrowEl.endPoint.y} L ${arrowEl.endPoint.x - headSize * Math.cos(endAngle + headAngle)} ${arrowEl.endPoint.y - headSize * Math.sin(endAngle + headAngle)}`}
968
1107
  {@const arrowAnimMode = arrowEl.animation?.mode ?? 'none'}
969
1108
  {@const arrowAnimDuration = arrowEl.animation?.duration ?? 500}
970
1109
  {@const isStyledArrow = arrowEl.style !== 'solid'}
1110
+ {@const isDrawType = arrowAnimMode === 'draw' || arrowAnimMode === 'undraw' || arrowAnimMode === 'draw-undraw'}
971
1111
  {@const baseDashArray = arrowEl.style === 'dashed' ? '10,5' : arrowEl.style === 'dotted' ? '2,5' : 'none'}
972
- <svg class="animot-arrow-element" class:arrow-animate-draw={arrowAnimMode === 'draw' && !isStyledArrow} class:arrow-animate-grow={arrowAnimMode === 'grow'} viewBox="0 0 {arrowEl.size.width} {arrowEl.size.height}" preserveAspectRatio="none" style="--arrow-anim-duration: {arrowAnimDuration}ms;">
973
- <path class="arrow-path" d={pathD} fill="none" stroke={arrowEl.color} stroke-width={arrowEl.strokeWidth} stroke-dasharray={baseDashArray} stroke-linecap="round" stroke-linejoin="round" use:animateStyledArrowDraw={{ enabled: arrowAnimMode === 'draw' && isStyledArrow, duration: arrowAnimDuration, dashPattern: baseDashArray, startX: arrowEl.startPoint.x, endX: arrowEl.endPoint.x, slideIndex: currentSlideIndex }} />
1112
+ <svg class="animot-arrow-element" class:arrow-animate-draw={arrowAnimMode === 'draw' && !isStyledArrow} class:arrow-animate-undraw={arrowAnimMode === 'undraw' && !isStyledArrow} class:arrow-animate-draw-undraw={arrowAnimMode === 'draw-undraw' && !isStyledArrow} class:arrow-animate-grow={arrowAnimMode === 'grow'} viewBox="0 0 {arrowEl.size.width} {arrowEl.size.height}" preserveAspectRatio="none" style="--arrow-anim-duration: {arrowAnimDuration}ms;">
1113
+ <path class="arrow-path" d={pathD} fill="none" stroke={arrowEl.color} stroke-width={arrowEl.strokeWidth} stroke-dasharray={baseDashArray} stroke-linecap="round" stroke-linejoin="round" use:animateStyledArrowDraw={{ enabled: isDrawType && isStyledArrow, mode: arrowAnimMode, duration: arrowAnimDuration, dashPattern: baseDashArray, startX: arrowEl.startPoint.x, endX: arrowEl.endPoint.x, slideIndex: currentSlideIndex }} />
974
1114
  {#if arrowEl.showHead !== false}
975
- <path class="arrow-head" class:arrow-head-styled-draw={arrowAnimMode === 'draw' && isStyledArrow} d={arrowHeadPath} fill="none" stroke={arrowEl.color} stroke-width={arrowEl.strokeWidth} stroke-linecap="round" stroke-linejoin="round" style={arrowAnimMode === 'draw' && isStyledArrow ? `--arrow-anim-duration: ${arrowAnimDuration}ms;` : ''} />
1115
+ <path class="arrow-head" class:arrow-head-styled-draw={isDrawType && isStyledArrow} class:arrow-head-undraw={arrowAnimMode === 'undraw'} class:arrow-head-draw-undraw={arrowAnimMode === 'draw-undraw'} d={arrowHeadPath} fill="none" stroke={arrowEl.color} stroke-width={arrowEl.strokeWidth} stroke-linecap="round" stroke-linejoin="round" style={isDrawType && isStyledArrow ? `--arrow-anim-duration: ${arrowAnimDuration}ms;` : ''} />
976
1116
  {/if}
977
1117
  </svg>
978
1118
  {:else if element.type === 'image'}
979
1119
  {@const imgEl = element as ImageElement}
980
1120
  {@const clipPath = imgEl.clipMask?.enabled ? (imgEl.clipMask.shapeType === 'circle' ? 'circle(50% at 50% 50%)' : imgEl.clipMask.shapeType === 'ellipse' ? 'ellipse(50% 50% at 50% 50%)' : imgEl.clipMask.shapeType === 'triangle' ? 'polygon(50% 0%, 0% 100%, 100% 100%)' : imgEl.clipMask.shapeType === 'star' ? 'polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%)' : imgEl.clipMask.shapeType === 'hexagon' ? 'polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%)' : (imgEl.clipMask.borderRadius ?? 0) > 0 ? `inset(0 round ${imgEl.clipMask.borderRadius}px)` : 'none') : 'none'}
981
- <img class="animot-image-element" src={imgEl.src} alt="" style:object-fit={imgEl.objectFit} style:border-radius="{imgEl.clipMask?.enabled ? 0 : imgEl.borderRadius}px" style:opacity={imgEl.opacity} style:filter={imgEl.blur ? `blur(${imgEl.blur}px)` : 'none'} style:clip-path={clipPath} style:background-color={imgEl.backgroundColor ?? 'transparent'} />
1121
+ <img class="animot-image-element" src={imgEl.src} alt="" style:object-fit={imgEl.objectFit} style:border-radius="{imgEl.clipMask?.enabled ? 0 : imgEl.borderRadius}px" style:opacity={imgEl.opacity} style:clip-path={clipPath} style:background-color={imgEl.backgroundColor ?? 'transparent'} />
982
1122
  {:else if element.type === 'shape'}
983
1123
  {@const shapeEl = element as ShapeElement}
984
1124
  {@const animFill = animated.fillColor?.current ?? shapeEl.fillColor}
@@ -1143,19 +1283,34 @@
1143
1283
 
1144
1284
  /* Code */
1145
1285
  .animot-code-block {
1146
- width: 100%; height: 100%; background: #0d1117; overflow: hidden;
1286
+ width: 100%; height: 100%; overflow: hidden;
1147
1287
  display: flex; flex-direction: column; box-shadow: 0 8px 32px rgba(0,0,0,0.4);
1148
1288
  margin: 0; box-sizing: border-box;
1149
1289
  }
1150
- .animot-code-block.transparent-bg { background: transparent; box-shadow: none; }
1151
- .animot-code-block.transparent-bg .animot-code-header { background: transparent; border-bottom-color: rgba(255,255,255,0.1); }
1152
- .animot-code-header { display: flex; align-items: center; gap: 12px; padding: 12px 16px; background: #161b22; border-bottom: 1px solid #30363d; flex-shrink: 0; }
1153
- .animot-window-controls { display: flex; gap: 8px; }
1154
- .animot-control { width: 12px; height: 12px; border-radius: 50%; display: block; }
1290
+ .animot-code-block.transparent-bg { background: transparent !important; box-shadow: none; }
1291
+ .animot-code-block.transparent-bg .animot-code-header { background: transparent; border-bottom-color: rgba(255,255,255,0.06); }
1292
+ .animot-code-header { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: rgba(0, 0, 0, 0.2); border-bottom: 1px solid rgba(255, 255, 255, 0.06); flex-shrink: 0; min-height: 40px; }
1293
+ .animot-window-controls { display: flex; gap: 8px; align-items: center; flex-shrink: 0; }
1294
+ .macos .animot-control { width: 12px; height: 12px; border-radius: 50%; display: block; }
1155
1295
  .macos .animot-control.close { background: #ff5f57; }
1156
1296
  .macos .animot-control.minimize { background: #febc2e; }
1157
1297
  .macos .animot-control.maximize { background: #28c840; }
1158
- .animot-filename { color: #8b949e; font-size: 14px; flex: 1; }
1298
+ .windows .animot-window-controls { order: 99; margin-left: auto; gap: 0; }
1299
+ .windows .animot-control { display: flex; align-items: center; justify-content: center; width: 28px; height: 24px; border-radius: 4px; color: rgba(255,255,255,0.45); }
1300
+ .animot-filename-tab { display: flex; align-items: center; gap: 6px; background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.08); border-radius: 6px; padding: 4px 10px; max-width: 220px; color: rgba(255,255,255,0.4); }
1301
+ .animot-file-icon { flex-shrink: 0; }
1302
+ .animot-filename { color: rgba(255,255,255,0.55); font-size: 12px; line-height: 18px; }
1303
+ .animot-copy-code-btn { display: flex; align-items: center; gap: 5px; height: 28px; padding: 0 8px; margin-left: auto; background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; color: rgba(255,255,255,0.4); cursor: pointer; opacity: 0; transition: opacity 0.2s, background 0.15s, color 0.15s; flex-shrink: 0; font-size: 12px; font-family: inherit; white-space: nowrap; }
1304
+ .animot-copy-code-btn:hover { background: rgba(255,255,255,0.12); color: rgba(255,255,255,0.8); }
1305
+ .animot-copy-code-btn svg { width: 14px; height: 14px; flex-shrink: 0; }
1306
+ .animot-copy-code-btn .animot-check-icon { display: none; }
1307
+ .animot-copy-code-btn .animot-copied-label { display: none; }
1308
+ .animot-copy-code-btn.copied .animot-copy-icon { display: none; }
1309
+ .animot-copy-code-btn.copied .animot-copy-label { display: none; }
1310
+ .animot-copy-code-btn.copied .animot-check-icon { display: block; color: #4ade80; }
1311
+ .animot-copy-code-btn.copied .animot-copied-label { display: inline; color: #4ade80; }
1312
+ .animot-copy-code-btn.animot-floating { position: absolute; top: 8px; right: 8px; z-index: 2; }
1313
+ .animot-code-block:hover .animot-copy-code-btn { opacity: 1; }
1159
1314
  .animot-code-content { flex: 1; overflow: hidden; position: relative; }
1160
1315
  .animot-highlighted-code { width: 100%; height: 100%; }
1161
1316
  .animot-code-content :global(pre), .animot-highlighted-code :global(pre) { margin: 0; padding: 16px; background: transparent !important; line-height: 1.6; font-size: inherit; overflow: visible; }
@@ -1170,11 +1325,19 @@
1170
1325
  /* Arrow */
1171
1326
  .animot-arrow-element { width: 100%; height: 100%; }
1172
1327
  .arrow-animate-draw .arrow-path { stroke-dasharray: 1000; stroke-dashoffset: 1000; animation: animot-arrow-draw var(--arrow-anim-duration, 500ms) ease-out forwards; }
1328
+ .arrow-animate-undraw .arrow-path { stroke-dasharray: 1000; stroke-dashoffset: 0; animation: animot-arrow-undraw var(--arrow-anim-duration, 500ms) ease-out forwards; }
1329
+ .arrow-animate-draw-undraw .arrow-path { stroke-dasharray: 1000; stroke-dashoffset: 1000; animation: animot-arrow-draw-undraw var(--arrow-anim-duration, 500ms) ease-out forwards; }
1173
1330
  .arrow-head-styled-draw { opacity: 0; animation: animot-arrow-head-appear var(--arrow-anim-duration, 500ms) ease-out forwards; animation-delay: calc(var(--arrow-anim-duration, 500ms) * 0.7); }
1174
1331
  .arrow-animate-draw .arrow-head { opacity: 0; animation: animot-arrow-head-appear var(--arrow-anim-duration, 500ms) ease-out forwards; animation-delay: calc(var(--arrow-anim-duration, 500ms) * 0.7); }
1332
+ .arrow-animate-undraw .arrow-head, .arrow-head-undraw { opacity: 1; animation: animot-arrow-head-disappear var(--arrow-anim-duration, 500ms) ease-out forwards; }
1333
+ .arrow-animate-draw-undraw .arrow-head, .arrow-head-draw-undraw { opacity: 0; animation: animot-arrow-head-draw-undraw var(--arrow-anim-duration, 500ms) ease-out forwards; }
1175
1334
  .arrow-animate-grow { transform-origin: left center; animation: animot-arrow-grow var(--arrow-anim-duration, 500ms) ease-out forwards; }
1176
1335
  @keyframes animot-arrow-draw { to { stroke-dashoffset: 0; } }
1336
+ @keyframes animot-arrow-undraw { from { stroke-dashoffset: 0; } to { stroke-dashoffset: 1000; } }
1337
+ @keyframes animot-arrow-draw-undraw { 0% { stroke-dashoffset: 1000; } 50% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: 1000; } }
1177
1338
  @keyframes animot-arrow-head-appear { from { opacity: 0; } to { opacity: 1; } }
1339
+ @keyframes animot-arrow-head-disappear { 0% { opacity: 1; } 70% { opacity: 1; } 100% { opacity: 0; } }
1340
+ @keyframes animot-arrow-head-draw-undraw { 0% { opacity: 0; } 35% { opacity: 1; } 65% { opacity: 1; } 100% { opacity: 0; } }
1178
1341
  @keyframes animot-arrow-grow { from { transform: scaleX(0); opacity: 0; } to { transform: scaleX(1); opacity: 1; } }
1179
1342
 
1180
1343
  /* Image */
@@ -1 +1 @@
1
- .code-morph.svelte-1hmk0l{width:100%;height:100%;margin:0;padding:0;background:transparent;font-family:var(--font-mono, "JetBrains Mono", monospace);font-size:inherit;line-height:1.6;white-space:pre-wrap;word-wrap:break-word;color:#e6edf3;box-sizing:border-box;overflow:visible}.code-morph.svelte-1hmk0l pre{margin:0;padding:16px;background:transparent!important;font-family:var(--font-mono);font-size:inherit;line-height:1.6;overflow:visible}.code-morph.svelte-1hmk0l code{font-family:inherit;font-size:inherit;font-weight:inherit}.code-morph.svelte-1hmk0l .line-number{display:inline-block;width:2.5em;margin-right:1em;text-align:right;color:#6e7681;-webkit-user-select:none;user-select:none;opacity:.6}.code-morph.svelte-1hmk0l .word-highlight{background:var(--highlight-color, #facc15);color:#000;border-radius:3px;padding:1px 3px;margin:0 -3px;-webkit-box-decoration-break:clone;box-decoration-break:clone;animation:svelte-1hmk0l-fadeHighlight var(--duration, 1s) ease-out forwards}@keyframes svelte-1hmk0l-fadeHighlight{0%{background:var(--highlight-color, #facc15);color:#000}70%{background:var(--highlight-color, #facc15);color:#000}to{background:transparent;color:inherit}}.counter.svelte-1er5jjj{width:100%;height:100%;display:flex;align-items:center;justify-content:center;box-sizing:border-box;overflow:hidden;white-space:nowrap}.chart.svelte-1mq2d7j{width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box;overflow:hidden}.chart-title.svelte-1mq2d7j{font-weight:600;text-align:center;margin-bottom:8px}.chart-content.svelte-1mq2d7j{flex:1;min-height:0}.chart-content.svelte-1mq2d7j svg:where(.svelte-1mq2d7j){width:100%;height:100%}.bar-chart.svelte-1mq2d7j,.line-chart.svelte-1mq2d7j{overflow:visible}.icon-element.svelte-2ld65o{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.icon-element.svelte-2ld65o svg{width:100%;height:100%}@keyframes float-vertical{0%,to{translate:0 0}50%{translate:0 calc(-1 * var(--float-amp, 10px))}}@keyframes float-horizontal{0%,to{translate:0 0}50%{translate:var(--float-amp, 10px) 0}}@keyframes float-both-0{0%{translate:0 0}15%{translate:calc(.8 * var(--float-amp, 10px)) calc(-.6 * var(--float-amp, 10px))}35%{translate:calc(-.4 * var(--float-amp, 10px)) calc(-1 * var(--float-amp, 10px))}55%{translate:calc(-.9 * var(--float-amp, 10px)) calc(.3 * var(--float-amp, 10px))}75%{translate:calc(.3 * var(--float-amp, 10px)) calc(.7 * var(--float-amp, 10px))}to{translate:0 0}}@keyframes float-both-1{0%{translate:0 0}20%{translate:calc(-.7 * var(--float-amp, 10px)) calc(-.8 * var(--float-amp, 10px))}40%{translate:calc(.5 * var(--float-amp, 10px)) calc(-.3 * var(--float-amp, 10px))}60%{translate:calc(.9 * var(--float-amp, 10px)) calc(.6 * var(--float-amp, 10px))}80%{translate:calc(-.4 * var(--float-amp, 10px)) calc(.9 * var(--float-amp, 10px))}to{translate:0 0}}@keyframes float-both-2{0%{translate:0 0}12%{translate:calc(.6 * var(--float-amp, 10px)) calc(.5 * var(--float-amp, 10px))}30%{translate:calc(1 * var(--float-amp, 10px)) calc(-.4 * var(--float-amp, 10px))}50%{translate:calc(-.3 * var(--float-amp, 10px)) calc(-.9 * var(--float-amp, 10px))}70%{translate:calc(-.8 * var(--float-amp, 10px)) calc(.2 * var(--float-amp, 10px))}88%{translate:calc(.2 * var(--float-amp, 10px)) calc(.8 * var(--float-amp, 10px))}to{translate:0 0}}@keyframes float-both-3{0%{translate:0 0}17%{translate:calc(-.9 * var(--float-amp, 10px)) calc(.4 * var(--float-amp, 10px))}33%{translate:calc(-.5 * var(--float-amp, 10px)) calc(-.7 * var(--float-amp, 10px))}50%{translate:calc(.7 * var(--float-amp, 10px)) calc(-.9 * var(--float-amp, 10px))}67%{translate:calc(.9 * var(--float-amp, 10px)) calc(.5 * var(--float-amp, 10px))}83%{translate:calc(-.2 * var(--float-amp, 10px)) calc(.8 * var(--float-amp, 10px))}to{translate:0 0}}.animot-presenter.svelte-16ocdv9 *{margin:0;padding:0;box-sizing:border-box}.animot-presenter.svelte-16ocdv9{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center;overflow:hidden;background:transparent;line-height:normal;font-size:16px;font-weight:400;font-style:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;text-indent:0;text-align:left;color:inherit}.animot-canvas-wrapper.svelte-16ocdv9{display:flex;align-items:center;justify-content:center}.animot-canvas.svelte-16ocdv9{position:relative;overflow:hidden}.animot-element.svelte-16ocdv9{position:absolute;box-sizing:border-box;will-change:transform,opacity,left,top,width,height;isolation:isolate}.animot-element.floating.svelte-16ocdv9{animation-duration:var(--float-speed, 3s);animation-timing-function:ease-in-out;animation-iteration-count:infinite;animation-delay:var(--float-delay, 0s)}.animot-code-block.svelte-16ocdv9{width:100%;height:100%;background:#0d1117;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 8px 32px #0006;margin:0;box-sizing:border-box}.animot-code-block.transparent-bg.svelte-16ocdv9{background:transparent;box-shadow:none}.animot-code-block.transparent-bg.svelte-16ocdv9 .animot-code-header:where(.svelte-16ocdv9){background:transparent;border-bottom-color:#ffffff1a}.animot-code-header.svelte-16ocdv9{display:flex;align-items:center;gap:12px;padding:12px 16px;background:#161b22;border-bottom:1px solid #30363d;flex-shrink:0}.animot-window-controls.svelte-16ocdv9{display:flex;gap:8px}.animot-control.svelte-16ocdv9{width:12px;height:12px;border-radius:50%;display:block}.macos.svelte-16ocdv9 .animot-control.close:where(.svelte-16ocdv9){background:#ff5f57}.macos.svelte-16ocdv9 .animot-control.minimize:where(.svelte-16ocdv9){background:#febc2e}.macos.svelte-16ocdv9 .animot-control.maximize:where(.svelte-16ocdv9){background:#28c840}.animot-filename.svelte-16ocdv9{color:#8b949e;font-size:14px;flex:1}.animot-code-content.svelte-16ocdv9{flex:1;overflow:hidden;position:relative}.animot-highlighted-code.svelte-16ocdv9{width:100%;height:100%}.animot-code-content.svelte-16ocdv9 pre,.animot-highlighted-code.svelte-16ocdv9 pre{margin:0;padding:16px;background:transparent!important;line-height:1.6;font-size:inherit;overflow:visible}.animot-highlighted-code.svelte-16ocdv9 code{font-family:inherit;font-size:inherit;font-weight:inherit}.animot-highlighted-code.svelte-16ocdv9 .line-number{display:inline-block;width:2.5em;margin-right:1em;text-align:right;color:#6e7681;-webkit-user-select:none;user-select:none;opacity:.6}.animot-text-element.svelte-16ocdv9{width:100%;height:100%;display:flex;align-items:center;white-space:pre-wrap;word-wrap:break-word}.animot-typewriter-cursor.svelte-16ocdv9{animation:svelte-16ocdv9-animot-blink .7s infinite;font-weight:100}@keyframes svelte-16ocdv9-animot-blink{0%,50%{opacity:1}51%,to{opacity:0}}.animot-arrow-element.svelte-16ocdv9{width:100%;height:100%}.arrow-animate-draw.svelte-16ocdv9 .arrow-path:where(.svelte-16ocdv9){stroke-dasharray:1000;stroke-dashoffset:1000;animation:svelte-16ocdv9-animot-arrow-draw var(--arrow-anim-duration, .5s) ease-out forwards}.arrow-head-styled-draw.svelte-16ocdv9{opacity:0;animation:svelte-16ocdv9-animot-arrow-head-appear var(--arrow-anim-duration, .5s) ease-out forwards;animation-delay:calc(var(--arrow-anim-duration, .5s) * .7)}.arrow-animate-draw.svelte-16ocdv9 .arrow-head:where(.svelte-16ocdv9){opacity:0;animation:svelte-16ocdv9-animot-arrow-head-appear var(--arrow-anim-duration, .5s) ease-out forwards;animation-delay:calc(var(--arrow-anim-duration, .5s) * .7)}.arrow-animate-grow.svelte-16ocdv9{transform-origin:left center;animation:svelte-16ocdv9-animot-arrow-grow var(--arrow-anim-duration, .5s) ease-out forwards}@keyframes svelte-16ocdv9-animot-arrow-draw{to{stroke-dashoffset:0}}@keyframes svelte-16ocdv9-animot-arrow-head-appear{0%{opacity:0}to{opacity:1}}@keyframes svelte-16ocdv9-animot-arrow-grow{0%{transform:scaleX(0);opacity:0}to{transform:scaleX(1);opacity:1}}.animot-image-element.svelte-16ocdv9{width:100%;height:100%;display:block}.animot-shape-element.svelte-16ocdv9{width:100%;height:100%;display:block;overflow:visible}.animot-canvas.svelte-16ocdv9{--transition-duration: .5s;transition:transform calc(var(--transition-duration) * .4) ease,opacity calc(var(--transition-duration) * .4) ease}.animot-canvas.transition-fade-out.svelte-16ocdv9{opacity:0}.animot-canvas.transition-fade-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-fadeIn calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-left-out.forward.svelte-16ocdv9{transform:translate(-100%);opacity:0}.animot-canvas.transition-slide-left-in.forward.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromRight calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-left-out.backward.svelte-16ocdv9{transform:translate(100%);opacity:0}.animot-canvas.transition-slide-left-in.backward.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromLeft calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-right-out.forward.svelte-16ocdv9{transform:translate(100%);opacity:0}.animot-canvas.transition-slide-right-in.forward.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromLeft calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-up-out.svelte-16ocdv9{transform:translateY(-100%);opacity:0}.animot-canvas.transition-slide-up-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromBottom calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-down-out.svelte-16ocdv9{transform:translateY(100%);opacity:0}.animot-canvas.transition-slide-down-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromTop calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-zoom-in-out.svelte-16ocdv9{transform:scale(.5);opacity:0}.animot-canvas.transition-zoom-in-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-zoomIn calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-zoom-out-out.svelte-16ocdv9{transform:scale(1.5);opacity:0}.animot-canvas.transition-zoom-out-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-zoomOut calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-flip-out.svelte-16ocdv9{transform:perspective(1000px) rotateY(90deg);opacity:0}.animot-canvas.transition-flip-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-flipIn calc(var(--transition-duration) * .6) ease forwards}@keyframes svelte-16ocdv9-animot-fadeIn{0%{opacity:0}to{opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromRight{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromLeft{0%{transform:translate(-100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromBottom{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromTop{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes svelte-16ocdv9-animot-zoomIn{0%{transform:scale(.5);opacity:0}to{transform:scale(1);opacity:1}}@keyframes svelte-16ocdv9-animot-zoomOut{0%{transform:scale(1.5);opacity:0}to{transform:scale(1);opacity:1}}@keyframes svelte-16ocdv9-animot-flipIn{0%{transform:perspective(1000px) rotateY(-90deg);opacity:0}to{transform:perspective(1000px) rotateY(0);opacity:1}}.animot-canvas.transition-flip-x-out.svelte-16ocdv9{transform:perspective(1000px) rotateX(90deg);opacity:0}.animot-canvas.transition-flip-x-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-flipXIn calc(var(--transition-duration) * .6) ease forwards}@keyframes svelte-16ocdv9-animot-flipXIn{0%{transform:perspective(1000px) rotateX(-90deg);opacity:0}to{transform:perspective(1000px) rotateX(0);opacity:1}}.animot-canvas.transition-flip-y-out.svelte-16ocdv9{transform:perspective(1000px) rotateY(90deg);opacity:0}.animot-canvas.transition-flip-y-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-flipYIn calc(var(--transition-duration) * .6) ease forwards}@keyframes svelte-16ocdv9-animot-flipYIn{0%{transform:perspective(1000px) rotateY(-90deg);opacity:0}to{transform:perspective(1000px) rotateY(0);opacity:1}}.animot-svg-element.svelte-16ocdv9{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.animot-svg-element.svelte-16ocdv9 svg{width:100%;height:100%}.animot-controls.svelte-16ocdv9{position:absolute;bottom:12px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:8px;padding:8px 16px;background:#000000b3;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:10px;opacity:0;transition:opacity .3s ease .15s;z-index:100}.animot-presenter.svelte-16ocdv9:hover .animot-controls:where(.svelte-16ocdv9),.animot-menu-visible.svelte-16ocdv9 .animot-controls:where(.svelte-16ocdv9){opacity:1;transition-delay:0s}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9){display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:6px;border:none;cursor:pointer;background:#ffffff1a;color:#fff;transition:background .2s}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9):hover:not(:disabled){background:#fff3}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9):disabled{opacity:.3;cursor:not-allowed}.animot-controls.svelte-16ocdv9 button.active:where(.svelte-16ocdv9){background:#6366f199}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9) svg:where(.svelte-16ocdv9){width:16px;height:16px}.animot-slide-indicator.svelte-16ocdv9{font-size:12px;color:#fff;min-width:50px;text-align:center;font-family:system-ui,sans-serif}.animot-arrow.svelte-16ocdv9{position:absolute;top:50%;transform:translateY(-50%);width:40px;height:40px;border-radius:50%;border:none;cursor:pointer;background:#00000080;color:#fff;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .3s .15s;z-index:100;padding:0;margin:0}.animot-presenter.svelte-16ocdv9:hover .animot-arrow:where(.svelte-16ocdv9){opacity:1;transition-delay:0s}.animot-presenter.svelte-16ocdv9:hover .animot-arrow:where(.svelte-16ocdv9):disabled{opacity:.3;cursor:not-allowed}.animot-arrow.svelte-16ocdv9:hover:not(:disabled){background:#000000b3}.animot-arrow.svelte-16ocdv9 svg:where(.svelte-16ocdv9){width:20px;height:20px}.animot-arrow-left.svelte-16ocdv9{left:8px}.animot-arrow-right.svelte-16ocdv9{right:8px}.animot-progress-bar.svelte-16ocdv9{position:absolute;bottom:0;left:0;right:0;height:3px;background:#ffffff1a;z-index:100;opacity:0;transition:opacity .3s .15s}.animot-presenter.svelte-16ocdv9:hover .animot-progress-bar:where(.svelte-16ocdv9){opacity:1;transition-delay:0s}.animot-progress-fill.svelte-16ocdv9{height:100%;background:linear-gradient(135deg,#7c3aed,#ec4899);transition:width .6s ease}.animot-loading.svelte-16ocdv9{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.animot-spinner.svelte-16ocdv9{width:32px;height:32px;border:3px solid rgba(255,255,255,.2);border-top-color:#7c3aed;border-radius:50%;animation:svelte-16ocdv9-animot-spin .8s linear infinite}@keyframes svelte-16ocdv9-animot-spin{to{transform:rotate(360deg)}}.animot-error.svelte-16ocdv9{color:#ef4444;padding:20px;text-align:center;font-family:system-ui,sans-serif}
1
+ .code-morph.svelte-1hmk0l{width:100%;height:100%;margin:0;padding:0;background:transparent;font-family:var(--font-mono, "JetBrains Mono", monospace);font-size:inherit;line-height:1.6;white-space:pre-wrap;word-wrap:break-word;color:#e6edf3;box-sizing:border-box;overflow:visible}.code-morph.svelte-1hmk0l pre{margin:0;padding:16px;background:transparent!important;font-family:var(--font-mono);font-size:inherit;line-height:1.6;overflow:visible}.code-morph.svelte-1hmk0l code{font-family:inherit;font-size:inherit;font-weight:inherit}.code-morph.svelte-1hmk0l .line-number{display:inline-block;width:2.5em;margin-right:1em;text-align:right;color:#6e7681;-webkit-user-select:none;user-select:none;opacity:.6}.code-morph.svelte-1hmk0l .word-highlight{background:var(--highlight-color, #facc15);color:#000;border-radius:3px;padding:1px 3px;margin:0 -3px;-webkit-box-decoration-break:clone;box-decoration-break:clone;animation:svelte-1hmk0l-fadeHighlight var(--duration, 1s) ease-out forwards}@keyframes svelte-1hmk0l-fadeHighlight{0%{background:var(--highlight-color, #facc15);color:#000}70%{background:var(--highlight-color, #facc15);color:#000}to{background:transparent;color:inherit}}.counter.svelte-1er5jjj{width:100%;height:100%;display:flex;align-items:center;justify-content:center;box-sizing:border-box;overflow:hidden;white-space:nowrap}.chart.svelte-1mq2d7j{width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box;overflow:hidden}.chart-title.svelte-1mq2d7j{font-weight:600;text-align:center;margin-bottom:8px}.chart-content.svelte-1mq2d7j{flex:1;min-height:0}.chart-content.svelte-1mq2d7j svg:where(.svelte-1mq2d7j){width:100%;height:100%}.bar-chart.svelte-1mq2d7j,.line-chart.svelte-1mq2d7j{overflow:visible}.icon-element.svelte-2ld65o{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.icon-element.svelte-2ld65o svg{width:100%;height:100%}@keyframes float-vertical{0%,to{translate:0 0}50%{translate:0 calc(-1 * var(--float-amp, 10px))}}@keyframes float-horizontal{0%,to{translate:0 0}50%{translate:var(--float-amp, 10px) 0}}@keyframes float-both-0{0%{translate:0 0}15%{translate:calc(.8 * var(--float-amp, 10px)) calc(-.6 * var(--float-amp, 10px))}35%{translate:calc(-.4 * var(--float-amp, 10px)) calc(-1 * var(--float-amp, 10px))}55%{translate:calc(-.9 * var(--float-amp, 10px)) calc(.3 * var(--float-amp, 10px))}75%{translate:calc(.3 * var(--float-amp, 10px)) calc(.7 * var(--float-amp, 10px))}to{translate:0 0}}@keyframes float-both-1{0%{translate:0 0}20%{translate:calc(-.7 * var(--float-amp, 10px)) calc(-.8 * var(--float-amp, 10px))}40%{translate:calc(.5 * var(--float-amp, 10px)) calc(-.3 * var(--float-amp, 10px))}60%{translate:calc(.9 * var(--float-amp, 10px)) calc(.6 * var(--float-amp, 10px))}80%{translate:calc(-.4 * var(--float-amp, 10px)) calc(.9 * var(--float-amp, 10px))}to{translate:0 0}}@keyframes float-both-2{0%{translate:0 0}12%{translate:calc(.6 * var(--float-amp, 10px)) calc(.5 * var(--float-amp, 10px))}30%{translate:calc(1 * var(--float-amp, 10px)) calc(-.4 * var(--float-amp, 10px))}50%{translate:calc(-.3 * var(--float-amp, 10px)) calc(-.9 * var(--float-amp, 10px))}70%{translate:calc(-.8 * var(--float-amp, 10px)) calc(.2 * var(--float-amp, 10px))}88%{translate:calc(.2 * var(--float-amp, 10px)) calc(.8 * var(--float-amp, 10px))}to{translate:0 0}}@keyframes float-both-3{0%{translate:0 0}17%{translate:calc(-.9 * var(--float-amp, 10px)) calc(.4 * var(--float-amp, 10px))}33%{translate:calc(-.5 * var(--float-amp, 10px)) calc(-.7 * var(--float-amp, 10px))}50%{translate:calc(.7 * var(--float-amp, 10px)) calc(-.9 * var(--float-amp, 10px))}67%{translate:calc(.9 * var(--float-amp, 10px)) calc(.5 * var(--float-amp, 10px))}83%{translate:calc(-.2 * var(--float-amp, 10px)) calc(.8 * var(--float-amp, 10px))}to{translate:0 0}}.animot-presenter.svelte-16ocdv9 *{margin:0;padding:0;box-sizing:border-box}.animot-presenter.svelte-16ocdv9{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center;overflow:hidden;background:transparent;line-height:normal;font-size:16px;font-weight:400;font-style:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;text-indent:0;text-align:left;color:inherit}.animot-canvas-wrapper.svelte-16ocdv9{display:flex;align-items:center;justify-content:center}.animot-canvas.svelte-16ocdv9{position:relative;overflow:hidden}.animot-element.svelte-16ocdv9{position:absolute;box-sizing:border-box;will-change:transform,opacity,left,top,width,height;isolation:isolate}.animot-element.floating.svelte-16ocdv9{animation-duration:var(--float-speed, 3s);animation-timing-function:ease-in-out;animation-iteration-count:infinite;animation-delay:var(--float-delay, 0s)}.animot-code-block.svelte-16ocdv9{width:100%;height:100%;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 8px 32px #0006;margin:0;box-sizing:border-box}.animot-code-block.transparent-bg.svelte-16ocdv9{background:transparent!important;box-shadow:none}.animot-code-block.transparent-bg.svelte-16ocdv9 .animot-code-header:where(.svelte-16ocdv9){background:transparent;border-bottom-color:#ffffff0f}.animot-code-header.svelte-16ocdv9{display:flex;align-items:center;gap:8px;padding:8px 12px;background:#0003;border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0;min-height:40px}.animot-window-controls.svelte-16ocdv9{display:flex;gap:8px;align-items:center;flex-shrink:0}.macos.svelte-16ocdv9 .animot-control:where(.svelte-16ocdv9){width:12px;height:12px;border-radius:50%;display:block}.macos.svelte-16ocdv9 .animot-control.close:where(.svelte-16ocdv9){background:#ff5f57}.macos.svelte-16ocdv9 .animot-control.minimize:where(.svelte-16ocdv9){background:#febc2e}.macos.svelte-16ocdv9 .animot-control.maximize:where(.svelte-16ocdv9){background:#28c840}.windows.svelte-16ocdv9 .animot-window-controls:where(.svelte-16ocdv9){order:99;margin-left:auto;gap:0}.windows.svelte-16ocdv9 .animot-control:where(.svelte-16ocdv9){display:flex;align-items:center;justify-content:center;width:28px;height:24px;border-radius:4px;color:#ffffff73}.animot-filename-tab.svelte-16ocdv9{display:flex;align-items:center;gap:6px;background:#ffffff0f;border:1px solid rgba(255,255,255,.08);border-radius:6px;padding:4px 10px;max-width:220px;color:#fff6}.animot-file-icon.svelte-16ocdv9{flex-shrink:0}.animot-filename.svelte-16ocdv9{color:#ffffff8c;font-size:12px;line-height:18px}.animot-copy-code-btn.svelte-16ocdv9{display:flex;align-items:center;gap:5px;height:28px;padding:0 8px;margin-left:auto;background:#ffffff0f;border:1px solid rgba(255,255,255,.1);border-radius:6px;color:#fff6;cursor:pointer;opacity:0;transition:opacity .2s,background .15s,color .15s;flex-shrink:0;font-size:12px;font-family:inherit;white-space:nowrap}.animot-copy-code-btn.svelte-16ocdv9:hover{background:#ffffff1f;color:#fffc}.animot-copy-code-btn.svelte-16ocdv9 svg:where(.svelte-16ocdv9){width:14px;height:14px;flex-shrink:0}.animot-copy-code-btn.svelte-16ocdv9 .animot-check-icon:where(.svelte-16ocdv9){display:none}.animot-copy-code-btn.svelte-16ocdv9 .animot-copied-label:where(.svelte-16ocdv9){display:none}.animot-copy-code-btn.copied.svelte-16ocdv9 .animot-copy-icon:where(.svelte-16ocdv9){display:none}.animot-copy-code-btn.copied.svelte-16ocdv9 .animot-copy-label:where(.svelte-16ocdv9){display:none}.animot-copy-code-btn.copied.svelte-16ocdv9 .animot-check-icon:where(.svelte-16ocdv9){display:block;color:#4ade80}.animot-copy-code-btn.copied.svelte-16ocdv9 .animot-copied-label:where(.svelte-16ocdv9){display:inline;color:#4ade80}.animot-copy-code-btn.animot-floating.svelte-16ocdv9{position:absolute;top:8px;right:8px;z-index:2}.animot-code-block.svelte-16ocdv9:hover .animot-copy-code-btn:where(.svelte-16ocdv9){opacity:1}.animot-code-content.svelte-16ocdv9{flex:1;overflow:hidden;position:relative}.animot-highlighted-code.svelte-16ocdv9{width:100%;height:100%}.animot-code-content.svelte-16ocdv9 pre,.animot-highlighted-code.svelte-16ocdv9 pre{margin:0;padding:16px;background:transparent!important;line-height:1.6;font-size:inherit;overflow:visible}.animot-highlighted-code.svelte-16ocdv9 code{font-family:inherit;font-size:inherit;font-weight:inherit}.animot-highlighted-code.svelte-16ocdv9 .line-number{display:inline-block;width:2.5em;margin-right:1em;text-align:right;color:#6e7681;-webkit-user-select:none;user-select:none;opacity:.6}.animot-text-element.svelte-16ocdv9{width:100%;height:100%;display:flex;align-items:center;white-space:pre-wrap;word-wrap:break-word}.animot-typewriter-cursor.svelte-16ocdv9{animation:svelte-16ocdv9-animot-blink .7s infinite;font-weight:100}@keyframes svelte-16ocdv9-animot-blink{0%,50%{opacity:1}51%,to{opacity:0}}.animot-arrow-element.svelte-16ocdv9{width:100%;height:100%}.arrow-animate-draw.svelte-16ocdv9 .arrow-path:where(.svelte-16ocdv9){stroke-dasharray:1000;stroke-dashoffset:1000;animation:svelte-16ocdv9-animot-arrow-draw var(--arrow-anim-duration, .5s) ease-out forwards}.arrow-animate-undraw.svelte-16ocdv9 .arrow-path:where(.svelte-16ocdv9){stroke-dasharray:1000;stroke-dashoffset:0;animation:svelte-16ocdv9-animot-arrow-undraw var(--arrow-anim-duration, .5s) ease-out forwards}.arrow-animate-draw-undraw.svelte-16ocdv9 .arrow-path:where(.svelte-16ocdv9){stroke-dasharray:1000;stroke-dashoffset:1000;animation:svelte-16ocdv9-animot-arrow-draw-undraw var(--arrow-anim-duration, .5s) ease-out forwards}.arrow-head-styled-draw.svelte-16ocdv9{opacity:0;animation:svelte-16ocdv9-animot-arrow-head-appear var(--arrow-anim-duration, .5s) ease-out forwards;animation-delay:calc(var(--arrow-anim-duration, .5s) * .7)}.arrow-animate-draw.svelte-16ocdv9 .arrow-head:where(.svelte-16ocdv9){opacity:0;animation:svelte-16ocdv9-animot-arrow-head-appear var(--arrow-anim-duration, .5s) ease-out forwards;animation-delay:calc(var(--arrow-anim-duration, .5s) * .7)}.arrow-animate-undraw.svelte-16ocdv9 .arrow-head:where(.svelte-16ocdv9),.arrow-head-undraw.svelte-16ocdv9{opacity:1;animation:svelte-16ocdv9-animot-arrow-head-disappear var(--arrow-anim-duration, .5s) ease-out forwards}.arrow-animate-draw-undraw.svelte-16ocdv9 .arrow-head:where(.svelte-16ocdv9),.arrow-head-draw-undraw.svelte-16ocdv9{opacity:0;animation:svelte-16ocdv9-animot-arrow-head-draw-undraw var(--arrow-anim-duration, .5s) ease-out forwards}.arrow-animate-grow.svelte-16ocdv9{transform-origin:left center;animation:svelte-16ocdv9-animot-arrow-grow var(--arrow-anim-duration, .5s) ease-out forwards}@keyframes svelte-16ocdv9-animot-arrow-draw{to{stroke-dashoffset:0}}@keyframes svelte-16ocdv9-animot-arrow-undraw{0%{stroke-dashoffset:0}to{stroke-dashoffset:1000}}@keyframes svelte-16ocdv9-animot-arrow-draw-undraw{0%{stroke-dashoffset:1000}50%{stroke-dashoffset:0}to{stroke-dashoffset:1000}}@keyframes svelte-16ocdv9-animot-arrow-head-appear{0%{opacity:0}to{opacity:1}}@keyframes svelte-16ocdv9-animot-arrow-head-disappear{0%{opacity:1}70%{opacity:1}to{opacity:0}}@keyframes svelte-16ocdv9-animot-arrow-head-draw-undraw{0%{opacity:0}35%{opacity:1}65%{opacity:1}to{opacity:0}}@keyframes svelte-16ocdv9-animot-arrow-grow{0%{transform:scaleX(0);opacity:0}to{transform:scaleX(1);opacity:1}}.animot-image-element.svelte-16ocdv9{width:100%;height:100%;display:block}.animot-shape-element.svelte-16ocdv9{width:100%;height:100%;display:block;overflow:visible}.animot-canvas.svelte-16ocdv9{--transition-duration: .5s;transition:transform calc(var(--transition-duration) * .4) ease,opacity calc(var(--transition-duration) * .4) ease}.animot-canvas.transition-fade-out.svelte-16ocdv9{opacity:0}.animot-canvas.transition-fade-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-fadeIn calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-left-out.forward.svelte-16ocdv9{transform:translate(-100%);opacity:0}.animot-canvas.transition-slide-left-in.forward.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromRight calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-left-out.backward.svelte-16ocdv9{transform:translate(100%);opacity:0}.animot-canvas.transition-slide-left-in.backward.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromLeft calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-right-out.forward.svelte-16ocdv9{transform:translate(100%);opacity:0}.animot-canvas.transition-slide-right-in.forward.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromLeft calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-up-out.svelte-16ocdv9{transform:translateY(-100%);opacity:0}.animot-canvas.transition-slide-up-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromBottom calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-down-out.svelte-16ocdv9{transform:translateY(100%);opacity:0}.animot-canvas.transition-slide-down-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromTop calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-zoom-in-out.svelte-16ocdv9{transform:scale(.5);opacity:0}.animot-canvas.transition-zoom-in-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-zoomIn calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-zoom-out-out.svelte-16ocdv9{transform:scale(1.5);opacity:0}.animot-canvas.transition-zoom-out-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-zoomOut calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-flip-out.svelte-16ocdv9{transform:perspective(1000px) rotateY(90deg);opacity:0}.animot-canvas.transition-flip-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-flipIn calc(var(--transition-duration) * .6) ease forwards}@keyframes svelte-16ocdv9-animot-fadeIn{0%{opacity:0}to{opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromRight{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromLeft{0%{transform:translate(-100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromBottom{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromTop{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes svelte-16ocdv9-animot-zoomIn{0%{transform:scale(.5);opacity:0}to{transform:scale(1);opacity:1}}@keyframes svelte-16ocdv9-animot-zoomOut{0%{transform:scale(1.5);opacity:0}to{transform:scale(1);opacity:1}}@keyframes svelte-16ocdv9-animot-flipIn{0%{transform:perspective(1000px) rotateY(-90deg);opacity:0}to{transform:perspective(1000px) rotateY(0);opacity:1}}.animot-canvas.transition-flip-x-out.svelte-16ocdv9{transform:perspective(1000px) rotateX(90deg);opacity:0}.animot-canvas.transition-flip-x-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-flipXIn calc(var(--transition-duration) * .6) ease forwards}@keyframes svelte-16ocdv9-animot-flipXIn{0%{transform:perspective(1000px) rotateX(-90deg);opacity:0}to{transform:perspective(1000px) rotateX(0);opacity:1}}.animot-canvas.transition-flip-y-out.svelte-16ocdv9{transform:perspective(1000px) rotateY(90deg);opacity:0}.animot-canvas.transition-flip-y-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-flipYIn calc(var(--transition-duration) * .6) ease forwards}@keyframes svelte-16ocdv9-animot-flipYIn{0%{transform:perspective(1000px) rotateY(-90deg);opacity:0}to{transform:perspective(1000px) rotateY(0);opacity:1}}.animot-svg-element.svelte-16ocdv9{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.animot-svg-element.svelte-16ocdv9 svg{width:100%;height:100%}.animot-controls.svelte-16ocdv9{position:absolute;bottom:12px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:8px;padding:8px 16px;background:#000000b3;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:10px;opacity:0;transition:opacity .3s ease .15s;z-index:100}.animot-presenter.svelte-16ocdv9:hover .animot-controls:where(.svelte-16ocdv9),.animot-menu-visible.svelte-16ocdv9 .animot-controls:where(.svelte-16ocdv9){opacity:1;transition-delay:0s}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9){display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:6px;border:none;cursor:pointer;background:#ffffff1a;color:#fff;transition:background .2s}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9):hover:not(:disabled){background:#fff3}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9):disabled{opacity:.3;cursor:not-allowed}.animot-controls.svelte-16ocdv9 button.active:where(.svelte-16ocdv9){background:#6366f199}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9) svg:where(.svelte-16ocdv9){width:16px;height:16px}.animot-slide-indicator.svelte-16ocdv9{font-size:12px;color:#fff;min-width:50px;text-align:center;font-family:system-ui,sans-serif}.animot-arrow.svelte-16ocdv9{position:absolute;top:50%;transform:translateY(-50%);width:40px;height:40px;border-radius:50%;border:none;cursor:pointer;background:#00000080;color:#fff;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .3s .15s;z-index:100;padding:0;margin:0}.animot-presenter.svelte-16ocdv9:hover .animot-arrow:where(.svelte-16ocdv9){opacity:1;transition-delay:0s}.animot-presenter.svelte-16ocdv9:hover .animot-arrow:where(.svelte-16ocdv9):disabled{opacity:.3;cursor:not-allowed}.animot-arrow.svelte-16ocdv9:hover:not(:disabled){background:#000000b3}.animot-arrow.svelte-16ocdv9 svg:where(.svelte-16ocdv9){width:20px;height:20px}.animot-arrow-left.svelte-16ocdv9{left:8px}.animot-arrow-right.svelte-16ocdv9{right:8px}.animot-progress-bar.svelte-16ocdv9{position:absolute;bottom:0;left:0;right:0;height:3px;background:#ffffff1a;z-index:100;opacity:0;transition:opacity .3s .15s}.animot-presenter.svelte-16ocdv9:hover .animot-progress-bar:where(.svelte-16ocdv9){opacity:1;transition-delay:0s}.animot-progress-fill.svelte-16ocdv9{height:100%;background:linear-gradient(135deg,#7c3aed,#ec4899);transition:width .6s ease}.animot-loading.svelte-16ocdv9{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.animot-spinner.svelte-16ocdv9{width:32px;height:32px;border:3px solid rgba(255,255,255,.2);border-top-color:#7c3aed;border-radius:50%;animation:svelte-16ocdv9-animot-spin .8s linear infinite}@keyframes svelte-16ocdv9-animot-spin{to{transform:rotate(360deg)}}.animot-error.svelte-16ocdv9{color:#ef4444;padding:20px;text-align:center;font-family:system-ui,sans-serif}