accessify-widget 0.3.79 → 0.3.81

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.
@@ -4,34 +4,105 @@ function createAnimationStopModule() {
4
4
  const STORAGE_KEY = "accessify-animation-stop";
5
5
  let mutationObserver = null;
6
6
  let scanInterval = null;
7
+ let scrollHandler = null;
7
8
  let originalVideoPlay = null;
8
9
  let originalAnimate = null;
10
+ let pausedVideos = [];
9
11
  let gifOriginals = /* @__PURE__ */ new Map();
10
- let debounceTimer = null;
11
- let delayedTimers = [];
12
- const WIDGET_SEL = ":not(#accessify-root):not(#accessify-root *)";
13
- function isWidgetElement(el) {
12
+ const VISUAL_ONLY_PROPS = /* @__PURE__ */ new Set([
13
+ "transform",
14
+ "scale",
15
+ "rotate",
16
+ "translate",
17
+ "filter",
18
+ "backdropFilter",
19
+ "backdrop-filter",
20
+ "webkitTransform",
21
+ "webkitFilter",
22
+ "-webkit-transform",
23
+ "-webkit-filter",
24
+ "offset",
25
+ "easing",
26
+ "composite"
27
+ ]);
28
+ function isVisualOnlyKeyframes(keyframes) {
29
+ if (!keyframes) return false;
14
30
  try {
15
- let node = el;
16
- while (node) {
17
- if (node.id === "accessify-root") return true;
18
- const parent = node.parentNode || node.host || null;
19
- if (parent === node) break;
20
- node = parent;
31
+ if (Array.isArray(keyframes)) {
32
+ for (const kf of keyframes) {
33
+ if (!kf || typeof kf !== "object") return false;
34
+ for (const key of Object.keys(kf)) {
35
+ if (!VISUAL_ONLY_PROPS.has(key)) return false;
36
+ }
37
+ }
38
+ return true;
39
+ }
40
+ for (const key of Object.keys(keyframes)) {
41
+ if (!VISUAL_ONLY_PROPS.has(key)) return false;
21
42
  }
43
+ return true;
22
44
  } catch {
45
+ return false;
46
+ }
47
+ }
48
+ function patchAnimate() {
49
+ if (originalAnimate) return;
50
+ originalAnimate = Element.prototype.animate;
51
+ Element.prototype.animate = function(keyframes, options) {
52
+ if (!enabled) {
53
+ return originalAnimate.call(this, keyframes, options);
54
+ }
55
+ try {
56
+ let node = this;
57
+ while (node) {
58
+ if (node.id === "accessify-root") {
59
+ return originalAnimate.call(this, keyframes, options);
60
+ }
61
+ const parent = node.parentNode || node.host;
62
+ if (parent === node) break;
63
+ node = parent;
64
+ }
65
+ } catch {
66
+ }
67
+ const visualOnly = isVisualOnlyKeyframes(keyframes);
68
+ let opts;
69
+ if (typeof options === "number") {
70
+ opts = { duration: 1e-3, fill: "forwards" };
71
+ } else {
72
+ opts = {
73
+ ...options || {},
74
+ duration: 1e-3,
75
+ delay: 0,
76
+ iterations: 1,
77
+ fill: "forwards"
78
+ };
79
+ delete opts.iterationStart;
80
+ delete opts.endDelay;
81
+ }
82
+ const anim = originalAnimate.call(this, keyframes, opts);
83
+ try {
84
+ if (visualOnly) {
85
+ anim.cancel();
86
+ } else {
87
+ anim.finish();
88
+ }
89
+ } catch {
90
+ }
91
+ return anim;
92
+ };
93
+ }
94
+ function restoreAnimate() {
95
+ if (originalAnimate) {
96
+ Element.prototype.animate = originalAnimate;
97
+ originalAnimate = null;
23
98
  }
24
- return false;
25
99
  }
26
100
  function injectStyles() {
27
101
  if (document.getElementById(STYLE_ID)) return;
28
102
  const style = document.createElement("style");
29
103
  style.id = STYLE_ID;
30
104
  style.textContent = `
31
- /* --- Kill all CSS-driven animations & transitions --- */
32
- *${WIDGET_SEL},
33
- *${WIDGET_SEL}::before,
34
- *${WIDGET_SEL}::after {
105
+ *, *::before, *::after {
35
106
  animation-duration: 0.001ms !important;
36
107
  animation-iteration-count: 1 !important;
37
108
  animation-delay: 0s !important;
@@ -42,42 +113,19 @@ function createAnimationStopModule() {
42
113
  animation-timeline: auto !important;
43
114
  scroll-timeline: none !important;
44
115
  }
45
-
46
- /* --- Force Framer appear-elements visible --- *
47
- * Framer sets inline opacity:0.001 + transform:translateY(...)
48
- * on elements waiting for scroll/appear animations. We override
49
- * with !important which beats inline styles. When animation-stop
50
- * is deactivated, removing this stylesheet instantly restores
51
- * Framer's inline values — no cleanup needed. */
52
- [data-framer-appear-id]${WIDGET_SEL} {
53
- opacity: 1 !important;
116
+ /* Neutralize interaction transforms (hover zoom, click scale, focus
117
+ lift). Without this, CSS like \`.card:hover { transform: scale(1.05) }\`
118
+ still visibly changes the element — just instantly. Users who
119
+ disable animations expect NO motion including the end-state. */
120
+ *:not(#accessify-root):not(#accessify-root *):hover,
121
+ *:not(#accessify-root):not(#accessify-root *):focus,
122
+ *:not(#accessify-root):not(#accessify-root *):focus-within,
123
+ *:not(#accessify-root):not(#accessify-root *):focus-visible,
124
+ *:not(#accessify-root):not(#accessify-root *):active {
54
125
  transform: none !important;
55
- }
56
-
57
- /* --- Force any inline-hidden elements visible ---
58
- * Some animation frameworks (AOS, wow.js, Framer scroll) hide
59
- * elements via inline opacity:0 or visibility:hidden. */
60
- [style*="opacity: 0"]${WIDGET_SEL},
61
- [style*="opacity:0"]${WIDGET_SEL} {
62
- opacity: 1 !important;
63
- }
64
- [style*="visibility: hidden"]${WIDGET_SEL},
65
- [style*="visibility:hidden"]${WIDGET_SEL} {
66
- visibility: visible !important;
67
- }
68
-
69
- /* --- Neutralize interaction transforms --- */
70
- *${WIDGET_SEL}:hover,
71
- *${WIDGET_SEL}:focus,
72
- *${WIDGET_SEL}:focus-within,
73
- *${WIDGET_SEL}:focus-visible,
74
- *${WIDGET_SEL}:active {
75
- transform: none !important;
76
- scale: 1 !important;
77
- rotate: 0deg !important;
78
- translate: 0 0 !important;
79
- filter: none !important;
80
- -webkit-filter: none !important;
126
+ scale: none !important;
127
+ rotate: none !important;
128
+ translate: none !important;
81
129
  }
82
130
  `;
83
131
  document.head.appendChild(style);
@@ -89,58 +137,35 @@ function createAnimationStopModule() {
89
137
  try {
90
138
  const target = anim.effect?.target;
91
139
  if (!target) return false;
92
- return isWidgetElement(target);
140
+ let node = target;
141
+ while (node) {
142
+ if (node.id === "accessify-root") return true;
143
+ const parent = node.parentNode || node.host;
144
+ if (parent === node) break;
145
+ node = parent;
146
+ }
93
147
  } catch {
94
148
  }
95
149
  return false;
96
150
  }
97
- function cancelAllAnimations() {
151
+ function finishAllAnimations() {
98
152
  try {
99
153
  const animations = document.getAnimations?.();
100
154
  if (!animations) return;
101
155
  for (const anim of animations) {
102
156
  if (isWidgetAnimation(anim)) continue;
103
157
  try {
104
- anim.cancel();
158
+ anim.finish();
105
159
  } catch {
160
+ try {
161
+ anim.cancel();
162
+ } catch {
163
+ }
106
164
  }
107
165
  }
108
166
  } catch {
109
167
  }
110
168
  }
111
- function patchAnimate() {
112
- if (originalAnimate) return;
113
- originalAnimate = Element.prototype.animate;
114
- Element.prototype.animate = function(keyframes, options) {
115
- if (!enabled) {
116
- return originalAnimate.call(this, keyframes, options);
117
- }
118
- if (isWidgetElement(this)) {
119
- return originalAnimate.call(this, keyframes, options);
120
- }
121
- const opts = typeof options === "number" ? { duration: 1e-3, fill: "none" } : {
122
- ...options || {},
123
- duration: 1e-3,
124
- delay: 0,
125
- iterations: 1,
126
- fill: "none"
127
- };
128
- delete opts.iterationStart;
129
- delete opts.endDelay;
130
- const anim = originalAnimate.call(this, keyframes, opts);
131
- try {
132
- anim.cancel();
133
- } catch {
134
- }
135
- return anim;
136
- };
137
- }
138
- function restoreAnimate() {
139
- if (originalAnimate) {
140
- Element.prototype.animate = originalAnimate;
141
- originalAnimate = null;
142
- }
143
- }
144
169
  function patchGSAP() {
145
170
  const g = window.gsap;
146
171
  if (g?.globalTimeline) {
@@ -161,11 +186,111 @@ function createAnimationStopModule() {
161
186
  }
162
187
  }
163
188
  }
189
+ function forceHiddenElementsVisible() {
190
+ const viewH = window.innerHeight;
191
+ const margin = viewH * 1.5;
192
+ const all = document.querySelectorAll("*");
193
+ for (const el of all) {
194
+ if (el.tagName === "SCRIPT" || el.tagName === "STYLE" || el.tagName === "NOSCRIPT" || el.tagName === "META" || el.tagName === "LINK") continue;
195
+ if (el.closest("#accessify-root") || el.closest("accessify-widget")) continue;
196
+ if (el.dataset.a11yOrigStyle) continue;
197
+ const computed = window.getComputedStyle(el);
198
+ if (computed.display === "none") continue;
199
+ const rect = el.getBoundingClientRect();
200
+ if (rect.top > viewH + margin) continue;
201
+ if (rect.bottom < -margin) continue;
202
+ const inline = el.style;
203
+ let needsFix = false;
204
+ const originals = {};
205
+ const opacityVal = parseFloat(computed.opacity);
206
+ if (opacityVal < 0.1 && inline.opacity !== "") {
207
+ originals.opacity = inline.opacity;
208
+ el.style.opacity = "1";
209
+ needsFix = true;
210
+ } else if (opacityVal < 0.1 && el.hasAttribute("data-framer-appear-id")) {
211
+ originals.opacity = inline.opacity || "";
212
+ el.style.opacity = "1";
213
+ needsFix = true;
214
+ }
215
+ if (inline.transform && /translate[XY]\([^0]/.test(inline.transform)) {
216
+ originals.transform = inline.transform;
217
+ el.style.transform = "none";
218
+ needsFix = true;
219
+ }
220
+ if (inline.visibility === "hidden") {
221
+ originals.visibility = inline.visibility;
222
+ el.style.visibility = "visible";
223
+ needsFix = true;
224
+ }
225
+ if (inline.clipPath && inline.clipPath !== "none") {
226
+ originals.clipPath = inline.clipPath;
227
+ el.style.clipPath = "none";
228
+ needsFix = true;
229
+ }
230
+ if (needsFix) {
231
+ el.dataset.a11yOrigStyle = JSON.stringify(originals);
232
+ }
233
+ }
234
+ }
235
+ function restoreHiddenElements() {
236
+ document.querySelectorAll("[data-a11y-orig-style]").forEach((el) => {
237
+ try {
238
+ const orig = JSON.parse(el.dataset.a11yOrigStyle || "{}");
239
+ for (const [prop, val] of Object.entries(orig)) {
240
+ if (val === "") {
241
+ el.style.removeProperty(prop);
242
+ } else {
243
+ el.style[prop] = val;
244
+ }
245
+ }
246
+ } catch {
247
+ }
248
+ delete el.dataset.a11yOrigStyle;
249
+ });
250
+ }
251
+ function freezeScrollAnimations() {
252
+ document.querySelectorAll("[style]").forEach((el) => {
253
+ if (el.closest("#accessify-root") || el.closest("accessify-widget")) return;
254
+ if (el.dataset.a11yFrozenStyle) return;
255
+ const s = el.style;
256
+ if (s.transform || s.opacity) {
257
+ el.dataset.a11yFrozenStyle = JSON.stringify({
258
+ transform: s.transform || "",
259
+ opacity: s.opacity || ""
260
+ });
261
+ }
262
+ });
263
+ if (!scrollHandler) {
264
+ scrollHandler = () => {
265
+ if (!enabled) return;
266
+ document.querySelectorAll("[data-a11y-frozen-style]").forEach((el) => {
267
+ try {
268
+ const frozen = JSON.parse(el.dataset.a11yFrozenStyle || "{}");
269
+ if (frozen.transform && el.style.transform !== frozen.transform) {
270
+ el.style.transform = frozen.transform;
271
+ }
272
+ } catch {
273
+ }
274
+ });
275
+ };
276
+ window.addEventListener("scroll", scrollHandler, { passive: true, capture: true });
277
+ }
278
+ }
279
+ function unfreezeScrollAnimations() {
280
+ if (scrollHandler) {
281
+ window.removeEventListener("scroll", scrollHandler, true);
282
+ scrollHandler = null;
283
+ }
284
+ document.querySelectorAll("[data-a11y-frozen-style]").forEach((el) => {
285
+ delete el.dataset.a11yFrozenStyle;
286
+ });
287
+ }
164
288
  function pauseAllVideos() {
165
289
  document.querySelectorAll("video").forEach((v) => {
166
290
  if (!v.paused) {
167
291
  v.dataset.a11yPaused = "true";
168
292
  v.pause();
293
+ pausedVideos.push(v);
169
294
  }
170
295
  });
171
296
  }
@@ -192,6 +317,7 @@ function createAnimationStopModule() {
192
317
  }
193
318
  delete v.dataset.a11yPaused;
194
319
  });
320
+ pausedVideos = [];
195
321
  }
196
322
  function freezeGif(img) {
197
323
  const src = (img.currentSrc || img.src || "").toLowerCase();
@@ -260,16 +386,6 @@ function createAnimationStopModule() {
260
386
  }
261
387
  });
262
388
  }
263
- function debouncedRescan() {
264
- if (debounceTimer) clearTimeout(debounceTimer);
265
- debounceTimer = setTimeout(() => {
266
- if (!enabled) return;
267
- cancelAllAnimations();
268
- pauseAllVideos();
269
- freezeAllGifs();
270
- pauseSVG();
271
- }, 150);
272
- }
273
389
  function setupObserver() {
274
390
  if (mutationObserver) return;
275
391
  mutationObserver = new MutationObserver((mutations) => {
@@ -282,7 +398,11 @@ function createAnimationStopModule() {
282
398
  }
283
399
  }
284
400
  if (hasNewContent) {
285
- debouncedRescan();
401
+ finishAllAnimations();
402
+ forceHiddenElementsVisible();
403
+ pauseAllVideos();
404
+ freezeAllGifs();
405
+ pauseSVG();
286
406
  }
287
407
  });
288
408
  mutationObserver.observe(document.body, { childList: true, subtree: true });
@@ -290,17 +410,13 @@ function createAnimationStopModule() {
290
410
  function teardownObserver() {
291
411
  mutationObserver?.disconnect();
292
412
  mutationObserver = null;
293
- if (debounceTimer) {
294
- clearTimeout(debounceTimer);
295
- debounceTimer = null;
296
- }
297
413
  }
298
414
  function startPeriodicScan() {
299
415
  if (scanInterval) return;
300
416
  scanInterval = setInterval(() => {
301
417
  if (!enabled) return;
302
- cancelAllAnimations();
303
- }, 2e3);
418
+ finishAllAnimations();
419
+ }, 500);
304
420
  }
