# Troubleshooting Common Issues When Using emilkowalski/skills with AI Agents

> Fix common emilkowalski/skills animation issues with AI agents. Learn how to adhere to decision trees for compliant and performant motion. Resolve frequency gate, CPU usage, and easing curve problems.

- Repository: [Emil Kowalski/skills](https://github.com/emilkowalski/skills)
- Tags: how-to-guide
- Published: 2026-08-09

---

**AI agents fail the `emilkowalski/skills` animation standards by ignoring frequency gates, using CPU-heavy properties, and selecting incorrect easing curves, but strict adherence to the decision trees in [`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md) and [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) ensures compliant, performant motion.**

The `emilkowalski/skills` repository encodes Emil Kowalski’s design-engineering philosophy into structured Markdown documents that prescribe strict decision-making processes for building and reviewing UI motion. When AI agents consume these skills without implementing their guardrails, they generate animation code that violates performance budgets and accessibility requirements. This guide maps the most frequent agent errors to their specific fixes in the source skills.

## Decision Gate Violations: Animating High-Frequency Actions

The most common failure occurs when agents ignore the **frequency-appropriate** rule in [`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md). The skill explicitly forbids animation for actions occurring more than 100 times per day, such as keyboard shortcuts or command-palette toggles.

Agents often bypass the *Should this animate?* gate and add unnecessary transitions to high-frequency interactions. To fix this, implement the gate logic before generating CSS:

```typescript
// Check frequency tier first
if (frequency > 100) {
  // No animation – return static style
  return <Button className="btn-static">Click</Button>;
}
// Otherwise apply motion

```

If the frequency tier is marked *"No animation. Ever."* in the skill tables, the agent must return static state changes instead of transition code.

## Easing and Timing Mistakes

### Using `ease-in` Instead of `ease-out`

The standards in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) require `ease-out` or custom cubic-bezier curves for UI entrances. The **`ease-in`** curve delays the moment the user sees movement, making interfaces feel sluggish.

Replace any `ease-in` with the strong custom curve from the *easing.dev* catalogue:

```css
:root {
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
}

.button {
  transition: transform 200ms var(--ease-out);
}

```

### Oversized Durations Without Justification

UI animations must stay under **300 ms** unless the element is rare or first-time, according to the duration tables in the standards. Agents frequently generate 500 ms–1000 ms transitions for common dropdowns.

Cut durations to the recommended range (e.g., dropdown 150–250 ms) or lower the motion budget to maintain responsiveness.

## CSS Performance Anti-Patterns

### Declaring `transition: all`

Using **`transition: all`** violates the *GPU-only properties* rule in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) and triggers *Aggressive Escalation* warnings. This animates layout-changing properties on the main thread, causing jank and recalculation storms.

Specify exact properties that leverage compositor threads:

```css
/* Wrong */
.element {
  transition: all 300ms ease;
}

/* Correct */
.element {
  transition: transform 200ms var(--ease-out), 
              opacity 200ms var(--ease-out);
}

```

Valid GPU-accelerated properties include **`transform`**, **`opacity`**, and **`clip-path`**.

### Keyframes on Rapidly-Triggered UI

Agents often implement **@keyframes** for interactive elements like toggles or dropdowns. However, keyframes restart from zero on each activation, breaking the *Interruptibility* rule.

Use CSS **transitions** or the **Web Animations API (WAAPI)** for rapid UI changes. Reserve keyframes exclusively for long-running decorative animations that do not respond to user input.

### Framer Motion Shorthands Under Load

When using Framer Motion, agents rely on shorthand props like **`x`**, **`y`**, and **`scale`**. These bypass GPU acceleration and drop frames when the page is busy, violating the *Performance* section guidelines.

Animate with the full **`transform`** string to ensure hardware acceleration:

```javascript
// Avoid during heavy load
<motion.div x={100} scale={1.2} />

// Prefer
<motion.div 
  transform="translateX(100px) scale(1.2)" 
/>

```

## Visual Correctness and Transform Errors

### Animating from `scale(0)`

Starting animations from **`scale(0)`** creates a "pop-in from nowhere" effect that feels artificial, violating the *Never animate from scale(0)* guideline.

Start from a subtle scale combined with opacity:

```css
.tooltip {
  opacity: 0;
  transform: scale(0.95);
  transition: opacity 120ms var(--ease-out),
              transform 120ms var(--ease-out);
}

```

### Wrong `transform-origin` on Popovers

Popovers must scale from their trigger point rather than the center. The **origin & physical correctness** rule requires using **`var(--transform-origin)`** for trigger-anchored components; keep centre origin only for modals.

```css
.popover {
  transform-origin: var(--transform-origin);
}

```

## Accessibility and Group Animation

