[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6JC78WBJ95WAYFG78QZJB1P":3,"skill-same:01M6JC78WBJ95WAYFG78QZJB1P":76},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":25,"publishedAt":46,"linkOnly":47,"markdownContent":48,"markdownBody":49,"frontMatter":50,"refName":54,"commitSha":55,"skillDirectory":56,"forksCount":57,"repositoryHtmlUrl":58,"repositoryHomepageUrl":59,"ownerHtmlUrl":60,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":61,"install":62,"resources":75},"01M6JC78WBJ95WAYFG78QZJB1P","landing-page-workflows",null,"Build, duplicate, and deploy landing pages for Ibrahim Ramzy's coaching funnels. Covers copy patterns, asset linking, Vercel deployment, and client-specific design preferences.","S3YED\u002Fappie-kit","S3YED","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F62743867?v=4","01M6JBKBRRVP6KMS0VWZ27T3R6","01M6JBKBX0KG30284PW1DBYJT1",14,"MIT","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fcontent\u002Flanding-page-workflows\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000015","视觉设计","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],"workflows","landing page workflows","landing page","landing","page","vercel deployment","preferences","copywriting","deployment","build","coaching","deploy","client","copy","for","linking","ibrahim","landing-pages","the-creed","design","2026-11-10 10:12:30",false,"---\nname: landing-page-workflows\ndescription: Build, duplicate, and deploy landing pages for Ibrahim Ramzy's coaching funnels. Covers copy patterns, asset linking, Vercel deployment, and client-specific design preferences.\nversion: 1.2.0\ntags: [landing-pages, vercel, copywriting, ibrahim, the-creed]\n---\n\n# Landing Page Workflows (Ibrahim Ramzy)\n\nBuild landing pages for The Creed \u002F Health in Motion \u002F giveaways. All pages use the same design system (navy + silver + royal blue, or gold for giveaways).\n\n## Source of Truth\n\nThe master high-ticket landing page lives at:\n- **Local:** `\u002Froot\u002Fibrahim\u002Findex.html`\n- **Live:** `https:\u002F\u002Fthecreed-one.vercel.app`\n\nThe giveaway landing page lives at:\n- **Local:** `\u002Froot\u002Fibrahim-giveaway\u002Findex.html` (complete, with VSL section)\n- **Live:** `https:\u002F\u002Fibrahim-giveaway.vercel.app` (primary, includes VSL, hero, steps, prizes, testimonials, typeform)\n- **Legacy (inactive):** `https:\u002F\u002Fcreed-coaching-giveaway.vercel.app` (older copy without VSL — do not edit)\n- **Motion upgrade (Next.js + motion\u002Freact):** `https:\u002F\u002Fibrahim-giveaway-v2.vercel.app` — deployed from `\u002Froot\u002Fibrahim-giveaway-v2`. Source: `src\u002Fapp\u002Fcomponents\u002FSections.tsx`, `ConversionOptimizers.tsx`, `page.tsx`. Has all animations, conversion optimizers, Lucide icons, and premium design. NOT yet domain-swapped — lives on its own Vercel project.\n\nAlways duplicate from one of these sources. Never start from scratch.\n\n## Duplication Pattern\n\n```bash\ncp -r \u002Froot\u002Fibrahim \u002Froot\u002Fibrahim-{project-name}\nrm -rf \u002Froot\u002Fibrahim-{project-name}\u002F.vercel   # critical — forces new Vercel project\n```\n\nThen edit `index.html`:\n1. Change `\u003Ctitle>`, hero copy, CTAs\n2. Update Typeform widget ID in the embed\n3. Test locally with a browser\n\n## Asset Linking\n\nVideos and images are NOT copied to new projects. Reference the master deployment:\n\n```html\n\u003C!-- Videos -->\n\u003Csource src=\"https:\u002F\u002Fthecreed-one.vercel.app\u002Fvideos\u002F{name}.mp4\">\n\n\u003C!-- Transformation images -->\n\u003Cimg src=\"https:\u002F\u002Fthecreed-one.vercel.app\u002Ftransformations\u002F{name}.jpg\">\n\n\u003C!-- Video posters -->\n\u003Cvideo poster=\"https:\u002F\u002Fthecreed-one.vercel.app\u002Fposters\u002F{name}.jpg\">\n```\n\nAvailable videos: pangina, davide, mohammed, matthew, mariel, ashley, asmond\n**Steven's video must be deployed locally** — see \"Steven's Video Fix\" below.\n\nAvailable transformations: davide, fatuma, konstantin, marielle, matthew, mohammed, omar, pangina, steven\n\n### Steven's Video Fix (CORS workaround)\n\nSteven's video (113MB) is on Google Drive. **Do NOT stream from Google Drive** — the direct download URL (`drive.usercontent.google.com`) does NOT have CORS headers for browser video tags. Curl works (no CORS enforcement) but browser `\u003Cvideo>` tags fail with NETWORK_NO_SOURCE. Proven in session 20260701_042630.\n\n**Correct approach — download, compress, deploy locally:**\n\n1. Download from Google Drive:\n   ```bash\n   curl -L -o \u002Ftmp\u002Fsteven_raw.mp4 \"https:\u002F\u002Fdrive.usercontent.google.com\u002Fdownload?id=FILE_ID&confirm=t&authuser=0\"\n   ```\n\n2. Compress with ffmpeg (113MB → ~17MB):\n   ```bash\n   ffmpeg -y -i \u002Ftmp\u002Fsteven_raw.mp4 -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 64k -movflags +faststart videos\u002Fsteven.mp4\n   ```\n   - CRF 28: good quality\u002Fsize balance\n   - `-movflags +faststart`: enables streaming (video plays before full download)\n\n3. Include `videos\u002Fsteven.mp4` in the same deployment directory as `index.html`. Vercel serves static files from any subdirectory automatically — no vercel.json needed.\n\n4. Reference with relative path:\n   ```html\n   \u003Csource src=\"videos\u002Fsteven.mp4\" type=\"video\u002Fmp4\">\n   ```\n\n5. Clean up temp files after deploy:\n   ```bash\n   rm \u002Ftmp\u002Fsteven_raw.mp4  # raw 113GB original\n   ```\n\n**Why this works:** Vercel serves the video from the same origin as the page — no CORS issue. The compressed 17MB file is well under Vercel's 100MB limit.\n\nSee `ops\u002Fvercel-deploy\u002Freferences\u002Fgoogle-drive-video-to-vercel.md` for a dedicated static-host variant (deploying video to a separate Vercel project).\n\n## Deployment\n\n```bash\ncd \u002Froot\u002Fibrahim-{project-name}\nnpx vercel --prod --token $VERCEL_TOKEN --yes\n```\n\nOutput: `https:\u002F\u002F{project-name}.vercel.app`\n\n### Custom domain (if needed)\n```bash\nvercel domain add {subdomain}.cali-creed.com {project-name} --token $VERCEL_TOKEN\n```\nNote: DNS is managed outside Vercel. User must add CNAME record at their provider.\n\n### Pitfalls & Recoveries\n\n**Vercel free tier deployment expiry:** Deployments on the free Hobby plan expire after 30 days. The Vercel project still exists (`.vercel\u002Fproject.json` stays valid) but all deployments are wiped. Fix: just redeploy — `npx vercel deploy --prod --token $TOKEN --yes` from the same directory reuses the project ID.\n\n**Project linking mismatch:** If `.vercel\u002Fproject.json` points to a different project than the one assigned the domain, the deploy succeeds (new deployment URL) but the domain alias fails. Fix: edit `.vercel\u002Fproject.json` to match the project that owns the domain, or reassign the domain via Vercel API:\n```python\n# Delete domain from old project, add to new project\nrequests.delete(f'https:\u002F\u002Fapi.vercel.com\u002Fv9\u002Fprojects\u002F{old_proj}\u002Fdomains\u002F{domain}?teamId={team}')\nrequests.post(f'https:\u002F\u002Fapi.vercel.com\u002Fv9\u002Fprojects\u002F{new_proj}\u002Fdomains?teamId={team}',\n              json={\"name\": domain})\n```\n\n**Next.js vs static project confusion:** If a Vercel project was originally created with a Next.js framework, subsequent static HTML-only deploys may silently serve the old Next.js build instead. The project's framework detection takes priority. Fix: create a new project for the static page and move the domain to it.\n\n**Local file recovery (Vercel deploy expiry):** When `https:\u002F\u002F{project}.vercel.app` returns 404 or a stale page, DON'T rebuild from scratch. First check:\n1. Does the local source directory still exist? Check `\u002Froot\u002F{project-name}\u002Findex.html`\n2. Check `.vercel\u002Fproject.json` for the project ID\n3. If the project exists on Vercel but has zero deployments, just redeploy from the local files\n4. If the `.vercel\u002Fproject.json` links to a different project than the one with the domain, update the file or reassign the domain\n\nCommon Vercel project IDs for Ibrahim:\n- `creed-coaching-giveaway` → `prj_jt07yuTFHQJQRsdmdHvNYArq0cZV` (domain: creed-coaching-giveaway.vercel.app)\n- `ibrahim-giveaway-lp` → `prj_8b9xHvKIPNFyvb0URaR4fyhN1wVj` **← this owns ibrahim-giveaway.vercel.app** (active, July 2026)\n- `ibrahim-giveaway` → separate project, no domain (gets `-creed-ramzy.vercel.app` subdomain)\n- `ibrahim-giveaway-v2` → Next.js + motion\u002Freact upgrade, deployed at `https:\u002F\u002Fibrahim-giveaway-v2.vercel.app`, local at `\u002Froot\u002Fibrahim-giveaway-v2`\n- `ibrahim-lowticket` → `prj_Yh0Wbqv9JaYlcWCLea6HA0KztjZm`\n- `ibrahim` → `prj_USPQzYyNdhjxDxZIyw0AAh6h6GkG`\n- `creed-funnel` → `prj_9lU3PPSggFIJpaETTf0Pt4zAXI96`\n\n**⚠️ Dual-project domain trap:** The domain `ibrahim-giveaway.vercel.app` is assigned to project `ibrahim-giveaway-lp`. There is a SEPARATE project named `ibrahim-giveaway` (no assigned domain). If you `vercel link` without specifying `--project ibrahim-giveaway-lp`, auto-detection may link to the wrong one. Always force-link before deploying to that domain:\n```bash\nnpx vercel link --yes --project ibrahim-giveaway-lp --token \"$(cat \u002Ftmp\u002Fvtoken)\"\n```\n\n**Dual-project deployment (same code, two domains):** When the same landing page needs to serve from two domains (e.g. `creed-coaching-giveaway.vercel.app` AND `ibrahim-giveaway.vercel.app`), you must deploy to each project separately:\n1. Link to project A → deploy → confirms domain A\n2. Relink to project B → deploy → confirms domain B\n3. Both deployments are independent — update both when code changes\n```bash\n# Deploy to domain A\ncd \u002Froot\u002Fibrahim-giveaway\nnpx vercel link --yes --project creed-coaching-giveaway --token \"$(cat \u002Ftmp\u002Fvtoken)\"\nnpx vercel deploy --prod --token \"$(cat \u002Ftmp\u002Fvtoken)\"\n\n# Deploy same code to domain B\nnpx vercel link --yes --project ibrahim-giveaway-lp --token \"$(cat \u002Ftmp\u002Fvtoken)\"\nnpx vercel deploy --prod --token \"$(cat \u002Ftmp\u002Fvtoken)\"\n```\n\n**Token masking bug:** Vercel tokens get masked to `***` in agent response text, corrupting inline commands. Store in `\u002Ftmp` via `printf`:\n```bash\nprintf 'vcp_yourtokenhere' > \u002Ftmp\u002Fvtoken.txt\n# Then use: --token \"$(cat \u002Ftmp\u002Fvtoken.txt)\"\n```\n\n**Google Drive video CORS trap:** `drive.usercontent.google.com` URLs work via curl (no CORS enforcement) but FAIL in browser `\u003Cvideo>` tags. The video element shows \"Unable to play media\" with NETWORK_NO_SOURCE. Always download and deploy locally — see \"Steven's Video Fix\" section above.\n\n## Mobile Optimization\n\nEvery page must be optimized for phone-first viewing - Ibrahim explicitly confirmed that most visitors come from phone.\n\n### Premium mobile breakpoints (768px and 400px)\n\n```\n@media (max-width: 768px) {\n  section { padding: 70px 16px; }\n  .hero { padding: 50px 16px 30px; }\n  .hero-headline { font-size: clamp(1.6rem, 7vw, 2.2rem); }\n  .hero-sub { font-size: 0.9rem; }\n  .hero-price { font-size: 1.1rem; }\n  .hero-cta { width: 100%; padding: 18px 24px; font-size: 1rem; }\n  .hero-badge { font-size: 0.6rem; padding: 6px 14px; }\n  .steps-grid, .prize-grid, .pillars-grid, .features-grid { grid-template-columns: 1fr; }\n  .testimonial-grid { grid-template-columns: 1fr; }\n  .trans-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }\n  .prize-card.gold { transform: none; }\n  .testimonial-card { padding: 20px 16px; }\n  .typeform-frame { border-radius: 12px; }\n  .step-card, .prize-card, .pillar-card { padding: 28px 20px; }\n  .prize-card .value { font-size: 1.3rem; }\n  .trans-name { font-size: 0.75rem; }\n  .trans-result { font-size: 0.7rem; }\n  .feat-item { padding: 20px 16px; }\n  .vsl-section { padding: 60px 16px; }\n  .vsl-video { border-radius: 12px; }\n  .section-sub { margin-bottom: 40px; }\n  .step-num { width: 42px; height: 42px; font-size: 1.1rem; }\n  .exit-modal { padding: 32px 24px; }\n}\n```\n\nKey improvements from the old values:\n- Hero top padding: 50px (was 80px) - content was sitting too low\n- Section padding: 70px (was 50px) - more breathing room\n- Card internal padding: 28px (was 24px)\n- Breakpoint: 768px (was 640px) - covers more phone sizes\n- Added exit-modal and hero-headline fine-tuning\n\n### Sticky CTA safe areas\nFor fixed-bottom bars, respect notched phones:\n```\npadding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));\n```\n\n### Verification on mobile\nAfter deploy, open the page on a real phone or DevTools mobile emulation (iPhone SE \u002F Galaxy S8+ viewports). Check:\n- CTA button spans full width and is tappable with one thumb\n- Headings fit in 2 lines (no overflow\u002Fellipsis)\n- Video player controls are usable at small sizes\n- Typeform embed fills the screen width\n- No horizontal scroll anywhere\n\n## Content Preservation Rule (critical for design\u002Fmotion upgrades)\n\nWhen the user says **\"don't change the content\"** or **\"keep the content the same\"** during a design or motion upgrade:\n- Every word, heading, subtitle, badge, button, and disclaimer must be copied exactly as-is.\n- Do NOT rewrite, condense, rephrase, or \"improve\" any copy.\n- Do NOT move sections around or reorder elements.\n- Do NOT add new sections of copy (FAQ, entry counter, etc. are ADDED as separate UI elements, not inserted into existing copy blocks).\n- The only acceptable changes: wrapping existing text in `\u003Cem>` tags for gold styling (if the original did that), or adding CSS classes\u002Fstyles that don't affect text content.\n- Test after deploy: grep the live page for key phrases from the original to verify they survived.\n\nThis rule is separate from (and overrides) any copywriting instincts. Motion\u002Fdesign upgrades are NOT copywriting passes.\n\n## Icon Standards\n\nUse **Lucide icons** for all UI elements. Never use emoji as icons — the user explicitly corrected this.\n\n### Icon mapping for The Creed pages\n\n| Purpose | Lucide Icon | Size |\n|---|---|---|\n| Hero badge alarm | `AlarmClock` | 14px |\n| 1st place | `Trophy` | 36px |\n| 2nd\u002F3rd place | `Medal` | 36px |\n| Everyone else | `Gift` | 36px |\n| Pillar: Mindset | `Brain` | 36px |\n| Pillar: Nutrition | `Apple` | 36px |\n| Pillar: Training | `Dumbbell` | 36px |\n| Feature: Mentorship | `Calendar` | 28px |\n| Feature: Onboarding | `Target` | 28px |\n| Feature: Training | `Dumbbell` | 28px |\n| Feature: Nutrition | `CookingPot` | 28px |\n| Feature: Touchpoints | `Phone` | 28px |\n| Feature: Mastery | `BookOpen` | 28px |\n| VSL play indicator | `Play` | 12px |\n| FAQ arrow | `ChevronDown` | 16px |\n| Exit close | `X` | 18px |\n| Live dot | `Circle` (fill green) | 6-8px |\n| CTA arrows | Inline SVG arrow (path) | 18px |\n\nStyle: All icons are `strokeWidth={2.5}` (default). Pillar icons use `color: var(--gold)`. Feature icons use `color: var(--gold)`. Render Lucide icons as JSX components, not string class names — they're SVGs that scale crisply at any resolution.\n\n```tsx\nimport { Trophy, Medal, Gift, Brain, Apple, Dumbbell } from \"lucide-react\";\n```\n\n## Premium Design Patterns\n\nWhen the user asks to \"make the page more premium\" or improve the look, apply these refinements.\n\n### Typography hierarchy\n- Hero headline: `clamp(2.2rem, 5.5vw, 3.8rem)` with `letter-spacing: -0.02em` and `font-weight: 900`\n- Section headings: `clamp(1.6rem, 3.6vw, 2.6rem)` with `letter-spacing: -0.01em`\n- Body text: `var(--silver-light)` (`#D4D4DC`) at `opacity: 0.7-0.85` — brighter than default silver for readability\n### Gold accent for em tags\n\n- All `em` tags inside headings get solid gold: `font-style: normal; color: var(--gold)`\n- Gradient text variant (`-webkit-background-clip: text`) can render inconsistently — reserved for hero headline only\n- Section headings default to solid gold as the verified safe choice\n\n### Gold gradient usage\nAlways define a gold gradient for premium accents:\n```css\n--gold-gradient: linear-gradient(135deg, #FFD700, #FFA500);\n--gold-light: #FFED4A;\n```\nApply to: CTA buttons, prize values, heading em tags, scroll progress bar, winner badge borders.\n\n### Glass-morphism cards\nEvery card should use a subtle glass background instead of bare transparent:\n```css\n--glass-bg: rgba(255, 255, 255, 0.03);\n--glass-border: rgba(255, 255, 255, 0.08);\n--glass-border-hover: rgba(255, 215, 0, 0.25);\n```\nCards get: `border-radius: 16px`, `background: var(--glass-bg)`, `border: 1px solid var(--glass-border)`.\n\n### Section transitions\nEvery section needs a `::before` pseudo-element with a 1px gold gradient line at the top:\n```css\nsection::before {\n  content: '';\n  position: absolute;\n  top: 0; left: 0; right: 0;\n  height: 1px;\n  background: linear-gradient(90deg, transparent, rgba(255, 215, 0, 0.1), transparent);\n}\n```\nSections should alternate background gradients (e.g., `linear-gradient(180deg, var(--near-black) 0%, #151515 100%)` then `linear-gradient(180deg, var(--dark-navy) 0%, #06203A 100%)`).\n\n### Hero enhancements\n- Background: dark gradient with radial gold glow overlay + grid pattern\n- Badge: **solid gold background** (`background: var(--gold); color: #000`) — the user rejected outlined\u002Ftransparent badges. Solid gold is the verified preference.\n- CTA: 12px border-radius, gold gradient, drop shadow (`box-shadow: 0 4px 24px rgba(255, 215, 0, 0.3)`)\n- Bottom fade: `::after` with `linear-gradient(to top, var(--near-black), transparent)` at 120px height\n- Entry counter + countdown timer must be placed **inside** the hero section (as direct children of the `\u003Csection className=\"hero\">`), not between hero and VSL.\n\n### Card hover effects\n- Lift: `y: -3` to `y: -4` on hover\n- Step cards: gold gradient top border that appears on hover (2px, `::before` with `opacity: 0 → 1`)\n- Gold prize card: `scale: 1.05` with `box-shadow: 0 8px 40px rgba(255, 215, 0, 0.08)`, hover to `scale: 1.08`\n- Feature cards: glass background + border (not bare text), hover lift `y: -3`\n\n### Testimonial refinements\n- Result badges: **solid gold background** (`background: var(--gold); color: #000`) — the user rejected outlined badges. Solid gold is the verified preference.\n- Author avatars: **solid gold background** (`background: var(--gold); color: #000`) — not gradient.\n- Video elements: 12px border-radius inside 16px card border-radius (concentric radii)\n\n### Pillar card refinements\n- Bullet list items: use gold checkmark (`'\\\\2713'` character via `::before` pseudo-element). This is the verified original pattern from Ibrahim's existing pages. Gold dot variant (`width: 6px; height: 6px; border-radius: 50%`) is experimental — use checkmark as the safe default.\n- Icons: gold color (`svg { color: var(--gold) }`)\n- Text: `opacity: 0.8` for readability\n\n### Easing\nUse `var(--ease-out-expo)` = `cubic-bezier(0.16, 1, 0.3, 1)` for all hover transitions and section animations. This is the same easing used by motion\u002Freact defaults.\n\n## Copy Preferences (Ibrahim)\n\n- **Headings:** 2 lines max. Use `\u003Cbr>` for manual line break. No text overflow.\n- **No em dashes (—).** Use regular hyphens (-) or commas.\n- **Button copy:** \"Enter the Giveaway\", \"Join Now\", \"Start Your Transformation\" — specific per funnel. Not \"Submit\" or \"Apply\".\n- **Hero spacing (giveaway pages):** Content should sit HIGH with minimal top gap. Use min-height: auto (NOT 100vh), align-items: flex-start, padding: 40px 20px 50px. User rejected centered-vertical-hero — wants badge\u002Fheadline\u002FCTA visible at top without scrolling.\n- **Under-How-to-Win copy (giveaway):** Always include below the 3-step grid: \"Follow the simple steps and look out for the message you will receive once done.\"\n- **Gold accent for giveaways:** Use var(--gold) for highlights, not royal blue.\n- **Style corrections the user has flagged:**\n  - Headings MUST be max 2 lines. If a heading wraps to 3 lines on mobile, condense it.\n  - Remove all em dashes from copy immediately when building new pages.\n  - Testimonial videos and before\u002Fafter images must be verified live after deploy — user will notice if they don't load.\n\n### Edit Precision (critical workflow rule)\n\nWhen the user says **\"replace X with Y\"**, do EXACTLY that:\n- Find X in its current location and replace it with Y there\n- Do NOT add Y somewhere else while leaving X in place\n- Do NOT duplicate Y in a second location unless explicitly told to\n- EXAMPLE: User said \"replace the text that says 'I'm looking for the next testimonial' with 'Follow the simple steps...'\" — the fix is to find THAT `.section-sub` paragraph and change its content. NOT add the new text below the steps grid and leave the old one in place.\n\nThis is the single most common correction the user makes. Read his edit instruction twice before executing.\n\n## Page Sections — Design Patterns\n\n### VSL (Video Sales Letter) Section\n\nPlace between hero and \"How to Win\" — Ibrahim's preferred position. The VSL sits in a dark section (same as hero bg or `var(--near-black)`) to avoid competing with the gold\u002FHero.\n\n**When to add:**\n- Giveaway pages (high-value prize \u002F $5K coaching)\n- High-ticket landing pages where proof of results is the sticking point\n- Any page where a short video (30-90s) can communicate value faster than text\n\n**CSS (add to the existing styles):**\n```css\n\u002F* ===== VSL SECTION ===== *\u002F\n.vsl-section {\n  padding: 60px 20px;\n  background: var(--near-black);\n  text-align: center;\n}\n.vsl-wrapper { max-width: 800px; margin: 0 auto; }\n.vsl-section .section-sub { margin-bottom: 32px; }\n.vsl-video {\n  width: 100%;\n  border-radius: 12px;\n  box-shadow: 0 8px 40px rgba(0,0,0,0.4);\n  display: block;\n}\n.vsl-caption {\n  font-size: 0.85rem;\n  color: var(--silver);\n  opacity: 0.6;\n  margin-top: 16px;\n}\n```\n\n**HTML (insert between hero closing `\u003C\u002Fsection>` and How to Win opening `\u003Csection>`):**\n```html\n\u003Csection class=\"vsl-section\">\n  \u003Cdiv class=\"vsl-wrapper\">\n    \u003Ch2 class=\"section-h2\">See What \u003Cem>$5,000 Coaching\u003C\u002Fem> Looks Like\u003C\u002Fh2>\n    \u003Cp class=\"section-sub\">Hit play. This is what 12 weeks of 1:1 work with me actually delivers.\u003C\u002Fp>\n    \u003Cvideo class=\"vsl-video\" controls playsinline poster=\"\">\n      \u003Csource src=\"vsl.mp4\" type=\"video\u002Fmp4\">\n    \u003C\u002Fvideo>\n    \u003Cp class=\"vsl-caption\">▶ 1 minute — no fluff. This is what you're playing for.\u003C\u002Fp>\n  \u003C\u002Fdiv>\n\u003C\u002Fsection>\n```\n\n**Headline formula:** `\"See What [Prize Value] Looks Like\"` or `\"Watch [Client Name]'s Transformation\"`. Always use `\u003Cem>` tags on the high-value phrase (e.g. `$5,000 Coaching`) to trigger the gold accent from `var(--gold)` via `.section-h2 em`.\n\n**Mobile overrides (add to `@media (max-width: 640px)` block):**\n```css\n.vsl-section { padding: 40px 16px; }\n.vsl-video { border-radius: 8px; }\n.vsl-section .section-sub { margin-bottom: 20px; }\n.vsl-caption { font-size: 0.82rem; margin-top: 12px; }\n```\n\n### Video Compression for Landing Pages\n\nTwo patterns depending on use case:\n\n**A. Testimonial videos (longer, ~60-120s, 100MB+ raw):** Use CRF-based compression. Quality priority, filesize secondary. CRF 28 is the sweet spot (good quality, ~6-8x smaller):\n```bash\nffmpeg -y -i input.mov -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 64k -movflags +faststart output.mp4\n```\n\n**B. VSL \u002F short promo videos (~30-90s, need under 5MB for fast loading):** Use bitrate-based compression with a hard cap. Size target controls the bitrate:\n```bash\nffmpeg -y -i input.mov -vf \"scale=848:464\" -c:v libx264 -preset fast \\\n  -b:v 600k -maxrate 800k -bufsize 1200k -c:a aac -b:a 64k -movflags +faststart output.mp4\n```\n- `-b:v 600k`: target bitrate (adjust: 600k → ~5MB per 60s, 1M → ~8MB per 60s)\n- `-maxrate 800k`: peak cap (avoids quality spikes causing buffering)\n- Scale to 848px wide (standard mobile-friendly width)\n\n**Both patterns require `-movflags +faststart`** — enables progressive download so the video starts playing before fully buffered.\n\n**Audio quality trap when re-encoding for web:** The default `-b:a 64k` (or Typeform's native 62kbps AAC) sounds noticeably degraded, especially on voice\u002Ffitness videos where audio clarity matters. Ibrahim flagged this after the first compressed VSL deployed. Fix: use `-b:a 128k` for voice-heavy VSL content. The filesize increase is negligible (~7.5MB vs 5.4MB for a 60s video) but the quality difference is obvious.\n\n```bash\n# BAD — muddy audio\nffmpeg -i input.mov ... -c:a aac -b:a 64k output.mp4\n\n# GOOD — crisp audio for voice\u002FVSL content\nffmpeg -i input.mov ... -c:a aac -b:a 128k output.mp4\n```\n\n**Post-compression cleanup:**\n```bash\nrm \u002Froot\u002Fibrahim-giveaway\u002Fvsl-original.mov  # raw original\n```\n\n## Funnel-Specific Copy\n\n### Giveaway Page\n- Headline: \"Win 12 Weeks 1:1 Coaching With Ibrahim Ramzy\"\n- Subtitle: \"Valued at $5,000 — Yours Free If You Win\"\n- Badge: \"14 Days Left to Enter\" (gold, pulsing)\n- Prize cards: 1st\u002F$5K, 2nd+3rd\u002F$500 off, Everyone\u002Fexclusive offer\n- How to Win: 3-step section (Fill in the Form → Reply to WhatsApp → Winner Announced on 7 July). Subtitle reads: \"Follow the simple steps and look out for the message you will receive once done.\"\n- What's Included: 3 pillars (Head Right \u002F Eat Without Rules \u002F Train for Body You Want) from OCR'd images\n- Testimonials: flood with 8 transformation cards + 8 video testimonials\n\n### Low-Ticket Page ($99\u002Fmo Health in Motion)\n- Headline: \"Get the body, energy, and confidence you deserve — for $99\u002Fmonth\"\n- Benefits: 6-card grid (Training, Nutrition, Community, Live Session, Everfit app, Mastery Library)\n- Pricing card: $99\u002Fmonth, cancel anytime\n- FAQ: 6 low-ticket specific questions\n- Typeform: Simplified flow (Yes\u002FNo gate → Why now → Contact)\n\n## Verification\n\nAfter deploy, validate in order:\n\n### 1. HTTP status\n```bash\ncurl -s -o \u002Fdev\u002Fnull -w \"%{http_code}\" https:\u002F\u002F{project}.vercel.app\n# Must be 200\n```\n\n### 2. Page content check\n```bash\ncurl -s https:\u002F\u002F{project}.vercel.app | grep -c 'N4LbJCHT\\|Win 12 Weeks\\|The Creed'\n# Must match at least 1 — confirms the right page is serving, not a stale Next.js default\n```\n\n### 3. Video\u002Fasset health (browser-level)\nHTTP 200 is NOT enough. Videos that return 200 via curl can still fail in browsers due to CORS. Use browser console on the live page:\n```javascript\ndocument.querySelectorAll('video').forEach((v,i) => {\n  let err = v.error ? `${v.error.code}: ${v.error.message}` : 'OK';\n  let src = v.querySelector('source')?.src?.split('\u002F').pop() || 'no source';\n  console.log(`Video ${i}: ${src} → ${err}`);\n});\n```\nAll should show \"OK\". Any \"NETWORK_NO_SOURCE\" or \"MEDIA_ERR_SRC_NOT_SUPPORTED\" means a CORS or broken URL.\n\n### 4. Typeform embed\nCheck the widget div exists and the embed script tag is present:\n```javascript\ndocument.querySelector('[data-tf-widget]') ? 'widget OK' : 'MISSING widget'\n```\nThe widget loads an iframe asynchronously. If `\u003Cscript src=\"https:\u002F\u002Fembed.typeform.com\u002Fnext\u002Fembed.js\">` is missing from the page bottom, the form won't render.\n\n### 5. Transformation images\n```javascript\ndocument.querySelectorAll('.trans-card img').forEach((img,i) => {\n  console.log(`Img ${i}: ${img.complete && img.naturalWidth > 0 ? 'LOADED' : 'BROKEN'} ${img.src.split('\u002F').pop()}`);\n});\n```\n\n---\n\n### Related References\n- `references\u002Fgiveaway-page-state.md`\n- `references\u002Fgiveaway-conversion-research.md` — Research-backed conversion optimizer patterns for giveaway landing pages: entry counter, countdown timer, sticky mobile CTA, exit-intent popup, FAQ accordion, scroll progress bar.\n\n## Motion\u002FAnimation Upgrade (Static HTML → Next.js + motion\u002Freact)\n\nWhen the user asks to add animations\u002Fmotion to an existing landing page, follow this pattern.\n\n### How the conversion works\n\n1. **Create a fresh Next.js project** (never modify the existing static HTML in-place):\n   ```bash\n   npx create-next-app@latest {project-name} --typescript --tailwind --eslint --app --src-dir --import-alias \"@\u002F*\" --use-npm\n   cd {project-name}\n   npm install motion\n   ```\n\n2. **Port every CSS class 1:1 into `globals.css`** — do NOT rewrite or simplify the styles. The brand styling (navy, silver, gold, dark background, grid patterns, card borders, responsive breakpoints) must survive unchanged.\n\n3. **Split sections into client components** under `src\u002Fapp\u002Fcomponents\u002F`:\n   - Each section (Hero, VSL, HowToWin, Prizes, etc.) is one component\n   - All are `\"use client\"` since they use `motion\u002Freact`\n   - Page files must NOT have `\"use client\"` — the page itself stays a server component; individual section components carry the directive\n\n4. **The Typeform embed script** must be added dynamically in the page component:\n   ```tsx\n   useEffect(() => {\n     const script = document.createElement(\"script\");\n     script.src = \"https:\u002F\u002Fembed.typeform.com\u002Fnext\u002Fembed.js\";\n     script.async = true;\n     document.body.appendChild(script);\n   }, []);\n   ```\n\n### Animation patterns used\n\n| Pattern | Code | Used for |\n|---|---|---|\n| **Staggered entrance** | `stagger` variant + `cardFade` variant on each child | All grids (steps, prizes, transformations, testimonials, pillars, features) |\n| **Scroll reveal** | `whileInView={{ opacity: 1, y: 0 }}` + `viewport={{ once: true }}` | Every section on the page |\n| **Hover lift** | `whileHover={{ y: -3, borderColor: \"var(--gold)\" }}` | Cards, CTAs |\n| **Button feedback** | `whileHover={{ scale: 1.03 }}` + `whileTap={{ scale: 0.97 }}` | All CTAs |\n| **Icon\u002Femoji hover** | `whileHover={{ scale: 1.15, rotate: 5 }}` | Pillar icons, feature icons |\n| **Continuous pulse** | `animate={{ scale: [1, 1.05, 1] }}` with `repeat: Infinity` | Badge (countdown), hero CTA |\n| **FadeInView wrapper** | Reusable wrapper component around each section | Consistent section entrance animation |\n\n### The FadeInView wrapper\n\n```tsx\nfunction FadeInView({ children, className = \"\" }: { children: React.ReactNode; className?: string }) {\n  const reduce = useReducedMotion();\n  return (\n    \u003Cmotion.div\n      className={className}\n      variants={{ hidden: { opacity: 0, y: reduce ? 0 : 24 }, visible: { opacity: 1, y: 0, transition: { duration: 0.5, ease: [0.22, 1, 0.36, 1] as const } } }}\n      initial=\"hidden\"\n      whileInView=\"visible\"\n      viewport={{ once: true, margin: \"-60px\" }}\n    >\n      {children}\n    \u003C\u002Fmotion.div>\n  );\n}\n```\n\n### Pitfall: TypeScript easing type\n\n`motion\u002Freact` (v12+) requires cubic bezier arrays to have `as const` assertion:\n\n```tsx\n\u002F\u002F WRONG — TypeScript error\nease: [0.22, 1, 0.36, 1]\n\n\u002F\u002F CORRECT\nease: [0.22, 1, 0.36, 1] as const\n```\n\nSame applies anywhere you embed an easing array in a `transition` object or `variants` definition.\n\n### Reduced motion support\n\nEvery animated component must check `useReducedMotion()`:\n\n```tsx\nconst reduce = useReducedMotion();\n\u002F\u002F When reduce is true, set y: 0 in hidden states, skip scale transforms\n```\n\nThe `FadeInView` wrapper handles this — but individual section components that use custom variants (like stagger children) need explicit reduce checks on their `cardFade`\u002F`fadeUp` variants.\n\n## Giveaway Page Conversion Optimizers\n\nThese are ADDED elements (not content replacements) that research shows improve conversion and retention on giveaway landing pages. Keep existing copy 100% intact — these slot into the page as new UI.\n\n### 1. Scroll Progress Bar\n\nFixed to top of viewport. A thin (2-3px) bar that fills as the user scrolls down the page.\n\n```tsx\nimport { motion, useScroll, useSpring } from \"motion\u002Freact\";\n\nexport function ScrollProgress() {\n  const { scrollYProgress } = useScroll();\n  const scaleX = useSpring(scrollYProgress, { stiffness: 100, damping: 30 });\n  return \u003Cmotion.div className=\"scroll-progress\" style={{ scaleX }} \u002F>;\n}\n```\n\nCSS: `position: fixed; top: 0; left: 0; height: 3px; background: linear-gradient(90deg, var(--gold), #FFA500); z-index: 9999; transform-origin: left;`\n\n### 2. Sticky Mobile CTA\n\nA fixed bottom bar with the CTA button that appears when the hero scrolls past viewport. Mobile-only. Helps recover abandoners who scroll without entering.\n\n```tsx\nconst [visible, setVisible] = useState(false);\nuseEffect(() => {\n  const handleScroll = () => {\n    const hero = document.querySelector(\".hero\");\n    if (hero) setVisible(hero.getBoundingClientRect().bottom \u003C 0);\n  };\n  window.addEventListener(\"scroll\", handleScroll, { passive: true });\n  return () => window.removeEventListener(\"scroll\", handleScroll);\n}, []);\n```\n\nCSS: `position: fixed; bottom: 0; z-index: 9998; background: rgba(var(--dark-navy), 0.95); backdrop-filter: blur(12px); transform: translateY(100%); transition: transform 0.3s var(--ease); &.visible { transform: translateY(0); }`\n\n### 3. Live Entry Counter\n\nShows social proof: \"X people have entered so far\". Count increments randomly every ~8s to feel live. Place **inside** the Hero section (after the hero-inner div), not between hero and VSL.\n\n```tsx\nconst [count, setCount] = useState(128);\nuseEffect(() => {\n  const interval = setInterval(() => setCount(prev => prev + Math.floor(Math.random() * 3) + 1), 8000);\n  return () => clearInterval(interval);\n}, []);\n```\n\nUse `font-variant-numeric: tabular-nums` on the count number to prevent layout shift as digits change.\n\n### 4. Countdown Timer\n\nA real-time countdown to the giveaway close date. Place **inside** the Hero section, after the EntryCounter.\n\n```tsx\nconst [timeLeft, setTimeLeft] = useState({ days: 0, hours: 0, mins: 0, secs: 0 });\nuseEffect(() => {\n  const target = new Date(\"2026-07-07T23:59:59\");\n  const tick = () => { \u002F* calculate diff, set state *\u002F };\n  tick(); const i = setInterval(tick, 1000); return () => clearInterval(i);\n}, []);\n```\n\nDisplay: `\"Closes in 02d 14h 32m 08s\"`. Also use `tabular-nums` for digit stability.\n\n### 5. Exit Intent Popup\n\nTriggers when the mouse cursor leaves the viewport (user about to close tab). Shows a last-chance message: \"Wait — don't lose this chance\". Only show once per session (use `sessionStorage` to track dismissal).\n\n```tsx\nuseEffect(() => {\n  const handleMouseLeave = (e: MouseEvent) => {\n    if (e.clientY \u003C= 0 && !sessionStorage.getItem(\"exit-popup-dismissed\")) setShow(true);\n  };\n  document.addEventListener(\"mouseleave\", handleMouseLeave);\n  return () => document.removeEventListener(\"mouseleave\", handleMouseLeave);\n}, []);\n```\n\nModal content: Headline `\"Wait — \u003Cem>don't lose this chance\u003C\u002Fem>\"`, subtext about everyone getting access to the coaching package, and a CTA button linking to `#enter`.\n\n### 6. FAQ Accordion\n\nPlaced between the features strip and the Typeform section. Addresses common objections about the giveaway: winner selection, eligibility, what happens if you don't win, program duration, suitability for beginners.\n\nImplementation: Animate height and opacity using `motion.div animate={{ height: open ? \"auto\" : 0, opacity: open ? 1 : 0 }}`. Each question is a button that toggles open\u002Fclose. Only one open at a time.\n\n5 questions minimum. Topics based on real visitor concerns:\n1. \"How is the winner chosen?\" — transparency about selection\n2. \"Do I need to be in a specific country?\" — addresses eligibility worry\n3. \"What happens if I don't win?\" — frames consolation offer\n4. \"How long does the coaching last?\" — sets expectations\n5. \"Is this suitable for beginners?\" — removes intimidation\n\n### Order on page (giveaway)\n\n```\nScrollProgress (always visible)\nStickyCTA (appears on scroll)\nExitIntentPopup (triggers on mouse leave)\nHero\n  └─ EntryCounter (inside Hero, after the hero-inner div)\n  └─ CountdownTimer (inside Hero, after EntryCounter)\nVSL\nHowToWin\nPrizes\nTransformations\nTestimonials\nIncluded\nFeaturesStrip\nFAQ (NEW — between features and typeform)\nTypeform\nFooter\n```","# Landing Page Workflows (Ibrahim Ramzy)\n\nBuild landing pages for The Creed \u002F Health in Motion \u002F giveaways. All pages use the same design system (navy + silver + royal blue, or gold for giveaways).\n\n## Source of Truth\n\nThe master high-ticket landing page lives at:\n- **Local:** `\u002Froot\u002Fibrahim\u002Findex.html`\n- **Live:** `https:\u002F\u002Fthecreed-one.vercel.app`\n\nThe giveaway landing page lives at:\n- **Local:** `\u002Froot\u002Fibrahim-giveaway\u002Findex.html` (complete, with VSL section)\n- **Live:** `https:\u002F\u002Fibrahim-giveaway.vercel.app` (primary, includes VSL, hero, steps, prizes, testimonials, typeform)\n- **Legacy (inactive):** `https:\u002F\u002Fcreed-coaching-giveaway.vercel.app` (older copy without VSL — do not edit)\n- **Motion upgrade (Next.js + motion\u002Freact):** `https:\u002F\u002Fibrahim-giveaway-v2.vercel.app` — deployed from `\u002Froot\u002Fibrahim-giveaway-v2`. Source: `src\u002Fapp\u002Fcomponents\u002FSections.tsx`, `ConversionOptimizers.tsx`, `page.tsx`. Has all animations, conversion optimizers, Lucide icons, and premium design. NOT yet domain-swapped — lives on its own Vercel project.\n\nAlways duplicate from one of these sources. Never start from scratch.\n\n## Duplication Pattern\n\n```bash\ncp -r \u002Froot\u002Fibrahim \u002Froot\u002Fibrahim-{project-name}\nrm -rf \u002Froot\u002Fibrahim-{project-name}\u002F.vercel   # critical — forces new Vercel project\n```\n\nThen edit `index.html`:\n1. Change `\u003Ctitle>`, hero copy, CTAs\n2. Update Typeform widget ID in the embed\n3. Test locally with a browser\n\n## Asset Linking\n\nVideos and images are NOT copied to new projects. Reference the master deployment:\n\n```html\n\u003C!-- Videos -->\n\u003Csource src=\"https:\u002F\u002Fthecreed-one.vercel.app\u002Fvideos\u002F{name}.mp4\">\n\n\u003C!-- Transformation images -->\n\u003Cimg src=\"https:\u002F\u002Fthecreed-one.vercel.app\u002Ftransformations\u002F{name}.jpg\">\n\n\u003C!-- Video posters -->\n\u003Cvideo poster=\"https:\u002F\u002Fthecreed-one.vercel.app\u002Fposters\u002F{name}.jpg\">\n```\n\nAvailable videos: pangina, davide, mohammed, matthew, mariel, ashley, asmond\n**Steven's video must be deployed locally** — see \"Steven's Video Fix\" below.\n\nAvailable transformations: davide, fatuma, konstantin, marielle, matthew, mohammed, omar, pangina, steven\n\n### Steven's Video Fix (CORS workaround)\n\nSteven's video (113MB) is on Google Drive. **Do NOT stream from Google Drive** — the direct download URL (`drive.usercontent.google.com`) does NOT have CORS headers for browser video tags. Curl works (no CORS enforcement) but browser `\u003Cvideo>` tags fail with NETWORK_NO_SOURCE. Proven in session 20260701_042630.\n\n**Correct approach — download, compress, deploy locally:**\n\n1. Download from Google Drive:\n   ```bash\n   curl -L -o \u002Ftmp\u002Fsteven_raw.mp4 \"https:\u002F\u002Fdrive.usercontent.google.com\u002Fdownload?id=FILE_ID&confirm=t&authuser=0\"\n   ```\n\n2. Compress with ffmpeg (113MB → ~17MB):\n   ```bash\n   ffmpeg -y -i \u002Ftmp\u002Fsteven_raw.mp4 -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 64k -movflags +faststart videos\u002Fsteven.mp4\n   ```\n   - CRF 28: good quality\u002Fsize balance\n   - `-movflags +faststart`: enables streaming (video plays before full download)\n\n3. Include `videos\u002Fsteven.mp4` in the same deployment directory as `index.html`. Vercel serves static files from any subdirectory automatically — no vercel.json needed.\n\n4. Reference with relative path:\n   ```html\n   \u003Csource src=\"videos\u002Fsteven.mp4\" type=\"video\u002Fmp4\">\n   ```\n\n5. Clean up temp files after deploy:\n   ```bash\n   rm \u002Ftmp\u002Fsteven_raw.mp4  # raw 113GB original\n   ```\n\n**Why this works:** Vercel serves the video from the same origin as the page — no CORS issue. The compressed 17MB file is well under Vercel's 100MB limit.\n\nSee `ops\u002Fvercel-deploy\u002Freferences\u002Fgoogle-drive-video-to-vercel.md` for a dedicated static-host variant (deploying video to a separate Vercel project).\n\n## Deployment\n\n```bash\ncd \u002Froot\u002Fibrahim-{project-name}\nnpx vercel --prod --token $VERCEL_TOKEN --yes\n```\n\nOutput: `https:\u002F\u002F{project-name}.vercel.app`\n\n### Custom domain (if needed)\n```bash\nvercel domain add {subdomain}.cali-creed.com {project-name} --token $VERCEL_TOKEN\n```\nNote: DNS is managed outside Vercel. User must add CNAME record at their provider.\n\n### Pitfalls & Recoveries\n\n**Vercel free tier deployment expiry:** Deployments on the free Hobby plan expire after 30 days. The Vercel project still exists (`.vercel\u002Fproject.json` stays valid) but all deployments are wiped. Fix: just redeploy — `npx vercel deploy --prod --token $TOKEN --yes` from the same directory reuses the project ID.\n\n**Project linking mismatch:** If `.vercel\u002Fproject.json` points to a different project than the one assigned the domain, the deploy succeeds (new deployment URL) but the domain alias fails. Fix: edit `.vercel\u002Fproject.json` to match the project that owns the domain, or reassign the domain via Vercel API:\n```python\n# Delete domain from old project, add to new project\nrequests.delete(f'https:\u002F\u002Fapi.vercel.com\u002Fv9\u002Fprojects\u002F{old_proj}\u002Fdomains\u002F{domain}?teamId={team}')\nrequests.post(f'https:\u002F\u002Fapi.vercel.com\u002Fv9\u002Fprojects\u002F{new_proj}\u002Fdomains?teamId={team}',\n              json={\"name\": domain})\n```\n\n**Next.js vs static project confusion:** If a Vercel project was originally created with a Next.js framework, subsequent static HTML-only deploys may silently serve the old Next.js build instead. The project's framework detection takes priority. Fix: create a new project for the static page and move the domain to it.\n\n**Local file recovery (Vercel deploy expiry):** When `https:\u002F\u002F{project}.vercel.app` returns 404 or a stale page, DON'T rebuild from scratch. First check:\n1. Does the local source directory still exist? Check `\u002Froot\u002F{project-name}\u002Findex.html`\n2. Check `.vercel\u002Fproject.json` for the project ID\n3. If the project exists on Vercel but has zero deployments, just redeploy from the local files\n4. If the `.vercel\u002Fproject.json` links to a different project than the one with the domain, update the file or reassign the domain\n\nCommon Vercel project IDs for Ibrahim:\n- `creed-coaching-giveaway` → `prj_jt07yuTFHQJQRsdmdHvNYArq0cZV` (domain: creed-coaching-giveaway.vercel.app)\n- `ibrahim-giveaway-lp` → `prj_8b9xHvKIPNFyvb0URaR4fyhN1wVj` **← this owns ibrahim-giveaway.vercel.app** (active, July 2026)\n- `ibrahim-giveaway` → separate project, no domain (gets `-creed-ramzy.vercel.app` subdomain)\n- `ibrahim-giveaway-v2` → Next.js + motion\u002Freact upgrade, deployed at `https:\u002F\u002Fibrahim-giveaway-v2.vercel.app`, local at `\u002Froot\u002Fibrahim-giveaway-v2`\n- `ibrahim-lowticket` → `prj_Yh0Wbqv9JaYlcWCLea6HA0KztjZm`\n- `ibrahim` → `prj_USPQzYyNdhjxDxZIyw0AAh6h6GkG`\n- `creed-funnel` → `prj_9lU3PPSggFIJpaETTf0Pt4zAXI96`\n\n**⚠️ Dual-project domain trap:** The domain `ibrahim-giveaway.vercel.app` is assigned to project `ibrahim-giveaway-lp`. There is a SEPARATE project named `ibrahim-giveaway` (no assigned domain). If you `vercel link` without specifying `--project ibrahim-giveaway-lp`, auto-detection may link to the wrong one. Always force-link before deploying to that domain:\n```bash\nnpx vercel link --yes --project ibrahim-giveaway-lp --token \"$(cat \u002Ftmp\u002Fvtoken)\"\n```\n\n**Dual-project deployment (same code, two domains):** When the same landing page needs to serve from two domains (e.g. `creed-coaching-giveaway.vercel.app` AND `ibrahim-giveaway.vercel.app`), you must deploy to each project separately:\n1. Link to project A → deploy → confirms domain A\n2. Relink to project B → deploy → confirms domain B\n3. Both deployments are independent — update both when code changes\n```bash\n# Deploy to domain A\ncd \u002Froot\u002Fibrahim-giveaway\nnpx vercel link --yes --project creed-coaching-giveaway --token \"$(cat \u002Ftmp\u002Fvtoken)\"\nnpx vercel deploy --prod --token \"$(cat \u002Ftmp\u002Fvtoken)\"\n\n# Deploy same code to domain B\nnpx vercel link --yes --project ibrahim-giveaway-lp --token \"$(cat \u002Ftmp\u002Fvtoken)\"\nnpx vercel deploy --prod --token \"$(cat \u002Ftmp\u002Fvtoken)\"\n```\n\n**Token masking bug:** Vercel tokens get masked to `***` in agent response text, corrupting inline commands. Store in `\u002Ftmp` via `printf`:\n```bash\nprintf 'vcp_yourtokenhere' > \u002Ftmp\u002Fvtoken.txt\n# Then use: --token \"$(cat \u002Ftmp\u002Fvtoken.txt)\"\n```\n\n**Google Drive video CORS trap:** `drive.usercontent.google.com` URLs work via curl (no CORS enforcement) but FAIL in browser `\u003Cvideo>` tags. The video element shows \"Unable to play media\" with NETWORK_NO_SOURCE. Always download and deploy locally — see \"Steven's Video Fix\" section above.\n\n## Mobile Optimization\n\nEvery page must be optimized for phone-first viewing - Ibrahim explicitly confirmed that most visitors come from phone.\n\n### Premium mobile breakpoints (768px and 400px)\n\n```\n@media (max-width: 768px) {\n  section { padding: 70px 16px; }\n  .hero { padding: 50px 16px 30px; }\n  .hero-headline { font-size: clamp(1.6rem, 7vw, 2.2rem); }\n  .hero-sub { font-size: 0.9rem; }\n  .hero-price { font-size: 1.1rem; }\n  .hero-cta { width: 100%; padding: 18px 24px; font-size: 1rem; }\n  .hero-badge { font-size: 0.6rem; padding: 6px 14px; }\n  .steps-grid, .prize-grid, .pillars-grid, .features-grid { grid-template-columns: 1fr; }\n  .testimonial-grid { grid-template-columns: 1fr; }\n  .trans-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }\n  .prize-card.gold { transform: none; }\n  .testimonial-card { padding: 20px 16px; }\n  .typeform-frame { border-radius: 12px; }\n  .step-card, .prize-card, .pillar-card { padding: 28px 20px; }\n  .prize-card .value { font-size: 1.3rem; }\n  .trans-name { font-size: 0.75rem; }\n  .trans-result { font-size: 0.7rem; }\n  .feat-item { padding: 20px 16px; }\n  .vsl-section { padding: 60px 16px; }\n  .vsl-video { border-radius: 12px; }\n  .section-sub { margin-bottom: 40px; }\n  .step-num { width: 42px; height: 42px; font-size: 1.1rem; }\n  .exit-modal { padding: 32px 24px; }\n}\n```\n\nKey improvements from the old values:\n- Hero top padding: 50px (was 80px) - content was sitting too low\n- Section padding: 70px (was 50px) - more breathing room\n- Card internal padding: 28px (was 24px)\n- Breakpoint: 768px (was 640px) - covers more phone sizes\n- Added exit-modal and hero-headline fine-tuning\n\n### Sticky CTA safe areas\nFor fixed-bottom bars, respect notched phones:\n```\npadding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));\n```\n\n### Verification on mobile\nAfter deploy, open the page on a real phone or DevTools mobile emulation (iPhone SE \u002F Galaxy S8+ viewports). Check:\n- CTA button spans full width and is tappable with one thumb\n- Headings fit in 2 lines (no overflow\u002Fellipsis)\n- Video player controls are usable at small sizes\n- Typeform embed fills the screen width\n- No horizontal scroll anywhere\n\n## Content Preservation Rule (critical for design\u002Fmotion upgrades)\n\nWhen the user says **\"don't change the content\"** or **\"keep the content the same\"** during a design or motion upgrade:\n- Every word, heading, subtitle, badge, button, and disclaimer must be copied exactly as-is.\n- Do NOT rewrite, condense, rephrase, or \"improve\" any copy.\n- Do NOT move sections around or reorder elements.\n- Do NOT add new sections of copy (FAQ, entry counter, etc. are ADDED as separate UI elements, not inserted into existing copy blocks).\n- The only acceptable changes: wrapping existing text in `\u003Cem>` tags for gold styling (if the original did that), or adding CSS classes\u002Fstyles that don't affect text content.\n- Test after deploy: grep the live page for key phrases from the original to verify they survived.\n\nThis rule is separate from (and overrides) any copywriting instincts. Motion\u002Fdesign upgrades are NOT copywriting passes.\n\n## Icon Standards\n\nUse **Lucide icons** for all UI elements. Never use emoji as icons — the user explicitly corrected this.\n\n### Icon mapping for The Creed pages\n\n| Purpose | Lucide Icon | Size |\n|---|---|---|\n| Hero badge alarm | `AlarmClock` | 14px |\n| 1st place | `Trophy` | 36px |\n| 2nd\u002F3rd place | `Medal` | 36px |\n| Everyone else | `Gift` | 36px |\n| Pillar: Mindset | `Brain` | 36px |\n| Pillar: Nutrition | `Apple` | 36px |\n| Pillar: Training | `Dumbbell` | 36px |\n| Feature: Mentorship | `Calendar` | 28px |\n| Feature: Onboarding | `Target` | 28px |\n| Feature: Training | `Dumbbell` | 28px |\n| Feature: Nutrition | `CookingPot` | 28px |\n| Feature: Touchpoints | `Phone` | 28px |\n| Feature: Mastery | `BookOpen` | 28px |\n| VSL play indicator | `Play` | 12px |\n| FAQ arrow | `ChevronDown` | 16px |\n| Exit close | `X` | 18px |\n| Live dot | `Circle` (fill green) | 6-8px |\n| CTA arrows | Inline SVG arrow (path) | 18px |\n\nStyle: All icons are `strokeWidth={2.5}` (default). Pillar icons use `color: var(--gold)`. Feature icons use `color: var(--gold)`. Render Lucide icons as JSX components, not string class names — they're SVGs that scale crisply at any resolution.\n\n```tsx\nimport { Trophy, Medal, Gift, Brain, Apple, Dumbbell } from \"lucide-react\";\n```\n\n## Premium Design Patterns\n\nWhen the user asks to \"make the page more premium\" or improve the look, apply these refinements.\n\n### Typography hierarchy\n- Hero headline: `clamp(2.2rem, 5.5vw, 3.8rem)` with `letter-spacing: -0.02em` and `font-weight: 900`\n- Section headings: `clamp(1.6rem, 3.6vw, 2.6rem)` with `letter-spacing: -0.01em`\n- Body text: `var(--silver-light)` (`#D4D4DC`) at `opacity: 0.7-0.85` — brighter than default silver for readability\n### Gold accent for em tags\n\n- All `em` tags inside headings get solid gold: `font-style: normal; color: var(--gold)`\n- Gradient text variant (`-webkit-background-clip: text`) can render inconsistently — reserved for hero headline only\n- Section headings default to solid gold as the verified safe choice\n\n### Gold gradient usage\nAlways define a gold gradient for premium accents:\n```css\n--gold-gradient: linear-gradient(135deg, #FFD700, #FFA500);\n--gold-light: #FFED4A;\n```\nApply to: CTA buttons, prize values, heading em tags, scroll progress bar, winner badge borders.\n\n### Glass-morphism cards\nEvery card should use a subtle glass background instead of bare transparent:\n```css\n--glass-bg: rgba(255, 255, 255, 0.03);\n--glass-border: rgba(255, 255, 255, 0.08);\n--glass-border-hover: rgba(255, 215, 0, 0.25);\n```\nCards get: `border-radius: 16px`, `background: var(--glass-bg)`, `border: 1px solid var(--glass-border)`.\n\n### Section transitions\nEvery section needs a `::before` pseudo-element with a 1px gold gradient line at the top:\n```css\nsection::before {\n  content: '';\n  position: absolute;\n  top: 0; left: 0; right: 0;\n  height: 1px;\n  background: linear-gradient(90deg, transparent, rgba(255, 215, 0, 0.1), transparent);\n}\n```\nSections should alternate background gradients (e.g., `linear-gradient(180deg, var(--near-black) 0%, #151515 100%)` then `linear-gradient(180deg, var(--dark-navy) 0%, #06203A 100%)`).\n\n### Hero enhancements\n- Background: dark gradient with radial gold glow overlay + grid pattern\n- Badge: **solid gold background** (`background: var(--gold); color: #000`) — the user rejected outlined\u002Ftransparent badges. Solid gold is the verified preference.\n- CTA: 12px border-radius, gold gradient, drop shadow (`box-shadow: 0 4px 24px rgba(255, 215, 0, 0.3)`)\n- Bottom fade: `::after` with `linear-gradient(to top, var(--near-black), transparent)` at 120px height\n- Entry counter + countdown timer must be placed **inside** the hero section (as direct children of the `\u003Csection className=\"hero\">`), not between hero and VSL.\n\n### Card hover effects\n- Lift: `y: -3` to `y: -4` on hover\n- Step cards: gold gradient top border that appears on hover (2px, `::before` with `opacity: 0 → 1`)\n- Gold prize card: `scale: 1.05` with `box-shadow: 0 8px 40px rgba(255, 215, 0, 0.08)`, hover to `scale: 1.08`\n- Feature cards: glass background + border (not bare text), hover lift `y: -3`\n\n### Testimonial refinements\n- Result badges: **solid gold background** (`background: var(--gold); color: #000`) — the user rejected outlined badges. Solid gold is the verified preference.\n- Author avatars: **solid gold background** (`background: var(--gold); color: #000`) — not gradient.\n- Video elements: 12px border-radius inside 16px card border-radius (concentric radii)\n\n### Pillar card refinements\n- Bullet list items: use gold checkmark (`'\\\\2713'` character via `::before` pseudo-element). This is the verified original pattern from Ibrahim's existing pages. Gold dot variant (`width: 6px; height: 6px; border-radius: 50%`) is experimental — use checkmark as the safe default.\n- Icons: gold color (`svg { color: var(--gold) }`)\n- Text: `opacity: 0.8` for readability\n\n### Easing\nUse `var(--ease-out-expo)` = `cubic-bezier(0.16, 1, 0.3, 1)` for all hover transitions and section animations. This is the same easing used by motion\u002Freact defaults.\n\n## Copy Preferences (Ibrahim)\n\n- **Headings:** 2 lines max. Use `\u003Cbr>` for manual line break. No text overflow.\n- **No em dashes (—).** Use regular hyphens (-) or commas.\n- **Button copy:** \"Enter the Giveaway\", \"Join Now\", \"Start Your Transformation\" — specific per funnel. Not \"Submit\" or \"Apply\".\n- **Hero spacing (giveaway pages):** Content should sit HIGH with minimal top gap. Use min-height: auto (NOT 100vh), align-items: flex-start, padding: 40px 20px 50px. User rejected centered-vertical-hero — wants badge\u002Fheadline\u002FCTA visible at top without scrolling.\n- **Under-How-to-Win copy (giveaway):** Always include below the 3-step grid: \"Follow the simple steps and look out for the message you will receive once done.\"\n- **Gold accent for giveaways:** Use var(--gold) for highlights, not royal blue.\n- **Style corrections the user has flagged:**\n  - Headings MUST be max 2 lines. If a heading wraps to 3 lines on mobile, condense it.\n  - Remove all em dashes from copy immediately when building new pages.\n  - Testimonial videos and before\u002Fafter images must be verified live after deploy — user will notice if they don't load.\n\n### Edit Precision (critical workflow rule)\n\nWhen the user says **\"replace X with Y\"**, do EXACTLY that:\n- Find X in its current location and replace it with Y there\n- Do NOT add Y somewhere else while leaving X in place\n- Do NOT duplicate Y in a second location unless explicitly told to\n- EXAMPLE: User said \"replace the text that says 'I'm looking for the next testimonial' with 'Follow the simple steps...'\" — the fix is to find THAT `.section-sub` paragraph and change its content. NOT add the new text below the steps grid and leave the old one in place.\n\nThis is the single most common correction the user makes. Read his edit instruction twice before executing.\n\n## Page Sections — Design Patterns\n\n### VSL (Video Sales Letter) Section\n\nPlace between hero and \"How to Win\" — Ibrahim's preferred position. The VSL sits in a dark section (same as hero bg or `var(--near-black)`) to avoid competing with the gold\u002FHero.\n\n**When to add:**\n- Giveaway pages (high-value prize \u002F $5K coaching)\n- High-ticket landing pages where proof of results is the sticking point\n- Any page where a short video (30-90s) can communicate value faster than text\n\n**CSS (add to the existing styles):**\n```css\n\u002F* ===== VSL SECTION ===== *\u002F\n.vsl-section {\n  padding: 60px 20px;\n  background: var(--near-black);\n  text-align: center;\n}\n.vsl-wrapper { max-width: 800px; margin: 0 auto; }\n.vsl-section .section-sub { margin-bottom: 32px; }\n.vsl-video {\n  width: 100%;\n  border-radius: 12px;\n  box-shadow: 0 8px 40px rgba(0,0,0,0.4);\n  display: block;\n}\n.vsl-caption {\n  font-size: 0.85rem;\n  color: var(--silver);\n  opacity: 0.6;\n  margin-top: 16px;\n}\n```\n\n**HTML (insert between hero closing `\u003C\u002Fsection>` and How to Win opening `\u003Csection>`):**\n```html\n\u003Csection class=\"vsl-section\">\n  \u003Cdiv class=\"vsl-wrapper\">\n    \u003Ch2 class=\"section-h2\">See What \u003Cem>$5,000 Coaching\u003C\u002Fem> Looks Like\u003C\u002Fh2>\n    \u003Cp class=\"section-sub\">Hit play. This is what 12 weeks of 1:1 work with me actually delivers.\u003C\u002Fp>\n    \u003Cvideo class=\"vsl-video\" controls playsinline poster=\"\">\n      \u003Csource src=\"vsl.mp4\" type=\"video\u002Fmp4\">\n    \u003C\u002Fvideo>\n    \u003Cp class=\"vsl-caption\">▶ 1 minute — no fluff. This is what you're playing for.\u003C\u002Fp>\n  \u003C\u002Fdiv>\n\u003C\u002Fsection>\n```\n\n**Headline formula:** `\"See What [Prize Value] Looks Like\"` or `\"Watch [Client Name]'s Transformation\"`. Always use `\u003Cem>` tags on the high-value phrase (e.g. `$5,000 Coaching`) to trigger the gold accent from `var(--gold)` via `.section-h2 em`.\n\n**Mobile overrides (add to `@media (max-width: 640px)` block):**\n```css\n.vsl-section { padding: 40px 16px; }\n.vsl-video { border-radius: 8px; }\n.vsl-section .section-sub { margin-bottom: 20px; }\n.vsl-caption { font-size: 0.82rem; margin-top: 12px; }\n```\n\n### Video Compression for Landing Pages\n\nTwo patterns depending on use case:\n\n**A. Testimonial videos (longer, ~60-120s, 100MB+ raw):** Use CRF-based compression. Quality priority, filesize secondary. CRF 28 is the sweet spot (good quality, ~6-8x smaller):\n```bash\nffmpeg -y -i input.mov -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 64k -movflags +faststart output.mp4\n```\n\n**B. VSL \u002F short promo videos (~30-90s, need under 5MB for fast loading):** Use bitrate-based compression with a hard cap. Size target controls the bitrate:\n```bash\nffmpeg -y -i input.mov -vf \"scale=848:464\" -c:v libx264 -preset fast \\\n  -b:v 600k -maxrate 800k -bufsize 1200k -c:a aac -b:a 64k -movflags +faststart output.mp4\n```\n- `-b:v 600k`: target bitrate (adjust: 600k → ~5MB per 60s, 1M → ~8MB per 60s)\n- `-maxrate 800k`: peak cap (avoids quality spikes causing buffering)\n- Scale to 848px wide (standard mobile-friendly width)\n\n**Both patterns require `-movflags +faststart`** — enables progressive download so the video starts playing before fully buffered.\n\n**Audio quality trap when re-encoding for web:** The default `-b:a 64k` (or Typeform's native 62kbps AAC) sounds noticeably degraded, especially on voice\u002Ffitness videos where audio clarity matters. Ibrahim flagged this after the first compressed VSL deployed. Fix: use `-b:a 128k` for voice-heavy VSL content. The filesize increase is negligible (~7.5MB vs 5.4MB for a 60s video) but the quality difference is obvious.\n\n```bash\n# BAD — muddy audio\nffmpeg -i input.mov ... -c:a aac -b:a 64k output.mp4\n\n# GOOD — crisp audio for voice\u002FVSL content\nffmpeg -i input.mov ... -c:a aac -b:a 128k output.mp4\n```\n\n**Post-compression cleanup:**\n```bash\nrm \u002Froot\u002Fibrahim-giveaway\u002Fvsl-original.mov  # raw original\n```\n\n## Funnel-Specific Copy\n\n### Giveaway Page\n- Headline: \"Win 12 Weeks 1:1 Coaching With Ibrahim Ramzy\"\n- Subtitle: \"Valued at $5,000 — Yours Free If You Win\"\n- Badge: \"14 Days Left to Enter\" (gold, pulsing)\n- Prize cards: 1st\u002F$5K, 2nd+3rd\u002F$500 off, Everyone\u002Fexclusive offer\n- How to Win: 3-step section (Fill in the Form → Reply to WhatsApp → Winner Announced on 7 July). Subtitle reads: \"Follow the simple steps and look out for the message you will receive once done.\"\n- What's Included: 3 pillars (Head Right \u002F Eat Without Rules \u002F Train for Body You Want) from OCR'd images\n- Testimonials: flood with 8 transformation cards + 8 video testimonials\n\n### Low-Ticket Page ($99\u002Fmo Health in Motion)\n- Headline: \"Get the body, energy, and confidence you deserve — for $99\u002Fmonth\"\n- Benefits: 6-card grid (Training, Nutrition, Community, Live Session, Everfit app, Mastery Library)\n- Pricing card: $99\u002Fmonth, cancel anytime\n- FAQ: 6 low-ticket specific questions\n- Typeform: Simplified flow (Yes\u002FNo gate → Why now → Contact)\n\n## Verification\n\nAfter deploy, validate in order:\n\n### 1. HTTP status\n```bash\ncurl -s -o \u002Fdev\u002Fnull -w \"%{http_code}\" https:\u002F\u002F{project}.vercel.app\n# Must be 200\n```\n\n### 2. Page content check\n```bash\ncurl -s https:\u002F\u002F{project}.vercel.app | grep -c 'N4LbJCHT\\|Win 12 Weeks\\|The Creed'\n# Must match at least 1 — confirms the right page is serving, not a stale Next.js default\n```\n\n### 3. Video\u002Fasset health (browser-level)\nHTTP 200 is NOT enough. Videos that return 200 via curl can still fail in browsers due to CORS. Use browser console on the live page:\n```javascript\ndocument.querySelectorAll('video').forEach((v,i) => {\n  let err = v.error ? `${v.error.code}: ${v.error.message}` : 'OK';\n  let src = v.querySelector('source')?.src?.split('\u002F').pop() || 'no source';\n  console.log(`Video ${i}: ${src} → ${err}`);\n});\n```\nAll should show \"OK\". Any \"NETWORK_NO_SOURCE\" or \"MEDIA_ERR_SRC_NOT_SUPPORTED\" means a CORS or broken URL.\n\n### 4. Typeform embed\nCheck the widget div exists and the embed script tag is present:\n```javascript\ndocument.querySelector('[data-tf-widget]') ? 'widget OK' : 'MISSING widget'\n```\nThe widget loads an iframe asynchronously. If `\u003Cscript src=\"https:\u002F\u002Fembed.typeform.com\u002Fnext\u002Fembed.js\">` is missing from the page bottom, the form won't render.\n\n### 5. Transformation images\n```javascript\ndocument.querySelectorAll('.trans-card img').forEach((img,i) => {\n  console.log(`Img ${i}: ${img.complete && img.naturalWidth > 0 ? 'LOADED' : 'BROKEN'} ${img.src.split('\u002F').pop()}`);\n});\n```\n\n---\n\n### Related References\n- `references\u002Fgiveaway-page-state.md`\n- `references\u002Fgiveaway-conversion-research.md` — Research-backed conversion optimizer patterns for giveaway landing pages: entry counter, countdown timer, sticky mobile CTA, exit-intent popup, FAQ accordion, scroll progress bar.\n\n## Motion\u002FAnimation Upgrade (Static HTML → Next.js + motion\u002Freact)\n\nWhen the user asks to add animations\u002Fmotion to an existing landing page, follow this pattern.\n\n### How the conversion works\n\n1. **Create a fresh Next.js project** (never modify the existing static HTML in-place):\n   ```bash\n   npx create-next-app@latest {project-name} --typescript --tailwind --eslint --app --src-dir --import-alias \"@\u002F*\" --use-npm\n   cd {project-name}\n   npm install motion\n   ```\n\n2. **Port every CSS class 1:1 into `globals.css`** — do NOT rewrite or simplify the styles. The brand styling (navy, silver, gold, dark background, grid patterns, card borders, responsive breakpoints) must survive unchanged.\n\n3. **Split sections into client components** under `src\u002Fapp\u002Fcomponents\u002F`:\n   - Each section (Hero, VSL, HowToWin, Prizes, etc.) is one component\n   - All are `\"use client\"` since they use `motion\u002Freact`\n   - Page files must NOT have `\"use client\"` — the page itself stays a server component; individual section components carry the directive\n\n4. **The Typeform embed script** must be added dynamically in the page component:\n   ```tsx\n   useEffect(() => {\n     const script = document.createElement(\"script\");\n     script.src = \"https:\u002F\u002Fembed.typeform.com\u002Fnext\u002Fembed.js\";\n     script.async = true;\n     document.body.appendChild(script);\n   }, []);\n   ```\n\n### Animation patterns used\n\n| Pattern | Code | Used for |\n|---|---|---|\n| **Staggered entrance** | `stagger` variant + `cardFade` variant on each child | All grids (steps, prizes, transformations, testimonials, pillars, features) |\n| **Scroll reveal** | `whileInView={{ opacity: 1, y: 0 }}` + `viewport={{ once: true }}` | Every section on the page |\n| **Hover lift** | `whileHover={{ y: -3, borderColor: \"var(--gold)\" }}` | Cards, CTAs |\n| **Button feedback** | `whileHover={{ scale: 1.03 }}` + `whileTap={{ scale: 0.97 }}` | All CTAs |\n| **Icon\u002Femoji hover** | `whileHover={{ scale: 1.15, rotate: 5 }}` | Pillar icons, feature icons |\n| **Continuous pulse** | `animate={{ scale: [1, 1.05, 1] }}` with `repeat: Infinity` | Badge (countdown), hero CTA |\n| **FadeInView wrapper** | Reusable wrapper component around each section | Consistent section entrance animation |\n\n### The FadeInView wrapper\n\n```tsx\nfunction FadeInView({ children, className = \"\" }: { children: React.ReactNode; className?: string }) {\n  const reduce = useReducedMotion();\n  return (\n    \u003Cmotion.div\n      className={className}\n      variants={{ hidden: { opacity: 0, y: reduce ? 0 : 24 }, visible: { opacity: 1, y: 0, transition: { duration: 0.5, ease: [0.22, 1, 0.36, 1] as const } } }}\n      initial=\"hidden\"\n      whileInView=\"visible\"\n      viewport={{ once: true, margin: \"-60px\" }}\n    >\n      {children}\n    \u003C\u002Fmotion.div>\n  );\n}\n```\n\n### Pitfall: TypeScript easing type\n\n`motion\u002Freact` (v12+) requires cubic bezier arrays to have `as const` assertion:\n\n```tsx\n\u002F\u002F WRONG — TypeScript error\nease: [0.22, 1, 0.36, 1]\n\n\u002F\u002F CORRECT\nease: [0.22, 1, 0.36, 1] as const\n```\n\nSame applies anywhere you embed an easing array in a `transition` object or `variants` definition.\n\n### Reduced motion support\n\nEvery animated component must check `useReducedMotion()`:\n\n```tsx\nconst reduce = useReducedMotion();\n\u002F\u002F When reduce is true, set y: 0 in hidden states, skip scale transforms\n```\n\nThe `FadeInView` wrapper handles this — but individual section components that use custom variants (like stagger children) need explicit reduce checks on their `cardFade`\u002F`fadeUp` variants.\n\n## Giveaway Page Conversion Optimizers\n\nThese are ADDED elements (not content replacements) that research shows improve conversion and retention on giveaway landing pages. Keep existing copy 100% intact — these slot into the page as new UI.\n\n### 1. Scroll Progress Bar\n\nFixed to top of viewport. A thin (2-3px) bar that fills as the user scrolls down the page.\n\n```tsx\nimport { motion, useScroll, useSpring } from \"motion\u002Freact\";\n\nexport function ScrollProgress() {\n  const { scrollYProgress } = useScroll();\n  const scaleX = useSpring(scrollYProgress, { stiffness: 100, damping: 30 });\n  return \u003Cmotion.div className=\"scroll-progress\" style={{ scaleX }} \u002F>;\n}\n```\n\nCSS: `position: fixed; top: 0; left: 0; height: 3px; background: linear-gradient(90deg, var(--gold), #FFA500); z-index: 9999; transform-origin: left;`\n\n### 2. Sticky Mobile CTA\n\nA fixed bottom bar with the CTA button that appears when the hero scrolls past viewport. Mobile-only. Helps recover abandoners who scroll without entering.\n\n```tsx\nconst [visible, setVisible] = useState(false);\nuseEffect(() => {\n  const handleScroll = () => {\n    const hero = document.querySelector(\".hero\");\n    if (hero) setVisible(hero.getBoundingClientRect().bottom \u003C 0);\n  };\n  window.addEventListener(\"scroll\", handleScroll, { passive: true });\n  return () => window.removeEventListener(\"scroll\", handleScroll);\n}, []);\n```\n\nCSS: `position: fixed; bottom: 0; z-index: 9998; background: rgba(var(--dark-navy), 0.95); backdrop-filter: blur(12px); transform: translateY(100%); transition: transform 0.3s var(--ease); &.visible { transform: translateY(0); }`\n\n### 3. Live Entry Counter\n\nShows social proof: \"X people have entered so far\". Count increments randomly every ~8s to feel live. Place **inside** the Hero section (after the hero-inner div), not between hero and VSL.\n\n```tsx\nconst [count, setCount] = useState(128);\nuseEffect(() => {\n  const interval = setInterval(() => setCount(prev => prev + Math.floor(Math.random() * 3) + 1), 8000);\n  return () => clearInterval(interval);\n}, []);\n```\n\nUse `font-variant-numeric: tabular-nums` on the count number to prevent layout shift as digits change.\n\n### 4. Countdown Timer\n\nA real-time countdown to the giveaway close date. Place **inside** the Hero section, after the EntryCounter.\n\n```tsx\nconst [timeLeft, setTimeLeft] = useState({ days: 0, hours: 0, mins: 0, secs: 0 });\nuseEffect(() => {\n  const target = new Date(\"2026-07-07T23:59:59\");\n  const tick = () => { \u002F* calculate diff, set state *\u002F };\n  tick(); const i = setInterval(tick, 1000); return () => clearInterval(i);\n}, []);\n```\n\nDisplay: `\"Closes in 02d 14h 32m 08s\"`. Also use `tabular-nums` for digit stability.\n\n### 5. Exit Intent Popup\n\nTriggers when the mouse cursor leaves the viewport (user about to close tab). Shows a last-chance message: \"Wait — don't lose this chance\". Only show once per session (use `sessionStorage` to track dismissal).\n\n```tsx\nuseEffect(() => {\n  const handleMouseLeave = (e: MouseEvent) => {\n    if (e.clientY \u003C= 0 && !sessionStorage.getItem(\"exit-popup-dismissed\")) setShow(true);\n  };\n  document.addEventListener(\"mouseleave\", handleMouseLeave);\n  return () => document.removeEventListener(\"mouseleave\", handleMouseLeave);\n}, []);\n```\n\nModal content: Headline `\"Wait — \u003Cem>don't lose this chance\u003C\u002Fem>\"`, subtext about everyone getting access to the coaching package, and a CTA button linking to `#enter`.\n\n### 6. FAQ Accordion\n\nPlaced between the features strip and the Typeform section. Addresses common objections about the giveaway: winner selection, eligibility, what happens if you don't win, program duration, suitability for beginners.\n\nImplementation: Animate height and opacity using `motion.div animate={{ height: open ? \"auto\" : 0, opacity: open ? 1 : 0 }}`. Each question is a button that toggles open\u002Fclose. Only one open at a time.\n\n5 questions minimum. Topics based on real visitor concerns:\n1. \"How is the winner chosen?\" — transparency about selection\n2. \"Do I need to be in a specific country?\" — addresses eligibility worry\n3. \"What happens if I don't win?\" — frames consolation offer\n4. \"How long does the coaching last?\" — sets expectations\n5. \"Is this suitable for beginners?\" — removes intimidation\n\n### Order on page (giveaway)\n\n```\nScrollProgress (always visible)\nStickyCTA (appears on scroll)\nExitIntentPopup (triggers on mouse leave)\nHero\n  └─ EntryCounter (inside Hero, after the hero-inner div)\n  └─ CountdownTimer (inside Hero, after EntryCounter)\nVSL\nHowToWin\nPrizes\nTransformations\nTestimonials\nIncluded\nFeaturesStrip\nFAQ (NEW — between features and typeform)\nTypeform\nFooter\n```",{"name":5,"tags":51,"version":53,"description":7},[43,52,33,42,44],"vercel","1.2.0","master","8ec37df6d71fb664ea19d32c079e7d3ff931a8e0","skills\u002Fcontent\u002Flanding-page-workflows",3,"https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit","https:\u002F\u002Fweblyfe.ai","https:\u002F\u002Fgithub.com\u002FS3YED","2026-08-27 01:54:02",{"source":8,"skillName":5,"commands":63,"prompt":73,"zipAvailable":74},[64,67,70],{"tool":65,"command":66},"npx","npx skills add S3YED\u002Fappie-kit --skill landing-page-workflows",{"tool":68,"command":69},"bunx","bunx skills add S3YED\u002Fappie-kit --skill landing-page-workflows",{"tool":71,"command":72},"pnpm","pnpm dlx skills add S3YED\u002Fappie-kit --skill landing-page-workflows","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fcontent\u002Flanding-page-workflows\u002FSKILL.md",true,[],[77,109,141,167,194,217],{"skillNo":78,"name":79,"nameZh":6,"description":80,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":90,"publishedAt":46},"01M6JFD4M6N4DSGC7TXEJ5R3J2","ai-music","AI music generation and audio tools: HeartMuLa lyrics-to-music generation, songwriting craft (+ Suno prompts), and audio spectrogram\u002Ffeature visualization.","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fwethlete\u002Fai-music\u002FSKILL.md",[83,86,89],{"categoryNo":84,"categoryName":85,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000013","分析与可视化",{"categoryNo":87,"categoryName":88,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000016","图像与多媒体",{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},[91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108],"music","ai music","humanizer","visualization","Tools","Audio","hermes","hermes agent","songwriting","suno","lyrics","prompts","heartmula","craft","generation","feature","ai music generation","music generation",{"skillNo":110,"name":111,"nameZh":6,"description":112,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":113,"categories":114,"keywords":121,"publishedAt":46},"01M6JFCZE4XNFQFMNZDHKHT5V5","agentic-webdesign-design-system-ingestion","Use v0 Design Systems 2.0, Bolt Design System Agents, or Lovable to generate production UI from a client's real design system components — not generic Tailwind. Use when building a client website where brand consistency matters.","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fweb-design\u002Fagentic-webdesign-design-system-ingestion\u002FSKILL.md",[115,116],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":117,"categoryName":118,"taxonomyType":119,"taxonomyTypeDesc":120},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[45,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140],"agentic","design system","system","ingestion","webdesign","agentic webdesign design system ingestion","components","generate","design systems","website","ui","Tailwind","bolt","lovable","v0","design-system","wed","design system components","appie",{"skillNo":142,"name":143,"nameZh":6,"description":144,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":145,"categories":146,"keywords":149,"publishedAt":46},"01M6JFCVPX3913CFAS6QQJ33ZB","agentic-webdesign-agent-elements","Use 21st.dev Agent Elements — 25 shadcn\u002Fui components purpose-built for AI agent UIs. Tool cards (Bash, Edit, Search, Plan, Subagent, MCP), chat, input, streaming. Open source, shadcn-registry install, no runtime lock-in.","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fweb-design\u002Fagentic-webdesign-agent-elements\u002FSKILL.md",[147,148],{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":117,"categoryName":118,"taxonomyType":119,"taxonomyTypeDesc":120},[122,150,126,151,152,153,128,154,155,156,157,158,159,160,161,162,163,164,165,166],"elements","agentic webdesign agent elements","MCP","ai agent","registry","search","streaming","open source","open","Bash","plan","subagent","edit","install","input","lock","source",{"skillNo":168,"name":169,"nameZh":6,"description":170,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":171,"categories":172,"keywords":177,"publishedAt":46},"01M6JFCQC7H65M9QJ6TRE71BS1","vercel-deployment","Deploy static sites and frontends to Vercel — handles both CLI and REST API paths, including the CLI token sanitization workaround.","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fsoftware-development\u002Fvercel-deployment\u002FSKILL.md",[173,176],{"categoryNo":174,"categoryName":175,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000011","运维与部署",{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},[34,31,52,178,179,180,181,37,182,183,184,185,186,187,188,189,190,191,192,193],"macos","cli","linux","windows","vercel deploy","REST","api","site","deploy to vercel","token","rest api","host","sites","paths","sanitization","static site",{"skillNo":195,"name":196,"nameZh":6,"description":197,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":198,"categories":199,"keywords":201,"publishedAt":46},"01M6JFCM4SMTXBM5A01BK2YQG1","software-quality-workflows","Umbrella workflow for TDD, debugging, code simplification, spikes, pre-commit review, and debugger-assisted investigation.","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fsoftware-development\u002Fsoftware-quality-workflows\u002FSKILL.md",[200],{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},[26,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,40],"quality","software","software quality workflows","review","tdd","workflow","commit","debugging","code","debugger","pre-commit","investigation","code simplification","user","simplification",{"skillNo":218,"name":219,"nameZh":6,"description":220,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":221,"categories":222,"keywords":230,"publishedAt":46},"01M6JFCGD0M6CEATY01W7YN6DB","react-component-refactoring","Safely refactor large React components into smaller, maintainable pieces using proven patterns","https:\u002F\u002Fgithub.com\u002FS3YED\u002Fappie-kit\u002Fblob\u002Fmaster\u002Fskills\u002Fsoftware-development\u002Freact-component-refactoring\u002FSKILL.md",[223,226,229],{"categoryNo":224,"categoryName":225,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000007","代码审查",{"categoryNo":227,"categoryName":228,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},[231,232,233,234,235,236,237,238,178,239,240,128,241,181,242,210,243,244,245,246],"react","component","refactoring","component refactoring","react component","react component refactoring","frontend","writing","safe","typescript","react components","modular","refactor","simplify","patterns","test-driven-development"]