305
421
  function stopPeriodicScan() {
306
422
  if (scanInterval) {
@@ -313,8 +429,10 @@ function createAnimationStopModule() {
313
429
  enabled = true;
314
430
  patchAnimate();
315
431
  injectStyles();
316
- cancelAllAnimations();
432
+ finishAllAnimations();
317
433
  patchGSAP();
434
+ forceHiddenElementsVisible();
435
+ freezeScrollAnimations();
318
436
  pauseAllVideos();
319
437
  interceptVideoPlay();
320
438
  freezeAllGifs();
@@ -322,29 +440,26 @@ function createAnimationStopModule() {
322
440
  stopMarquees();
323
441
  setupObserver();
324
442
  startPeriodicScan();
325
- const schedule = (fn, ms) => setTimeout(() => {
326
- if (enabled) fn();
327
- }, ms);
328
- delayedTimers.push(schedule(() => {
329
- cancelAllAnimations();
330
- pauseAllVideos();
331
- freezeAllGifs();
332
- }, 500));
333
- delayedTimers.push(schedule(() => {
334
- cancelAllAnimations();
335
- pauseAllVideos();
336
- freezeAllGifs();
337
- }, 2e3));
443
+ for (const delay of [50, 200, 500, 1e3, 2e3, 4e3]) {
444
+ setTimeout(() => {
445
+ if (!enabled) return;
446
+ finishAllAnimations();
447
+ forceHiddenElementsVisible();
448
+ freezeScrollAnimations();
449
+ pauseAllVideos();
450
+ freezeAllGifs();
451
+ }, delay);
452
+ }
338
453
  localStorage.setItem(STORAGE_KEY, "true");
339
454
  }
340
455
  function deactivate() {
341
456
  enabled = false;
342
- for (const t of delayedTimers) clearTimeout(t);
343
- delayedTimers = [];
344
457
  stopPeriodicScan();
345
458
  teardownObserver();
346
459
  restoreAnimate();
460
+ unfreezeScrollAnimations();
347
461
  restoreGSAP();
462
+ restoreHiddenElements();
348
463
  startMarquees();
349
464
  resumeSVG();
350
465
  restoreAllGifs();
@@ -370,4 +485,4 @@ function createAnimationStopModule() {
370
485
  export {
371
486
  createAnimationStopModule as default
372
487
  };
373
- //# sourceMappingURL=animation-stop-_C-YdTs3.js.map
488
+ //# sourceMappingURL=animation-stop-C2Ced0LV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animation-stop-C2Ced0LV.js","sources":["../src/features/animation-stop.ts"],"sourcesContent":["import type { FeatureModule, FeatureState } from '../types';\n\n/**\n * Animation Stop – V4 (Clean 3-Layer Approach)\n *\n * Layer 1: CSS injection — kill all CSS animations/transitions via 0.001ms duration\n * Layer 2: Web Animations API — finish() all running WAAPI animations (Framer Motion etc.)\n * Layer 3: JS library detection — GSAP globalTimeline, inline-style freeze for rAF-based libs\n * Layer 4: Media — pause videos, freeze GIFs, stop SVG SMIL, stop marquees\n *\n * + MutationObserver for dynamic content\n * + Periodic re-scan (every 500ms) for frameworks that create new animations\n *\n * DOES NOT:\n * - Monkey-patch IntersectionObserver (breaks lazy loading)\n * - Override requestAnimationFrame (breaks entire page)\n * - Override Element.prototype.animate() (too invasive)\n * - Override matchMedia (too invasive)\n * - Set opacity:1 !important via CSS (breaks modals/hidden elements)\n * - Use animation:none or transition:none (breaks JS events)\n */\nexport default function createAnimationStopModule(): FeatureModule {\n let enabled = false;\n const STYLE_ID = 'a11y-stop-animations';\n const STORAGE_KEY = 'accessify-animation-stop';\n\n // --- State ---\n let mutationObserver: MutationObserver | null = null;\n let scanInterval: ReturnType<typeof setInterval> | null = null;\n let scrollHandler: (() => void) | null = null;\n let originalVideoPlay: typeof HTMLVideoElement.prototype.play | null = null;\n let originalAnimate: typeof Element.prototype.animate | null = null;\n let pausedVideos: HTMLVideoElement[] = [];\n let gifOriginals = new Map<HTMLImageElement, string>();\n\n // =========================================================================\n // Layer 0: Element.prototype.animate() intercept\n //\n // This is THE critical piece for Framer Motion. Framer uses WAAPI\n // (Element.prototype.animate()) for ALL visual animations — hover,\n // appear, scroll, transitions. CSS rules do NOT affect WAAPI.\n // We intercept at creation time and force duration to 0.001ms\n // so every animation completes instantly.\n // =========================================================================\n\n /**\n * Detect animations whose keyframes only modify transform-like or filter\n * properties. These are the signature of interaction animations (hover\n * zoom, click scale, focus rings) that Framer Motion and similar libs\n * create on-the-fly. We must CANCEL these instead of FINISHING them,\n * otherwise the element lands in the visible end-state (e.g. scale(1.05)).\n */\n const VISUAL_ONLY_PROPS = new Set([\n 'transform', 'scale', 'rotate', 'translate',\n 'filter', 'backdropFilter', 'backdrop-filter',\n 'webkitTransform', 'webkitFilter', '-webkit-transform', '-webkit-filter',\n 'offset', 'easing', 'composite',\n ]);\n function isVisualOnlyKeyframes(\n keyframes: Keyframe[] | PropertyIndexedKeyframes | null,\n ): boolean {\n if (!keyframes) return false;\n try {\n if (Array.isArray(keyframes)) {\n for (const kf of keyframes) {\n if (!kf || typeof kf !== 'object') return false;\n for (const key of Object.keys(kf)) {\n if (!VISUAL_ONLY_PROPS.has(key)) return false;\n }\n }\n return true;\n }\n // PropertyIndexedKeyframes\n for (const key of Object.keys(keyframes)) {\n if (!VISUAL_ONLY_PROPS.has(key)) return false;\n }\n return true;\n } catch {\n return false;\n }\n }\n\n function patchAnimate() {\n if (originalAnimate) return;\n originalAnimate = Element.prototype.animate;\n\n Element.prototype.animate = function (\n this: Element,\n keyframes: Keyframe[] | PropertyIndexedKeyframes | null,\n options?: number | KeyframeAnimationOptions,\n ): Animation {\n if (!enabled) {\n return originalAnimate!.call(this, keyframes, options);\n }\n\n // Never interfere with the widget's own animations. The widget lives\n // in shadow DOM under #accessify-root — walk up through shadow roots\n // and skip if we find the accessify host.\n try {\n let node: Node | null = this;\n while (node) {\n if ((node as Element).id === 'accessify-root') {\n return originalAnimate!.call(this, keyframes, options);\n }\n const parent = (node as any).parentNode || (node as any).host;\n if (parent === node) break;\n node = parent;\n }\n } catch { /* ignore */ }\n\n const visualOnly = isVisualOnlyKeyframes(keyframes);\n\n // Force instant completion: duration 0.001ms, no delay, 1 iteration, fill forwards\n let opts: KeyframeAnimationOptions;\n if (typeof options === 'number') {\n opts = { duration: 0.001, fill: 'forwards' as FillMode };\n } else {\n opts = {\n ...(options || {}),\n duration: 0.001,\n delay: 0,\n iterations: 1,\n fill: 'forwards' as FillMode,\n };\n // Remove iterationStart, endDelay etc. that could interfere\n delete (opts as any).iterationStart;\n delete (opts as any).endDelay;\n }\n\n const anim = originalAnimate!.call(this, keyframes, opts);\n try {\n if (visualOnly) {\n anim.cancel();\n } else {\n anim.finish();\n }\n } catch { /* ignore */ }\n return anim;\n };\n }\n\n function restoreAnimate() {\n if (originalAnimate) {\n Element.prototype.animate = originalAnimate;\n originalAnimate = null;\n }\n }\n\n // =========================================================================\n // Layer 1: CSS Injection\n // =========================================================================\n\n function injectStyles() {\n if (document.getElementById(STYLE_ID)) return;\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = `\n *, *::before, *::after {\n animation-duration: 0.001ms !important;\n animation-iteration-count: 1 !important;\n animation-delay: 0s !important;\n animation-fill-mode: forwards !important;\n transition-duration: 0.001ms !important;\n transition-delay: 0s !important;\n scroll-behavior: auto !important;\n animation-timeline: auto !important;\n scroll-timeline: none !important;\n }\n /* Neutralize interaction transforms (hover zoom, click scale, focus\n lift). Without this, CSS like \\`.card:hover { transform: scale(1.05) }\\`\n still visibly changes the element — just instantly. Users who\n disable animations expect NO motion including the end-state. */\n *:not(#accessify-root):not(#accessify-root *):hover,\n *:not(#accessify-root):not(#accessify-root *):focus,\n *:not(#accessify-root):not(#accessify-root *):focus-within,\n *:not(#accessify-root):not(#accessify-root *):focus-visible,\n *:not(#accessify-root):not(#accessify-root *):active {\n transform: none !important;\n scale: none !important;\n rotate: none !important;\n translate: none !important;\n }\n `;\n document.head.appendChild(style);\n }\n\n function removeStyles() {\n document.getElementById(STYLE_ID)?.remove();\n }\n\n // =========================================================================\n // Layer 2: Web Animations API — finish all WAAPI animations\n // =========================================================================\n\n function isWidgetAnimation(anim: Animation): boolean {\n try {\n const target = (anim.effect as any)?.target as Element | null;\n if (!target) return false;\n let node: Node | null = target;\n while (node) {\n if ((node as Element).id === 'accessify-root') return true;\n const parent = (node as any).parentNode || (node as any).host;\n if (parent === node) break;\n node = parent;\n }\n } catch { /* ignore */ }\n return false;\n }\n\n function finishAllAnimations() {\n try {\n const animations = document.getAnimations?.();\n if (!animations) return;\n for (const anim of animations) {\n if (isWidgetAnimation(anim)) continue;\n try {\n anim.finish();\n } catch {\n try { anim.cancel(); } catch { /* ignore */ }\n }\n }\n } catch { /* getAnimations not supported */ }\n }\n\n // =========================================================================\n // Layer 3: JS animation library detection + inline style freeze\n // =========================================================================\n\n function patchGSAP() {\n const g = (window as any).gsap;\n if (g?.globalTimeline) {\n try {\n g.globalTimeline.timeScale(0);\n (window as any)._a11yGsapPatched = true;\n } catch { /* ignore */ }\n }\n }\n\n function restoreGSAP() {\n const g = (window as any).gsap;\n if ((window as any)._a11yGsapPatched && g?.globalTimeline) {\n try {\n g.globalTimeline.timeScale(1);\n delete (window as any)._a11yGsapPatched;\n } catch { /* ignore */ }\n }\n }\n\n /**\n * Force hidden-by-animation elements visible.\n * Only touches INLINE styles — never sets CSS !important on opacity etc.\n * which would break modals and intentionally hidden elements.\n */\n function forceHiddenElementsVisible() {\n // Only process elements near the viewport to avoid layout chaos on\n // Framer/scroll-animated pages where dozens of off-screen elements\n // are hidden via opacity:0 / translateY as part of scroll reveals.\n const viewH = window.innerHeight;\n const margin = viewH * 1.5; // 1.5x viewport ahead\n\n const all = document.querySelectorAll<HTMLElement>('*');\n for (const el of all) {\n if (el.tagName === 'SCRIPT' || el.tagName === 'STYLE' || el.tagName === 'NOSCRIPT' || el.tagName === 'META' || el.tagName === 'LINK') continue;\n if (el.closest('#accessify-root') || el.closest('accessify-widget')) continue;\n if (el.dataset.a11yOrigStyle) continue; // Already processed\n\n const computed = window.getComputedStyle(el);\n if (computed.display === 'none') continue; // Intentionally hidden\n\n // Skip elements far below the current scroll position —\n // they will be handled when the user scrolls to them (periodic re-scan).\n const rect = el.getBoundingClientRect();\n if (rect.top > viewH + margin) continue; // Too far below viewport\n // Also skip if entirely above viewport (already scrolled past)\n if (rect.bottom < -margin) continue;\n\n const inline = el.style;\n let needsFix = false;\n const originals: Record<string, string> = {};\n\n // Inline opacity 0 or near-0 (computed, not stylesheet)\n const opacityVal = parseFloat(computed.opacity);\n if (opacityVal < 0.1 && inline.opacity !== '') {\n originals.opacity = inline.opacity;\n el.style.opacity = '1';\n needsFix = true;\n } else if (opacityVal < 0.1 && el.hasAttribute('data-framer-appear-id')) {\n // Framer appear elements: opacity set via WAAPI or framework\n originals.opacity = inline.opacity || '';\n el.style.opacity = '1';\n needsFix = true;\n }\n\n // Inline transform with translate that moves element off-screen\n if (inline.transform && /translate[XY]\\([^0]/.test(inline.transform)) {\n originals.transform = inline.transform;\n el.style.transform = 'none';\n needsFix = true;\n }\n\n // Inline visibility hidden\n if (inline.visibility === 'hidden') {\n originals.visibility = inline.visibility;\n el.style.visibility = 'visible';\n needsFix = true;\n }\n\n // Inline clip-path that hides element\n if (inline.clipPath && inline.clipPath !== 'none') {\n originals.clipPath = inline.clipPath;\n el.style.clipPath = 'none';\n needsFix = true;\n }\n\n if (needsFix) {\n el.dataset.a11yOrigStyle = JSON.stringify(originals);\n }\n }\n }\n\n function restoreHiddenElements() {\n document.querySelectorAll<HTMLElement>('[data-a11y-orig-style]').forEach(el => {\n try {\n const orig: Record<string, string> = JSON.parse(el.dataset.a11yOrigStyle || '{}');\n for (const [prop, val] of Object.entries(orig)) {\n if (val === '') {\n el.style.removeProperty(prop);\n } else {\n (el.style as any)[prop] = val;\n }\n }\n } catch { /* malformed JSON */ }\n delete el.dataset.a11yOrigStyle;\n });\n }\n\n /**\n * Freeze inline-animated styles so scroll-handlers can't update them.\n * Takes a snapshot of current inline transforms and enforces them on scroll.\n */\n function freezeScrollAnimations() {\n document.querySelectorAll<HTMLElement>('[style]').forEach(el => {\n if (el.closest('#accessify-root') || el.closest('accessify-widget')) return;\n if (el.dataset.a11yFrozenStyle) return;\n const s = el.style;\n if (s.transform || s.opacity) {\n el.dataset.a11yFrozenStyle = JSON.stringify({\n transform: s.transform || '',\n opacity: s.opacity || '',\n });\n }\n });\n\n if (!scrollHandler) {\n scrollHandler = () => {\n if (!enabled) return;\n document.querySelectorAll<HTMLElement>('[data-a11y-frozen-style]').forEach(el => {\n try {\n const frozen = JSON.parse(el.dataset.a11yFrozenStyle || '{}');\n if (frozen.transform && el.style.transform !== frozen.transform) {\n el.style.transform = frozen.transform;\n }\n } catch { /* ignore */ }\n });\n };\n window.addEventListener('scroll', scrollHandler, { passive: true, capture: true });\n }\n }\n\n function unfreezeScrollAnimations() {\n if (scrollHandler) {\n window.removeEventListener('scroll', scrollHandler, true);\n scrollHandler = null;\n }\n document.querySelectorAll<HTMLElement>('[data-a11y-frozen-style]').forEach(el => {\n delete el.dataset.a11yFrozenStyle;\n });\n }\n\n // =========================================================================\n // Layer 4: Media\n // =========================================================================\n\n function pauseAllVideos() {\n document.querySelectorAll<HTMLVideoElement>('video').forEach(v => {\n if (!v.paused) {\n v.dataset.a11yPaused = 'true';\n v.pause();\n pausedVideos.push(v);\n }\n });\n }\n\n function interceptVideoPlay() {\n if (originalVideoPlay) return;\n originalVideoPlay = HTMLVideoElement.prototype.play;\n HTMLVideoElement.prototype.play = function () {\n if (enabled) return Promise.resolve();\n return originalVideoPlay!.call(this);\n };\n }\n\n function restoreVideoPlay() {\n if (originalVideoPlay) {\n HTMLVideoElement.prototype.play = originalVideoPlay;\n originalVideoPlay = null;\n }\n }\n\n function resumeAllVideos() {\n restoreVideoPlay();\n document.querySelectorAll<HTMLVideoElement>('video[data-a11y-paused]').forEach(v => {\n try { v.play(); } catch { /* gone */ }\n delete v.dataset.a11yPaused;\n });\n pausedVideos = [];\n }\n\n function freezeGif(img: HTMLImageElement) {\n const src = (img.currentSrc || img.src || '').toLowerCase();\n if (!src.match(/\\.gif(\\?|$)/i)) return;\n if (gifOriginals.has(img)) return;\n\n const doFreeze = () => {\n try {\n const w = img.naturalWidth || img.width;\n const h = img.naturalHeight || img.height;\n if (w === 0 || h === 0) return;\n const c = document.createElement('canvas');\n c.width = w; c.height = h;\n const ctx = c.getContext('2d');\n if (!ctx) return;\n ctx.drawImage(img, 0, 0);\n gifOriginals.set(img, img.src);\n img.src = c.toDataURL('image/png');\n } catch { /* CORS */ }\n };\n\n if (img.complete && img.naturalWidth > 0) doFreeze();\n else img.addEventListener('load', doFreeze, { once: true });\n }\n\n function freezeAllGifs() {\n document.querySelectorAll<HTMLImageElement>('img').forEach(freezeGif);\n }\n\n function restoreAllGifs() {\n for (const [img, src] of gifOriginals) {\n try { img.src = src; } catch { /* gone */ }\n }\n gifOriginals.clear();\n }\n\n function pauseSVG() {\n document.querySelectorAll('svg').forEach(s => {\n try { (s as any).pauseAnimations?.(); } catch { /* ignore */ }\n });\n }\n\n function resumeSVG() {\n document.querySelectorAll('svg').forEach(s => {\n try { (s as any).unpauseAnimations?.(); } catch { /* ignore */ }\n });\n }\n\n function stopMarquees() {\n document.querySelectorAll('marquee').forEach(m => {\n try { (m as any).stop?.(); } catch { /* ignore */ }\n });\n }\n\n function startMarquees() {\n document.querySelectorAll('marquee').forEach(m => {\n try { (m as any).start?.(); } catch { /* ignore */ }\n });\n }\n\n // =========================================================================\n // MutationObserver — dynamic content\n // =========================================================================\n\n function setupObserver() {\n if (mutationObserver) return;\n mutationObserver = new MutationObserver(mutations => {\n if (!enabled) return;\n let hasNewContent = false;\n for (const m of mutations) {\n if (m.addedNodes.length > 0) { hasNewContent = true; break; }\n }\n if (hasNewContent) {\n finishAllAnimations();\n forceHiddenElementsVisible();\n pauseAllVideos();\n freezeAllGifs();\n pauseSVG();\n }\n });\n mutationObserver.observe(document.body, { childList: true, subtree: true });\n }\n\n function teardownObserver() {\n mutationObserver?.disconnect();\n mutationObserver = null;\n }\n\n // =========================================================================\n // Periodic re-scan — frameworks create new animations constantly\n // =========================================================================\n\n function startPeriodicScan() {\n if (scanInterval) return;\n scanInterval = setInterval(() => {\n if (!enabled) return;\n finishAllAnimations();\n }, 500);\n }\n\n function stopPeriodicScan() {\n if (scanInterval) {\n clearInterval(scanInterval);\n scanInterval = null;\n }\n }\n\n // =========================================================================\n // Lifecycle\n // =========================================================================\n\n function activate() {\n if (enabled) return;\n enabled = true;\n\n // Layer 0: Intercept Element.animate() — catches ALL new WAAPI animations instantly\n patchAnimate();\n\n // Layer 1: CSS\n injectStyles();\n\n // Layer 2: Kill all currently running WAAPI animations\n finishAllAnimations();\n\n // Layer 3: JS libs + inline style fixes\n patchGSAP();\n forceHiddenElementsVisible();\n freezeScrollAnimations();\n\n // Layer 4: Media\n pauseAllVideos();\n interceptVideoPlay();\n freezeAllGifs();\n pauseSVG();\n stopMarquees();\n\n // Observers\n setupObserver();\n startPeriodicScan();\n\n // Delayed re-scans for async rendering frameworks\n for (const delay of [50, 200, 500, 1000, 2000, 4000]) {\n setTimeout(() => {\n if (!enabled) return;\n finishAllAnimations();\n forceHiddenElementsVisible();\n freezeScrollAnimations();\n pauseAllVideos();\n freezeAllGifs();\n }, delay);\n }\n\n localStorage.setItem(STORAGE_KEY, 'true');\n }\n\n function deactivate() {\n enabled = false;\n\n stopPeriodicScan();\n teardownObserver();\n restoreAnimate();\n unfreezeScrollAnimations();\n restoreGSAP();\n restoreHiddenElements();\n startMarquees();\n resumeSVG();\n restoreAllGifs();\n resumeAllVideos();\n removeStyles();\n\n localStorage.removeItem(STORAGE_KEY);\n }\n\n return {\n id: 'animation-stop',\n name: () => 'Stop Animations',\n description: 'Pause all animations, transitions, and auto-playing videos (WCAG 2.3.1)',\n icon: 'animation-stop',\n category: 'visual',\n activate,\n deactivate,\n getState: (): FeatureState => ({ id: 'animation-stop', enabled }),\n setState: (state: { enabled: boolean }) => {\n if (state.enabled) activate();\n else deactivate();\n },\n };\n}\n"],"names":[],"mappings":"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"}
@@ -6644,17 +6644,17 @@ function FeatureGrid($$anchor, $$props) {
6644
6644
  const FEATURE_LOADERS = {
6645
6645
  contrast: () => import("./contrast-CqsOs6Uo.js"),
6646
6646
  "text-size": () => import("./text-size-m_mHNPWo.js"),
6647
- "keyboard-nav": () => import("./keyboard-nav-C3G7ZKjD.js"),
6647
+ "keyboard-nav": () => import("./keyboard-nav-BZXsqIA2.js"),
6648
6648
  "link-highlight": () => import("./link-highlight-D9gxFmiG.js"),
6649
6649
  "reading-guide": () => import("./reading-guide-C_jxzorm.js"),
6650
6650
  "reading-mask": () => import("./reading-mask-B_NxbhTN.js"),
6651
- "animation-stop": () => import("./animation-stop-_C-YdTs3.js"),
6651
+ "animation-stop": () => import("./animation-stop-C2Ced0LV.js"),
6652
6652
  "hide-images": () => import("./hide-images-B_LeCBcd.js"),
6653
6653
  "big-cursor": () => import("./big-cursor-B2UKu9dQ.js"),
6654
- "page-structure": () => import("./page-structure-BuEeO_fi.js"),
6654
+ "page-structure": () => import("./page-structure-BKyxP7oX.js"),
6655
6655
  tts: () => import("./tts-zrXtEd07.js"),
6656
6656
  "text-simplify": () => import("./text-simplify-H4aHr88a.js"),
6657
- "alt-text": () => import("./alt-text-D_iJlJtX.js")
6657
+ "alt-text": () => import("./alt-text-By2PvE1U.js")
6658
6658
  };
6659
6659
  let contrastMode = /* @__PURE__ */ state(proxy(readStoredContrastMode()));
6660
6660
  let textSize = /* @__PURE__ */ state(proxy(readStoredTextSize()));
@@ -8332,7 +8332,7 @@ async function init(userConfig = {}) {
8332
8332
  window.removeEventListener("message", handleMessage);
8333
8333
  };
8334
8334
  document.body.appendChild(containerEl);
8335
- import("./alt-text-D_iJlJtX.js").then((m) => m.autoApplyCachedAltTexts(config)).catch(() => {
8335
+ import("./alt-text-By2PvE1U.js").then((m) => m.autoApplyCachedAltTexts(config)).catch(() => {
8336
8336
  });
8337
8337
  config.onReady?.();
8338
8338
  }
@@ -8377,4 +8377,4 @@ export {
8377
8377
  init as i,
8378
8378
  t
8379
8379
  };
8380
- //# sourceMappingURL=index-BUfTIuEG.js.map
8380
+ //# sourceMappingURL=index-B8IGMa5t.js.map