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 + +
+ + + + + + + + +
+ + [description] +
+ +
+ +

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 + +
+ +
+ + + + + + + +
+ [Descriptive alt text — what is the product, what does it look like] + > +
+ +
+ +

Your Brand Name

+ +

Supporting description that provides context for screen readers

+ + Explore Features + + +
+ +
+ +
+

Why Choose [Product]

+ +
+
+``` + +--- + +## 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 + + +
+ ... +
+``` + +--- + +## 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 + +Tall glass of fresh orange juice with ice, floating on a gradient background + + + + + + + +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: `

`, `

`, `