From 7145b62bfd3cda79ac0b5bd49020e3465fb6f027 Mon Sep 17 00:00:00 2001 From: enyst Date: Tue, 24 Feb 2026 04:23:06 +0000 Subject: [PATCH 1/8] Add frontend-slides skill Co-authored-by: openhands --- .plugin/marketplace.json | 15 + skills/frontend-slides/LICENSE.txt | 21 + skills/frontend-slides/README.md | 157 +++++ skills/frontend-slides/SKILL.md | 42 ++ .../references/ANIMATION_PATTERNS.md | 98 ++++ .../references/PPT_CONVERSION.md | 120 ++++ .../references/STYLE_EFFECT_MAPPING.md | 52 ++ .../references/STYLE_PRESETS.md | 527 +++++++++++++++++ .../references/TROUBLESHOOTING.md | 28 + .../references/VIEWPORT_FITTING.md | 228 ++++++++ skills/frontend-slides/references/WORKFLOW.md | 552 ++++++++++++++++++ 11 files changed, 1840 insertions(+) create mode 100644 skills/frontend-slides/LICENSE.txt create mode 100644 skills/frontend-slides/README.md create mode 100644 skills/frontend-slides/SKILL.md create mode 100644 skills/frontend-slides/references/ANIMATION_PATTERNS.md create mode 100644 skills/frontend-slides/references/PPT_CONVERSION.md create mode 100644 skills/frontend-slides/references/STYLE_EFFECT_MAPPING.md create mode 100644 skills/frontend-slides/references/STYLE_PRESETS.md create mode 100644 skills/frontend-slides/references/TROUBLESHOOTING.md create mode 100644 skills/frontend-slides/references/VIEWPORT_FITTING.md create mode 100644 skills/frontend-slides/references/WORKFLOW.md diff --git a/.plugin/marketplace.json b/.plugin/marketplace.json index 14acf5a..9631641 100644 --- a/.plugin/marketplace.json +++ b/.plugin/marketplace.json @@ -153,6 +153,21 @@ "css" ] }, + { + "name": "frontend-slides", + "source": "./frontend-slides", + "description": "Create stunning, animation-rich HTML presentations from scratch or by converting PowerPoint files. Use when the user wants to build a presentation, convert a PPT/PPTX to web, or create slides for a talk/pitch.", + "category": "design", + "keywords": [ + "slides", + "presentation", + "ppt", + "pptx", + "html", + "css", + "animation" + ] + }, { "name": "github", "source": "./github", diff --git a/skills/frontend-slides/LICENSE.txt b/skills/frontend-slides/LICENSE.txt new file mode 100644 index 0000000..746da68 --- /dev/null +++ b/skills/frontend-slides/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Zara Zhang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/skills/frontend-slides/README.md b/skills/frontend-slides/README.md new file mode 100644 index 0000000..03178ce --- /dev/null +++ b/skills/frontend-slides/README.md @@ -0,0 +1,157 @@ +# Frontend Slides + +An [Agent Skills](https://agentskills.io/) skill for creating stunning, animation-rich HTML presentations — from scratch or by converting PowerPoint files. + +This skill is published in the OpenHands extensions registry and can be used by OpenHands (CLI/GUI/Cloud) and other AgentSkills-compatible runtimes. + +## What This Does + +**Frontend Slides** helps non-designers create beautiful web presentations without knowing CSS or JavaScript. It uses a "show, don't tell" approach: instead of asking you to describe your aesthetic preferences in words, it generates visual previews and lets you pick what you like. + +### Key Features + +- **Zero Dependencies** — Single HTML files with inline CSS/JS. No npm, no build tools, no frameworks. +- **Visual Style Discovery** — Can't articulate design preferences? No problem. Pick from generated visual previews. +- **PPT Conversion** — Convert existing PowerPoint files to web, preserving all images and content. +- **Anti-AI-Slop** — Curated distinctive styles that avoid generic AI aesthetics (bye-bye, purple gradients on white). +- **Production Quality** — Accessible, responsive, well-commented code you can customize. + +## Installation + +### For Claude Code Users + +Copy the entire `frontend-slides/` directory (including `references/`) to your skills directory: + +```bash +# From the directory containing frontend-slides/ +mkdir -p ~/.claude/skills +cp -R frontend-slides ~/.claude/skills/ +``` + +Then use it by typing `/frontend-slides` in Claude Code. + +### Manual Download + +1. Download `SKILL.md` and the `references/` directory (at minimum `references/STYLE_PRESETS.md`). +2. Place them in `~/.claude/skills/frontend-slides/` preserving the `references/` folder. +3. Restart Claude Code + +## Usage + +### Create a New Presentation + +``` +/frontend-slides + +> "I want to create a pitch deck for my AI startup" +``` + +The skill will: +1. Ask about your content (slides, messages, images) +2. Ask about the feeling you want (impressed? excited? calm?) +3. Generate 3 visual style previews for you to compare +4. Create the full presentation in your chosen style +5. Open it in your browser + +### Convert a PowerPoint + +``` +/frontend-slides + +> "Convert my presentation.pptx to a web slideshow" +``` + +The skill will: +1. Extract all text, images, and notes from your PPT +2. Show you the extracted content for confirmation +3. Let you pick a visual style +4. Generate an HTML presentation with all your original assets + +## Included Styles + +### Dark Themes +- **Neon Cyber** — Futuristic, techy, particle effects +- **Midnight Executive** — Premium, corporate, trustworthy +- **Deep Space** — Cinematic, inspiring, vast +- **Terminal Green** — Developer-focused, hacker aesthetic + +### Light Themes +- **Paper & Ink** — Editorial, literary, refined +- **Swiss Modern** — Clean, Bauhaus-inspired, geometric +- **Soft Pastel** — Friendly, playful, creative +- **Warm Editorial** — Magazine-style, photographic + +### Specialty +- **Brutalist** — Raw, bold, attention-grabbing +- **Gradient Wave** — Modern SaaS aesthetic + +## Output Example + +Each presentation is a single, self-contained HTML file: + +```html + + + + + + +
+

Your Title

+
+ +
+

Slide Content

+
+ + + + + +``` + +Features included: +- Keyboard navigation (arrows, space) +- Touch/swipe support +- Mouse wheel scrolling +- Progress bar +- Navigation dots +- Scroll-triggered animations +- Responsive design +- Reduced motion support + +## Philosophy + +This skill was born from the belief that: + +1. **You don't need to be a designer to make beautiful things.** You just need to react to what you see. + +2. **Dependencies are debt.** A single HTML file will work in 10 years. A React project from 2019? Good luck. + +3. **Generic is forgettable.** Every presentation should feel custom-crafted, not template-generated. + +4. **Comments are kindness.** Code should explain itself to future-you (or anyone else who opens it). + +## Files + +| File | Purpose | +|------|---------| +| `SKILL.md` | Main skill instructions for Claude Code | +| `STYLE_PRESETS.md` | Reference file with 10 curated visual styles | + +## Requirements + +- [Claude Code](https://claude.ai/claude-code) CLI +- For PPT conversion: Python with `python-pptx` library + +## Credits + +Created by [@zarazhangrui](https://github.com/zarazhangrui) with Claude Code. + +Inspired by the "Vibe Coding" philosophy — building beautiful things without being a traditional software engineer. + +## License + +MIT — Use it, modify it, share it. diff --git a/skills/frontend-slides/SKILL.md b/skills/frontend-slides/SKILL.md new file mode 100644 index 0000000..4a92d32 --- /dev/null +++ b/skills/frontend-slides/SKILL.md @@ -0,0 +1,42 @@ +--- +name: frontend-slides +description: Create stunning, animation-rich HTML presentations from scratch or by converting PowerPoint files. Use when the user wants to build a presentation, convert a PPT/PPTX to web, or create slides for a talk/pitch. Helps non-designers discover their aesthetic through visual exploration rather than abstract choices. +license: MIT (see LICENSE.txt) +compatibility: For PPT/PPTX conversion requires Python and the python-pptx package. +--- + +# Frontend Slides Skill + +Create **zero-dependency**, animation-rich HTML presentations that run entirely in the browser. + +## Non-negotiables + +- **Single-file output:** generate a self-contained `.html` with inline CSS/JS (no npm, no build tools). +- **Distinctive design:** avoid generic, templated “AI slop” aesthetics. +- **Viewport fitting (CRITICAL):** every slide must fit exactly in the viewport; **no scrolling within slides**. + - Details + mandatory base CSS: see [references/VIEWPORT_FITTING.md](references/VIEWPORT_FITTING.md). + +## How to use (choose a mode) + +1. **New presentation** (from scratch) + - Use the structured workflow in [references/WORKFLOW.md](references/WORKFLOW.md). + - Use curated styles in [references/STYLE_PRESETS.md](references/STYLE_PRESETS.md). + +2. **PPT/PPTX conversion** + - Extract content + images with the workflow in [references/PPT_CONVERSION.md](references/PPT_CONVERSION.md). + +3. **Enhance an existing HTML presentation** + - Read the existing HTML/CSS/JS, preserve the content structure, then apply the same constraints: + - viewport fitting + - accessibility + - performance + - distinctive visuals + +## Design + animation references + +- Effect → feeling mapping: [references/STYLE_EFFECT_MAPPING.md](references/STYLE_EFFECT_MAPPING.md) +- Animation patterns (CSS/JS snippets): [references/ANIMATION_PATTERNS.md](references/ANIMATION_PATTERNS.md) + +## Troubleshooting + +See [references/TROUBLESHOOTING.md](references/TROUBLESHOOTING.md). diff --git a/skills/frontend-slides/references/ANIMATION_PATTERNS.md b/skills/frontend-slides/references/ANIMATION_PATTERNS.md new file mode 100644 index 0000000..4e34bc9 --- /dev/null +++ b/skills/frontend-slides/references/ANIMATION_PATTERNS.md @@ -0,0 +1,98 @@ +## Animation Patterns Reference + +### Entrance Animations + +```css +/* Fade + Slide Up (most common) */ +.reveal { + opacity: 0; + transform: translateY(30px); + transition: opacity 0.6s var(--ease-out-expo), + transform 0.6s var(--ease-out-expo); +} + +.visible .reveal { + opacity: 1; + transform: translateY(0); +} + +/* Scale In */ +.reveal-scale { + opacity: 0; + transform: scale(0.9); + transition: opacity 0.6s, transform 0.6s var(--ease-out-expo); +} + +/* Slide from Left */ +.reveal-left { + opacity: 0; + transform: translateX(-50px); + transition: opacity 0.6s, transform 0.6s var(--ease-out-expo); +} + +/* Blur In */ +.reveal-blur { + opacity: 0; + filter: blur(10px); + transition: opacity 0.8s, filter 0.8s var(--ease-out-expo); +} +``` + +### Background Effects + +```css +/* Gradient Mesh */ +.gradient-bg { + background: + radial-gradient(ellipse at 20% 80%, rgba(120, 0, 255, 0.3) 0%, transparent 50%), + radial-gradient(ellipse at 80% 20%, rgba(0, 255, 200, 0.2) 0%, transparent 50%), + var(--bg-primary); +} + +/* Noise Texture */ +.noise-bg { + background-image: url("data:image/svg+xml,..."); /* Inline SVG noise */ +} + +/* Grid Pattern */ +.grid-bg { + background-image: + linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px), + linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px); + background-size: 50px 50px; +} +``` + +### Interactive Effects + +```javascript +/* 3D Tilt on Hover */ +class TiltEffect { + constructor(element) { + this.element = element; + this.element.style.transformStyle = 'preserve-3d'; + this.element.style.perspective = '1000px'; + this.bindEvents(); + } + + bindEvents() { + this.element.addEventListener('mousemove', (e) => { + const rect = this.element.getBoundingClientRect(); + const x = (e.clientX - rect.left) / rect.width - 0.5; + const y = (e.clientY - rect.top) / rect.height - 0.5; + + this.element.style.transform = ` + rotateY(${x * 10}deg) + rotateX(${-y * 10}deg) + `; + }); + + this.element.addEventListener('mouseleave', () => { + this.element.style.transform = 'rotateY(0) rotateX(0)'; + }); + } +} +``` + +--- + diff --git a/skills/frontend-slides/references/PPT_CONVERSION.md b/skills/frontend-slides/references/PPT_CONVERSION.md new file mode 100644 index 0000000..b3d96cd --- /dev/null +++ b/skills/frontend-slides/references/PPT_CONVERSION.md @@ -0,0 +1,120 @@ +## Phase 4: PPT Conversion + +When converting PowerPoint files: + +### Step 4.1: Extract Content + +Use Python with `python-pptx` to extract: + +```python +from pptx import Presentation +from pptx.util import Inches, Pt +import json +import os +import base64 + +def extract_pptx(file_path, output_dir): + """ + Extract all content from a PowerPoint file. + Returns a JSON structure with slides, text, and images. + """ + prs = Presentation(file_path) + slides_data = [] + + # Create assets directory + assets_dir = os.path.join(output_dir, 'assets') + os.makedirs(assets_dir, exist_ok=True) + + for slide_num, slide in enumerate(prs.slides): + slide_data = { + 'number': slide_num + 1, + 'title': '', + 'content': [], + 'images': [], + 'notes': '' + } + + for shape in slide.shapes: + # Extract title + if shape.has_text_frame: + if shape == slide.shapes.title: + slide_data['title'] = shape.text + else: + slide_data['content'].append({ + 'type': 'text', + 'content': shape.text + }) + + # Extract images + if shape.shape_type == 13: # Picture + image = shape.image + image_bytes = image.blob + image_ext = image.ext + image_name = f"slide{slide_num + 1}_img{len(slide_data['images']) + 1}.{image_ext}" + image_path = os.path.join(assets_dir, image_name) + + with open(image_path, 'wb') as f: + f.write(image_bytes) + + slide_data['images'].append({ + 'path': f"assets/{image_name}", + 'width': shape.width, + 'height': shape.height + }) + + # Extract notes + if slide.has_notes_slide: + notes_frame = slide.notes_slide.notes_text_frame + slide_data['notes'] = notes_frame.text + + slides_data.append(slide_data) + + return slides_data +``` + +### Step 4.2: Confirm Content Structure + +Present the extracted content to the user: + +``` +I've extracted the following from your PowerPoint: + +**Slide 1: [Title]** +- [Content summary] +- Images: [count] + +**Slide 2: [Title]** +- [Content summary] +- Images: [count] + +... + +All images have been saved to the assets folder. + +Does this look correct? Should I proceed with style selection? +``` + +### Step 4.3: Style Selection + +Proceed to Phase 2 (Style Discovery) with the extracted content in mind. + +### Step 4.4: Generate HTML + +Convert the extracted content into the chosen style, preserving: +- All text content +- All images (referenced from assets folder) +- Slide order +- Any speaker notes (as HTML comments or separate file) + +--- + +## Conversion Session Flow + +1. User: "Convert my slides.pptx to a web presentation" +2. Skill extracts content and images from PPT +3. Skill confirms extracted content with user +4. Skill asks about desired feeling/style +5. Skill generates style previews +6. User picks a style +7. Skill generates HTML presentation with preserved assets +8. Final presentation delivered diff --git a/skills/frontend-slides/references/STYLE_EFFECT_MAPPING.md b/skills/frontend-slides/references/STYLE_EFFECT_MAPPING.md new file mode 100644 index 0000000..b261d82 --- /dev/null +++ b/skills/frontend-slides/references/STYLE_EFFECT_MAPPING.md @@ -0,0 +1,52 @@ +## Style Reference: Effect → Feeling Mapping + +Use this guide to match animations to intended feelings: + +### Dramatic / Cinematic +- Slow fade-ins (1-1.5s) +- Large scale transitions (0.9 → 1) +- Dark backgrounds with spotlight effects +- Parallax scrolling +- Full-bleed images + +### Techy / Futuristic +- Neon glow effects (box-shadow with accent color) +- Particle systems (canvas background) +- Grid patterns +- Monospace fonts for accents +- Glitch or scramble text effects +- Cyan, magenta, electric blue palette + +### Playful / Friendly +- Bouncy easing (spring physics) +- Rounded corners (large radius) +- Pastel or bright colors +- Floating/bobbing animations +- Hand-drawn or illustrated elements + +### Professional / Corporate +- Subtle, fast animations (200-300ms) +- Clean sans-serif fonts +- Navy, slate, or charcoal backgrounds +- Precise spacing and alignment +- Minimal decorative elements +- Data visualization focus + +### Calm / Minimal +- Very slow, subtle motion +- High whitespace +- Muted color palette +- Serif typography +- Generous padding +- Content-focused, no distractions + +### Editorial / Magazine +- Strong typography hierarchy +- Pull quotes and callouts +- Image-text interplay +- Grid-breaking layouts +- Serif headlines, sans-serif body +- Black and white with one accent + +--- + diff --git a/skills/frontend-slides/references/STYLE_PRESETS.md b/skills/frontend-slides/references/STYLE_PRESETS.md new file mode 100644 index 0000000..e118f8b --- /dev/null +++ b/skills/frontend-slides/references/STYLE_PRESETS.md @@ -0,0 +1,527 @@ +# Style Presets Reference + +Curated visual styles for Frontend Slides. Each preset is inspired by real design references—no generic "AI slop" aesthetics. **Abstract shapes only—no illustrations.** + +--- + +## ⚠️ CRITICAL: Viewport Fitting (Non-Negotiable) + +**Every slide MUST fit exactly in the viewport. No scrolling within slides, ever.** + +### Content Density Limits Per Slide + +| Slide Type | Maximum Content | +|------------|-----------------| +| Title slide | 1 heading + 1 subtitle | +| Content slide | 1 heading + 4-6 bullets (max 2 lines each) | +| Feature grid | 1 heading + 6 cards (2x3 or 3x2) | +| Code slide | 1 heading + 8-10 lines of code | +| Quote slide | 1 quote (max 3 lines) + attribution | + +**Too much content? → Split into multiple slides. Never scroll.** + +### Required Base CSS (Include in ALL Presentations) + +```css +/* =========================================== + VIEWPORT FITTING: MANDATORY + Copy this entire block into every presentation + =========================================== */ + +/* 1. Lock document to viewport */ +html, body { + height: 100%; + overflow-x: hidden; +} + +html { + scroll-snap-type: y mandatory; + scroll-behavior: smooth; +} + +/* 2. Each slide = exact viewport height */ +.slide { + width: 100vw; + height: 100vh; + height: 100dvh; /* Dynamic viewport for mobile */ + overflow: hidden; /* CRITICAL: No overflow ever */ + scroll-snap-align: start; + display: flex; + flex-direction: column; + position: relative; +} + +/* 3. Content wrapper */ +.slide-content { + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + max-height: 100%; + overflow: hidden; + padding: var(--slide-padding); +} + +/* 4. ALL sizes use clamp() - scales with viewport */ +:root { + /* Typography */ + --title-size: clamp(1.5rem, 5vw, 4rem); + --h2-size: clamp(1.25rem, 3.5vw, 2.5rem); + --body-size: clamp(0.75rem, 1.5vw, 1.125rem); + --small-size: clamp(0.65rem, 1vw, 0.875rem); + + /* Spacing */ + --slide-padding: clamp(1rem, 4vw, 4rem); + --content-gap: clamp(0.5rem, 2vw, 2rem); +} + +/* 5. Cards/containers use viewport-relative max sizes */ +.card, .container { + max-width: min(90vw, 1000px); + max-height: min(80vh, 700px); +} + +/* 6. Images constrained */ +img { + max-width: 100%; + max-height: min(50vh, 400px); + object-fit: contain; +} + +/* 7. Grids adapt to space */ +.grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); + gap: clamp(0.5rem, 1.5vw, 1rem); +} + +/* =========================================== + RESPONSIVE BREAKPOINTS - Height-based + =========================================== */ + +/* Short screens (< 700px height) */ +@media (max-height: 700px) { + :root { + --slide-padding: clamp(0.75rem, 3vw, 2rem); + --content-gap: clamp(0.4rem, 1.5vw, 1rem); + --title-size: clamp(1.25rem, 4.5vw, 2.5rem); + } +} + +/* Very short (< 600px height) */ +@media (max-height: 600px) { + :root { + --slide-padding: clamp(0.5rem, 2.5vw, 1.5rem); + --title-size: clamp(1.1rem, 4vw, 2rem); + --body-size: clamp(0.7rem, 1.2vw, 0.95rem); + } + + .nav-dots, .keyboard-hint, .decorative { + display: none; + } +} + +/* Extremely short - landscape phones (< 500px) */ +@media (max-height: 500px) { + :root { + --slide-padding: clamp(0.4rem, 2vw, 1rem); + --title-size: clamp(1rem, 3.5vw, 1.5rem); + --body-size: clamp(0.65rem, 1vw, 0.85rem); + } +} + +/* Narrow screens */ +@media (max-width: 600px) { + .grid { + grid-template-columns: 1fr; + } +} + +/* Reduced motion */ +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 0.01ms !important; + transition-duration: 0.2s !important; + } +} +``` + +### Viewport Fitting Checklist + +Before finalizing any presentation, verify: + +- [ ] Every `.slide` has `height: 100vh; height: 100dvh; overflow: hidden;` +- [ ] All font sizes use `clamp(min, preferred, max)` +- [ ] All spacing uses `clamp()` or viewport units +- [ ] Breakpoints exist for heights: 700px, 600px, 500px +- [ ] Content respects density limits (max 6 bullets, max 6 cards) +- [ ] No fixed pixel heights on content elements +- [ ] Images have `max-height` constraints + +--- + +## Dark Themes + +### 1. Bold Signal + +**Vibe:** Confident, bold, modern, high-impact + +**Layout:** Colored card on dark gradient. Number top-left, navigation top-right, title bottom-left. + +**Typography:** +- Display: `Archivo Black` (900) +- Body: `Space Grotesk` (400/500) + +**Colors:** +```css +:root { + --bg-primary: #1a1a1a; + --bg-gradient: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 50%, #1a1a1a 100%); + --card-bg: #FF5722; + --text-primary: #ffffff; + --text-on-card: #1a1a1a; +} +``` + +**Signature Elements:** +- Bold colored card as focal point (orange, coral, or vibrant accent) +- Large section numbers (01, 02, etc.) +- Navigation breadcrumbs with active/inactive opacity states +- Grid-based layout for precise alignment + +--- + +### 2. Electric Studio + +**Vibe:** Bold, clean, professional, high contrast + +**Layout:** Split panel—white top, blue bottom. Brand marks in corners. + +**Typography:** +- Display: `Manrope` (800) +- Body: `Manrope` (400/500) + +**Colors:** +```css +:root { + --bg-dark: #0a0a0a; + --bg-white: #ffffff; + --accent-blue: #4361ee; + --text-dark: #0a0a0a; + --text-light: #ffffff; +} +``` + +**Signature Elements:** +- Two-panel vertical split +- Accent bar on panel edge +- Quote typography as hero element +- Minimal, confident spacing + +--- + +### 3. Creative Voltage + +**Vibe:** Bold, creative, energetic, retro-modern + +**Layout:** Split panels—electric blue left, dark right. Script accents. + +**Typography:** +- Display: `Syne` (700/800) +- Mono: `Space Mono` (400/700) + +**Colors:** +```css +:root { + --bg-primary: #0066ff; + --bg-dark: #1a1a2e; + --accent-neon: #d4ff00; + --text-light: #ffffff; +} +``` + +**Signature Elements:** +- Electric blue + neon yellow contrast +- Halftone texture patterns +- Neon badges/callouts +- Script typography for creative flair + +--- + +### 4. Dark Botanical + +**Vibe:** Elegant, sophisticated, artistic, premium + +**Layout:** Centered content on dark. Abstract soft shapes in corner. + +**Typography:** +- Display: `Cormorant` (400/600) — elegant serif +- Body: `IBM Plex Sans` (300/400) + +**Colors:** +```css +:root { + --bg-primary: #0f0f0f; + --text-primary: #e8e4df; + --text-secondary: #9a9590; + --accent-warm: #d4a574; + --accent-pink: #e8b4b8; + --accent-gold: #c9b896; +} +``` + +**Signature Elements:** +- Abstract soft gradient circles (blurred, overlapping) +- Warm color accents (pink, gold, terracotta) +- Thin vertical accent lines +- Italic signature typography +- **No illustrations—only abstract CSS shapes** + +--- + +## Light Themes + +### 5. Notebook Tabs + +**Vibe:** Editorial, organized, elegant, tactile + +**Layout:** Cream paper card on dark background. Colorful tabs on right edge. + +**Typography:** +- Display: `Bodoni Moda` (400/700) — classic editorial +- Body: `DM Sans` (400/500) + +**Colors:** +```css +:root { + --bg-outer: #2d2d2d; + --bg-page: #f8f6f1; + --text-primary: #1a1a1a; + --tab-1: #98d4bb; /* Mint */ + --tab-2: #c7b8ea; /* Lavender */ + --tab-3: #f4b8c5; /* Pink */ + --tab-4: #a8d8ea; /* Sky */ + --tab-5: #ffe6a7; /* Cream */ +} +``` + +**Signature Elements:** +- Paper container with subtle shadow +- Colorful section tabs on right edge (vertical text) +- Binder hole decorations on left +- Tab text must scale with viewport: `font-size: clamp(0.5rem, 1vh, 0.7rem)` + +--- + +### 6. Pastel Geometry + +**Vibe:** Friendly, organized, modern, approachable + +**Layout:** White card on pastel background. Vertical pills on right edge. + +**Typography:** +- Display: `Plus Jakarta Sans` (700/800) +- Body: `Plus Jakarta Sans` (400/500) + +**Colors:** +```css +:root { + --bg-primary: #c8d9e6; + --card-bg: #faf9f7; + --pill-pink: #f0b4d4; + --pill-mint: #a8d4c4; + --pill-sage: #5a7c6a; + --pill-lavender: #9b8dc4; + --pill-violet: #7c6aad; +} +``` + +**Signature Elements:** +- Rounded card with soft shadow +- **Vertical pills on right edge** with varying heights (like tabs) +- Consistent pill width, heights: short → medium → tall → medium → short +- Download/action icon in corner + +--- + +### 7. Split Pastel + +**Vibe:** Playful, modern, friendly, creative + +**Layout:** Two-color vertical split (peach left, lavender right). + +**Typography:** +- Display: `Outfit` (700/800) +- Body: `Outfit` (400/500) + +**Colors:** +```css +:root { + --bg-peach: #f5e6dc; + --bg-lavender: #e4dff0; + --text-dark: #1a1a1a; + --badge-mint: #c8f0d8; + --badge-yellow: #f0f0c8; + --badge-pink: #f0d4e0; +} +``` + +**Signature Elements:** +- Split background colors +- Playful badge pills with icons +- Grid pattern overlay on right panel +- Rounded CTA buttons + +--- + +### 8. Vintage Editorial + +**Vibe:** Witty, confident, editorial, personality-driven + +**Layout:** Centered content on cream. Abstract geometric shapes as accent. + +**Typography:** +- Display: `Fraunces` (700/900) — distinctive serif +- Body: `Work Sans` (400/500) + +**Colors:** +```css +:root { + --bg-cream: #f5f3ee; + --text-primary: #1a1a1a; + --text-secondary: #555; + --accent-warm: #e8d4c0; +} +``` + +**Signature Elements:** +- Abstract geometric shapes (circle outline + line + dot) +- Bold bordered CTA boxes +- Witty, conversational copy style +- **No illustrations—only geometric CSS shapes** + +--- + +## Specialty Themes + +### 9. Neon Cyber + +**Vibe:** Futuristic, techy, confident + +**Typography:** `Clash Display` + `Satoshi` (Fontshare) + +**Colors:** Deep navy (#0a0f1c), cyan accent (#00ffcc), magenta (#ff00aa) + +**Signature:** Particle backgrounds, neon glow, grid patterns + +--- + +### 10. Terminal Green + +**Vibe:** Developer-focused, hacker aesthetic + +**Typography:** `JetBrains Mono` (monospace only) + +**Colors:** GitHub dark (#0d1117), terminal green (#39d353) + +**Signature:** Scan lines, blinking cursor, code syntax styling + +--- + +### 11. Swiss Modern + +**Vibe:** Clean, precise, Bauhaus-inspired + +**Typography:** `Archivo` (800) + `Nunito` (400) + +**Colors:** Pure white, pure black, red accent (#ff3300) + +**Signature:** Visible grid, asymmetric layouts, geometric shapes + +--- + +### 12. Paper & Ink + +**Vibe:** Editorial, literary, thoughtful + +**Typography:** `Cormorant Garamond` + `Source Serif 4` + +**Colors:** Warm cream (#faf9f7), charcoal (#1a1a1a), crimson accent (#c41e3a) + +**Signature:** Drop caps, pull quotes, elegant horizontal rules + +--- + +## Font Pairing Quick Reference + +| Preset | Display Font | Body Font | Source | +|--------|--------------|-----------|--------| +| Bold Signal | Archivo Black | Space Grotesk | Google | +| Electric Studio | Manrope | Manrope | Google | +| Creative Voltage | Syne | Space Mono | Google | +| Dark Botanical | Cormorant | IBM Plex Sans | Google | +| Notebook Tabs | Bodoni Moda | DM Sans | Google | +| Pastel Geometry | Plus Jakarta Sans | Plus Jakarta Sans | Google | +| Split Pastel | Outfit | Outfit | Google | +| Vintage Editorial | Fraunces | Work Sans | Google | +| Neon Cyber | Clash Display | Satoshi | Fontshare | +| Terminal Green | JetBrains Mono | JetBrains Mono | JetBrains | + +--- + +## DO NOT USE (Generic AI Patterns) + +**Fonts:** Inter, Roboto, Arial, system fonts as display + +**Colors:** `#6366f1` (generic indigo), purple gradients on white + +**Layouts:** Everything centered, generic hero sections, identical card grids + +**Decorations:** Realistic illustrations, gratuitous glassmorphism, drop shadows without purpose + +--- + +## Troubleshooting Viewport Issues + +### Content Overflows the Slide + +**Symptoms:** Scrollbar appears, content cut off, elements outside viewport + +**Solutions:** +1. Check slide has `overflow: hidden` (not `overflow: auto` or `visible`) +2. Reduce content — split into multiple slides +3. Ensure all fonts use `clamp()` not fixed `px` or `rem` +4. Add/fix height breakpoints for smaller screens +5. Check images have `max-height: min(50vh, 400px)` + +### Text Too Small on Mobile / Too Large on Desktop + +**Symptoms:** Unreadable text on phones, oversized text on big screens + +**Solutions:** +```css +/* Use clamp with viewport-relative middle value */ +font-size: clamp(1rem, 3vw, 2.5rem); +/* ↑ ↑ ↑ + minimum scales maximum */ +``` + +### Content Doesn't Fill Short Screens + +**Symptoms:** Excessive whitespace on landscape phones or short browser windows + +**Solutions:** +1. Add `@media (max-height: 600px)` and `(max-height: 500px)` breakpoints +2. Reduce padding at smaller heights +3. Hide decorative elements (`display: none`) +4. Consider hiding nav dots and hints on short screens + +### Testing Recommendations + +Test at these viewport sizes: +- **Desktop:** 1920×1080, 1440×900, 1280×720 +- **Tablet:** 1024×768 (landscape), 768×1024 (portrait) +- **Mobile:** 375×667 (iPhone SE), 414×896 (iPhone 11) +- **Landscape phone:** 667×375, 896×414 + +Use browser DevTools responsive mode to quickly test multiple sizes. diff --git a/skills/frontend-slides/references/TROUBLESHOOTING.md b/skills/frontend-slides/references/TROUBLESHOOTING.md new file mode 100644 index 0000000..df6e6e5 --- /dev/null +++ b/skills/frontend-slides/references/TROUBLESHOOTING.md @@ -0,0 +1,28 @@ +## Troubleshooting + +### Common Issues + +**Fonts not loading:** +- Check Fontshare/Google Fonts URL +- Ensure font names match in CSS + +**Animations not triggering:** +- Verify Intersection Observer is running +- Check that `.visible` class is being added + +**Scroll snap not working:** +- Ensure `scroll-snap-type` on html/body +- Each slide needs `scroll-snap-align: start` + +**Mobile issues:** +- Disable heavy effects at 768px breakpoint +- Test touch events +- Reduce particle count or disable canvas + +**Performance issues:** +- Use `will-change` sparingly +- Prefer `transform` and `opacity` animations +- Throttle scroll/mousemove handlers + +--- + diff --git a/skills/frontend-slides/references/VIEWPORT_FITTING.md b/skills/frontend-slides/references/VIEWPORT_FITTING.md new file mode 100644 index 0000000..0548105 --- /dev/null +++ b/skills/frontend-slides/references/VIEWPORT_FITTING.md @@ -0,0 +1,228 @@ +## CRITICAL: Viewport Fitting Requirements + +**This section is mandatory for ALL presentations. Every slide must be fully visible without scrolling on any screen size.** + +### The Golden Rule + +``` +Each slide = exactly one viewport height (100vh/100dvh) +Content overflows? → Split into multiple slides or reduce content +Never scroll within a slide. +``` + +### Content Density Limits + +To guarantee viewport fitting, enforce these limits per slide: + +| Slide Type | Maximum Content | +|------------|-----------------| +| Title slide | 1 heading + 1 subtitle + optional tagline | +| Content slide | 1 heading + 4-6 bullet points OR 1 heading + 2 paragraphs | +| Feature grid | 1 heading + 6 cards maximum (2x3 or 3x2 grid) | +| Code slide | 1 heading + 8-10 lines of code maximum | +| Quote slide | 1 quote (max 3 lines) + attribution | +| Image slide | 1 heading + 1 image (max 60vh height) | + +**If content exceeds these limits → Split into multiple slides** + +### Required CSS Architecture + +Every presentation MUST include this base CSS for viewport fitting: + +```css +/* =========================================== + VIEWPORT FITTING: MANDATORY BASE STYLES + These styles MUST be included in every presentation. + They ensure slides fit exactly in the viewport. + =========================================== */ + +/* 1. Lock html/body to viewport */ +html, body { + height: 100%; + overflow-x: hidden; +} + +html { + scroll-snap-type: y mandatory; + scroll-behavior: smooth; +} + +/* 2. Each slide = exact viewport height */ +.slide { + width: 100vw; + height: 100vh; + height: 100dvh; /* Dynamic viewport height for mobile browsers */ + overflow: hidden; /* CRITICAL: Prevent ANY overflow */ + scroll-snap-align: start; + display: flex; + flex-direction: column; + position: relative; +} + +/* 3. Content container with flex for centering */ +.slide-content { + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + max-height: 100%; + overflow: hidden; /* Double-protection against overflow */ + padding: var(--slide-padding); +} + +/* 4. ALL typography uses clamp() for responsive scaling */ +:root { + /* Titles scale from mobile to desktop */ + --title-size: clamp(1.5rem, 5vw, 4rem); + --h2-size: clamp(1.25rem, 3.5vw, 2.5rem); + --h3-size: clamp(1rem, 2.5vw, 1.75rem); + + /* Body text */ + --body-size: clamp(0.75rem, 1.5vw, 1.125rem); + --small-size: clamp(0.65rem, 1vw, 0.875rem); + + /* Spacing scales with viewport */ + --slide-padding: clamp(1rem, 4vw, 4rem); + --content-gap: clamp(0.5rem, 2vw, 2rem); + --element-gap: clamp(0.25rem, 1vw, 1rem); +} + +/* 5. Cards/containers use viewport-relative max sizes */ +.card, .container, .content-box { + max-width: min(90vw, 1000px); + max-height: min(80vh, 700px); +} + +/* 6. Lists auto-scale with viewport */ +.feature-list, .bullet-list { + gap: clamp(0.4rem, 1vh, 1rem); +} + +.feature-list li, .bullet-list li { + font-size: var(--body-size); + line-height: 1.4; +} + +/* 7. Grids adapt to available space */ +.grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr)); + gap: clamp(0.5rem, 1.5vw, 1rem); +} + +/* 8. Images constrained to viewport */ +img, .image-container { + max-width: 100%; + max-height: min(50vh, 400px); + object-fit: contain; +} + +/* =========================================== + RESPONSIVE BREAKPOINTS + Aggressive scaling for smaller viewports + =========================================== */ + +/* Short viewports (< 700px height) */ +@media (max-height: 700px) { + :root { + --slide-padding: clamp(0.75rem, 3vw, 2rem); + --content-gap: clamp(0.4rem, 1.5vw, 1rem); + --title-size: clamp(1.25rem, 4.5vw, 2.5rem); + --h2-size: clamp(1rem, 3vw, 1.75rem); + } +} + +/* Very short viewports (< 600px height) */ +@media (max-height: 600px) { + :root { + --slide-padding: clamp(0.5rem, 2.5vw, 1.5rem); + --content-gap: clamp(0.3rem, 1vw, 0.75rem); + --title-size: clamp(1.1rem, 4vw, 2rem); + --body-size: clamp(0.7rem, 1.2vw, 0.95rem); + } + + /* Hide non-essential elements */ + .nav-dots, .keyboard-hint, .decorative { + display: none; + } +} + +/* Extremely short (landscape phones, < 500px height) */ +@media (max-height: 500px) { + :root { + --slide-padding: clamp(0.4rem, 2vw, 1rem); + --title-size: clamp(1rem, 3.5vw, 1.5rem); + --h2-size: clamp(0.9rem, 2.5vw, 1.25rem); + --body-size: clamp(0.65rem, 1vw, 0.85rem); + } +} + +/* Narrow viewports (< 600px width) */ +@media (max-width: 600px) { + :root { + --title-size: clamp(1.25rem, 7vw, 2.5rem); + } + + /* Stack grids vertically */ + .grid { + grid-template-columns: 1fr; + } +} + +/* =========================================== + REDUCED MOTION + Respect user preferences + =========================================== */ +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 0.01ms !important; + transition-duration: 0.2s !important; + } + + html { + scroll-behavior: auto; + } +} +``` + +### Overflow Prevention Checklist + +Before generating any presentation, mentally verify: + +1. ✅ Every `.slide` has `height: 100vh; height: 100dvh; overflow: hidden;` +2. ✅ All font sizes use `clamp(min, preferred, max)` +3. ✅ All spacing uses `clamp()` or viewport units +4. ✅ Content containers have `max-height` constraints +5. ✅ Images have `max-height: min(50vh, 400px)` or similar +6. ✅ Grids use `auto-fit` with `minmax()` for responsive columns +7. ✅ Breakpoints exist for heights: 700px, 600px, 500px +8. ✅ No fixed pixel heights on content elements +9. ✅ Content per slide respects density limits + +### When Content Doesn't Fit + +If you find yourself with too much content: + +**DO:** +- Split into multiple slides +- Reduce bullet points (max 5-6 per slide) +- Shorten text (aim for 1-2 lines per bullet) +- Use smaller code snippets +- Create a "continued" slide + +**DON'T:** +- Reduce font size below readable limits +- Remove padding/spacing entirely +- Allow any scrolling +- Cram content to fit + +### Testing Viewport Fit + +After generating, recommend the user test at these sizes: +- Desktop: 1920×1080, 1440×900, 1280×720 +- Tablet: 1024×768, 768×1024 (portrait) +- Mobile: 375×667, 414×896 +- Landscape phone: 667×375, 896×414 + +--- + diff --git a/skills/frontend-slides/references/WORKFLOW.md b/skills/frontend-slides/references/WORKFLOW.md new file mode 100644 index 0000000..3a0e27f --- /dev/null +++ b/skills/frontend-slides/references/WORKFLOW.md @@ -0,0 +1,552 @@ +## Phase 0: Detect Mode + +First, determine what the user wants: + +**Mode A: New Presentation** +- User wants to create slides from scratch +- Proceed to Phase 1 (Content Discovery) + +**Mode B: PPT Conversion** +- User has a PowerPoint file (.ppt, .pptx) to convert +- Proceed to Phase 4 (PPT Extraction) + +**Mode C: Existing Presentation Enhancement** +- User has an HTML presentation and wants to improve it +- Read the existing file, understand the structure, then enhance + +--- + +## Phase 1: Content Discovery (New Presentations) + +Before designing, understand the content. Ask the user: + +### Step 1.1: Presentation Context + +**Question 1: Purpose** +- Header: "Purpose" +- Question: "What is this presentation for?" +- Options: + - "Pitch deck" — Selling an idea, product, or company to investors/clients + - "Teaching/Tutorial" — Explaining concepts, how-to guides, educational content + - "Conference talk" — Speaking at an event, tech talk, keynote + - "Internal presentation" — Team updates, strategy meetings, company updates + +**Question 2: Slide Count** +- Header: "Length" +- Question: "Approximately how many slides?" +- Options: + - "Short (5-10)" — Quick pitch, lightning talk + - "Medium (10-20)" — Standard presentation + - "Long (20+)" — Deep dive, comprehensive talk + +**Question 3: Content** +- Header: "Content" +- Question: "Do you have the content ready, or do you need help structuring it?" +- Options: + - "I have all content ready" — Just need to design the presentation + - "I have rough notes" — Need help organizing into slides + - "I have a topic only" — Need help creating the full outline + +If user has content, ask them to share it (text, bullet points, images, etc.). + +--- + +## Phase 2: Style Discovery (Visual Exploration) + +**CRITICAL: This is the "show, don't tell" phase.** + +Most people can't articulate design preferences in words. Instead of asking "do you want minimalist or bold?", we generate mini-previews and let them react. + +### How Users Choose Presets + +Users can select a style in **two ways**: + +**Option A: Guided Discovery (Default)** +- User answers mood questions +- Skill generates 3 preview files based on their answers +- User views previews in browser and picks their favorite +- This is best for users who don't have a specific style in mind + +**Option B: Direct Selection** +- If user already knows what they want, they can request a preset by name +- Example: "Use the Bold Signal style" or "I want something like Dark Botanical" +- Skip to Phase 3 immediately + +**Available Presets:** +| Preset | Vibe | Best For | +|--------|------|----------| +| Bold Signal | Confident, high-impact | Pitch decks, keynotes | +| Electric Studio | Clean, professional | Agency presentations | +| Creative Voltage | Energetic, retro-modern | Creative pitches | +| Dark Botanical | Elegant, sophisticated | Premium brands | +| Notebook Tabs | Editorial, organized | Reports, reviews | +| Pastel Geometry | Friendly, approachable | Product overviews | +| Split Pastel | Playful, modern | Creative agencies | +| Vintage Editorial | Witty, personality-driven | Personal brands | +| Neon Cyber | Futuristic, techy | Tech startups | +| Terminal Green | Developer-focused | Dev tools, APIs | +| Swiss Modern | Minimal, precise | Corporate, data | +| Paper & Ink | Literary, thoughtful | Storytelling | + +### Step 2.0: Style Path Selection + +First, ask how the user wants to choose their style: + +**Question: Style Selection Method** +- Header: "Style" +- Question: "How would you like to choose your presentation style?" +- Options: + - "Show me options" — Generate 3 previews based on my needs (recommended for most users) + - "I know what I want" — Let me pick from the preset list directly + +**If "Show me options"** → Continue to Step 2.1 (Mood Selection) + +**If "I know what I want"** → Show preset picker: + +**Question: Pick a Preset** +- Header: "Preset" +- Question: "Which style would you like to use?" +- Options: + - "Bold Signal" — Vibrant card on dark, confident and high-impact + - "Dark Botanical" — Elegant dark with soft abstract shapes + - "Notebook Tabs" — Editorial paper look with colorful section tabs + - "Pastel Geometry" — Friendly pastels with decorative pills + +(If user picks one, skip to Phase 3. If they want to see more options, show additional presets or proceed to guided discovery.) + +### Step 2.1: Mood Selection (Guided Discovery) + +**Question 1: Feeling** +- Header: "Vibe" +- Question: "What feeling should the audience have when viewing your slides?" +- Options: + - "Impressed/Confident" — Professional, trustworthy, this team knows what they're doing + - "Excited/Energized" — Innovative, bold, this is the future + - "Calm/Focused" — Clear, thoughtful, easy to follow + - "Inspired/Moved" — Emotional, storytelling, memorable +- multiSelect: true (can choose up to 2) + +### Step 2.2: Generate Style Previews + +Based on their mood selection, generate **3 distinct style previews** as mini HTML files in a temporary directory. Each preview should be a single title slide showing: + +- Typography (font choices, heading/body hierarchy) +- Color palette (background, accent, text colors) +- Animation style (how elements enter) +- Overall aesthetic feel + +**Preview Styles to Consider (pick 3 based on mood):** + +| Mood | Style Options | +|------|---------------| +| Impressed/Confident | "Bold Signal", "Electric Studio", "Dark Botanical" | +| Excited/Energized | "Creative Voltage", "Neon Cyber", "Split Pastel" | +| Calm/Focused | "Notebook Tabs", "Paper & Ink", "Swiss Modern" | +| Inspired/Moved | "Dark Botanical", "Vintage Editorial", "Pastel Geometry" | + +**IMPORTANT: Never use these generic patterns:** +- Purple gradients on white backgrounds +- Inter, Roboto, or system fonts +- Standard blue primary colors +- Predictable hero layouts + +**Instead, use distinctive choices:** +- Unique font pairings (Clash Display, Satoshi, Cormorant Garamond, DM Sans, etc.) +- Cohesive color themes with personality +- Atmospheric backgrounds (gradients, subtle patterns, depth) +- Signature animation moments + +### Step 2.3: Present Previews + +Create the previews in: `.claude-design/slide-previews/` + +``` +.claude-design/slide-previews/ +├── style-a.html # First style option +├── style-b.html # Second style option +├── style-c.html # Third style option +└── assets/ # Any shared assets +``` + +Each preview file should be: +- Self-contained (inline CSS/JS) +- A single "title slide" showing the aesthetic +- Animated to demonstrate motion style +- ~50-100 lines, not a full presentation + +Present to user: +``` +I've created 3 style previews for you to compare: + +**Style A: [Name]** — [1 sentence description] +**Style B: [Name]** — [1 sentence description] +**Style C: [Name]** — [1 sentence description] + +Open each file to see them in action: +- .claude-design/slide-previews/style-a.html +- .claude-design/slide-previews/style-b.html +- .claude-design/slide-previews/style-c.html + +Take a look and tell me: +1. Which style resonates most? +2. What do you like about it? +3. Anything you'd change? +``` + +Then ask the user: + +**Question: Pick Your Style** +- Header: "Style" +- Question: "Which style preview do you prefer?" +- Options: + - "Style A: [Name]" — [Brief description] + - "Style B: [Name]" — [Brief description] + - "Style C: [Name]" — [Brief description] + - "Mix elements" — Combine aspects from different styles + +If "Mix elements", ask for specifics. + +--- + +## Phase 3: Generate Presentation + +Now generate the full presentation based on: +- Content from Phase 1 +- Style from Phase 2 + +### File Structure + +For single presentations: +``` +presentation.html # Self-contained presentation +assets/ # Images, if any +``` + +For projects with multiple presentations: +``` +[presentation-name].html +[presentation-name]-assets/ +``` + +### HTML Architecture + +Follow this structure for all presentations: + +```html + + + + + + Presentation Title + + + + + + + + +
+ + + + + +
+

Presentation Title

+

Subtitle or author

+
+ +
+

Slide Title

+

Content...

+
+ + + + + + +``` + +### Required JavaScript Features + +Every presentation should include: + +1. **SlidePresentation Class** — Main controller + - Keyboard navigation (arrows, space) + - Touch/swipe support + - Mouse wheel navigation + - Progress bar updates + - Navigation dots + +2. **Intersection Observer** — For scroll-triggered animations + - Add `.visible` class when slides enter viewport + - Trigger CSS animations efficiently + +3. **Optional Enhancements** (based on style): + - Custom cursor with trail + - Particle system background (canvas) + - Parallax effects + - 3D tilt on hover + - Magnetic buttons + - Counter animations + +### Code Quality Requirements + +**Comments:** +Every section should have clear comments explaining: +- What it does +- Why it exists +- How to modify it + +```javascript +/* =========================================== + CUSTOM CURSOR + Creates a stylized cursor that follows mouse with a trail effect. + - Uses lerp (linear interpolation) for smooth movement + - Grows larger when hovering over interactive elements + =========================================== */ +class CustomCursor { + constructor() { + // ... + } +} +``` + +**Accessibility:** +- Semantic HTML (`
`, `