### Missing `prefers-reduced-motion` Handling

Accessibility requirements in the skills mandate gentler fallbacks for users who opt out of motion. Agents frequently omit the **`@media (prefers-reduced-motion: reduce)`** wrapper.

Wrap motion-heavy rules and keep only opacity or color transitions for the reduced case:

```css
@media (prefers-reduced-motion: reduce) {
  .tooltip {
    transition: opacity 80ms ease;
    transform: none;
  }
}

```

### Lack of Stagger for Groups

Animating entire lists simultaneously feels clunky. The *Stagger Animations* section prescribes a **30–80 ms** delay between items.

Apply incremental delays based on child indices:

```css
.item {
  opacity: 0;
  transform: translateY(8px);
  animation: fadeIn 300ms var(--ease-out) forwards;
}

.item:nth-child(1) { animation-delay: 0ms; }
.item:nth-child(2) { animation-delay: 40ms; }
.item:nth-child(3) { animation-delay: 80ms; }
/* … */

@keyframes fadeIn {
  to { opacity: 1; transform: translateY(0); }
}

```

## Implementation Examples

### Example 1: Correctly Gating an Animation

This TypeScript snippet implements the frequency gate from [`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md):

```tsx
// AI‑generated snippet (simplified)
if (frequency > 100) {
  // No animation – return static style
  return <Button className="btn">Click</Button>;
}

// Otherwise, apply a subtle transition
return (
  <Button className="btn">
    Click
  </Button>
);

```

```css
/* CSS respects GPU-only and origin rules */
.btn {
  transition: transform 150ms var(--ease-out);
  transform-origin: var(--transform-origin);
}

```

### Example 2: Custom Easing with Reduced Motion Fallback

Using the official `--ease-out` variable from [`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md) with accessibility wrapper:

```css
:root {
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
}

.tooltip {
  opacity: 0;
  transform: scale(0.95);
  transition: opacity 120ms var(--ease-out),
              transform 120ms var(--ease-out);
}

/* Reduced‑motion fallback */
@media (prefers-reduced-motion: reduce) {
  .tooltip {
    transition: opacity 80ms ease;
  }
}

```

## Key Source Files

| File | Purpose |
|------|---------|
| [`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md) | Primary build skill containing the decision flow and frequency gates |
| [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) | Catalog of easing curves, duration budgets, and GPU property rules |
| [`skills/review-animations/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/SKILL.md) | Review skill that validates motion against standards |
| [`skills/emil-design-eng/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/emil-design-eng/SKILL.md) | High-level philosophy underlying all animation decisions |
| [`README.md`](https://github.com/emilkowalski/skills/blob/main/README.md) | Repository overview and installation guidance |

## Summary

- **Check frequency gates first**: Actions occurring >100 times daily must never animate, as specified in [`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md).
- **Use GPU-only properties**: Animate `transform`, `opacity`, or `clip-path` only; never use `transition: all`.
- **Select correct easing**: Replace `ease-in` with `cubic-bezier(0.23, 1, 0.32, 1)` or other `ease-out` variants from the standards.
- **Respect transform rules**: Start scales from `0.95` not `0`, and set `transform-origin` to `var(--transform-origin)` for popovers.
- **Handle accessibility**: Wrap motion in `prefers-reduced-motion` media queries and provide opacity-only fallbacks.
- **Optimize performance**: Avoid Framer Motion shorthands under load, use transitions (not keyframes) for rapid UI, and stagger group animations by 30–80 ms.

## Frequently Asked Questions

### Why does emilkowalski/skills forbid animation on high-frequency actions?

The **frequency-appropriate** rule in [`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md) states that animations occurring more than 100 times per day create cognitive fatigue and performance overhead. Forcing static state changes on keyboard shortcuts and command-palette toggles preserves user focus and battery life while complying with the built-in review standards.

### What is the correct replacement for `transition: all`?

Replace the shorthand with explicit property declarations targeting compositor-only layers. According to [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md), valid declarations look like `transition: transform 200ms var(--ease-out), opacity 200ms var(--ease-out)`, ensuring layout and paint calculations remain off the main thread to prevent jank.

### How should AI agents handle staggered list animations?

Agents must apply incremental delays between 30–80 ms per item, calculated from the *Stagger Animations* section. Use `nth-child` selectors or inline styles with increasing delay values to create the cascading effect, ensuring the total sequence does not exceed the 300 ms budget for standard UI elements.

### Where are the official easing curves defined?

The **easing.dev** catalogue and custom variables are defined in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) under the *Responsive easing* rules. The primary recommended curve is `--ease-out: cubic-bezier(0.23, 1, 0.32, 1)`, which provides natural deceleration for UI entrances and is enforced by the `review-animations` skill.