tribunal-kit 2.4.6 → 3.0.0

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.
Files changed (142) hide show
  1. package/.agent/agents/accessibility-reviewer.md +220 -134
  2. package/.agent/agents/ai-code-reviewer.md +233 -129
  3. package/.agent/agents/backend-specialist.md +238 -178
  4. package/.agent/agents/code-archaeologist.md +181 -119
  5. package/.agent/agents/database-architect.md +207 -164
  6. package/.agent/agents/debugger.md +218 -151
  7. package/.agent/agents/dependency-reviewer.md +136 -55
  8. package/.agent/agents/devops-engineer.md +238 -175
  9. package/.agent/agents/documentation-writer.md +221 -137
  10. package/.agent/agents/explorer-agent.md +180 -142
  11. package/.agent/agents/frontend-reviewer.md +194 -80
  12. package/.agent/agents/frontend-specialist.md +237 -188
  13. package/.agent/agents/game-developer.md +52 -184
  14. package/.agent/agents/logic-reviewer.md +149 -78
  15. package/.agent/agents/mobile-developer.md +223 -152
  16. package/.agent/agents/mobile-reviewer.md +195 -79
  17. package/.agent/agents/orchestrator.md +211 -170
  18. package/.agent/agents/penetration-tester.md +174 -131
  19. package/.agent/agents/performance-optimizer.md +203 -139
  20. package/.agent/agents/performance-reviewer.md +211 -108
  21. package/.agent/agents/product-manager.md +162 -108
  22. package/.agent/agents/project-planner.md +162 -142
  23. package/.agent/agents/qa-automation-engineer.md +242 -138
  24. package/.agent/agents/security-auditor.md +194 -170
  25. package/.agent/agents/seo-specialist.md +213 -132
  26. package/.agent/agents/sql-reviewer.md +194 -73
  27. package/.agent/agents/supervisor-agent.md +203 -156
  28. package/.agent/agents/test-coverage-reviewer.md +193 -81
  29. package/.agent/agents/type-safety-reviewer.md +208 -65
  30. package/.agent/scripts/__pycache__/auto_preview.cpython-311.pyc +0 -0
  31. package/.agent/scripts/__pycache__/bundle_analyzer.cpython-311.pyc +0 -0
  32. package/.agent/scripts/__pycache__/checklist.cpython-311.pyc +0 -0
  33. package/.agent/scripts/__pycache__/dependency_analyzer.cpython-311.pyc +0 -0
  34. package/.agent/scripts/__pycache__/security_scan.cpython-311.pyc +0 -0
  35. package/.agent/scripts/__pycache__/session_manager.cpython-311.pyc +0 -0
  36. package/.agent/scripts/__pycache__/skill_integrator.cpython-311.pyc +0 -0
  37. package/.agent/scripts/__pycache__/swarm_dispatcher.cpython-311.pyc +0 -0
  38. package/.agent/scripts/__pycache__/test_runner.cpython-311.pyc +0 -0
  39. package/.agent/scripts/__pycache__/verify_all.cpython-311.pyc +0 -0
  40. package/.agent/skills/agent-organizer/SKILL.md +126 -132
  41. package/.agent/skills/ai-prompt-injection-defense/SKILL.md +155 -66
  42. package/.agent/skills/api-patterns/SKILL.md +289 -257
  43. package/.agent/skills/api-security-auditor/SKILL.md +172 -70
  44. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +1 -1
  45. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +1 -1
  46. package/.agent/skills/appflow-wireframe/SKILL.md +107 -100
  47. package/.agent/skills/architecture/SKILL.md +331 -200
  48. package/.agent/skills/authentication-best-practices/SKILL.md +168 -67
  49. package/.agent/skills/bash-linux/SKILL.md +154 -215
  50. package/.agent/skills/brainstorming/SKILL.md +104 -210
  51. package/.agent/skills/building-native-ui/SKILL.md +169 -70
  52. package/.agent/skills/clean-code/SKILL.md +360 -206
  53. package/.agent/skills/config-validator/SKILL.md +141 -165
  54. package/.agent/skills/csharp-developer/SKILL.md +528 -107
  55. package/.agent/skills/database-design/SKILL.md +455 -275
  56. package/.agent/skills/deployment-procedures/SKILL.md +145 -188
  57. package/.agent/skills/devops-engineer/SKILL.md +332 -134
  58. package/.agent/skills/devops-incident-responder/SKILL.md +113 -98
  59. package/.agent/skills/edge-computing/SKILL.md +157 -213
  60. package/.agent/skills/extract-design-system/SKILL.md +129 -69
  61. package/.agent/skills/framer-motion-expert/SKILL.md +939 -0
  62. package/.agent/skills/game-design-expert/SKILL.md +105 -0
  63. package/.agent/skills/game-engineering-expert/SKILL.md +122 -0
  64. package/.agent/skills/geo-fundamentals/SKILL.md +124 -215
  65. package/.agent/skills/github-operations/SKILL.md +314 -354
  66. package/.agent/skills/gsap-expert/SKILL.md +901 -0
  67. package/.agent/skills/i18n-localization/SKILL.md +138 -216
  68. package/.agent/skills/intelligent-routing/SKILL.md +127 -139
  69. package/.agent/skills/llm-engineering/SKILL.md +357 -258
  70. package/.agent/skills/local-first/SKILL.md +154 -203
  71. package/.agent/skills/mcp-builder/SKILL.md +118 -224
  72. package/.agent/skills/nextjs-react-expert/SKILL.md +783 -203
  73. package/.agent/skills/nodejs-best-practices/SKILL.md +559 -280
  74. package/.agent/skills/observability/SKILL.md +330 -285
  75. package/.agent/skills/parallel-agents/SKILL.md +122 -181
  76. package/.agent/skills/performance-profiling/SKILL.md +254 -197
  77. package/.agent/skills/plan-writing/SKILL.md +118 -188
  78. package/.agent/skills/platform-engineer/SKILL.md +123 -135
  79. package/.agent/skills/playwright-best-practices/SKILL.md +157 -76
  80. package/.agent/skills/powershell-windows/SKILL.md +146 -230
  81. package/.agent/skills/python-pro/SKILL.md +879 -114
  82. package/.agent/skills/react-specialist/SKILL.md +931 -108
  83. package/.agent/skills/realtime-patterns/SKILL.md +304 -296
  84. package/.agent/skills/rust-pro/SKILL.md +701 -240
  85. package/.agent/skills/seo-fundamentals/SKILL.md +154 -181
  86. package/.agent/skills/server-management/SKILL.md +190 -212
  87. package/.agent/skills/shadcn-ui-expert/SKILL.md +201 -68
  88. package/.agent/skills/sql-pro/SKILL.md +633 -104
  89. package/.agent/skills/swiftui-expert/SKILL.md +171 -70
  90. package/.agent/skills/systematic-debugging/SKILL.md +118 -186
  91. package/.agent/skills/tailwind-patterns/SKILL.md +576 -232
  92. package/.agent/skills/tdd-workflow/SKILL.md +137 -209
  93. package/.agent/skills/testing-patterns/SKILL.md +573 -205
  94. package/.agent/skills/vue-expert/SKILL.md +964 -119
  95. package/.agent/skills/vulnerability-scanner/SKILL.md +269 -316
  96. package/.agent/skills/web-accessibility-auditor/SKILL.md +188 -71
  97. package/.agent/skills/webapp-testing/SKILL.md +145 -236
  98. package/.agent/workflows/api-tester.md +151 -279
  99. package/.agent/workflows/audit.md +138 -168
  100. package/.agent/workflows/brainstorm.md +110 -146
  101. package/.agent/workflows/changelog.md +112 -144
  102. package/.agent/workflows/create.md +124 -139
  103. package/.agent/workflows/debug.md +189 -196
  104. package/.agent/workflows/deploy.md +189 -153
  105. package/.agent/workflows/enhance.md +151 -139
  106. package/.agent/workflows/fix.md +135 -143
  107. package/.agent/workflows/generate.md +157 -164
  108. package/.agent/workflows/migrate.md +160 -163
  109. package/.agent/workflows/orchestrate.md +168 -151
  110. package/.agent/workflows/performance-benchmarker.md +123 -305
  111. package/.agent/workflows/plan.md +173 -151
  112. package/.agent/workflows/preview.md +80 -137
  113. package/.agent/workflows/refactor.md +183 -153
  114. package/.agent/workflows/review-ai.md +129 -140
  115. package/.agent/workflows/review.md +116 -155
  116. package/.agent/workflows/session.md +94 -154
  117. package/.agent/workflows/status.md +79 -125
  118. package/.agent/workflows/strengthen-skills.md +139 -99
  119. package/.agent/workflows/swarm.md +179 -194
  120. package/.agent/workflows/test.md +211 -166
  121. package/.agent/workflows/tribunal-backend.md +113 -111
  122. package/.agent/workflows/tribunal-database.md +115 -132
  123. package/.agent/workflows/tribunal-frontend.md +118 -115
  124. package/.agent/workflows/tribunal-full.md +133 -136
  125. package/.agent/workflows/tribunal-mobile.md +119 -123
  126. package/.agent/workflows/tribunal-performance.md +133 -152
  127. package/.agent/workflows/ui-ux-pro-max.md +143 -171
  128. package/README.md +11 -15
  129. package/package.json +1 -1
  130. package/.agent/skills/dotnet-core-expert/SKILL.md +0 -103
  131. package/.agent/skills/framer-motion-animations/SKILL.md +0 -74
  132. package/.agent/skills/game-development/2d-games/SKILL.md +0 -119
  133. package/.agent/skills/game-development/3d-games/SKILL.md +0 -135
  134. package/.agent/skills/game-development/SKILL.md +0 -236
  135. package/.agent/skills/game-development/game-art/SKILL.md +0 -185
  136. package/.agent/skills/game-development/game-audio/SKILL.md +0 -190
  137. package/.agent/skills/game-development/game-design/SKILL.md +0 -129
  138. package/.agent/skills/game-development/mobile-games/SKILL.md +0 -108
  139. package/.agent/skills/game-development/multiplayer/SKILL.md +0 -132
  140. package/.agent/skills/game-development/pc-games/SKILL.md +0 -144
  141. package/.agent/skills/game-development/vr-ar/SKILL.md +0 -123
  142. package/.agent/skills/game-development/web-games/SKILL.md +0 -150
