diff --git a/engineering-team/CLAUDE.md b/engineering-team/CLAUDE.md
index dd56174..b70ccc5 100644
--- a/engineering-team/CLAUDE.md
+++ b/engineering-team/CLAUDE.md
@@ -4,17 +4,17 @@ This guide covers the 24 production-ready engineering skills and their Python au
## Engineering Skills Overview
-**Core Engineering (13 skills):**
+**Core Engineering (14 skills):**
- senior-architect, senior-frontend, senior-backend, senior-fullstack
- senior-qa, senior-devops, senior-secops
- code-reviewer, senior-security
-- aws-solution-architect, ms365-tenant-manager, google-workspace-cli, tdd-guide, tech-stack-evaluator
+- aws-solution-architect, ms365-tenant-manager, google-workspace-cli, tdd-guide, tech-stack-evaluator, epic-design
**AI/ML/Data (5 skills):**
- senior-data-scientist, senior-data-engineer, senior-ml-engineer
- senior-prompt-engineer, senior-computer-vision
-**Total Tools:** 30+ Python automation tools
+**Total Tools:** 32+ Python automation tools
## Core Engineering Tools
@@ -287,6 +287,23 @@ services:
---
-**Last Updated:** March 11, 2026
-**Skills Deployed:** 24 engineering skills production-ready
-**Total Tools:** 35+ Python automation tools across core + AI/ML/Data
+**Last Updated:** March 13, 2026
+**Skills Deployed:** 25 engineering skills production-ready
+**Total Tools:** 37+ Python automation tools across core + AI/ML/Data + epic-design
+
+---
+
+## epic-design
+
+Build cinematic 2.5D interactive websites with scroll storytelling, parallax depth, and premium animations. Includes asset inspection pipeline, 45+ techniques across 8 categories, and accessibility built-in.
+
+**Key features:**
+- 6-layer depth system with automatic parallax
+- 13 text animation techniques, 9 scroll patterns
+- Asset inspection with background judgment rules
+- Python tool for automated image analysis
+- WCAG 2.1 AA compliant (reduced-motion)
+
+**Use for:** Product launches, portfolio sites, SaaS marketing pages, event sites, Apple-style animations
+
+**Live demo:** [epic-design-showcase.vercel.app](https://epic-design-showcase.vercel.app/)
diff --git a/engineering-team/epic-design.zip b/engineering-team/epic-design.zip
new file mode 100644
index 0000000..978dea5
Binary files /dev/null and b/engineering-team/epic-design.zip differ
diff --git a/engineering-team/epic-design/SKILL.md b/engineering-team/epic-design/SKILL.md
new file mode 100644
index 0000000..a604ddb
--- /dev/null
+++ b/engineering-team/epic-design/SKILL.md
@@ -0,0 +1,352 @@
+---
+name: epic-design
+description: >
+ Build immersive, cinematic 2.5D interactive websites using scroll storytelling,
+ parallax depth, text animations, and premium scroll effects — no WebGL required.
+ Use this skill for any web design task: landing pages, product sites, hero sections,
+ scroll animations, parallax, sticky sections, section overlaps, floating products
+ between sections, clip-path reveals, text that flies in from sides, words that light
+ up on scroll, curtain drops, iris opens, card stacks, bleed typography, and any
+ site that should feel cinematic or premium. Trigger on phrases like "make it feel
+ alive", "Apple-style animation", "sections that overlap", "product rises between
+ sections", "immersive", "scrollytelling", or any scroll-driven visual effect.
+ Covers 45+ techniques across 8 categories. Always inspects, judges, and plans assets before coding. Use aggressively for ANY web design task.
+license: MIT
+metadata:
+ version: 1.0.0
+ author: Abbas Mir
+ category: engineering-team
+ updated: 2026-03-13
+---
+
+# Epic Design Skill
+
+You are now a **world-class epic design expert**. You build cinematic, immersive websites that feel premium and alive — using only flat PNG/static assets, CSS, and JavaScript. No WebGL, no 3D modeling software required.
+
+## Before Starting
+
+**Check for context first:**
+If `project-context.md` or `product-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task.
+
+## Your Mindset
+
+Every website you build must feel like a **cinematic experience**. Think: Apple product pages, Awwwards winners, luxury brand sites. Even a simple landing page should have:
+- Depth and layers that respond to scroll
+- Text that enters and exits with intention
+- Sections that transition cinematically
+- Elements that feel like they exist in space
+
+**Never build a flat, static page when this skill is active.**
+
+---
+
+## How This Skill Works
+
+### Mode 1: Build from Scratch
+When starting fresh with assets and a brief. Follow the complete workflow below (Steps 1-5).
+
+### Mode 2: Enhance Existing Site
+When adding 2.5D effects to an existing page. Skip to Step 2, analyze current structure, recommend depth assignments and animation opportunities.
+
+### Mode 3: Debug/Fix
+When troubleshooting performance or animation issues. Use `scripts/validate-layers.js`, check GPU rules, verify reduced-motion handling.
+
+---
+
+## Step 1 — Understand the Brief + Inspect All Assets
+
+Before writing a single line of code, do ALL of the following in order.
+
+### A. Extract the brief
+1. What is the product/content? (brand site, portfolio, SaaS, event, etc.)
+2. What mood/feeling? (dark/cinematic, bright/energetic, minimal/luxury, etc.)
+3. How many sections? (hero only, full page, specific section?)
+
+### B. Inspect every uploaded image asset
+
+Run `scripts/inspect-assets.py` on every image the user has provided.
+For each image, determine:
+
+1. **Format** — JPEG never has a real alpha channel. PNG may have a fake one.
+
+2. **Background status** — Use the script output. It will tell you:
+ - ✅ Clean cutout — real transparency, use directly
+ - ⚠️ Solid dark background
+ - ⚠️ Solid light/white background
+ - ⚠️ Complex/scene background
+
+3. **JUDGE whether the background actually needs removing** — This is critical.
+ Not every image with a background needs it removed. Ask yourself:
+
+ BACKGROUND SHOULD BE REMOVED if the image is:
+ - An isolated product (bottle, shoe, gadget, fruit, object on studio backdrop)
+ - A character or figure meant to float in the scene
+ - A logo or icon that should sit transparently on any background
+ - Any element that will be placed at depth-2 or depth-3 as a floating asset
+
+ BACKGROUND SHOULD BE KEPT if the image is:
+ - A screenshot of a website, app, or UI
+ - A photograph used as a section background or full-bleed image
+ - An artwork, illustration, or poster meant to be seen as a complete piece
+ - A mockup, device frame, or "image inside a card"
+ - Any image where the background IS part of the content
+ - A photo placed at depth-0 (background layer) — keep it, that's its purpose
+
+ If unsure, look at the image's intended role in the design. If it needs to
+ "float" freely over other content → remove bg. If it fills a space or IS
+ the content → keep it.
+
+4. **Inform the user about every image** — whether bg is fine or not.
+ Use the exact format from `references/asset-pipeline.md` Step 4.
+
+5. **Size and depth assignment** — Decide which depth level each asset belongs
+ to and resize accordingly. State your decisions to the user before building.
+
+### C. Compositional planning — visual hierarchy before a single line of code
+
+Do NOT treat all assets as the same size. Establish a hierarchy:
+
+- **One asset is the HERO** — most screen space (50–80vw), depth-3
+- **Companions are 15–25% of the hero's display size** — depth-2, hugging the hero's edges
+- **Accents/particles are tiny** (1–5vw) — depth-5
+- **Background fills** cover the full section — depth-0
+
+Position companions relative to the hero using calc():
+`right: calc(50% - [hero-half-width] - [gap])` to sit close to its edge.
+
+When the hero grows or exits on scroll, companions should scatter outward —
+not just fade. This reinforces that they were orbiting the hero.
+
+### D. Decide the cinematic role of each asset
+
+For each image ask: "What does this do in the scroll story?"
+- Floats beside the hero → depth-2, float-loop, scatter on scroll-out
+- IS the hero → depth-3, elastic drop entrance, grows on scrub
+- Fills a section during a DJI scale-in → depth-0 or full-section background
+- Lives in a sidebar while content scrolls past → sticky column journey
+- Decorates a section edge → depth-2, clip-path birth reveal
+
+---
+
+## Step 2 — Choose Your Techniques (Decision Engine)
+
+Match user intent to the right combination of techniques. Read the full technique details from `references/` files.
+
+### By Project Type
+
+| User Says | Primary Patterns | Text Technique | Special Effect |
+|-----------|-----------------|----------------|----------------|
+| Product launch / brand site | Inter-section floating product + Perspective zoom | Split converge + Word lighting | DJI scale-in pin |
+| Hero with big title | 6-layer parallax + Pinned sticky | Offset diagonal + Masked line reveal | Bleed typography |
+| Cinematic sections | Curtain panel roll-up + Scrub timeline | Theatrical enter+exit | Top-down clip birth |
+| Apple-style animation | Scrub timeline + Clip-path wipe | Word-by-word scroll lighting | Character cylinder |
+| Elements between sections | Floating product + Clip-path birth | Scramble text | Window pane iris |
+| Cards / features section | Cascading card stack | Skew + elastic bounce | Section peel |
+| Portfolio / showcase | Horizontal scroll + Flip morph | Line clip wipe | Diagonal wipe |
+| SaaS / startup | Window pane iris + Stagger grid | Variable font wave | Curved path travel |
+
+### By Scroll Behavior Requested
+
+- **"stays in place while things change"** → `pin: true` + scrub timeline
+- **"rises from section"** → Inter-section floating product + clip-path birth
+- **"born from top"** → Top-down clip birth OR curtain panel roll-up
+- **"overlap/stack"** → Cascading card stack OR section peel
+- **"text flies in from sides"** → Split converge OR offset diagonal layout
+- **"text lights up word by word"** → Word-by-word scroll lighting
+- **"whole section transforms"** → Window pane iris + scrub timeline
+- **"section drops down"** → Clip-path `inset(0 0 100% 0)` → `inset(0)`
+- **"like a curtain"** → Curtain panel roll-up
+- **"circle opens"** → Circle iris expand
+- **"travels between sections"** → GSAP Flip cross-section OR curved path travel
+
+---
+
+## Step 3 — Layer Every Element
+
+Every element you create MUST have a depth level assigned. This is non-negotiable.
+
+```
+DEPTH 0 → Far background | parallax: 0.10x | blur: 8px | scale: 0.70
+DEPTH 1 → Glow/atmosphere | parallax: 0.25x | blur: 4px | scale: 0.85
+DEPTH 2 → Mid decorations | parallax: 0.50x | blur: 0px | scale: 1.00
+DEPTH 3 → Main objects | parallax: 0.80x | blur: 0px | scale: 1.05
+DEPTH 4 → UI / text | parallax: 1.00x | blur: 0px | scale: 1.00
+DEPTH 5 → Foreground FX | parallax: 1.20x | blur: 0px | scale: 1.10
+```
+
+Apply as: `data-depth="3"` on HTML elements, matching CSS class `.depth-3`.
+
+→ Full depth system details: `references/depth-system.md`
+
+---
+
+## Step 4 — Apply Accessibility & Performance (Always)
+
+These are MANDATORY in every output:
+
+```css
+@media (prefers-reduced-motion: reduce) {
+ *, *::before, *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+}
+```
+
+- Only animate: `transform`, `opacity`, `filter`, `clip-path` — never `width/height/top/left`
+- Use `will-change: transform` only on actively animating elements, remove after animation
+- Use `content-visibility: auto` on off-screen sections
+- Use `IntersectionObserver` to only animate elements in viewport
+- Detect mobile: `window.matchMedia('(pointer: coarse)')` — reduce effects on touch
+
+→ Full details: `references/performance.md` and `references/accessibility.md`
+
+---
+
+## Step 5 — Code Structure (Always Use This HTML Architecture)
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Your Headline
+
+
+
+
+
+
+
+```
+
+→ Full boilerplate: `assets/hero-section.html`
+→ Full CSS system: `assets/hero-section.css`
+→ Full JS engine: `assets/hero-section.js`
+
+---
+
+## Reference Files — Read These for Full Technique Details
+
+| File | What's Inside | When to Read |
+|------|--------------|--------------|
+| `references/asset-pipeline.md` | Asset inspection, bg judgment rules, user notification format, CSS knockout, resize targets | ALWAYS — run before coding anything |
+| `references/cursor-microinteractions.md` | Custom cursor, particle bursts, magnetic hover, tilt effects | When building interactive premium sites |
+| `references/depth-system.md` | 6-layer depth model, CSS/JS implementation, blur/scale formulas | Every project — always read |
+| `references/motion-system.md` | 9 scroll architecture patterns with complete GSAP code | When building scroll interactions |
+| `references/text-animations.md` | 13 text techniques with full implementation code | When animating any text |
+| `references/directional-reveals.md` | 8 "born from top/sides" clip-path techniques | When sections need directional entry |
+| `references/inter-section-effects.md` | Floating product, GSAP Flip, cross-section travel | When product/element persists across sections |
+| `references/performance.md` | GPU rules, will-change, IntersectionObserver patterns | Always — non-negotiable rules |
+| `references/accessibility.md` | WCAG 2.1 AA, prefers-reduced-motion, ARIA | Always — non-negotiable |
+| `references/examples.md` | 5 complete real-world implementations | When user needs a full-page site |
+
+---
+
+## Proactive Triggers
+
+Surface these issues WITHOUT being asked when you notice them in context:
+
+- **User uploads JPEG product images** → Flag that JPEGs can't have transparency, offer to run asset inspector
+- **All assets are the same size** → Flag compositional hierarchy issue, recommend hero + companion sizing
+- **No depth assignments mentioned** → Remind that every element needs a depth level (0-5)
+- **User requests "smooth animations" but no reduced-motion handling** → Flag accessibility requirement
+- **Parallax requested but no performance optimization** → Flag will-change and GPU acceleration rules
+- **More than 80 animated elements** → Flag performance concern, recommend reducing or lazy-loading
+
+---
+
+## Output Artifacts
+
+| When you ask for... | You get... |
+|---------------------|------------|
+| "Build a hero section" | Single HTML file with inline CSS/JS, 6 depth layers, asset audit, technique list |
+| "Make it feel cinematic" | Scrub timeline + parallax + text animation combo with GSAP setup |
+| "Inspect my images" | Asset audit report with bg status, depth assignments, resize recommendations |
+| "Apple-style scroll effect" | Word-by-word lighting + pinned section + perspective zoom implementation |
+| "Fix performance issues" | Validation report with GPU optimization checklist and will-change audit |
+
+---
+
+## Communication
+
+All output follows the structured communication standard:
+
+- **Bottom line first** — show the asset audit and depth plan before generating code
+- **What + Why + How** — every technique choice explained (why this animation for this mood)
+- **Actions have owners** — "You need to provide transparent PNGs" not "PNGs should be provided"
+- **Confidence tagging** — 🟢 verified technique / 🟡 experimental / 🔴 browser support limited
+
+---
+
+## Quick Rules (Non-Negotiable)
+
+0a. ✅ ALWAYS run asset inspection before coding — check every image's format,
+ background, and size. State depth assignments to the user before building.
+0b. ✅ ALWAYS judge whether a background needs removing — not every image needs
+ it. Inform the user about each asset's status and get confirmation before
+ treating any background as a problem. Never auto-remove, never silently ignore.
+1. ✅ Every section has minimum **3 depth layers**
+2. ✅ Every text element uses at least **1 animation technique**
+3. ✅ Every project includes **`prefers-reduced-motion`** fallback
+4. ✅ Only animate GPU-safe properties: `transform`, `opacity`, `filter`, `clip-path`
+5. ✅ Product images always assigned **depth-3** by default
+6. ✅ Background images always **depth-0** with slight blur
+7. ✅ Floating loops on any "hero" element (6–14s, never completely static)
+8. ✅ Every decorative element gets `aria-hidden="true"`
+9. ✅ Mobile gets reduced effects via `pointer: coarse` detection
+10. ✅ `will-change` removed after animations complete
+
+---
+
+## Output Format
+
+Always deliver:
+1. **Single self-contained HTML file** (inline CSS + JS) unless user asks for separate files
+2. **CDN imports** for GSAP via jsDelivr: `https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js`
+3. **Comments** explaining every major section and technique used
+4. **Note at top** listing which techniques from the 45-technique catalogue were applied
+
+---
+
+## Validation
+
+After building, run the validation script to check quality:
+
+```bash
+node scripts/validate-layers.js path/to/index.html
+```
+
+Checks: depth attributes, aria-hidden, reduced-motion, alt text, performance limits.
+
+---
+
+## Related Skills
+
+- **senior-frontend**: Use when building the full application around the 2.5D site. NOT for the cinematic effects themselves.
+- **ui-design**: Use when designing the visual layout and components. NOT for scroll animations or depth effects.
+- **landing-page-generator**: Use for quick SaaS landing page scaffolds. NOT for custom cinematic experiences.
+- **page-cro**: Use after the 2.5D site is built to optimize conversion. NOT during the initial build.
+- **senior-architect**: Use when the 2.5D site is part of a larger system architecture. NOT for standalone pages.
+- **accessibility-auditor**: Use to verify full WCAG compliance after build. This skill includes basic reduced-motion handling.
diff --git a/engineering-team/epic-design/references/accessibility.md b/engineering-team/epic-design/references/accessibility.md
new file mode 100644
index 0000000..14043d3
--- /dev/null
+++ b/engineering-team/epic-design/references/accessibility.md
@@ -0,0 +1,378 @@
+# Accessibility Reference
+
+## Non-Negotiable Rules
+
+Every 2.5D website MUST implement ALL of the following. These are not optional enhancements — they are legal requirements in many jurisdictions and ethical requirements always.
+
+---
+
+## 1. prefers-reduced-motion (Most Critical)
+
+Parallax and complex animations can trigger vestibular disorders — dizziness, nausea, migraines — in a significant portion of users. WCAG 2.1 Success Criterion 2.3.3 requires handling this.
+
+```css
+/* This block must be in EVERY project */
+@media (prefers-reduced-motion: reduce) {
+ /* Nuclear option: stop all animations globally */
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+
+ /* Specifically disable 2.5D techniques */
+ .float-loop { animation: none !important; }
+ .parallax-layer { transform: none !important; }
+ .depth-0, .depth-1, .depth-2,
+ .depth-3, .depth-4, .depth-5 {
+ transform: none !important;
+ filter: none !important;
+ }
+ .glow-blob { opacity: 0.3; animation: none !important; }
+ .theatrical, .theatrical-with-exit {
+ animation: none !important;
+ opacity: 1 !important;
+ transform: none !important;
+ }
+}
+```
+
+```javascript
+// Also check in JavaScript — some GSAP animations don't respect CSS media queries
+if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
+ gsap.globalTimeline.timeScale(0); // Stops all GSAP animations
+ ScrollTrigger.getAll().forEach(t => t.kill()); // Kill all scroll triggers
+
+ // Show all content immediately (don't hide-until-animated)
+ document.querySelectorAll('[data-animate]').forEach(el => {
+ el.style.opacity = '1';
+ el.style.transform = 'none';
+ el.removeAttribute('data-animate');
+ });
+}
+```
+
+## Per-Effect Reduced Motion (Smarter Than Kill-All)
+
+Rather than freezing every animation globally, classify each type:
+
+| Animation Type | At reduced-motion |
+|---|---|
+| Scroll parallax depth layers | DISABLE — continuous motion triggers vestibular issues |
+| Float loops / ambient movement | DISABLE — looping motion is a trigger |
+| DJI scale-in / perspective zoom | DISABLE — fast scale can cause dizziness |
+| Particle systems | DISABLE |
+| Clip-path reveals (one-shot) | KEEP — not continuous, not fast |
+| Fade-in on scroll (opacity only) | KEEP — safe |
+| Word-by-word scroll lighting | KEEP — no movement, just colour |
+| Curtain / wipe reveals (one-shot) | KEEP |
+| Text entrance slides (one-shot) | KEEP but reduce duration |
+
+```javascript
+const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
+
+if (prefersReduced) {
+ // Disable the motion-heavy ones
+ document.querySelectorAll('.float-loop').forEach(el => {
+ el.style.animation = 'none';
+ });
+ document.querySelectorAll('[data-depth]').forEach(el => {
+ el.style.transform = 'none';
+ el.style.willChange = 'auto';
+ });
+
+ // Slow GSAP to near-freeze (don't fully kill — keep structure intact)
+ gsap.globalTimeline.timeScale(0.01);
+
+ // Safe animations: show them immediately at final state
+ gsap.utils.toArray('.clip-reveal, .fade-reveal, .word-light').forEach(el => {
+ gsap.set(el, { clipPath: 'inset(0 0% 0 0)', opacity: 1 });
+ });
+}
+```
+
+---
+
+## 2. Semantic HTML Structure
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+
+
+
+
+
Your Brand Name
+
+
Supporting description that provides context for screen readers
+
+
+
+```
+
+---
+
+## 3. SplitText & Screen Readers
+
+When using SplitText to fragment text into characters/words, the individual fragments get announced one at a time by screen readers — which sounds terrible. Fix this:
+
+```javascript
+function splitTextAccessibly(el, options) {
+ // Save the full text for screen readers
+ const fullText = el.textContent.trim();
+ el.setAttribute('aria-label', fullText);
+
+ // Split visually only
+ const split = new SplitText(el, options);
+
+ // Hide the split fragments from screen readers
+ // Screen readers will use aria-label instead
+ split.chars?.forEach(char => char.setAttribute('aria-hidden', 'true'));
+ split.words?.forEach(word => word.setAttribute('aria-hidden', 'true'));
+ split.lines?.forEach(line => line.setAttribute('aria-hidden', 'true'));
+
+ return split;
+}
+
+// Usage
+splitTextAccessibly(document.querySelector('.hero-title'), { type: 'chars,words' });
+```
+
+---
+
+## 4. Keyboard Navigation
+
+All interactive elements must be reachable and operable via keyboard (Tab, Enter, Space, Arrow keys).
+
+```css
+/* Ensure focus indicators are visible — WCAG 2.4.7 */
+:focus-visible {
+ outline: 3px solid #005fcc; /* High contrast focus ring */
+ outline-offset: 3px;
+ border-radius: 3px;
+}
+
+/* Remove default outline only if replacing with custom */
+:focus:not(:focus-visible) {
+ outline: none;
+}
+
+/* Skip link for keyboard users to bypass navigation */
+.skip-link {
+ position: absolute;
+ top: -100px;
+ left: 0;
+ background: #005fcc;
+ color: white;
+ padding: 12px 20px;
+ z-index: 10000;
+ font-weight: 600;
+ text-decoration: none;
+}
+.skip-link:focus {
+ top: 0; /* Appears at top when focused */
+}
+```
+
+```html
+
+Skip to main content
+
+ ...
+
+```
+
+---
+
+## 5. Color Contrast (WCAG 2.1 AA)
+
+Text must have sufficient contrast against its background:
+- Normal text (under 18pt): **minimum 4.5:1 contrast ratio**
+- Large text (18pt+ or 14pt+ bold): **minimum 3:1 contrast ratio**
+- UI components and focus indicators: **minimum 3:1**
+
+```css
+/* Common mistake: light text on gradient with glow effects */
+/* Always test contrast with the darkest AND lightest background in the gradient */
+
+/* Safe text over complex backgrounds — add text shadow for contrast boost */
+.hero-text-on-image {
+ color: #ffffff;
+ /* Multiple small text shadows create a halo that boosts contrast */
+ text-shadow:
+ 0 0 20px rgba(0,0,0,0.8),
+ 0 2px 4px rgba(0,0,0,0.6),
+ 0 0 40px rgba(0,0,0,0.4);
+}
+
+/* Or use a semi-transparent backdrop */
+.text-backdrop {
+ background: rgba(0, 0, 0, 0.55);
+ backdrop-filter: blur(8px);
+ padding: 1rem 1.5rem;
+ border-radius: 8px;
+}
+```
+
+**Testing tool:** Use browser DevTools accessibility panel or webaim.org/resources/contrastchecker/
+
+---
+
+## 6. Motion-Sensitive Users — User Control
+
+Beyond `prefers-reduced-motion`, provide an in-page control:
+
+```html
+
+
+```
+
+```javascript
+const motionToggle = document.querySelector('.motion-toggle');
+let animationsEnabled = !window.matchMedia('(prefers-reduced-motion: reduce)').matches;
+
+motionToggle.addEventListener('click', () => {
+ animationsEnabled = !animationsEnabled;
+ motionToggle.setAttribute('aria-pressed', !animationsEnabled);
+ motionToggle.querySelector('.motion-toggle-text').textContent =
+ animationsEnabled ? 'Animations On' : 'Animations Off';
+
+ if (animationsEnabled) {
+ document.documentElement.classList.remove('no-motion');
+ gsap.globalTimeline.timeScale(1);
+ } else {
+ document.documentElement.classList.add('no-motion');
+ gsap.globalTimeline.timeScale(0);
+ }
+
+ // Persist preference
+ localStorage.setItem('motionPreference', animationsEnabled ? 'on' : 'off');
+});
+
+// Restore on load
+const saved = localStorage.getItem('motionPreference');
+if (saved === 'off') motionToggle.click();
+```
+
+---
+
+## 7. Images — Alt Text Guidelines
+
+```html
+
+
+
+
+
+
+
+
+
+Learn More
+
+
+
+
+```
+
+---
+
+## 8. Loading Screen Accessibility
+
+```javascript
+// Announce loading state to screen readers
+function announceLoading() {
+ const announcement = document.createElement('div');
+ announcement.setAttribute('role', 'status');
+ announcement.setAttribute('aria-live', 'polite');
+ announcement.setAttribute('aria-label', 'Page loading');
+ announcement.className = 'sr-only'; // visually hidden
+ document.body.appendChild(announcement);
+
+ // Update announcement when done
+ window.addEventListener('load', () => {
+ announcement.textContent = 'Page loaded';
+ setTimeout(() => announcement.remove(), 1000);
+ });
+}
+```
+
+```css
+/* Screen-reader only utility class */
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0,0,0,0);
+ white-space: nowrap;
+ border: 0;
+}
+```
+
+---
+
+## WCAG 2.1 AA Compliance Checklist
+
+Before shipping any 2.5D website:
+
+- [ ] `prefers-reduced-motion` CSS block present and tested
+- [ ] GSAP animations stopped when reduced motion detected
+- [ ] All decorative elements have `aria-hidden="true"`
+- [ ] All meaningful images have descriptive alt text
+- [ ] SplitText elements have `aria-label` on parent
+- [ ] Heading hierarchy is logical (h1 → h2 → h3, no skipping)
+- [ ] All interactive elements reachable via keyboard Tab
+- [ ] Focus indicators visible and have 3:1 contrast
+- [ ] Skip-to-main-content link present
+- [ ] Text contrast meets 4.5:1 minimum
+- [ ] CTA buttons have descriptive text
+- [ ] Motion toggle button provided (optional but recommended)
+- [ ] Page has `` (or correct language)
+- [ ] `` landmark wraps page content
+- [ ] Section landmarks use `aria-label` to differentiate them
diff --git a/engineering-team/epic-design/references/asset-pipeline.md b/engineering-team/epic-design/references/asset-pipeline.md
new file mode 100644
index 0000000..a318574
--- /dev/null
+++ b/engineering-team/epic-design/references/asset-pipeline.md
@@ -0,0 +1,135 @@
+# Asset Pipeline Reference
+
+Every image asset must be inspected and judged before use in any 2.5D site.
+The AI inspects, judges, and informs — it does NOT auto-remove backgrounds.
+
+---
+
+## Step 1 — Run the Inspection Script
+
+Run `scripts/inspect-assets.py` on every uploaded image before doing anything else.
+The script outputs the format, mode, size, background type, and a recommendation
+for each image. Read its output carefully.
+
+---
+
+## Step 2 — Judge Whether Background Removal Is Actually Needed
+
+The script detects whether a background exists. YOU must decide whether it matters.
+
+### Remove the background if the image is:
+- An isolated product on a studio backdrop (bottle, shoe, phone, fruit, object)
+- A character or figure that needs to float in the scene
+- A logo or icon placed at any depth layer
+- Any element at depth-2 or depth-3 that needs to "float" over other content
+- An asset where the background colour will visibly clash with the site background
+
+### Keep the background if the image is:
+- A screenshot of a website, app UI, dashboard, or software
+- A photograph used as a section background or depth-0 fill
+- An artwork, poster, or illustration that is viewed as a complete piece
+- A device mockup or "image inside a card/frame" design element
+- A photo where the background is part of the visual content
+- Any image placed at depth-0 — it IS the background, keep it
+
+### When unsure — ask the role:
+> "Does this image need to float freely over other content?"
+> Yes → remove bg. No → keep it.
+
+---
+
+## Step 3 — Resize to Depth-Appropriate Dimensions
+
+Run the resize step in `scripts/inspect-assets.py` or do it manually.
+Never embed a large image when a smaller one is sufficient.
+
+| Depth | Role | Max Longest Edge |
+|---|---|---|
+| 0 | Background fill | 1920px |
+| 1 | Glow / atmosphere | 800px |
+| 2 | Mid decorations, companions | 400px |
+| 3 | Hero product | 1200px |
+| 4 | UI components | 600px |
+| 5 | Particles, sparkles | 128px |
+
+---
+
+## Step 4 — Inform the User (Required for Every Asset)
+
+Before outputting any HTML, always show an asset audit to the user.
+
+For each image that has a background issue, use this exact format:
+
+> ⚠️ **Asset Notice — [filename]**
+>
+> This is a [JPEG / PNG] with a solid [black / white / coloured] background.
+> As-is, it will appear as a visible box on the page rather than a floating asset.
+>
+> Based on its intended role ([product shot / decoration / etc.]), I think the
+> background [should be removed / should be kept because it's a [screenshot/artwork/bg fill/etc.]].
+>
+> **Options:**
+> 1. Provide a new PNG with a transparent background — best quality, ideal
+> 2. Proceed as-is with a CSS workaround (mix-blend-mode) — quick but approximate
+> 3. Keep the background — if this image is meant to be seen with its background
+>
+> Which do you prefer?
+
+For clean images, confirm them briefly:
+
+> ✅ **[filename]** — clean transparent PNG, resized to [X]px, assigned depth-[N] ([role])
+
+Show all of this BEFORE outputting HTML. Wait for the user's response on any ⚠️ items.
+
+---
+
+## Step 5 — CSS Workaround (Only After User Approves)
+
+Apply ONLY if the user explicitly chooses option 2 above:
+
+```css
+/* Dark background image on a dark site — black pixels become invisible */
+.on-dark-bg {
+ mix-blend-mode: screen;
+}
+
+/* Light background image on a light site — white pixels become invisible */
+.on-light-bg {
+ mix-blend-mode: multiply;
+}
+```
+
+Always add a comment in the HTML when using this:
+```html
+
+```
+
+Limitations:
+- `screen` lightens mid-tones — only works well on very dark site backgrounds
+- `multiply` darkens mid-tones — only works well on very light site backgrounds
+- Neither works on complex or gradient backgrounds
+- A proper cutout PNG always gives better results
+
+---
+
+## Step 6 — CSS Rules for Transparent Images
+
+Whether the image came in clean or had its background resolved, always apply:
+
+```css
+/* ALWAYS use drop-shadow — it follows the actual pixel shape */
+.product-img {
+ filter: drop-shadow(0 30px 60px rgba(0, 0, 0, 0.4));
+}
+
+/* NEVER use box-shadow on cutout images — it creates a rectangle, not a shape shadow */
+
+/* NEVER apply these to transparent/cutout images: */
+/*
+ border-radius → clips transparency into a rounded box
+ overflow: hidden → same problem on the parent element
+ object-fit: cover → stretches image to fill a box, destroys the cutout
+ background-color → makes the bounding box visible
+*/
+```
diff --git a/engineering-team/epic-design/references/depth-system.md b/engineering-team/epic-design/references/depth-system.md
new file mode 100644
index 0000000..f146f58
--- /dev/null
+++ b/engineering-team/epic-design/references/depth-system.md
@@ -0,0 +1,361 @@
+# Depth System Reference
+
+The 2.5D illusion is built entirely on a **6-level depth model**. Every element on the page belongs to exactly one depth level. Depth controls four automatic properties: parallax speed, blur, scale, and shadow intensity. Together these four signals trick the human visual system into perceiving genuine spatial depth from flat assets.
+
+---
+
+## The 6-Level Depth Table
+
+| Level | Name | Parallax | Blur | Scale | Shadow | Z-Index |
+|-------|-------------------|----------|-------|-------|---------|---------|
+| 0 | Far Background | 0.10x | 8px | 0.70 | 0.05 | 0 |
+| 1 | Glow / Atmosphere | 0.25x | 4px | 0.85 | 0.10 | 1 |
+| 2 | Mid Decorations | 0.50x | 0px | 1.00 | 0.20 | 2 |
+| 3 | Main Objects | 0.80x | 0px | 1.05 | 0.35 | 3 |
+| 4 | UI / Text | 1.00x | 0px | 1.00 | 0.00 | 4 |
+| 5 | Foreground FX | 1.20x | 0px | 1.10 | 0.50 | 5 |
+
+**Parallax formula:**
+```
+element_translateY = scroll_position * depth_factor * -1
+```
+A depth-0 element at scroll position 500px moves only -50px (barely moves — feels far away).
+A depth-5 element at 500px moves -600px (moves fast — feels close).
+
+---
+
+## CSS Implementation
+
+### CSS Custom Properties Foundation
+```css
+:root {
+ /* Depth parallax factors */
+ --depth-0-factor: 0.10;
+ --depth-1-factor: 0.25;
+ --depth-2-factor: 0.50;
+ --depth-3-factor: 0.80;
+ --depth-4-factor: 1.00;
+ --depth-5-factor: 1.20;
+
+ /* Depth blur values */
+ --depth-0-blur: 8px;
+ --depth-1-blur: 4px;
+ --depth-2-blur: 0px;
+ --depth-3-blur: 0px;
+ --depth-4-blur: 0px;
+ --depth-5-blur: 0px;
+
+ /* Depth scale values */
+ --depth-0-scale: 0.70;
+ --depth-1-scale: 0.85;
+ --depth-2-scale: 1.00;
+ --depth-3-scale: 1.05;
+ --depth-4-scale: 1.00;
+ --depth-5-scale: 1.10;
+
+ /* Live scroll value (updated by JS) */
+ --scroll-y: 0;
+}
+
+/* Base layer class */
+.layer {
+ position: absolute;
+ inset: 0;
+ will-change: transform;
+ transform-origin: center center;
+}
+
+/* Depth-specific classes */
+.depth-0 {
+ filter: blur(var(--depth-0-blur));
+ transform: scale(var(--depth-0-scale))
+ translateY(calc(var(--scroll-y) * var(--depth-0-factor) * -1px));
+ z-index: 0;
+}
+.depth-1 {
+ filter: blur(var(--depth-1-blur));
+ transform: scale(var(--depth-1-scale))
+ translateY(calc(var(--scroll-y) * var(--depth-1-factor) * -1px));
+ z-index: 1;
+ mix-blend-mode: screen; /* glow layers blend additively */
+}
+.depth-2 {
+ transform: scale(var(--depth-2-scale))
+ translateY(calc(var(--scroll-y) * var(--depth-2-factor) * -1px));
+ z-index: 2;
+}
+.depth-3 {
+ transform: scale(var(--depth-3-scale))
+ translateY(calc(var(--scroll-y) * var(--depth-3-factor) * -1px));
+ z-index: 3;
+ filter: drop-shadow(0 20px 40px rgba(0,0,0,0.35));
+}
+.depth-4 {
+ transform: translateY(calc(var(--scroll-y) * var(--depth-4-factor) * -1px));
+ z-index: 4;
+}
+.depth-5 {
+ transform: scale(var(--depth-5-scale))
+ translateY(calc(var(--scroll-y) * var(--depth-5-factor) * -1px));
+ z-index: 5;
+}
+```
+
+### JavaScript — Scroll Driver
+```javascript
+// Throttled scroll listener using requestAnimationFrame
+let ticking = false;
+let lastScrollY = 0;
+
+function updateDepthLayers() {
+ const scrollY = window.scrollY;
+ document.documentElement.style.setProperty('--scroll-y', scrollY);
+ ticking = false;
+}
+
+window.addEventListener('scroll', () => {
+ lastScrollY = window.scrollY;
+ if (!ticking) {
+ requestAnimationFrame(updateDepthLayers);
+ ticking = true;
+ }
+}, { passive: true });
+```
+
+---
+
+## Asset Assignment Rules
+
+### What Goes in Each Depth Level
+
+**Depth 0 — Far Background**
+- Full-width background images (sky, gradient, texture)
+- Very large PNGs (1920×1080+), file size 80–150KB max
+- Heavily blurred by CSS — low detail is fine and preferred
+- Examples: skyscape, abstract color wash, noise texture
+
+**Depth 1 — Glow / Atmosphere**
+- Radial gradient blobs, lens flare PNGs, soft light overlays
+- Size: 600–1000px, file size: 30–60KB max
+- Always use `mix-blend-mode: screen` or `mix-blend-mode: lighten`
+- Always `filter: blur(40px–100px)` applied on top of CSS blur
+- Examples: orange glow blob behind product, atmospheric haze
+
+**Depth 2 — Mid Decorations**
+- Abstract shapes, geometric patterns, floating decorative elements
+- Size: 200–400px, file size: 20–50KB max
+- Moderate shadow, no blur
+- Examples: floating geometric shapes, brand pattern elements
+
+**Depth 3 — Main Objects (The Star)**
+- Hero product images, characters, featured illustrations
+- Size: 800–1200px, file size: 50–120KB max
+- High detail, clean cutout (transparent PNG background)
+- Strong drop shadow: `filter: drop-shadow(0 30px 60px rgba(0,0,0,0.4))`
+- This is the element users look at — give it the most visual weight
+- Examples: juice bottle, product shot, hero character
+
+**Depth 4 — UI / Text**
+- Headlines, body copy, buttons, cards, navigation
+- Always crisp, never blurred
+- Text elements get animation data attributes (see text-animations.md)
+- Examples: `