@@ -0,0 +1,901 @@
1
+ ---
2
+ name: gsap-expert
3
+ description: GreenSock Animation Platform (GSAP 3.12+) mastery. Core tweens, timelines, ScrollTrigger, plugins, gsap.utils, React useGSAP hook, performance optimization, and multi-framework lifecycle cleanup. Use when building scroll-driven animations, complex sequencing, SVG morphing, or any animation beyond CSS capabilities.
4
+ allowed-tools: Read, Write, Edit, Glob, Grep
5
+ version: 1.0.0
6
+ last-updated: 2026-03-30
7
+ applies-to-model: gemini-2.5-pro, claude-3-7-sonnet
8
+ ---
9
+
10
+ # GSAP Expert — GreenSock Animation Platform
11
+
12
+ > GSAP is the professional-grade animation library. It is NOT jQuery `.animate()`.
13
+ > Every tween must have a clear purpose, every timeline must clean up, and every ScrollTrigger must call `.kill()` on unmount.
14
+
15
+ ---
16
+
17
+ ## gsap-core — Core API
18
+
19
+ ### Tween Methods
20
+
21
+ ```js
22
+ // gsap.to() — animate FROM current state TO target
23
+ gsap.to(".box", { x: 200, duration: 1, ease: "power2.out" });
24
+
25
+ // gsap.from() — animate FROM target TO current state
26
+ gsap.from(".box", { opacity: 0, y: 50, duration: 0.8 });
27
+
28
+ // gsap.fromTo() — explicit start AND end (most predictable)
29
+ gsap.fromTo(".box",
30
+ { opacity: 0, y: 30 }, // from
31
+ { opacity: 1, y: 0, duration: 1 } // to
32
+ );
33
+
34
+ // gsap.set() — instant property set, no animation
35
+ gsap.set(".box", { transformOrigin: "center center" });
36
+ ```
37
+
38
+ ### Easing
39
+
40
+ GSAP eases follow a `name.type` pattern. The names: `power1`–`power4`, `back`, `bounce`, `elastic`, `circ`, `expo`, `sine`, `steps`.
41
+
42
+ ```js
43
+ // Types: .in, .out, .inOut
44
+ ease: "power3.inOut" // smooth acceleration + deceleration
45
+ ease: "back.out(1.7)" // overshoot by 1.7 (default)
46
+ ease: "elastic.out(1, 0.3)" // amplitude, period
47
+ ease: "steps(5)" // stepped animation (sprite sheets)
48
+ ease: "none" // linear
49
+
50
+ // ❌ HALLUCINATION TRAP: These do NOT exist in GSAP 3+
51
+ // ease: "easeInOut" — jQuery syntax, NOT GSAP
52
+ // ease: "Power2.easeOut" — GSAP 2 syntax, DEPRECATED
53
+ // ease: "Cubic.easeIn" — GSAP 2 syntax, DEPRECATED
54
+ ```
55
+
56
+ ### Duration & Stagger
57
+
58
+ ```js
59
+ // Duration is in seconds (NOT milliseconds like CSS/JS setTimeout)
60
+ gsap.to(".items", {
61
+ x: 100,
62
+ duration: 0.6, // 0.6 seconds
63
+ stagger: 0.1, // 0.1s between each element
64
+
65
+ // Advanced stagger object
66
+ stagger: {
67
+ each: 0.1, // time between each
68
+ from: "center", // "start", "center", "end", "edges", "random", or index
69
+ grid: "auto", // for grid layouts
70
+ ease: "power2.in", // ease the stagger distribution itself
71
+ amount: 0.8, // total stagger time (alternative to `each`)
72
+ }
73
+ });
74
+ ```
75
+
76
+ ### Defaults
77
+
78
+ ```js
79
+ // Set project-wide defaults — DRY animation config
80
+ gsap.defaults({
81
+ duration: 0.8,
82
+ ease: "power2.out",
83
+ overwrite: "auto", // auto-kill conflicting tweens on same target
84
+ });
85
+
86
+ // Per-tween overrides always win
87
+ gsap.to(".box", { x: 100, duration: 1.5 }); // uses 1.5, not 0.8
88
+ ```
89
+
90
+ ### Callbacks & Control
91
+
92
+ ```js
93
+ const tween = gsap.to(".box", {
94
+ x: 200,
95
+ onStart: () => console.log("started"),
96
+ onUpdate: (self) => console.log(self.progress()),
97
+ onComplete: () => console.log("done"),
98
+ onReverseComplete: () => console.log("reversed"),
99
+ });
100
+
101
+ // Control methods
102
+ tween.pause();
103
+ tween.resume();
104
+ tween.reverse();
105
+ tween.seek(0.5); // jump to 0.5 seconds
106
+ tween.progress(0.5); // jump to 50%
107
+ tween.kill(); // destroy and garbage collect
108
+ ```
109
+
110
+ ---
111
+
112
+ ## gsap-timeline — Timelines
113
+
114
+ ### Sequencing
115
+
116
+ ```js
117
+ const tl = gsap.timeline({
118
+ defaults: { duration: 0.5, ease: "power2.out" },
119
+ onComplete: () => console.log("Sequence done"),
120
+ });
121
+
122
+ tl.to(".title", { opacity: 1, y: 0 })
123
+ .to(".subtitle", { opacity: 1, y: 0 }) // plays AFTER .title
124
+ .to(".cta", { scale: 1, opacity: 1 }); // plays AFTER .subtitle
125
+ ```
126
+
127
+ ### Position Parameter (Critical Concept)
128
+
129
+ The position parameter is the **most powerful** sequencing tool in GSAP. It controls *when* a child animation starts relative to the timeline.
130
+
131
+ ```js
132
+ tl.to(".a", { x: 100 })
133
+ .to(".b", { x: 100 }, "<") // "<" = same start time as previous
134
+ .to(".c", { x: 100 }, ">") // ">" = after previous ends (default)
135
+ .to(".d", { x: 100 }, "-=0.3") // 0.3s before previous ends (overlap)
136
+ .to(".e", { x: 100 }, "+=0.5") // 0.5s after previous ends (gap)
137
+ .to(".f", { x: 100 }, 2) // absolute: at exactly 2 seconds
138
+ .to(".g", { x: 100 }, "<0.2") // 0.2s after previous animation's START
139
+ .to(".h", { x: 100 }, ">-0.1"); // 0.1s before previous animation's END
140
+
141
+ // ❌ HALLUCINATION TRAP: Position parameter is the 3rd argument, NOT a property
142
+ // WRONG: tl.to(".a", { x: 100, position: "<" })
143
+ // RIGHT: tl.to(".a", { x: 100 }, "<")
144
+ ```
145
+
146
+ ### Labels
147
+
148
+ ```js
149
+ tl.addLabel("intro")
150
+ .to(".title", { opacity: 1 })
151
+ .addLabel("middle")
152
+ .to(".content", { opacity: 1 })
153
+ .to(".sidebar", { x: 0 }, "middle") // starts at the "middle" label
154
+ .to(".footer", { y: 0 }, "middle+=0.3"); // 0.3s after the "middle" label
155
+ ```
156
+
157
+ ### Nesting Timelines
158
+
159
+ ```js
160
+ function introAnimation() {
161
+ const tl = gsap.timeline();
162
+ tl.from(".hero-title", { y: 60, opacity: 0 })
163
+ .from(".hero-sub", { y: 40, opacity: 0 }, "-=0.3");
164
+ return tl;
165
+ }
166
+
167
+ function contentAnimation() {
168
+ const tl = gsap.timeline();
169
+ tl.from(".card", { y: 80, opacity: 0, stagger: 0.15 });
170
+ return tl;
171
+ }
172
+
173
+ // Master timeline nests sub-timelines
174
+ const master = gsap.timeline();
175
+ master
176
+ .add(introAnimation())
177
+ .add(contentAnimation(), "-=0.4"); // overlap by 0.4s
178
+ ```
179
+
180
+ ### Playback Control
181
+
182
+ ```js
183
+ const tl = gsap.timeline({ paused: true, repeat: -1, yoyo: true });
184
+
185
+ tl.play();
186
+ tl.pause();
187
+ tl.reverse();
188
+ tl.restart();
189
+ tl.timeScale(2); // 2× speed
190
+ tl.seek("middle"); // jump to label
191
+ tl.totalProgress(); // 0–1 across all repeats
192
+ ```
193
+
194
+ ---
195
+
196
+ ## gsap-scrolltrigger — ScrollTrigger
197
+
198
+ ### Registration (Required)
199
+
200
+ ```js
201
+ import { gsap } from "gsap";
202
+ import { ScrollTrigger } from "gsap/ScrollTrigger";
203
+
204
+ gsap.registerPlugin(ScrollTrigger);
205
+
206
+ // ❌ HALLUCINATION TRAP: ScrollTrigger MUST be registered before use
207
+ // Forgetting gsap.registerPlugin() is the #1 GSAP bug in AI-generated code
208
+ ```
209
+
210
+ ### Basic Scroll-Linked Animation
211
+
212
+ ```js
213
+ gsap.to(".parallax-bg", {
214
+ y: -200,
215
+ scrollTrigger: {
216
+ trigger: ".hero-section", // element that triggers
217
+ start: "top bottom", // "triggerPoint viewportPoint"
218
+ end: "bottom top", // when to stop
219
+ scrub: true, // links animation progress to scroll position
220
+ markers: true, // DEBUG ONLY — remove in production
221
+ }
222
+ });
223
+ ```
224
+
225
+ ### Start / End Syntax
226
+
227
+ ```
228
+ start: "top center" // trigger's top hits viewport's center
229
+ start: "top 80%" // trigger's top hits 80% from viewport top
230
+ start: "top top" // trigger's top hits viewport's top
231
+ start: "center center" // trigger's center hits viewport's center
232
+ start: "top bottom-=100" // 100px before trigger's top hits viewport's bottom
233
+ ```
234
+
235
+ ### Pinning
236
+
237
+ ```js
238
+ ScrollTrigger.create({
239
+ trigger: ".sticky-section",
240
+ start: "top top",
241
+ end: "+=1000", // pin for 1000px of scrolling
242
+ pin: true, // locks element in place
243
+ pinSpacing: true, // adds equivalent space below (default: true)
244
+ anticipatePin: 1, // reduces jank — pre-calculates pin
245
+ });
246
+ ```
247
+
248
+ ### Scrub
249
+
250
+ ```js
251
+ // scrub: true — instant scrub (direct 1:1 with scroll)
252
+ // scrub: 0.5 — smoothed scrub (0.5 second lag behind scroll position)
253
+ // scrub: 3 — heavy smoothing (3 second catch-up, cinematic feel)
254
+
255
+ gsap.to(".progress-bar", {
256
+ scaleX: 1,
257
+ scrollTrigger: {
258
+ trigger: ".article",
259
+ start: "top top",
260
+ end: "bottom bottom",
261
+ scrub: 0.3,
262
+ }
263
+ });
264
+ ```
265
+
266
+ ### Refresh & Cleanup (Critical)
267
+
268
+ ```js
269
+ // Force recalculation after DOM changes (images loaded, content injected)
270
+ ScrollTrigger.refresh();
271
+
272
+ // Batch refresh after many DOM mutations
273
+ ScrollTrigger.refresh(true); // "safe" mode — deferred to next tick
274
+
275
+ // Kill ALL ScrollTriggers (page transitions, SPA navigation)
276
+ ScrollTrigger.killAll();
277
+
278
+ // Kill a specific instance
279
+ const st = ScrollTrigger.create({ /* ... */ });
280
+ st.kill();
281
+
282
+ // ❌ HALLUCINATION TRAP: Failing to kill ScrollTriggers on unmount
283
+ // causes memory leaks, zombie listeners, and broken scroll behavior
284
+ // in SPAs (Next.js, Nuxt, SvelteKit, Remix)
285
+ ```
286
+
287
+ ### Callbacks
288
+
289
+ ```js
290
+ ScrollTrigger.create({
291
+ trigger: ".section",
292
+ start: "top center",
293
+ end: "bottom center",
294
+ onEnter: () => console.log("entered from above"),
295
+ onLeave: () => console.log("left going down"),
296
+ onEnterBack: () => console.log("entered from below"),
297
+ onLeaveBack: () => console.log("left going up"),
298
+ onToggle: (self) => console.log("active:", self.isActive),
299
+ onUpdate: (self) => console.log("progress:", self.progress),
300
+ onRefresh: (self) => console.log("recalculated"),
301
+ });
302
+ ```
303
+
304
+ ---
305
+
306
+ ## gsap-plugins — Plugin Ecosystem
307
+
308
+ ### Registration Pattern (All Plugins)
309
+
310
+ ```js
311
+ import { gsap } from "gsap";
312
+ import { Flip } from "gsap/Flip";
313
+ import { Draggable } from "gsap/Draggable";
314
+ import { ScrollToPlugin } from "gsap/ScrollToPlugin";
315
+
316
+ gsap.registerPlugin(Flip, Draggable, ScrollToPlugin);
317
+
318
+ // ❌ HALLUCINATION TRAP: Every plugin MUST be registered
319
+ // ❌ HALLUCINATION TRAP: Some plugins require a GSAP Club license
320
+ // (ScrollSmoother, SplitText, Inertia, ScrambleText, MorphSVG, DrawSVG,
321
+ // MotionPath, Physics2D, PhysicsProps, CustomBounce, CustomWiggle)
322
+ // Free plugins: ScrollTrigger, Flip, Draggable, ScrollToPlugin, Observer,
323
+ // TextPlugin, MotionPathPlugin, EasePack, CustomEase, GSDevTools (trial)
324
+ ```
325
+
326
+ ### Flip Plugin (FLIP Technique)
327
+
328
+ ```js
329
+ // 1. Capture current state
330
+ const state = Flip.getState(".cards");
331
+
332
+ // 2. Make DOM change (reparent, reclass, reorder)
333
+ container.classList.toggle("grid-layout");
334
+
335
+ // 3. Animate from old state to new state
336
+ Flip.from(state, {
337
+ duration: 0.6,
338
+ ease: "power2.inOut",
339
+ stagger: 0.05,
340
+ absolute: true, // uses position:absolute during animation
341
+ onComplete: () => console.log("Flip done"),
342
+ });
343
+ ```
344
+
345
+ ### Draggable
346
+
347
+ ```js
348
+ Draggable.create(".slider-handle", {
349
+ type: "x", // "x", "y", "x,y", "rotation"
350
+ bounds: ".slider-track", // constrain to parent
351
+ inertia: true, // requires InertiaPlugin (Club)
352
+ edgeResistance: 0.65, // resistance at bounds edges
353
+ onDrag: function () {
354
+ console.log("x:", this.x); // `this` = Draggable instance
355
+ },
356
+ onDragEnd: function () {
357
+ console.log("endX:", this.endX); // projected landing position
358
+ },
359
+ snap: {
360
+ x: (val) => Math.round(val / 50) * 50, // snap to 50px grid
361
+ },
362
+ });
363
+ ```
364
+
365
+ ### ScrollToPlugin
366
+
367
+ ```js
368
+ gsap.to(window, {
369
+ duration: 1,
370
+ scrollTo: { y: "#section-3", offsetY: 80 },
371
+ ease: "power2.inOut",
372
+ });
373
+
374
+ // Horizontal scroll-to
375
+ gsap.to(".container", {
376
+ scrollTo: { x: 500 },
377
+ duration: 0.8,
378
+ });
379
+ ```
380
+
381
+ ### ScrollSmoother (Club GreenSock)
382
+
383
+ ```js
384
+ // ⚠️ Club GreenSock plugin — requires license
385
+ import { ScrollSmoother } from "gsap/ScrollSmoother";
386
+
387
+ // HTML structure required:
388
+ // <div id="smooth-wrapper">
389
+ // <div id="smooth-content"> ...page... </div>
390
+ // </div>
391
+
392
+ const smoother = ScrollSmoother.create({
393
+ wrapper: "#smooth-wrapper",
394
+ content: "#smooth-content",
395
+ smooth: 1.5, // seconds of smoothing
396
+ effects: true, // enables data-speed and data-lag
397
+ normalizeScroll: true, // prevents mobile address bar jank
398
+ });
399
+ ```
400
+
401
+ ### Observer
402
+
403
+ ```js
404
+ import { Observer } from "gsap/Observer";
405
+
406
+ Observer.create({
407
+ target: window,
408
+ type: "wheel,touch,pointer",
409
+ onUp: () => goToNextSlide(),
410
+ onDown: () => goToPrevSlide(),
411
+ tolerance: 10, // pixel threshold before firing
412
+ preventDefault: true,
413
+ wheelSpeed: -1, // invert wheel direction
414
+ });
415
+ ```
416
+
417
+ ### SplitText (Club GreenSock)
418
+
419
+ ```js
420
+ // ⚠️ Club GreenSock plugin — requires license
421
+ import { SplitText } from "gsap/SplitText";
422
+
423
+ const split = new SplitText(".hero-heading", {
424
+ type: "chars,words,lines",
425
+ linesClass: "split-line",
426
+ });
427
+
428
+ gsap.from(split.chars, {
429
+ opacity: 0,
430
+ y: 20,
431
+ rotateX: -60,
432
+ stagger: 0.02,
433
+ duration: 0.6,
434
+ ease: "back.out(1.7)",
435
+ onComplete: () => split.revert(), // CLEANUP — restore original DOM
436
+ });
437
+
438
+ // ❌ HALLUCINATION TRAP: Always call split.revert() when done
439
+ // Leaving split DOM nodes causes accessibility and SEO issues
440
+ ```
441
+
442
+ ### CustomEase
443
+
444
+ ```js
445
+ import { CustomEase } from "gsap/CustomEase";
446
+
447
+ CustomEase.create("myBounce", "M0,0 C0.14,0 0.27,0.58 0.32,0.82 ...");
448
+ gsap.to(".box", { x: 300, ease: "myBounce" });
449
+ ```
450
+
451
+ ### GSDevTools
452
+
453
+ ```js
454
+ // Debug timeline visually — NEVER ship to production
455
+ import { GSDevTools } from "gsap/GSDevTools";
456
+
457
+ GSDevTools.create({ animation: masterTimeline });
458
+ ```
459
+
460
+ ---
461
+
462
+ ## gsap-utils — Utility Functions
463
+
464
+ ```js
465
+ // clamp — constrain a value between min and max
466
+ gsap.utils.clamp(0, 100, 150); // 100
467
+
468
+ // mapRange — remap value from one range to another
469
+ gsap.utils.mapRange(0, 100, 0, 1, 50); // 0.5
470
+
471
+ // normalize — convert a value in a range to 0–1
472
+ gsap.utils.normalize(0, 500, 250); // 0.5
473
+
474
+ // interpolate — blend between values
475
+ gsap.utils.interpolate(0, 100, 0.75); // 75
476
+ gsap.utils.interpolate("red", "blue", 0.5); // blends colors
477
+ gsap.utils.interpolate({ x: 0 }, { x: 100 }, 0.5); // { x: 50 }
478
+
479
+ // random — random value (can be snapped)
480
+ gsap.utils.random(0, 100); // float
481
+ gsap.utils.random(0, 100, 5); // snapped to nearest 5
482
+ gsap.utils.random([10, 20, 30]); // pick from array
483
+
484
+ // snap — snap value to nearest increment or array value
485
+ gsap.utils.snap(10, 23); // 20
486
+ gsap.utils.snap([0, 50, 100], 38); // 50
487
+
488
+ // toArray — convert selector/NodeList to a real array (safe)
489
+ const boxes = gsap.utils.toArray(".box"); // always returns an Array
490
+
491
+ // selector — scoped querySelector factory
492
+ const q = gsap.utils.selector(myRef);
493
+ gsap.to(q(".title"), { opacity: 1 }); // only searches within myRef
494
+
495
+ // wrap — wrap index around an array
496
+ const colors = ["red", "green", "blue"];
497
+ gsap.utils.wrap(colors, 5); // "blue" (wraps around)
498
+
499
+ // pipe — compose multiple utility functions
500
+ const clampAndRound = gsap.utils.pipe(
501
+ gsap.utils.clamp(0, 100),
502
+ Math.round
503
+ );
504
+ clampAndRound(125.7); // 100
505
+ ```
506
+
507
+ ---
508
+
509
+ ## gsap-react — React Integration
510
+
511
+ ### The `useGSAP` Hook (Official)
512
+
513
+ ```jsx
514
+ import { useGSAP } from "@gsap/react";
515
+ import { gsap } from "gsap";
516
+
517
+ // ❌ HALLUCINATION TRAP: Do NOT use raw useEffect for GSAP in React
518
+ // useEffect does not scope selectors, does not auto-cleanup, and causes
519
+ // double-animation bugs in React 18+ Strict Mode
520
+
521
+ function HeroSection() {
522
+ const containerRef = useRef(null);
523
+
524
+ useGSAP(() => {
525
+ // All selectors are automatically scoped to containerRef
526
+ gsap.from(".hero-title", { y: 60, opacity: 0, duration: 0.8 });
527
+ gsap.from(".hero-sub", { y: 40, opacity: 0, duration: 0.6, delay: 0.3 });
528
+ }, { scope: containerRef }); // scope = auto querySelector boundary
529
+
530
+ return (
531
+ <div ref={containerRef}>
532
+ <h1 className="hero-title">Welcome</h1>
533
+ <p className="hero-sub">Subtitle</p>
534
+ </div>
535
+ );
536
+ }
537
+ ```
538
+
539
+ ### Dependency Array (Re-running Animations)
540
+
541
+ ```jsx
542
+ useGSAP(() => {
543
+ gsap.to(".counter", { innerText: count, snap: { innerText: 1 } });
544
+ }, { dependencies: [count], scope: containerRef });
545
+
546
+ // ❌ HALLUCINATION TRAP: The option is called `dependencies`, NOT `deps`
547
+ ```
548
+
549
+ ### Manual Context (Without useGSAP)
550
+
551
+ ```jsx
552
+ useEffect(() => {
553
+ const ctx = gsap.context(() => {
554
+ gsap.from(".box", { x: -100, opacity: 0 });
555
+ }, containerRef); // scope
556
+
557
+ return () => ctx.revert(); // CLEANUP — kills all tweens and ScrollTriggers
558
+ }, []);
559
+
560
+ // gsap.context() is GSAP's own cleanup mechanism
561
+ // ctx.revert() kills every tween and ScrollTrigger created inside it
562
+ ```
563
+
564
+ ### Refs vs. Selectors
565
+
566
+ ```jsx
567
+ // ✅ Preferred: useRef + scope
568
+ const boxRef = useRef(null);
569
+ useGSAP(() => {
570
+ gsap.to(boxRef.current, { x: 100 });
571
+ }, { scope: containerRef });
572
+
573
+ // ✅ Also fine: class selectors when scoped
574
+ useGSAP(() => {
575
+ gsap.to(".box", { x: 100 }); // scoped to containerRef
576
+ }, { scope: containerRef });
577
+
578
+ // ❌ BAD: Global selectors without scope
579
+ useGSAP(() => {
580
+ gsap.to(".box", { x: 100 }); // matches ALL .box elements globally
581
+ });
582
+ ```
583
+
584
+ ### SSR / Next.js Considerations
585
+
586
+ ```jsx
587
+ // Animations must only run on the client
588
+ useGSAP(() => {
589
+ // This hook already handles client-only execution
590
+ gsap.from(".element", { opacity: 0 });
591
+ }, { scope: containerRef });
592
+
593
+ // For dynamic imports in Next.js (App Router)
594
+ "use client"; // ← required at top of component file
595
+
596
+ // ❌ HALLUCINATION TRAP: Do NOT import GSAP in server components
597
+ // GSAP requires `window` and `document` — it will crash on the server
598
+ ```
599
+
600
+ ---
601
+
602
+ ## gsap-performance — Performance Optimization
603
+
604
+ ### Transforms Over Layout Properties (Critical)
605
+
606
+ ```js
607
+ // ✅ GPU-accelerated (composited — no layout recalculation)
608
+ gsap.to(".box", { x: 100, y: 50, rotation: 45, scale: 1.2, opacity: 0.5 });
609
+
610
+ // ❌ TRIGGERS LAYOUT REFLOW (expensive — avoid animating these)
611
+ gsap.to(".box", { width: 200, height: 100, top: 50, left: 100, padding: 20 });
612
+
613
+ // ❌ HALLUCINATION TRAP: AI often generates `{ left: 100 }` instead of `{ x: 100 }`
614
+ // x/y use CSS transform: translate(), which is GPU-composited
615
+ // left/top trigger layout recalculation on every frame = jank
616
+ ```
617
+
618
+ ### `will-change` Management
619
+
620
+ ```js
621
+ // GSAP auto-applies will-change: transform during animation
622
+ // Do NOT manually add will-change to many elements — it wastes GPU memory
623
+
624
+ // For known long-running animations, apply manually and remove after:
625
+ gsap.set(".persistent-animation", { willChange: "transform" });
626
+ // ... animation runs ...
627
+ gsap.set(".persistent-animation", { willChange: "auto" }); // release GPU memory
628
+ ```
629
+
630
+ ### Batching & `gsap.ticker`
631
+
632
+ ```js
633
+ // Use gsap.ticker instead of requestAnimationFrame for sync
634
+ gsap.ticker.add((time, deltaTime, frame) => {
635
+ // Runs in sync with GSAP's internal RAF loop
636
+ // Use for particle systems, canvas drawing, etc.
637
+ });
638
+
639
+ // Throttle ticker to 30fps (for low-power devices)
640
+ gsap.ticker.fps(30);
641
+
642
+ // Lazy rendering (default: true) — GSAP batches reads/writes
643
+ // Only disable if you need synchronous layout reads mid-animation
644
+ gsap.ticker.lagSmoothing(500, 33); // smooth large frame drops
645
+ ```
646
+
647
+ ### ScrollTrigger Performance
648
+
649
+ ```js
650
+ // ❌ BAD: One ScrollTrigger per item in a long list
651
+ document.querySelectorAll(".item").forEach(item => {
652
+ ScrollTrigger.create({ trigger: item, /* ... */ }); // 100+ instances = jank
653
+ });
654
+
655
+ // ✅ BETTER: Use ScrollTrigger.batch()
656
+ ScrollTrigger.batch(".item", {
657
+ onEnter: (elements) => {
658
+ gsap.from(elements, { opacity: 0, y: 50, stagger: 0.1 });
659
+ },
660
+ onLeave: (elements) => {
661
+ gsap.to(elements, { opacity: 0 });
662
+ },
663
+ });
664
+
665
+ // ❌ HALLUCINATION TRAP: Never use `markers: true` in production
666
+ // It injects visible debug DOM elements
667
+ ```
668
+
669
+ ### Overwrite Modes
670
+
671
+ ```js
672
+ // Prevent conflicting tweens from stacking
673
+ gsap.to(".box", { x: 100, overwrite: "auto" });
674
+
675
+ // Modes:
676
+ // "auto" — kill only conflicting properties on same target (recommended)
677
+ // true — kill ALL tweens on same target
678
+ // false — allow stacking (default, can cause jank)
679
+ ```
680
+
681
+ ---
682
+
683
+ ## gsap-frameworks — Vue, Svelte & Framework Lifecycle
684
+
685
+ ### Vue 3 (Composition API)
686
+
687
+ ```vue
688
+ <script setup>
689
+ import { ref, onMounted, onUnmounted } from "vue";
690
+ import { gsap } from "gsap";
691
+ import { ScrollTrigger } from "gsap/ScrollTrigger";
692
+
693
+ gsap.registerPlugin(ScrollTrigger);
694
+
695
+ const containerRef = ref(null);
696
+ let ctx;
697
+
698
+ onMounted(() => {
699
+ ctx = gsap.context(() => {
700
+ gsap.from(".box", {
701
+ y: 60, opacity: 0, duration: 0.8,
702
+ scrollTrigger: { trigger: ".box", start: "top 80%" },
703
+ });
704
+ }, containerRef.value); // scope to component root
705
+ });
706
+
707
+ onUnmounted(() => {
708
+ ctx.revert(); // CRITICAL: kills all tweens + ScrollTriggers
709
+ });
710
+ </script>
711
+
712
+ <template>
713
+ <div ref="containerRef">
714
+ <div class="box">Animated</div>
715
+ </div>
716
+ </template>
717
+ ```
718
+
719
+ ### Svelte
720
+
721
+ ```svelte
722
+ <script>
723
+ import { onMount, onDestroy } from "svelte";
724
+ import { gsap } from "gsap";
725
+ import { ScrollTrigger } from "gsap/ScrollTrigger";
726
+
727
+ gsap.registerPlugin(ScrollTrigger);
728
+
729
+ let container;
730
+ let ctx;
731
+
732
+ onMount(() => {
733
+ ctx = gsap.context(() => {
734
+ gsap.from(".box", { y: 60, opacity: 0, duration: 0.8 });
735
+ }, container);
736
+ });
737
+
738
+ onDestroy(() => {
739
+ ctx?.revert(); // cleanup on component destroy
740
+ });
741
+ </script>
742
+
743
+ <div bind:this={container}>
744
+ <div class="box">Animated</div>
745
+ </div>
746
+ ```
747
+
748
+ ### Universal Cleanup Rules
749
+
750
+ ```
751
+ ✅ ALWAYS use gsap.context() in framework components
752
+ ✅ ALWAYS call ctx.revert() on unmount/destroy/cleanup
753
+ ✅ ALWAYS call ScrollTrigger.kill() or .killAll() on route changes (SPA)
754
+ ✅ ALWAYS scope selectors to the component root
755
+
756
+ ❌ NEVER leave orphaned ScrollTriggers after navigation
757
+ ❌ NEVER use global selectors without scoping in component frameworks
758
+ ❌ NEVER forget to revert SplitText instances (corrupts DOM)
759
+ ```
760
+
761
+ ---
762
+
763
+ ## Common Animation Patterns
764
+
765
+ ### Fade-In On Scroll (Batch)
766
+
767
+ ```js
768
+ ScrollTrigger.batch(".fade-in", {
769
+ onEnter: (elements) => {
770
+ gsap.fromTo(elements,
771
+ { opacity: 0, y: 40 },
772
+ { opacity: 1, y: 0, duration: 0.6, stagger: 0.1, ease: "power2.out" }
773
+ );
774
+ },
775
+ start: "top 85%",
776
+ });
777
+ ```
778
+
779
+ ### Horizontal Scroll Section
780
+
781
+ ```js
782
+ const sections = gsap.utils.toArray(".panel");
783
+
784
+ gsap.to(sections, {
785
+ xPercent: -100 * (sections.length - 1),
786
+ ease: "none",
787
+ scrollTrigger: {
788
+ trigger: ".horizontal-container",
789
+ pin: true,
790
+ scrub: 1,
791
+ snap: 1 / (sections.length - 1),
792
+ end: () => "+=" + document.querySelector(".horizontal-container").offsetWidth,
793
+ },
794
+ });
795
+ ```
796
+
797
+ ### Magnetic Button
798
+
799
+ ```js
800
+ const btn = document.querySelector(".magnetic-btn");
801
+
802
+ btn.addEventListener("mousemove", (e) => {
803
+ const { left, top, width, height } = btn.getBoundingClientRect();
804
+ const x = (e.clientX - left - width / 2) * 0.3;
805
+ const y = (e.clientY - top - height / 2) * 0.3;
806
+ gsap.to(btn, { x, y, duration: 0.3, ease: "power2.out" });
807
+ });
808
+
809
+ btn.addEventListener("mouseleave", () => {
810
+ gsap.to(btn, { x: 0, y: 0, duration: 0.5, ease: "elastic.out(1, 0.3)" });
811
+ });
812
+ ```
813
+
814
+ ### Counter / Number Ticker
815
+
816
+ ```js
817
+ const obj = { val: 0 };
818
+ gsap.to(obj, {
819
+ val: 12847,
820
+ duration: 2,
821
+ ease: "power1.out",
822
+ snap: { val: 1 },
823
+ onUpdate: () => {
824
+ document.querySelector(".counter").textContent = obj.val.toLocaleString();
825
+ },
826
+ });
827
+ ```
828
+
829
+ ---
830
+
831
+ ## Output Format
832
+
833
+ When this skill produces or reviews code, structure your output as follows:
834
+
835
+ ```
836
+ ━━━ GSAP Expert Report ━━━━━━━━━━━━━━━━━━━━━━━━
837
+ Skill: GSAP Expert
838
+ GSAP Version: 3.12+
839
+ Scope: [N files · N animations]
840
+ ─────────────────────────────────────────────────
841
+ ✅ Passed: [checks that passed, or "All clean"]
842
+ ⚠️ Warnings: [non-blocking issues, or "None"]
843
+ ❌ Blocked: [blocking issues requiring fix, or "None"]
844
+ ─────────────────────────────────────────────────
845
+ VBC status: PENDING → VERIFIED
846
+ Evidence: [test output / lint pass / compile success]
847
+ ```
848
+
849
+ **VBC (Verification-Before-Completion) is mandatory.**
850
+ Do not mark status as VERIFIED until concrete terminal evidence is provided.
851
+
852
+ ---
853
+
854
+ ## 🤖 LLM-Specific Traps
855
+
856
+ AI coding assistants often fall into specific bad habits when generating GSAP code. These are strictly forbidden:
857
+
858
+ 1. **GSAP v2 Syntax:** Using `TweenMax`, `TweenLite`, `TimelineMax`, `TimelineLite`, `Power2.easeOut`, or `CSSPlugin`. These are ALL deprecated in GSAP 3+. The correct API is `gsap.to()`, `gsap.timeline()`, and `ease: "power2.out"`.
859
+ 2. **Missing Plugin Registration:** Every GSAP plugin MUST be registered with `gsap.registerPlugin()` before use. This includes ScrollTrigger, Flip, Draggable, etc.
860
+ 3. **Missing Cleanup:** Every `gsap.context()` must have a corresponding `.revert()` on unmount. Every `ScrollTrigger` must be `.kill()`ed. Orphaned animations cause memory leaks.
861
+ 4. **Layout Props Instead of Transforms:** Animating `width`, `height`, `top`, `left`, `margin`, `padding` instead of `x`, `y`, `scale`, `rotation`. Layout props trigger expensive reflows.
862
+ 5. **Using `useEffect` Instead of `useGSAP`:** In React, always prefer the official `@gsap/react` `useGSAP` hook. It handles scoping, cleanup, and React 18+ Strict Mode.
863
+ 6. **Hallucinating Easing Names:** `easeInOut`, `Cubic.easeIn`, `easeOutBounce` do NOT exist. Correct format: `power2.inOut`, `bounce.out`, `elastic.out(1, 0.3)`.
864
+ 7. **Confusing `duration` Units:** GSAP uses seconds. CSS uses milliseconds. `duration: 300` in GSAP means 5 minutes, not 300ms.
865
+ 8. **Shipping `markers: true`:** Debug markers must never reach production.
866
+ 9. **Hallucinated Imports:** Using `import gsap from "gsap"` (default import) instead of `import { gsap } from "gsap"` (named import). Both work, but named is the documented standard.
867
+ 10. **Inventing Plugin Names:** Only use real GSAP plugins. There is no `ParallaxPlugin`, `FadePlugin`, or `AnimatePlugin`.
868
+
869
+ ---
870
+
871
+ ## 🏛️ Tribunal Integration (Anti-Hallucination)
872
+
873
+ **Slash command: `/review` or `/tribunal-full`**
874
+ **Active reviewers: `logic-reviewer` · `security-auditor` · `performance-optimizer`**
875
+
876
+ ### ❌ Forbidden AI Tropes
877
+
878
+ 1. **Blind Assumptions:** Never make an assumption without documenting it clearly with `// VERIFY: [reason]`.
879
+ 2. **Silent Degradation:** Catching and suppressing GSAP errors without logging or handling.
880
+ 3. **Context Amnesia:** Forgetting the user's constraints (e.g., generating Club plugin code when the user has a free license).
881
+ 4. **Over-Animating:** Adding animations to every element "because it looks cool." Every animation must serve a UX purpose.
882
+
883
+ ### ✅ Pre-Flight Self-Audit
884
+
885
+ Review these questions before confirming output:
886
+ ```
887
+ ✅ Did I use GSAP 3+ syntax exclusively (no TweenMax/TweenLite)?
888
+ ✅ Did I register every plugin with gsap.registerPlugin()?
889
+ ✅ Did I clean up with gsap.context().revert() or ScrollTrigger.kill()?
890
+ ✅ Did I use transforms (x, y, scale, rotation) instead of layout props?
891
+ ✅ Did I use useGSAP (not useEffect) for React components?
892
+ ✅ Did I mark Club-only plugins with a license warning comment?
893
+ ✅ Did I remove markers: true from production code?
894
+ ✅ Did I respect prefers-reduced-motion for accessibility?
895
+ ```
896
+
897
+ ### 🛑 Verification-Before-Completion (VBC) Protocol
898
+
899
+ **CRITICAL:** You must follow a strict "evidence-based closeout" state machine.
900
+ - ❌ **Forbidden:** Declaring a task complete because the output "looks correct."
901
+ - ✅ **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended.