@jaimevalasek/aioson 1.6.0 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +74 -0
- package/README.md +729 -232
- package/docs/design-previews/pt.squarespace.com-homepage.html +889 -0
- package/docs/integrations/sdlc-genius-boundary.md +76 -0
- package/docs/integrations/sdlc-genius-eval-matrix.md +75 -0
- package/docs/integrations/sdlc-genius-install-checklist.md +93 -0
- package/docs/integrations/sdlc-genius-review-samples.md +86 -0
- package/docs/pt/README.md +3 -0
- package/docs/pt/agentes.md +1 -0
- package/docs/pt/comandos-cli.md +888 -2
- package/docs/pt/design-hybrid-forge.md +255 -6
- package/docs/pt/devlog-pipeline.md +270 -0
- package/docs/pt/fluxo-artefatos.md +178 -0
- package/docs/pt/hooks-session-guard.md +454 -0
- package/docs/pt/monitor-de-contexto.md +59 -5
- package/docs/pt/sdd-automation-scripts.md +557 -0
- package/docs/pt/site-forge.md +309 -0
- package/docs/pt/spec-learnings-pipeline.md +265 -0
- package/package.json +1 -1
- package/src/a2a/client.js +165 -0
- package/src/a2a/server.js +223 -0
- package/src/cli.js +235 -1
- package/src/commands/agent-audit.js +397 -0
- package/src/commands/agent-export-skill.js +229 -0
- package/src/commands/artifact-validate.js +189 -0
- package/src/commands/brief-gen.js +405 -0
- package/src/commands/brief-validate.js +65 -0
- package/src/commands/classify.js +256 -0
- package/src/commands/context-compact.js +49 -0
- package/src/commands/context-health.js +175 -0
- package/src/commands/context-monitor.js +71 -0
- package/src/commands/context-trim.js +177 -0
- package/src/commands/detect-test-runner.js +55 -0
- package/src/commands/devlog-export-brains.js +27 -0
- package/src/commands/devlog-process.js +292 -0
- package/src/commands/devlog-watch.js +131 -0
- package/src/commands/feature-close.js +165 -0
- package/src/commands/gate-check.js +228 -0
- package/src/commands/hooks-emit.js +253 -0
- package/src/commands/hooks-install.js +347 -0
- package/src/commands/learning-auto-promote.js +195 -0
- package/src/commands/learning-evolve.js +18 -9
- package/src/commands/learning-export.js +103 -0
- package/src/commands/learning-rollback.js +164 -0
- package/src/commands/live.js +25 -1
- package/src/commands/pattern-detect.js +33 -0
- package/src/commands/preflight-context.js +30 -0
- package/src/commands/preflight.js +208 -0
- package/src/commands/pulse-update.js +130 -0
- package/src/commands/runner-daemon.js +274 -0
- package/src/commands/runner-plan.js +70 -0
- package/src/commands/runner-queue-from-plan.js +166 -0
- package/src/commands/runner-queue.js +189 -0
- package/src/commands/runner-run.js +129 -0
- package/src/commands/runtime.js +47 -1
- package/src/commands/self-implement-loop.js +256 -0
- package/src/commands/session-guard.js +218 -0
- package/src/commands/sizing.js +165 -0
- package/src/commands/skill.js +65 -0
- package/src/commands/spec-checkpoint.js +177 -0
- package/src/commands/spec-status.js +79 -0
- package/src/commands/spec-sync.js +190 -0
- package/src/commands/spec-tasks.js +288 -0
- package/src/commands/squad-autorun.js +1220 -0
- package/src/commands/squad-bus.js +217 -0
- package/src/commands/squad-card.js +149 -0
- package/src/commands/squad-daemon.js +134 -0
- package/src/commands/squad-dependency-graph.js +164 -0
- package/src/commands/squad-review.js +106 -0
- package/src/commands/squad-scaffold.js +55 -0
- package/src/commands/squad-tool-register.js +157 -0
- package/src/commands/state-save.js +122 -0
- package/src/commands/update.js +2 -0
- package/src/commands/verify-gate.js +572 -0
- package/src/commands/workflow-execute.js +241 -0
- package/src/constants.js +22 -0
- package/src/install-profile.js +2 -2
- package/src/install-wizard.js +3 -2
- package/src/installer.js +6 -0
- package/src/lib/health-check.js +158 -0
- package/src/lib/hook-protocol.js +76 -0
- package/src/mcp/apps/squad-dashboard/app.js +163 -0
- package/src/mcp/apps/squad-dashboard/index.html +261 -0
- package/src/mcp/apps/squad-dashboard/mcp-manifest.json +23 -0
- package/src/mcp/resources/squad-state.js +130 -0
- package/src/preflight-engine.js +443 -0
- package/src/runner/cascade.js +97 -0
- package/src/runner/cli-launcher.js +109 -0
- package/src/runner/plan-importer.js +63 -0
- package/src/runner/queue-store.js +159 -0
- package/src/runtime-store.js +61 -3
- package/src/squad/agent-teams-adapter.js +264 -0
- package/src/squad/brief-validator.js +350 -0
- package/src/squad/bus-bridge.js +140 -0
- package/src/squad/context-compactor.js +265 -0
- package/src/squad/cross-ai-synthesizer.js +250 -0
- package/src/squad/hooks-generator.js +196 -0
- package/src/squad/inter-squad-events.js +175 -0
- package/src/squad/intra-bus.js +345 -0
- package/src/squad/learning-extractor.js +213 -0
- package/src/squad/pattern-detector.js +365 -0
- package/src/squad/preflight-context.js +296 -0
- package/src/squad/recovery-context.js +242 -71
- package/src/squad/reflection.js +365 -0
- package/src/squad/squad-scaffold.js +177 -0
- package/src/squad/state-manager.js +310 -0
- package/src/squad/task-decomposer.js +652 -0
- package/src/squad/verify-gate.js +303 -0
- package/src/updater.js +4 -5
- package/src/worker-runner.js +186 -1
- package/template/.aioson/agents/analyst.md +62 -1
- package/template/.aioson/agents/architect.md +61 -1
- package/template/.aioson/agents/copywriter.md +463 -0
- package/template/.aioson/agents/design-hybrid-forge.md +14 -0
- package/template/.aioson/agents/dev.md +271 -25
- package/template/.aioson/agents/deyvin.md +67 -8
- package/template/.aioson/agents/discovery-design-doc.md +44 -0
- package/template/.aioson/agents/genome.md +14 -0
- package/template/.aioson/agents/neo.md +83 -2
- package/template/.aioson/agents/orache.md +50 -4
- package/template/.aioson/agents/orchestrator.md +197 -1
- package/template/.aioson/agents/pm.md +35 -0
- package/template/.aioson/agents/product.md +50 -5
- package/template/.aioson/agents/profiler-enricher.md +14 -0
- package/template/.aioson/agents/profiler-forge.md +14 -0
- package/template/.aioson/agents/profiler-researcher.md +14 -0
- package/template/.aioson/agents/qa.md +273 -21
- package/template/.aioson/agents/setup.md +96 -10
- package/template/.aioson/agents/sheldon.md +131 -6
- package/template/.aioson/agents/site-forge.md +1753 -0
- package/template/.aioson/agents/squad.md +352 -0
- package/template/.aioson/agents/tester.md +53 -0
- package/template/.aioson/agents/ux-ui.md +203 -4
- package/template/.aioson/brains/README.md +128 -0
- package/template/.aioson/brains/_index.json +16 -0
- package/template/.aioson/brains/scripts/query.js +103 -0
- package/template/.aioson/brains/site-forge/visual-patterns.brain.json +205 -0
- package/template/.aioson/config.md +143 -13
- package/template/.aioson/constitution.md +33 -0
- package/template/.aioson/context/project-pulse.md +34 -0
- package/template/.aioson/docs/LAYERS.md +79 -0
- package/template/.aioson/docs/README.md +76 -0
- package/template/.aioson/docs/example-external-api-context.md +72 -0
- package/template/.aioson/genomes/copywriting.md +204 -0
- package/template/.aioson/locales/en/agents/architect.md +17 -0
- package/template/.aioson/locales/en/agents/dev.md +79 -13
- package/template/.aioson/locales/en/agents/orache.md +6 -0
- package/template/.aioson/locales/en/agents/orchestrator.md +24 -0
- package/template/.aioson/locales/en/agents/product.md +50 -0
- package/template/.aioson/locales/en/agents/sheldon.md +115 -0
- package/template/.aioson/locales/en/agents/squad.md +14 -0
- package/template/.aioson/locales/en/agents/tester.md +6 -0
- package/template/.aioson/locales/es/agents/analyst.md +2 -0
- package/template/.aioson/locales/es/agents/architect.md +19 -0
- package/template/.aioson/locales/es/agents/dev.md +64 -4
- package/template/.aioson/locales/es/agents/deyvin.md +2 -0
- package/template/.aioson/locales/es/agents/discovery-design-doc.md +2 -0
- package/template/.aioson/locales/es/agents/genome.md +2 -0
- package/template/.aioson/locales/es/agents/neo.md +2 -0
- package/template/.aioson/locales/es/agents/orache.md +2 -0
- package/template/.aioson/locales/es/agents/orchestrator.md +26 -0
- package/template/.aioson/locales/es/agents/pair.md +2 -0
- package/template/.aioson/locales/es/agents/pm.md +2 -0
- package/template/.aioson/locales/es/agents/product.md +52 -0
- package/template/.aioson/locales/es/agents/profiler-enricher.md +2 -0
- package/template/.aioson/locales/es/agents/profiler-forge.md +2 -0
- package/template/.aioson/locales/es/agents/profiler-researcher.md +2 -0
- package/template/.aioson/locales/es/agents/qa.md +2 -0
- package/template/.aioson/locales/es/agents/setup.md +2 -0
- package/template/.aioson/locales/es/agents/sheldon.md +117 -0
- package/template/.aioson/locales/es/agents/squad.md +16 -0
- package/template/.aioson/locales/es/agents/tester.md +9 -0
- package/template/.aioson/locales/es/agents/ux-ui.md +2 -0
- package/template/.aioson/locales/fr/agents/analyst.md +2 -0
- package/template/.aioson/locales/fr/agents/architect.md +19 -0
- package/template/.aioson/locales/fr/agents/dev.md +64 -4
- package/template/.aioson/locales/fr/agents/deyvin.md +2 -0
- package/template/.aioson/locales/fr/agents/discovery-design-doc.md +2 -0
- package/template/.aioson/locales/fr/agents/genome.md +2 -0
- package/template/.aioson/locales/fr/agents/neo.md +2 -0
- package/template/.aioson/locales/fr/agents/orache.md +2 -0
- package/template/.aioson/locales/fr/agents/orchestrator.md +26 -0
- package/template/.aioson/locales/fr/agents/pair.md +2 -0
- package/template/.aioson/locales/fr/agents/pm.md +2 -0
- package/template/.aioson/locales/fr/agents/product.md +52 -0
- package/template/.aioson/locales/fr/agents/profiler-enricher.md +2 -0
- package/template/.aioson/locales/fr/agents/profiler-forge.md +2 -0
- package/template/.aioson/locales/fr/agents/profiler-researcher.md +2 -0
- package/template/.aioson/locales/fr/agents/qa.md +2 -0
- package/template/.aioson/locales/fr/agents/setup.md +2 -0
- package/template/.aioson/locales/fr/agents/sheldon.md +117 -0
- package/template/.aioson/locales/fr/agents/squad.md +16 -0
- package/template/.aioson/locales/fr/agents/tester.md +9 -0
- package/template/.aioson/locales/fr/agents/ux-ui.md +2 -0
- package/template/.aioson/locales/pt-BR/agents/analyst.md +64 -3
- package/template/.aioson/locales/pt-BR/agents/architect.md +42 -0
- package/template/.aioson/locales/pt-BR/agents/dev.md +147 -14
- package/template/.aioson/locales/pt-BR/agents/deyvin.md +47 -0
- package/template/.aioson/locales/pt-BR/agents/neo.md +62 -1
- package/template/.aioson/locales/pt-BR/agents/orchestrator.md +158 -2
- package/template/.aioson/locales/pt-BR/agents/pm.md +95 -1
- package/template/.aioson/locales/pt-BR/agents/product.md +145 -18
- package/template/.aioson/locales/pt-BR/agents/qa.md +16 -0
- package/template/.aioson/locales/pt-BR/agents/setup.md +101 -18
- package/template/.aioson/locales/pt-BR/agents/sheldon.md +132 -1
- package/template/.aioson/locales/pt-BR/agents/squad.md +14 -0
- package/template/.aioson/locales/pt-BR/agents/tester.md +449 -0
- package/template/.aioson/rules/README.md +69 -0
- package/template/.aioson/rules/data-format-convention.md +136 -0
- package/template/.aioson/rules/example-monetary-values.md +30 -0
- package/template/.aioson/schemas/squad-manifest.schema.json +124 -3
- package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +2 -0
- package/template/.aioson/skills/design/pt.squarespace.com/.skill-meta.json +31 -0
- package/template/.aioson/skills/design/pt.squarespace.com/SKILL.md +66 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +368 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/design-tokens.md +150 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/motion.md +270 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/patterns.md +189 -0
- package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +165 -0
- package/template/.aioson/skills/marketing/references/anti-patterns.md +254 -0
- package/template/.aioson/skills/marketing/references/fascinations.md +192 -0
- package/template/.aioson/skills/marketing/references/five-acts.md +248 -0
- package/template/.aioson/skills/marketing/references/market-intelligence.md +198 -0
- package/template/.aioson/skills/marketing/references/offer-structure.md +203 -0
- package/template/.aioson/skills/marketing/references/one-belief.md +149 -0
- package/template/.aioson/skills/marketing/references/patterns.md +218 -0
- package/template/.aioson/skills/marketing/references/pms-research.md +193 -0
- package/template/.aioson/skills/marketing/vsl-craft.md +385 -0
- package/template/.aioson/skills/process/aioson-spec-driven/SKILL.md +1 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/analyst.md +30 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/architect.md +23 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/dev.md +47 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/deyvin.md +27 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/maintenance-and-state.md +35 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/product.md +25 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/qa.md +30 -0
- package/template/.aioson/skills/process/aioson-spec-driven/references/sheldon.md +25 -0
- package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +4 -1
- package/template/.aioson/skills/process/design-hybrid-forge/references/output-contract.md +15 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/pair-compatibility.md +32 -0
- package/template/.aioson/skills/process/design-hybrid-forge/references/quality-gates.md +20 -0
- package/template/.aioson/skills/process/simplify/SKILL.md +173 -0
- package/template/.aioson/skills/static/context-budget-guide.md +46 -0
- package/template/.aioson/skills/static/harness-sensors.md +74 -0
- package/template/.aioson/skills/static/landing-page-deploy.md +192 -0
- package/template/.aioson/skills/static/landing-page-forge.md +730 -0
- package/template/.aioson/skills/static/multi-agent-patterns.md +43 -0
- package/template/.aioson/skills/static/react-motion-patterns.md +22 -0
- package/template/.aioson/skills/static/static-html-patterns/checklists.md +43 -0
- package/template/.aioson/skills/static/static-html-patterns/css-tokens.md +609 -0
- package/template/.aioson/skills/static/static-html-patterns/motion.md +193 -0
- package/template/.aioson/skills/static/static-html-patterns/premium.md +711 -0
- package/template/.aioson/skills/static/static-html-patterns/structure.md +209 -0
- package/template/.aioson/skills/static/static-html-patterns/utilities.md +190 -0
- package/template/.aioson/skills/static/static-html-patterns.md +58 -1913
- package/template/.aioson/skills/static/threejs-patterns.md +929 -0
- package/template/.aioson/skills/static/ui-ux-modern.md +1 -0
- package/template/.aioson/skills/static/web-research-cache.md +112 -0
- package/template/.aioson/tasks/implementation-plan.md +21 -1
- package/template/.aioson/tasks/squad-create.md +22 -0
- package/template/.aioson/tasks/squad-design.md +30 -0
- package/template/.aioson/templates/squads/digital-marketing-agency/template.json +96 -0
- package/template/.claude/commands/aioson/agent/design-hybrid-forge.md +5 -0
- package/template/.claude/commands/aioson/agent/orache.md +5 -0
- package/template/.claude/commands/aioson/agent/sheldon.md +5 -0
- package/template/.claude/commands/aioson/agent/site-forge.md +5 -0
- package/template/AGENTS.md +55 -3
- package/template/CLAUDE.md +31 -0
- package/template/OPENCODE.md +4 -0
- package/template/researchs/.gitkeep +0 -0
- package/template/.aioson/skills/design-system/components/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/dashboards/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/foundations/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/motion/SKILL.md:Zone.Identifier +0 -0
- package/template/.aioson/skills/design-system/patterns/SKILL.md:Zone.Identifier +0 -0
|
@@ -1,1935 +1,80 @@
|
|
|
1
|
-
# Static HTML Patterns — Landing Page Production Guide
|
|
2
|
-
|
|
3
|
-
> Read this skill when building any landing page (project_type=site).
|
|
4
|
-
> This covers structure, modern CSS techniques, performance, and the "wow factor" that makes users stop scrolling.
|
|
5
|
-
|
|
6
1
|
---
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 1. HTML Structure — The Production Shell
|
|
21
|
-
|
|
22
|
-
Every landing page follows this semantic skeleton:
|
|
23
|
-
|
|
24
|
-
```html
|
|
25
|
-
<!DOCTYPE html>
|
|
26
|
-
<html lang="pt-BR">
|
|
27
|
-
<head>
|
|
28
|
-
<meta charset="UTF-8">
|
|
29
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
30
|
-
<meta name="description" content="[real product description]">
|
|
31
|
-
<title>[Product Name] — [Value Proposition]</title>
|
|
32
|
-
|
|
33
|
-
<!-- Preload critical fonts (eliminate layout shift) -->
|
|
34
|
-
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
35
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
36
|
-
<link href="https://fonts.googleapis.com/css2?family=[ChosenFont]:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
37
|
-
|
|
38
|
-
<!-- Inline critical CSS (above-the-fold only: reset, header, hero) -->
|
|
39
|
-
<style>
|
|
40
|
-
/* === CRITICAL CSS — inline here, rest in external file === */
|
|
41
|
-
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
42
|
-
html { font-size: 16px; scroll-behavior: smooth; }
|
|
43
|
-
body { font-family: var(--font-body); background: var(--color-bg); color: var(--color-text); -webkit-font-smoothing: antialiased; }
|
|
44
|
-
img { max-width: 100%; display: block; object-fit: cover; }
|
|
45
|
-
a { text-decoration: none; color: inherit; }
|
|
46
|
-
button { cursor: pointer; border: none; font: inherit; }
|
|
47
|
-
/* rest of CSS below */
|
|
48
|
-
</style>
|
|
49
|
-
</head>
|
|
50
|
-
<body>
|
|
51
|
-
|
|
52
|
-
<!-- HEADER: sticky, transparent → solid on scroll -->
|
|
53
|
-
<header class="header" id="header">
|
|
54
|
-
<div class="container header__inner">
|
|
55
|
-
<a href="/" class="header__logo" aria-label="Home">
|
|
56
|
-
<span class="logo-mark">●</span>
|
|
57
|
-
<span class="logo-text">ProductName</span>
|
|
58
|
-
</a>
|
|
59
|
-
<nav class="header__nav" aria-label="Main navigation">
|
|
60
|
-
<a href="#features">Features</a>
|
|
61
|
-
<a href="#how-it-works">How it works</a>
|
|
62
|
-
<a href="#pricing">Pricing</a>
|
|
63
|
-
</nav>
|
|
64
|
-
<a href="#cta" class="btn btn--primary btn--sm">Get started</a>
|
|
65
|
-
<button class="header__burger" aria-label="Open menu" aria-expanded="false">
|
|
66
|
-
<span></span><span></span><span></span>
|
|
67
|
-
</button>
|
|
68
|
-
</div>
|
|
69
|
-
</header>
|
|
70
|
-
|
|
71
|
-
<main>
|
|
72
|
-
<!-- HERO: full viewport, image/gradient + content -->
|
|
73
|
-
<section class="hero" aria-labelledby="hero-title">
|
|
74
|
-
<div class="hero__bg">
|
|
75
|
-
<img src="https://images.unsplash.com/photo-[id]?w=1920&q=80&fit=crop"
|
|
76
|
-
alt="" role="presentation" loading="eager" fetchpriority="high">
|
|
77
|
-
<div class="hero__overlay" aria-hidden="true"></div>
|
|
78
|
-
</div>
|
|
79
|
-
<div class="container hero__content">
|
|
80
|
-
<span class="hero__label reveal">Category / Tagline</span>
|
|
81
|
-
<h1 class="hero__title reveal reveal-delay-1" id="hero-title">
|
|
82
|
-
Bold Headline That <em class="gradient-text">Changes Everything</em>
|
|
83
|
-
</h1>
|
|
84
|
-
<p class="hero__subtitle reveal reveal-delay-2">
|
|
85
|
-
Supporting text that adds real context — who benefits, how fast, what outcome.
|
|
86
|
-
</p>
|
|
87
|
-
<div class="hero__actions reveal reveal-delay-3">
|
|
88
|
-
<a href="#signup" class="btn btn--primary btn--lg">Primary CTA</a>
|
|
89
|
-
<a href="#demo" class="btn btn--ghost btn--lg">
|
|
90
|
-
<span class="btn__icon" aria-hidden="true">▶</span>
|
|
91
|
-
Watch demo
|
|
92
|
-
</a>
|
|
93
|
-
</div>
|
|
94
|
-
<div class="hero__social-proof reveal reveal-delay-4">
|
|
95
|
-
<span>Trusted by 2,000+ teams</span>
|
|
96
|
-
<div class="avatar-group" aria-label="User avatars">
|
|
97
|
-
<img src="https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=40&h=40&fit=crop&crop=face" alt="User" width="40" height="40">
|
|
98
|
-
<img src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=40&h=40&fit=crop&crop=face" alt="User" width="40" height="40">
|
|
99
|
-
<img src="https://images.unsplash.com/photo-1527980965255-d3b416303d12?w=40&h=40&fit=crop&crop=face" alt="User" width="40" height="40">
|
|
100
|
-
</div>
|
|
101
|
-
<div class="star-rating" aria-label="5 out of 5 stars">★★★★★ <span>4.9</span></div>
|
|
102
|
-
</div>
|
|
103
|
-
</div>
|
|
104
|
-
<!-- Decorative floating elements (aria-hidden) -->
|
|
105
|
-
<div class="hero__decor" aria-hidden="true">
|
|
106
|
-
<div class="orb orb--1"></div>
|
|
107
|
-
<div class="orb orb--2"></div>
|
|
108
|
-
<div class="orb orb--3"></div>
|
|
109
|
-
</div>
|
|
110
|
-
</section>
|
|
111
|
-
|
|
112
|
-
<!-- LOGOS: social proof bar -->
|
|
113
|
-
<section class="logos-bar" aria-label="Trusted by">
|
|
114
|
-
<div class="container">
|
|
115
|
-
<p class="logos-bar__label">Trusted by teams at</p>
|
|
116
|
-
<div class="logos-bar__track">
|
|
117
|
-
<!-- Logo images or text placeholders -->
|
|
118
|
-
</div>
|
|
119
|
-
</div>
|
|
120
|
-
</section>
|
|
121
|
-
|
|
122
|
-
<!-- FEATURES: 3 or 6 cards in grid -->
|
|
123
|
-
<section class="features" id="features" aria-labelledby="features-title">
|
|
124
|
-
<div class="container">
|
|
125
|
-
<div class="section-header">
|
|
126
|
-
<span class="section-label">Features</span>
|
|
127
|
-
<h2 class="section-title" id="features-title">Everything you need</h2>
|
|
128
|
-
<p class="section-subtitle">One sentence expanding on the value.</p>
|
|
129
|
-
</div>
|
|
130
|
-
<div class="features__grid">
|
|
131
|
-
<article class="feature-card reveal">
|
|
132
|
-
<div class="feature-card__icon" aria-hidden="true">⚡</div>
|
|
133
|
-
<h3 class="feature-card__title">Feature Name</h3>
|
|
134
|
-
<p class="feature-card__desc">What it does and why it matters to the user.</p>
|
|
135
|
-
</article>
|
|
136
|
-
<!-- repeat 5 more -->
|
|
137
|
-
</div>
|
|
138
|
-
</div>
|
|
139
|
-
</section>
|
|
140
|
-
|
|
141
|
-
<!-- HOW IT WORKS: numbered steps, alternating layout -->
|
|
142
|
-
<section class="how-it-works" id="how-it-works" aria-labelledby="hiw-title">
|
|
143
|
-
<div class="container">
|
|
144
|
-
<div class="section-header">
|
|
145
|
-
<span class="section-label">Process</span>
|
|
146
|
-
<h2 class="section-title" id="hiw-title">How it works</h2>
|
|
147
|
-
</div>
|
|
148
|
-
<ol class="steps" role="list">
|
|
149
|
-
<li class="step reveal">
|
|
150
|
-
<span class="step__number" aria-hidden="true">01</span>
|
|
151
|
-
<div class="step__content">
|
|
152
|
-
<h3>Step title</h3>
|
|
153
|
-
<p>Explanation focused on what the user does and gets.</p>
|
|
154
|
-
</div>
|
|
155
|
-
<div class="step__visual">
|
|
156
|
-
<img src="https://images.unsplash.com/photo-[id]?w=600&q=80" alt="[descriptive alt]" loading="lazy">
|
|
157
|
-
</div>
|
|
158
|
-
</li>
|
|
159
|
-
</ol>
|
|
160
|
-
</div>
|
|
161
|
-
</section>
|
|
162
|
-
|
|
163
|
-
<!-- TESTIMONIALS -->
|
|
164
|
-
<section class="testimonials" aria-labelledby="testimonials-title">
|
|
165
|
-
<div class="container">
|
|
166
|
-
<h2 class="section-title" id="testimonials-title">What teams say</h2>
|
|
167
|
-
<div class="testimonials__grid">
|
|
168
|
-
<blockquote class="testimonial-card reveal">
|
|
169
|
-
<p class="testimonial-card__quote">"Specific outcome they achieved using the product."</p>
|
|
170
|
-
<footer class="testimonial-card__author">
|
|
171
|
-
<img src="https://images.unsplash.com/photo-[id]?w=48&h=48&fit=crop&crop=face"
|
|
172
|
-
alt="[Name]" width="48" height="48" loading="lazy">
|
|
173
|
-
<div>
|
|
174
|
-
<cite class="testimonial-card__name">Full Name</cite>
|
|
175
|
-
<span class="testimonial-card__role">Role, Company</span>
|
|
176
|
-
</div>
|
|
177
|
-
</footer>
|
|
178
|
-
</blockquote>
|
|
179
|
-
</div>
|
|
180
|
-
</div>
|
|
181
|
-
</section>
|
|
182
|
-
|
|
183
|
-
<!-- FINAL CTA -->
|
|
184
|
-
<section class="cta-final" id="cta" aria-labelledby="cta-title">
|
|
185
|
-
<div class="container">
|
|
186
|
-
<h2 class="cta-final__title reveal" id="cta-title">Ready to get started?</h2>
|
|
187
|
-
<p class="cta-final__subtitle reveal reveal-delay-1">Join thousands of teams already using [Product].</p>
|
|
188
|
-
<a href="#signup" class="btn btn--primary btn--xl reveal reveal-delay-2">Start for free</a>
|
|
189
|
-
<p class="cta-final__note">No credit card required · Cancel anytime</p>
|
|
190
|
-
</div>
|
|
191
|
-
</section>
|
|
192
|
-
</main>
|
|
193
|
-
|
|
194
|
-
<footer class="footer" role="contentinfo">
|
|
195
|
-
<div class="container footer__inner">
|
|
196
|
-
<a href="/" class="footer__logo" aria-label="Home">ProductName</a>
|
|
197
|
-
<nav class="footer__nav" aria-label="Footer navigation">
|
|
198
|
-
<a href="/privacy">Privacy</a>
|
|
199
|
-
<a href="/terms">Terms</a>
|
|
200
|
-
<a href="/contact">Contact</a>
|
|
201
|
-
</nav>
|
|
202
|
-
<p class="footer__copy">© 2026 ProductName. All rights reserved.</p>
|
|
203
|
-
</div>
|
|
204
|
-
</footer>
|
|
205
|
-
|
|
206
|
-
<!-- Scripts: async, non-blocking -->
|
|
207
|
-
<script async src="main.js"></script>
|
|
208
|
-
</body>
|
|
209
|
-
</html>
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
## 2. CSS Design Systems
|
|
215
|
-
|
|
216
|
-
### 2a. Bold & Cinematic (Dark, AI/Tech, Gradient-rich)
|
|
217
|
-
|
|
218
|
-
```css
|
|
219
|
-
/* === TOKENS === */
|
|
220
|
-
:root {
|
|
221
|
-
/* Background scale */
|
|
222
|
-
--bg-base: hsl(240, 15%, 6%); /* deepest: page bg */
|
|
223
|
-
--bg-surface: hsl(240, 12%, 10%); /* cards, panels */
|
|
224
|
-
--bg-elevated: hsl(240, 10%, 14%); /* modals, popovers */
|
|
225
|
-
--bg-glass: hsla(240, 20%, 100%, 0.06); /* glassmorphism */
|
|
226
|
-
|
|
227
|
-
/* Text scale */
|
|
228
|
-
--text-primary: hsl(220, 30%, 96%);
|
|
229
|
-
--text-secondary: hsl(220, 15%, 70%);
|
|
230
|
-
--text-muted: hsl(220, 10%, 50%);
|
|
231
|
-
|
|
232
|
-
/* Brand & accent */
|
|
233
|
-
--accent-primary: hsl(265, 80%, 65%); /* purple */
|
|
234
|
-
--accent-glow: hsla(265, 80%, 65%, 0.35);
|
|
235
|
-
--accent-alt: hsl(190, 80%, 55%); /* cyan complement */
|
|
236
|
-
--gradient-brand: linear-gradient(135deg, hsl(265, 80%, 65%), hsl(310, 75%, 60%));
|
|
237
|
-
--gradient-hero: linear-gradient(135deg,
|
|
238
|
-
hsla(240, 50%, 8%, 0.95) 0%,
|
|
239
|
-
hsla(265, 60%, 20%, 0.75) 50%,
|
|
240
|
-
hsla(310, 40%, 12%, 0.5) 100%);
|
|
241
|
-
|
|
242
|
-
/* Borders */
|
|
243
|
-
--border-faint: hsla(220, 100%, 90%, 0.07);
|
|
244
|
-
--border-subtle: hsla(220, 100%, 90%, 0.12);
|
|
245
|
-
--border-glow: hsla(265, 80%, 65%, 0.3);
|
|
246
|
-
|
|
247
|
-
/* Spacing */
|
|
248
|
-
--space-xs: 4px; --space-sm: 8px; --space-md: 16px;
|
|
249
|
-
--space-lg: 24px; --space-xl: 40px; --space-2xl: 64px;
|
|
250
|
-
--space-3xl: 96px; --space-4xl: 160px;
|
|
251
|
-
|
|
252
|
-
/* Typography */
|
|
253
|
-
--font-display: 'Space Grotesk', 'Syne', sans-serif;
|
|
254
|
-
--font-body: 'Inter', system-ui, sans-serif;
|
|
255
|
-
--font-mono: 'JetBrains Mono', monospace;
|
|
256
|
-
|
|
257
|
-
/* Type scale */
|
|
258
|
-
--text-sm: 0.875rem; /* 14px */
|
|
259
|
-
--text-base: 1rem; /* 16px */
|
|
260
|
-
--text-lg: 1.125rem; /* 18px */
|
|
261
|
-
--text-xl: 1.25rem; /* 20px */
|
|
262
|
-
--text-2xl: 1.5rem; /* 24px */
|
|
263
|
-
--text-3xl: 1.875rem; /* 30px */
|
|
264
|
-
--text-4xl: 2.25rem; /* 36px */
|
|
265
|
-
--text-5xl: 3rem; /* 48px */
|
|
266
|
-
--text-6xl: 3.75rem; /* 60px */
|
|
267
|
-
--text-7xl: 4.5rem; /* 72px */
|
|
268
|
-
|
|
269
|
-
/* Radius */
|
|
270
|
-
--radius-sm: 6px; --radius-md: 12px; --radius-lg: 20px; --radius-pill: 9999px;
|
|
271
|
-
|
|
272
|
-
/* Motion */
|
|
273
|
-
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
|
274
|
-
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
275
|
-
--duration-fast: 150ms; --duration-base: 250ms; --duration-slow: 400ms;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/* === LAYOUT === */
|
|
279
|
-
.container {
|
|
280
|
-
width: 100%;
|
|
281
|
-
max-width: 1200px;
|
|
282
|
-
margin: 0 auto;
|
|
283
|
-
padding: 0 var(--space-xl);
|
|
284
|
-
}
|
|
285
|
-
@media (max-width: 768px) { .container { padding: 0 var(--space-lg); } }
|
|
286
|
-
|
|
287
|
-
/* === HEADER: glassmorphism, sticky === */
|
|
288
|
-
.header {
|
|
289
|
-
position: sticky; top: 0; left: 0; right: 0; z-index: 100;
|
|
290
|
-
height: 72px;
|
|
291
|
-
backdrop-filter: blur(20px) saturate(180%);
|
|
292
|
-
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
293
|
-
background: hsla(240, 15%, 6%, 0.75);
|
|
294
|
-
border-bottom: 1px solid var(--border-faint);
|
|
295
|
-
transition: background var(--duration-base) ease;
|
|
296
|
-
}
|
|
297
|
-
.header.scrolled { background: hsla(240, 15%, 6%, 0.95); }
|
|
298
|
-
.header__inner {
|
|
299
|
-
height: 100%;
|
|
300
|
-
display: flex; align-items: center; gap: var(--space-xl);
|
|
301
|
-
}
|
|
302
|
-
.header__logo {
|
|
303
|
-
display: flex; align-items: center; gap: var(--space-sm);
|
|
304
|
-
font-family: var(--font-display); font-weight: 700; font-size: var(--text-lg);
|
|
305
|
-
color: var(--text-primary);
|
|
306
|
-
}
|
|
307
|
-
.logo-mark { color: var(--accent-primary); }
|
|
308
|
-
.header__nav {
|
|
309
|
-
display: flex; gap: var(--space-xl);
|
|
310
|
-
margin-left: auto; /* push right */
|
|
311
|
-
}
|
|
312
|
-
.header__nav a {
|
|
313
|
-
font-size: var(--text-sm); font-weight: 500;
|
|
314
|
-
color: var(--text-secondary);
|
|
315
|
-
transition: color var(--duration-fast) ease;
|
|
316
|
-
}
|
|
317
|
-
.header__nav a:hover { color: var(--text-primary); }
|
|
318
|
-
|
|
319
|
-
/* === HERO === */
|
|
320
|
-
.hero {
|
|
321
|
-
position: relative;
|
|
322
|
-
min-height: 100dvh;
|
|
323
|
-
display: flex; align-items: center; justify-content: center;
|
|
324
|
-
overflow: hidden;
|
|
325
|
-
}
|
|
326
|
-
.hero__bg {
|
|
327
|
-
position: absolute; inset: 0; z-index: 0;
|
|
328
|
-
}
|
|
329
|
-
.hero__bg img {
|
|
330
|
-
width: 100%; height: 100%;
|
|
331
|
-
object-fit: cover; object-position: center;
|
|
332
|
-
}
|
|
333
|
-
.hero__overlay {
|
|
334
|
-
position: absolute; inset: 0;
|
|
335
|
-
background: var(--gradient-hero);
|
|
336
|
-
}
|
|
337
|
-
.hero__content {
|
|
338
|
-
position: relative; z-index: 1;
|
|
339
|
-
text-align: center;
|
|
340
|
-
padding: var(--space-4xl) 0;
|
|
341
|
-
}
|
|
342
|
-
.hero__label {
|
|
343
|
-
display: inline-block;
|
|
344
|
-
padding: 6px 16px;
|
|
345
|
-
border-radius: var(--radius-pill);
|
|
346
|
-
border: 1px solid var(--border-glow);
|
|
347
|
-
background: hsla(265, 80%, 65%, 0.1);
|
|
348
|
-
font-size: var(--text-sm); font-weight: 500; letter-spacing: 0.05em; text-transform: uppercase;
|
|
349
|
-
color: var(--accent-primary);
|
|
350
|
-
margin-bottom: var(--space-xl);
|
|
351
|
-
}
|
|
352
|
-
.hero__title {
|
|
353
|
-
font-family: var(--font-display);
|
|
354
|
-
font-size: clamp(var(--text-4xl), 7vw, var(--text-7xl));
|
|
355
|
-
font-weight: 800; line-height: 1.05; letter-spacing: -0.03em;
|
|
356
|
-
color: var(--text-primary);
|
|
357
|
-
margin-bottom: var(--space-lg);
|
|
358
|
-
}
|
|
359
|
-
.hero__subtitle {
|
|
360
|
-
font-size: clamp(var(--text-lg), 2.5vw, var(--text-xl));
|
|
361
|
-
color: var(--text-secondary); line-height: 1.6; max-width: 600px; margin: 0 auto var(--space-xl);
|
|
362
|
-
}
|
|
363
|
-
.hero__actions { display: flex; gap: var(--space-md); justify-content: center; flex-wrap: wrap; }
|
|
364
|
-
|
|
365
|
-
/* Decorative glowing orbs */
|
|
366
|
-
.hero__decor { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
|
|
367
|
-
.orb {
|
|
368
|
-
position: absolute; border-radius: 50%;
|
|
369
|
-
filter: blur(80px); opacity: 0.35;
|
|
370
|
-
}
|
|
371
|
-
.orb--1 {
|
|
372
|
-
width: 600px; height: 600px;
|
|
373
|
-
background: radial-gradient(circle, hsl(265, 80%, 65%), transparent 70%);
|
|
374
|
-
top: -200px; left: -100px;
|
|
375
|
-
}
|
|
376
|
-
.orb--2 {
|
|
377
|
-
width: 400px; height: 400px;
|
|
378
|
-
background: radial-gradient(circle, hsl(190, 80%, 55%), transparent 70%);
|
|
379
|
-
bottom: -100px; right: -50px;
|
|
380
|
-
}
|
|
381
|
-
.orb--3 {
|
|
382
|
-
width: 300px; height: 300px;
|
|
383
|
-
background: radial-gradient(circle, hsl(310, 75%, 60%), transparent 70%);
|
|
384
|
-
top: 50%; left: 50%; transform: translate(-50%, -50%);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
/* === GRADIENT TEXT === */
|
|
388
|
-
.gradient-text {
|
|
389
|
-
background: var(--gradient-brand);
|
|
390
|
-
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
|
|
391
|
-
background-clip: text; display: inline;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
/* === BUTTONS === */
|
|
395
|
-
.btn {
|
|
396
|
-
display: inline-flex; align-items: center; gap: var(--space-sm);
|
|
397
|
-
font-weight: 600; border-radius: var(--radius-md);
|
|
398
|
-
transition: all var(--duration-base) var(--ease-out);
|
|
399
|
-
white-space: nowrap;
|
|
400
|
-
}
|
|
401
|
-
.btn--sm { padding: 8px 16px; font-size: var(--text-sm); }
|
|
402
|
-
.btn--md { padding: 12px 24px; font-size: var(--text-base); }
|
|
403
|
-
.btn--lg { padding: 14px 32px; font-size: var(--text-lg); }
|
|
404
|
-
.btn--xl { padding: 18px 48px; font-size: var(--text-xl); }
|
|
405
|
-
.btn--primary {
|
|
406
|
-
background: var(--gradient-brand);
|
|
407
|
-
color: white;
|
|
408
|
-
box-shadow: 0 0 32px var(--accent-glow), 0 4px 16px rgba(0,0,0,0.3);
|
|
409
|
-
}
|
|
410
|
-
.btn--primary:hover {
|
|
411
|
-
box-shadow: 0 0 48px hsla(265, 80%, 65%, 0.55), 0 8px 24px rgba(0,0,0,0.4);
|
|
412
|
-
transform: translateY(-2px) scale(1.02);
|
|
413
|
-
}
|
|
414
|
-
.btn--primary:active { transform: translateY(0) scale(0.99); }
|
|
415
|
-
.btn--ghost {
|
|
416
|
-
background: var(--bg-glass);
|
|
417
|
-
color: var(--text-primary);
|
|
418
|
-
border: 1px solid var(--border-subtle);
|
|
419
|
-
backdrop-filter: blur(8px);
|
|
420
|
-
}
|
|
421
|
-
.btn--ghost:hover {
|
|
422
|
-
background: hsla(240, 20%, 100%, 0.1);
|
|
423
|
-
border-color: var(--border-glow);
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
/* === GLASSMORPHISM CARDS === */
|
|
427
|
-
.feature-card {
|
|
428
|
-
background: var(--bg-glass);
|
|
429
|
-
border: 1px solid var(--border-faint);
|
|
430
|
-
border-radius: var(--radius-lg);
|
|
431
|
-
padding: var(--space-xl);
|
|
432
|
-
backdrop-filter: blur(16px);
|
|
433
|
-
-webkit-backdrop-filter: blur(16px);
|
|
434
|
-
transition: all var(--duration-base) var(--ease-out);
|
|
435
|
-
position: relative; overflow: hidden;
|
|
436
|
-
}
|
|
437
|
-
.feature-card::before {
|
|
438
|
-
/* Shimmer top border */
|
|
439
|
-
content: '';
|
|
440
|
-
position: absolute; top: 0; left: 0; right: 0; height: 1px;
|
|
441
|
-
background: linear-gradient(90deg, transparent, var(--accent-primary), transparent);
|
|
442
|
-
opacity: 0;
|
|
443
|
-
transition: opacity var(--duration-base) ease;
|
|
444
|
-
}
|
|
445
|
-
.feature-card:hover {
|
|
446
|
-
border-color: var(--border-glow);
|
|
447
|
-
transform: translateY(-4px);
|
|
448
|
-
box-shadow: 0 20px 60px rgba(0,0,0,0.3), 0 0 40px var(--accent-glow);
|
|
449
|
-
}
|
|
450
|
-
.feature-card:hover::before { opacity: 1; }
|
|
451
|
-
.feature-card__icon {
|
|
452
|
-
font-size: var(--text-3xl); margin-bottom: var(--space-md);
|
|
453
|
-
}
|
|
454
|
-
.feature-card__title {
|
|
455
|
-
font-family: var(--font-display); font-size: var(--text-xl); font-weight: 700;
|
|
456
|
-
color: var(--text-primary); margin-bottom: var(--space-sm);
|
|
457
|
-
}
|
|
458
|
-
.feature-card__desc { font-size: var(--text-base); color: var(--text-secondary); line-height: 1.6; }
|
|
459
|
-
|
|
460
|
-
/* Grid: 3 cols → 2 → 1 */
|
|
461
|
-
.features__grid {
|
|
462
|
-
display: grid;
|
|
463
|
-
grid-template-columns: repeat(3, 1fr);
|
|
464
|
-
gap: var(--space-lg);
|
|
465
|
-
margin-top: var(--space-3xl);
|
|
466
|
-
}
|
|
467
|
-
@media (max-width: 900px) { .features__grid { grid-template-columns: repeat(2, 1fr); } }
|
|
468
|
-
@media (max-width: 600px) { .features__grid { grid-template-columns: 1fr; } }
|
|
469
|
-
|
|
470
|
-
/* === ANIMATED GRADIENT BORDER === */
|
|
471
|
-
.card--glow-border {
|
|
472
|
-
position: relative;
|
|
473
|
-
background: var(--bg-surface);
|
|
474
|
-
border-radius: var(--radius-lg);
|
|
475
|
-
}
|
|
476
|
-
.card--glow-border::before {
|
|
477
|
-
content: '';
|
|
478
|
-
position: absolute; inset: -1px;
|
|
479
|
-
border-radius: inherit;
|
|
480
|
-
background: linear-gradient(135deg, hsl(265,80%,65%), hsl(190,80%,55%), hsl(310,75%,60%));
|
|
481
|
-
z-index: -1;
|
|
482
|
-
opacity: 0;
|
|
483
|
-
transition: opacity var(--duration-base) ease;
|
|
484
|
-
}
|
|
485
|
-
.card--glow-border:hover::before { opacity: 1; }
|
|
486
|
-
|
|
487
|
-
/* === SECTION HEADERS === */
|
|
488
|
-
.section-header { text-align: center; max-width: 700px; margin: 0 auto var(--space-3xl); }
|
|
489
|
-
.section-label {
|
|
490
|
-
display: inline-block;
|
|
491
|
-
font-size: var(--text-sm); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
|
|
492
|
-
color: var(--accent-primary); margin-bottom: var(--space-md);
|
|
493
|
-
}
|
|
494
|
-
.section-title {
|
|
495
|
-
font-family: var(--font-display);
|
|
496
|
-
font-size: clamp(var(--text-3xl), 4vw, var(--text-5xl));
|
|
497
|
-
font-weight: 800; line-height: 1.1; letter-spacing: -0.02em;
|
|
498
|
-
color: var(--text-primary); margin-bottom: var(--space-md);
|
|
499
|
-
}
|
|
500
|
-
.section-subtitle { font-size: var(--text-lg); color: var(--text-secondary); line-height: 1.6; }
|
|
501
|
-
|
|
502
|
-
/* Sections padding */
|
|
503
|
-
.features, .how-it-works, .testimonials { padding: var(--space-4xl) 0; }
|
|
504
|
-
|
|
505
|
-
/* Alternating section background */
|
|
506
|
-
.how-it-works {
|
|
507
|
-
background: linear-gradient(180deg, var(--bg-base) 0%, var(--bg-surface) 50%, var(--bg-base) 100%);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
/* === ANGULAR CLIP-PATH DIVIDER === */
|
|
511
|
-
.section--angled {
|
|
512
|
-
clip-path: polygon(0 4%, 100% 0%, 100% 96%, 0 100%);
|
|
513
|
-
margin: -40px 0;
|
|
514
|
-
padding: calc(var(--space-4xl) + 40px) 0;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
/* === TESTIMONIAL CARDS === */
|
|
518
|
-
.testimonials__grid {
|
|
519
|
-
display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-lg);
|
|
520
|
-
}
|
|
521
|
-
.testimonial-card {
|
|
522
|
-
background: var(--bg-surface);
|
|
523
|
-
border: 1px solid var(--border-faint);
|
|
524
|
-
border-radius: var(--radius-lg);
|
|
525
|
-
padding: var(--space-xl);
|
|
526
|
-
transition: border-color var(--duration-base) ease;
|
|
527
|
-
}
|
|
528
|
-
.testimonial-card:hover { border-color: var(--border-glow); }
|
|
529
|
-
.testimonial-card__quote {
|
|
530
|
-
font-size: var(--text-base); line-height: 1.7; color: var(--text-secondary);
|
|
531
|
-
font-style: italic; margin-bottom: var(--space-lg);
|
|
532
|
-
}
|
|
533
|
-
.testimonial-card__quote::before { content: '"'; font-size: var(--text-3xl); color: var(--accent-primary); line-height: 0; vertical-align: -0.4em; margin-right: 4px; }
|
|
534
|
-
.testimonial-card__author { display: flex; align-items: center; gap: var(--space-md); }
|
|
535
|
-
.testimonial-card__author img { border-radius: 50%; border: 2px solid var(--border-subtle); }
|
|
536
|
-
.testimonial-card__name { display: block; font-weight: 600; color: var(--text-primary); }
|
|
537
|
-
.testimonial-card__role { font-size: var(--text-sm); color: var(--text-muted); }
|
|
538
|
-
@media (max-width: 900px) { .testimonials__grid { grid-template-columns: 1fr; } }
|
|
539
|
-
|
|
540
|
-
/* === FINAL CTA === */
|
|
541
|
-
.cta-final {
|
|
542
|
-
text-align: center; padding: var(--space-4xl) 0;
|
|
543
|
-
background: radial-gradient(ellipse 80% 60% at 50% 50%, hsla(265,60%,30%,0.3), transparent);
|
|
544
|
-
border-top: 1px solid var(--border-faint);
|
|
545
|
-
}
|
|
546
|
-
.cta-final__title {
|
|
547
|
-
font-family: var(--font-display);
|
|
548
|
-
font-size: clamp(var(--text-4xl), 5vw, var(--text-6xl));
|
|
549
|
-
font-weight: 800; line-height: 1.1; letter-spacing: -0.02em;
|
|
550
|
-
color: var(--text-primary); margin-bottom: var(--space-md);
|
|
551
|
-
}
|
|
552
|
-
.cta-final__subtitle { font-size: var(--text-xl); color: var(--text-secondary); margin-bottom: var(--space-xl); }
|
|
553
|
-
.cta-final__note { font-size: var(--text-sm); color: var(--text-muted); margin-top: var(--space-md); }
|
|
554
|
-
|
|
555
|
-
/* === FOOTER === */
|
|
556
|
-
.footer {
|
|
557
|
-
background: var(--bg-surface); border-top: 1px solid var(--border-faint);
|
|
558
|
-
padding: var(--space-xl) 0;
|
|
559
|
-
}
|
|
560
|
-
.footer__inner {
|
|
561
|
-
display: flex; align-items: center; gap: var(--space-xl);
|
|
562
|
-
flex-wrap: wrap;
|
|
563
|
-
}
|
|
564
|
-
.footer__logo { font-family: var(--font-display); font-weight: 700; color: var(--text-primary); }
|
|
565
|
-
.footer__nav { display: flex; gap: var(--space-lg); margin-left: auto; }
|
|
566
|
-
.footer__nav a { font-size: var(--text-sm); color: var(--text-muted); transition: color var(--duration-fast) ease; }
|
|
567
|
-
.footer__nav a:hover { color: var(--text-primary); }
|
|
568
|
-
.footer__copy { font-size: var(--text-sm); color: var(--text-muted); }
|
|
569
|
-
|
|
570
|
-
/* === SCROLL REVEAL ANIMATIONS === */
|
|
571
|
-
.reveal {
|
|
572
|
-
animation: fadeUp 0.7s var(--ease-out) both;
|
|
573
|
-
}
|
|
574
|
-
.reveal-delay-1 { animation-delay: 0.1s; }
|
|
575
|
-
.reveal-delay-2 { animation-delay: 0.2s; }
|
|
576
|
-
.reveal-delay-3 { animation-delay: 0.3s; }
|
|
577
|
-
.reveal-delay-4 { animation-delay: 0.4s; }
|
|
578
|
-
@keyframes fadeUp {
|
|
579
|
-
from { opacity: 0; transform: translateY(28px); }
|
|
580
|
-
to { opacity: 1; transform: translateY(0); }
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
/* === COUNTER ANIMATION (hero stats) === */
|
|
584
|
-
.stat-number {
|
|
585
|
-
font-family: var(--font-display); font-size: var(--text-5xl); font-weight: 800;
|
|
586
|
-
background: var(--gradient-brand);
|
|
587
|
-
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
/* === AVATAR GROUP === */
|
|
591
|
-
.avatar-group { display: flex; }
|
|
592
|
-
.avatar-group img {
|
|
593
|
-
width: 32px; height: 32px; border-radius: 50%;
|
|
594
|
-
border: 2px solid var(--bg-base);
|
|
595
|
-
margin-left: -8px;
|
|
596
|
-
}
|
|
597
|
-
.avatar-group img:first-child { margin-left: 0; }
|
|
598
|
-
|
|
599
|
-
/* === STAR RATING === */
|
|
600
|
-
.star-rating { color: hsl(45, 100%, 60%); font-size: var(--text-sm); font-weight: 600; }
|
|
601
|
-
.star-rating span { color: var(--text-secondary); margin-left: 4px; }
|
|
602
|
-
|
|
603
|
-
/* === ACCESSIBILITY === */
|
|
604
|
-
:focus-visible {
|
|
605
|
-
outline: 2px solid var(--accent-primary);
|
|
606
|
-
outline-offset: 3px;
|
|
607
|
-
border-radius: var(--radius-sm);
|
|
608
|
-
}
|
|
609
|
-
.sr-only {
|
|
610
|
-
position: absolute; width: 1px; height: 1px;
|
|
611
|
-
padding: 0; margin: -1px; overflow: hidden;
|
|
612
|
-
clip: rect(0,0,0,0); white-space: nowrap; border: 0;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
/* === REDUCED MOTION === */
|
|
616
|
-
@media (prefers-reduced-motion: reduce) {
|
|
617
|
-
*, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
|
|
618
|
-
}
|
|
619
|
-
```
|
|
620
|
-
|
|
621
|
-
### 2a-extra. Mandatory "Wow" Techniques for Bold & Cinematic
|
|
622
|
-
|
|
623
|
-
These three techniques are **required** — not optional. They separate a premium landing page from a generic dark dashboard.
|
|
624
|
-
|
|
625
|
-
#### Animated mesh background (background breathes)
|
|
626
|
-
|
|
627
|
-
```css
|
|
628
|
-
/* Replace the static mesh with an animated one */
|
|
629
|
-
.hero__bg--mesh {
|
|
630
|
-
position: absolute; inset: 0; z-index: 0;
|
|
631
|
-
background:
|
|
632
|
-
radial-gradient(ellipse 120% 80% at -15% -10%, hsla(265,70%,55%,0.28), transparent 55%),
|
|
633
|
-
radial-gradient(ellipse 100% 70% at 115% 15%, hsla(190,70%,50%,0.25), transparent 50%),
|
|
634
|
-
radial-gradient(ellipse 120% 80% at 50% 110%, hsla(310,65%,55%,0.2), transparent 52%),
|
|
635
|
-
linear-gradient(160deg, hsl(240,18%,6%) 0%, hsl(240,15%,10%) 100%);
|
|
636
|
-
background-size: 200% 200%;
|
|
637
|
-
animation: meshDrift 20s ease infinite alternate;
|
|
638
|
-
}
|
|
639
|
-
@keyframes meshDrift {
|
|
640
|
-
0% { background-position: 0% 0%; }
|
|
641
|
-
33% { background-position: 60% 40%; }
|
|
642
|
-
66% { background-position: 40% 80%; }
|
|
643
|
-
100% { background-position: 100% 100%; }
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
@media (prefers-reduced-motion: reduce) {
|
|
647
|
-
.hero__bg--mesh { animation: none; }
|
|
648
|
-
}
|
|
649
|
-
```
|
|
650
|
-
|
|
651
|
-
**HTML usage:**
|
|
652
|
-
```html
|
|
653
|
-
<section class="hero">
|
|
654
|
-
<div class="hero__bg--mesh" aria-hidden="true"></div>
|
|
655
|
-
<!-- orbs still work on top of this -->
|
|
656
|
-
<div class="hero__decor" aria-hidden="true">
|
|
657
|
-
<div class="orb orb--1"></div>
|
|
658
|
-
<div class="orb orb--2"></div>
|
|
659
|
-
</div>
|
|
660
|
-
<div class="container hero__content"> ... </div>
|
|
661
|
-
</section>
|
|
662
|
-
```
|
|
663
|
-
|
|
2
|
+
name: static-html-patterns
|
|
3
|
+
description: Landing page production guide — HTML structure, CSS systems, animations, and premium patterns. Entry point; load the reference files below based on the current task.
|
|
4
|
+
load_when:
|
|
5
|
+
structure: "HTML skeleton, hero section, semantic structure, page shell, section layout"
|
|
6
|
+
css-tokens: "CSS tokens, design system, Bold & Cinematic, Clean & Luminous, buttons, cards, glassmorphism, gradient text, animated mesh, 3D card tilt"
|
|
7
|
+
motion: "GSAP, ScrollTrigger, scroll animations, hero intro timeline, Swiper, slider, carousel, counter animation"
|
|
8
|
+
premium: "premium patterns, award-worthy, Aigocy, effectFade, marquee logos, SVG paths, hub-and-spoke, scroll progress, split testimonials, progress bar slider, box-black/box-white, FAQ accordion, watermark footer, cursor trail"
|
|
9
|
+
utilities: "performance, lazy loading, fetchpriority, BEM, responsive, accessibility checklist, a11y, Unsplash images, SCSS architecture"
|
|
10
|
+
checklists: "section checklist, pre-delivery, QA, which sections to include, final check"
|
|
11
|
+
skip_if: "app dashboard, admin panel, React/Vue/Next.js component — this skill is for static landing pages only"
|
|
664
12
|
---
|
|
665
13
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
The headline `<em>` or key phrase has a gradient that slowly shifts — subtle but unmistakably premium.
|
|
669
|
-
|
|
670
|
-
```css
|
|
671
|
-
.gradient-text--animated {
|
|
672
|
-
background: linear-gradient(
|
|
673
|
-
135deg,
|
|
674
|
-
var(--accent-primary),
|
|
675
|
-
hsl(190, 80%, 55%),
|
|
676
|
-
hsl(310, 75%, 65%),
|
|
677
|
-
var(--accent-primary)
|
|
678
|
-
);
|
|
679
|
-
background-size: 300% 300%;
|
|
680
|
-
-webkit-background-clip: text;
|
|
681
|
-
-webkit-text-fill-color: transparent;
|
|
682
|
-
background-clip: text;
|
|
683
|
-
display: inline;
|
|
684
|
-
animation: textGradient 8s ease infinite;
|
|
685
|
-
}
|
|
686
|
-
@keyframes textGradient {
|
|
687
|
-
0%, 100% { background-position: 0% 50%; }
|
|
688
|
-
50% { background-position: 100% 50%; }
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
@media (prefers-reduced-motion: reduce) {
|
|
692
|
-
.gradient-text--animated { animation: none; }
|
|
693
|
-
}
|
|
694
|
-
```
|
|
695
|
-
|
|
696
|
-
**HTML usage:**
|
|
697
|
-
```html
|
|
698
|
-
<h1 class="hero__title">
|
|
699
|
-
The fastest way to <em class="gradient-text--animated">ship AI products</em>
|
|
700
|
-
</h1>
|
|
701
|
-
```
|
|
702
|
-
|
|
703
|
-
---
|
|
704
|
-
|
|
705
|
-
#### 3D Card Tilt on hover (cards feel physical)
|
|
706
|
-
|
|
707
|
-
Cards that tilt toward the cursor. One of the strongest single micro-interactions.
|
|
708
|
-
|
|
709
|
-
```css
|
|
710
|
-
/* CSS: enable GPU compositing and smooth reset */
|
|
711
|
-
.feature-card {
|
|
712
|
-
transform-style: preserve-3d;
|
|
713
|
-
transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1),
|
|
714
|
-
box-shadow 0.3s ease;
|
|
715
|
-
will-change: transform;
|
|
716
|
-
}
|
|
717
|
-
```
|
|
718
|
-
|
|
719
|
-
```js
|
|
720
|
-
// JS: 3D tilt on mousemove, smooth reset on mouseleave
|
|
721
|
-
function initCardTilt(selector = '.feature-card') {
|
|
722
|
-
document.querySelectorAll(selector).forEach(card => {
|
|
723
|
-
card.addEventListener('mousemove', e => {
|
|
724
|
-
const r = card.getBoundingClientRect();
|
|
725
|
-
const x = (e.clientX - r.left) / r.width - 0.5; // -0.5 → +0.5
|
|
726
|
-
const y = (e.clientY - r.top) / r.height - 0.5;
|
|
727
|
-
card.style.transition = 'none';
|
|
728
|
-
card.style.transform =
|
|
729
|
-
`perspective(700px) rotateY(${x * 14}deg) rotateX(${-y * 14}deg) translateZ(10px)`;
|
|
730
|
-
});
|
|
731
|
-
card.addEventListener('mouseleave', () => {
|
|
732
|
-
card.style.transition = 'transform 0.6s cubic-bezier(0.16, 1, 0.3, 1)';
|
|
733
|
-
card.style.transform = '';
|
|
734
|
-
});
|
|
735
|
-
});
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
// Initialize on DOM ready
|
|
739
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
740
|
-
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
|
741
|
-
initCardTilt('.feature-card');
|
|
742
|
-
initCardTilt('.tool-card');
|
|
743
|
-
}
|
|
744
|
-
});
|
|
745
|
-
```
|
|
746
|
-
|
|
747
|
-
**Important:** do NOT apply tilt on touch devices:
|
|
748
|
-
```js
|
|
749
|
-
if (window.matchMedia('(hover: none)').matches) return; // skip on touch
|
|
750
|
-
```
|
|
751
|
-
|
|
752
|
-
---
|
|
753
|
-
|
|
754
|
-
### 2b. Clean & Luminous (Light, Apple-like)
|
|
755
|
-
|
|
756
|
-
```css
|
|
757
|
-
:root {
|
|
758
|
-
--bg-base: hsl(0, 0%, 100%);
|
|
759
|
-
--bg-surface: hsl(220, 20%, 97%);
|
|
760
|
-
--bg-sunken: hsl(220, 15%, 94%);
|
|
761
|
-
|
|
762
|
-
--text-primary: hsl(220, 30%, 10%);
|
|
763
|
-
--text-secondary: hsl(220, 15%, 40%);
|
|
764
|
-
--text-muted: hsl(220, 10%, 65%);
|
|
765
|
-
|
|
766
|
-
--accent-primary: hsl(250, 90%, 58%);
|
|
767
|
-
--accent-light: hsla(250, 90%, 58%, 0.1);
|
|
768
|
-
--gradient-brand: linear-gradient(135deg, hsl(250,90%,58%), hsl(280,80%,65%));
|
|
769
|
-
|
|
770
|
-
--border-faint: hsl(220, 20%, 92%);
|
|
771
|
-
--border-subtle: hsl(220, 15%, 86%);
|
|
772
|
-
--shadow-sm: 0 1px 3px hsla(220,30%,10%,0.06), 0 4px 16px hsla(220,30%,10%,0.04);
|
|
773
|
-
--shadow-md: 0 4px 12px hsla(220,30%,10%,0.08), 0 16px 40px hsla(220,30%,10%,0.06);
|
|
774
|
-
--shadow-lg: 0 8px 24px hsla(220,30%,10%,0.1), 0 32px 64px hsla(220,30%,10%,0.08);
|
|
775
|
-
|
|
776
|
-
/* Same spacing/radius/motion tokens as Bold & Cinematic */
|
|
777
|
-
--font-display: 'Plus Jakarta Sans', sans-serif;
|
|
778
|
-
--font-body: 'Plus Jakarta Sans', sans-serif;
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
/* Header: white with subtle border */
|
|
782
|
-
.header {
|
|
783
|
-
background: hsla(0, 0%, 100%, 0.85);
|
|
784
|
-
backdrop-filter: blur(20px);
|
|
785
|
-
border-bottom: 1px solid var(--border-faint);
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
/* Cards with elegant hover */
|
|
789
|
-
.feature-card {
|
|
790
|
-
background: var(--bg-base);
|
|
791
|
-
border: 1px solid var(--border-faint);
|
|
792
|
-
border-radius: var(--radius-lg);
|
|
793
|
-
padding: var(--space-xl);
|
|
794
|
-
box-shadow: var(--shadow-sm);
|
|
795
|
-
transition: box-shadow var(--duration-base) ease, transform var(--duration-base) var(--ease-out);
|
|
796
|
-
}
|
|
797
|
-
.feature-card:hover {
|
|
798
|
-
box-shadow: var(--shadow-md);
|
|
799
|
-
transform: translateY(-4px);
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
/* Accent rule under section titles */
|
|
803
|
-
.section-title::after {
|
|
804
|
-
content: '';
|
|
805
|
-
display: block;
|
|
806
|
-
width: 48px; height: 3px;
|
|
807
|
-
border-radius: 2px;
|
|
808
|
-
background: var(--gradient-brand);
|
|
809
|
-
margin-top: 12px;
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
/* Soft section background alternation */
|
|
813
|
-
.how-it-works { background: var(--bg-surface); }
|
|
814
|
-
```
|
|
815
|
-
|
|
816
|
-
---
|
|
817
|
-
|
|
818
|
-
## 3. Performance Patterns (always apply)
|
|
819
|
-
|
|
820
|
-
```html
|
|
821
|
-
<!-- Critical: preconnect fonts before CSS -->
|
|
822
|
-
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
823
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
824
|
-
|
|
825
|
-
<!-- Hero image: eager + fetchpriority for LCP -->
|
|
826
|
-
<img src="hero.jpg" loading="eager" fetchpriority="high" alt="">
|
|
827
|
-
|
|
828
|
-
<!-- Below-fold images: lazy -->
|
|
829
|
-
<img src="feature.jpg" loading="lazy" alt="[descriptive]">
|
|
830
|
-
|
|
831
|
-
<!-- Non-critical CSS: preload then apply -->
|
|
832
|
-
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
|
833
|
-
<noscript><link rel="stylesheet" href="styles.css"></noscript>
|
|
834
|
-
|
|
835
|
-
<!-- Scripts: always async or defer -->
|
|
836
|
-
<script async src="analytics.js"></script>
|
|
837
|
-
<script defer src="interactions.js"></script>
|
|
838
|
-
```
|
|
839
|
-
|
|
840
|
-
**Critical CSS inline rule:** Only header + hero CSS in `<style>` tag. Everything else in external file.
|
|
841
|
-
|
|
842
|
-
---
|
|
843
|
-
|
|
844
|
-
## 4. Minimal JavaScript (interactions only)
|
|
845
|
-
|
|
846
|
-
```js
|
|
847
|
-
// Header: add .scrolled class after scroll
|
|
848
|
-
window.addEventListener('scroll', () => {
|
|
849
|
-
document.getElementById('header')
|
|
850
|
-
.classList.toggle('scrolled', window.scrollY > 40);
|
|
851
|
-
}, { passive: true });
|
|
852
|
-
|
|
853
|
-
// Mobile menu toggle
|
|
854
|
-
document.querySelector('.header__burger')?.addEventListener('click', function() {
|
|
855
|
-
const expanded = this.getAttribute('aria-expanded') === 'true';
|
|
856
|
-
this.setAttribute('aria-expanded', String(!expanded));
|
|
857
|
-
document.querySelector('.header__nav').classList.toggle('open', !expanded);
|
|
858
|
-
});
|
|
859
|
-
|
|
860
|
-
// Scroll reveal with IntersectionObserver
|
|
861
|
-
const observer = new IntersectionObserver((entries) => {
|
|
862
|
-
entries.forEach(entry => {
|
|
863
|
-
if (entry.isIntersecting) {
|
|
864
|
-
entry.target.classList.add('revealed');
|
|
865
|
-
observer.unobserve(entry.target);
|
|
866
|
-
}
|
|
867
|
-
});
|
|
868
|
-
}, { threshold: 0.15 });
|
|
869
|
-
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
|
|
870
|
-
|
|
871
|
-
// Counter animation (for stats section)
|
|
872
|
-
function animateCounter(el) {
|
|
873
|
-
const target = +el.dataset.target;
|
|
874
|
-
const duration = 1500;
|
|
875
|
-
const start = performance.now();
|
|
876
|
-
requestAnimationFrame(function tick(now) {
|
|
877
|
-
const progress = Math.min((now - start) / duration, 1);
|
|
878
|
-
const eased = 1 - Math.pow(1 - progress, 3); // ease-out cubic
|
|
879
|
-
el.textContent = Math.round(eased * target).toLocaleString();
|
|
880
|
-
if (progress < 1) requestAnimationFrame(tick);
|
|
881
|
-
});
|
|
882
|
-
}
|
|
883
|
-
```
|
|
884
|
-
|
|
885
|
-
---
|
|
886
|
-
|
|
887
|
-
## 5. CSS Naming Convention (BEM-lite)
|
|
888
|
-
|
|
889
|
-
```
|
|
890
|
-
component → .hero, .feature-card, .testimonial-card
|
|
891
|
-
component__element → .hero__title, .feature-card__icon
|
|
892
|
-
component--modifier → .btn--primary, .btn--lg, .card--glow-border
|
|
893
|
-
```
|
|
894
|
-
|
|
895
|
-
Rules:
|
|
896
|
-
- Class names are lowercase, hyphenated
|
|
897
|
-
- No deep nesting in CSS (max 2 levels: `.hero .hero__content`)
|
|
898
|
-
- No `id` for styling — only for anchor links and `aria-labelledby`
|
|
899
|
-
- Utility classes for single-purpose overrides: `.sr-only`, `.reveal`, `.gradient-text`
|
|
900
|
-
|
|
901
|
-
---
|
|
902
|
-
|
|
903
|
-
## 6. Responsive Strategy
|
|
904
|
-
|
|
905
|
-
**Do NOT just reflow columns on mobile. Also:**
|
|
906
|
-
- Hide secondary navigation links → show only logo + CTA + burger
|
|
907
|
-
- Reduce heading sizes with `clamp()` instead of media queries for font-size
|
|
908
|
-
- Stack `.hero__actions` buttons vertically below 480px
|
|
909
|
-
- Remove decorative orbs/blobs on mobile (performance + layout stability)
|
|
910
|
-
- Simplify card grids: 3 → 2 → 1 columns
|
|
911
|
-
- Show testimonials as carousel or stacked, not 3-column grid
|
|
912
|
-
|
|
913
|
-
```css
|
|
914
|
-
/* Prefer clamp() for fluid typography over breakpoint-heavy font-size */
|
|
915
|
-
.hero__title { font-size: clamp(2rem, 6vw, 4.5rem); }
|
|
916
|
-
.section-title { font-size: clamp(1.875rem, 4vw, 3rem); }
|
|
917
|
-
|
|
918
|
-
/* Hide decorative elements on mobile */
|
|
919
|
-
@media (max-width: 768px) {
|
|
920
|
-
.hero__decor { display: none; }
|
|
921
|
-
.header__nav { display: none; }
|
|
922
|
-
.header__nav.open { display: flex; flex-direction: column; }
|
|
923
|
-
.hero__actions { flex-direction: column; align-items: center; }
|
|
924
|
-
}
|
|
925
|
-
```
|
|
926
|
-
|
|
927
|
-
---
|
|
928
|
-
|
|
929
|
-
## 7. Accessibility Checklist (non-negotiable)
|
|
930
|
-
|
|
931
|
-
- [ ] All `<img>` have `alt` — decorative images use `alt=""` + `role="presentation"`
|
|
932
|
-
- [ ] All interactive elements reachable by `Tab` and operable by `Enter`/`Space`
|
|
933
|
-
- [ ] `:focus-visible` styles visible and clear (2px outline, offset, accent color)
|
|
934
|
-
- [ ] All `<button>` have `type="button"` or `type="submit"`
|
|
935
|
-
- [ ] Icon-only buttons have `aria-label`
|
|
936
|
-
- [ ] Sections have `aria-labelledby` pointing to their heading `id`
|
|
937
|
-
- [ ] Color contrast ≥ 4.5:1 for body text, ≥ 3:1 for large text and UI controls
|
|
938
|
-
- [ ] `prefers-reduced-motion: reduce` disables all animations
|
|
939
|
-
- [ ] Mobile menu uses `aria-expanded` toggling
|
|
940
|
-
- [ ] Footer `<nav>` has `aria-label="Footer navigation"` distinct from header nav
|
|
941
|
-
|
|
942
|
-
---
|
|
943
|
-
|
|
944
|
-
## 8. Curated Unsplash Images by Domain
|
|
945
|
-
|
|
946
|
-
Format: `https://images.unsplash.com/photo-{ID}?w=1920&q=80&fit=crop`
|
|
947
|
-
|
|
948
|
-
| Domain | Hero | Feature/Section |
|
|
949
|
-
|---|---|---|
|
|
950
|
-
| Tech/AI/SaaS | `1518770660439-4636190af475` | `1551288049-bebda4e38f71` |
|
|
951
|
-
| Business/Corp | `1497366216548-37526070297c` | `1522071820081-009f0129c71c` |
|
|
952
|
-
| Creative/Agency | `1558618666-fcd25c85cd64` | `1504607798333-52a30db54a5d` |
|
|
953
|
-
| Wellness/Health | `1506905925346-21bda4d32df4` | `1571019613454-1cb2f99b2d8b` |
|
|
954
|
-
| Food/Restaurant | `1414235077428-338989a2e8c0` | `1555939594-58d7cb561ad1` |
|
|
955
|
-
| Architecture | `1486325212027-8081e485255e` | `1460317442991-0ec209397118` |
|
|
956
|
-
| Nature/Travel | `1441974231531-c6227db76b6e` | `1506197603052-3cc9c3a201bd` |
|
|
957
|
-
| People/Teams | `1522202176988-66273c2fd55f` | `1582213782179-e0d53f98f2ca` |
|
|
958
|
-
| Avatars (face) | `1535713875002-d1d0cf377fde` | `1494790108377-be9c29b29330` |
|
|
14
|
+
# Static HTML Patterns — Landing Page Production Guide
|
|
959
15
|
|
|
960
|
-
|
|
16
|
+
> Read this skill when building any landing page (`project_type=site`).
|
|
17
|
+
> This index is ~100 lines. Load only the reference files you need for the current task.
|
|
961
18
|
|
|
962
19
|
---
|
|
963
20
|
|
|
964
|
-
##
|
|
965
|
-
|
|
966
|
-
Source: Aigocy / GSAP ScrollTrigger — gsap.com/docs/v3/Plugins/ScrollTrigger
|
|
967
|
-
|
|
968
|
-
### Setup
|
|
969
|
-
|
|
970
|
-
```html
|
|
971
|
-
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js" defer></script>
|
|
972
|
-
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js" defer></script>
|
|
973
|
-
```
|
|
974
|
-
|
|
975
|
-
```js
|
|
976
|
-
// Register plugin once
|
|
977
|
-
gsap.registerPlugin(ScrollTrigger);
|
|
978
|
-
```
|
|
979
|
-
|
|
980
|
-
### Reusable animation helpers (add to main.js)
|
|
981
|
-
|
|
982
|
-
```js
|
|
983
|
-
// 1. Reveal elements on scroll (fade + translateY)
|
|
984
|
-
function revealOnScroll(selector, options = {}) {
|
|
985
|
-
const els = document.querySelectorAll(selector);
|
|
986
|
-
if (!els.length) return;
|
|
987
|
-
gsap.fromTo(els,
|
|
988
|
-
{ opacity: 0, y: options.y ?? 40 },
|
|
989
|
-
{
|
|
990
|
-
opacity: 1, y: 0,
|
|
991
|
-
duration: options.duration ?? 0.7,
|
|
992
|
-
ease: 'power3.out',
|
|
993
|
-
stagger: options.stagger ?? 0.1,
|
|
994
|
-
scrollTrigger: {
|
|
995
|
-
trigger: els[0].closest('section') ?? els[0],
|
|
996
|
-
start: 'top 80%',
|
|
997
|
-
once: true,
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
);
|
|
1001
|
-
}
|
|
21
|
+
## Loading guide
|
|
1002
22
|
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
23
|
+
| Task | Load |
|
|
24
|
+
|---|---|
|
|
25
|
+
| Building any new page from scratch | `structure.md` + `css-tokens.md` |
|
|
26
|
+
| Setting up CSS tokens and design system | `css-tokens.md` |
|
|
27
|
+
| Adding animations, scroll reveals, or sliders | `motion.md` |
|
|
28
|
+
| Elevating to premium / award-worthy quality | `premium.md` |
|
|
29
|
+
| Performance, a11y, responsive, images, SCSS | `utilities.md` |
|
|
30
|
+
| Planning sections or final QA pass | `checklists.md` |
|
|
31
|
+
| Bold & Cinematic animated mesh, gradient text, 3D tilt | `css-tokens.md` |
|
|
32
|
+
| Three.js particles, WebGL effects | `.aioson/skills/static/threejs-patterns.md` (separate skill) |
|
|
1012
33
|
|
|
1013
|
-
|
|
1014
|
-
function cardsStaggerIn(sectionSelector) {
|
|
1015
|
-
const section = document.querySelector(sectionSelector);
|
|
1016
|
-
if (!section) return;
|
|
1017
|
-
gsap.fromTo(section.querySelectorAll('.card, .feature-card, .service-card'),
|
|
1018
|
-
{ opacity: 0, y: 50, scale: 0.97 },
|
|
1019
|
-
{
|
|
1020
|
-
opacity: 1, y: 0, scale: 1,
|
|
1021
|
-
duration: 0.6, ease: 'power3.out', stagger: 0.1,
|
|
1022
|
-
scrollTrigger: { trigger: section, start: 'top 75%', once: true }
|
|
1023
|
-
}
|
|
1024
|
-
);
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
// 4. Light parallax on hero background
|
|
1028
|
-
function parallaxLight(selector) {
|
|
1029
|
-
gsap.to(selector, {
|
|
1030
|
-
yPercent: 30,
|
|
1031
|
-
ease: 'none',
|
|
1032
|
-
scrollTrigger: { trigger: selector, start: 'top top', end: 'bottom top', scrub: true }
|
|
1033
|
-
});
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
// 5. Counter animation (stats section)
|
|
1037
|
-
function animateCounters() {
|
|
1038
|
-
document.querySelectorAll('[data-counter]').forEach(el => {
|
|
1039
|
-
const target = +el.dataset.counter;
|
|
1040
|
-
ScrollTrigger.create({
|
|
1041
|
-
trigger: el, start: 'top 85%', once: true,
|
|
1042
|
-
onEnter: () => {
|
|
1043
|
-
gsap.fromTo(el,
|
|
1044
|
-
{ textContent: 0 },
|
|
1045
|
-
{
|
|
1046
|
-
textContent: target, duration: 1.5, ease: 'power2.out',
|
|
1047
|
-
snap: { textContent: 1 },
|
|
1048
|
-
onUpdate() { el.textContent = Math.round(+el.textContent).toLocaleString(); }
|
|
1049
|
-
}
|
|
1050
|
-
);
|
|
1051
|
-
}
|
|
1052
|
-
});
|
|
1053
|
-
});
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
// 6. Animated gradient border on hover (section highlight)
|
|
1057
|
-
function initGlowCards() {
|
|
1058
|
-
document.querySelectorAll('.card--glow-border').forEach(card => {
|
|
1059
|
-
card.addEventListener('mousemove', (e) => {
|
|
1060
|
-
const rect = card.getBoundingClientRect();
|
|
1061
|
-
const x = ((e.clientX - rect.left) / rect.width * 100).toFixed(1);
|
|
1062
|
-
const y = ((e.clientY - rect.top) / rect.height * 100).toFixed(1);
|
|
1063
|
-
card.style.setProperty('--mouse-x', `${x}%`);
|
|
1064
|
-
card.style.setProperty('--mouse-y', `${y}%`);
|
|
1065
|
-
});
|
|
1066
|
-
});
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
// Initialize on DOM ready
|
|
1070
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
1071
|
-
heroIntroTimeline();
|
|
1072
|
-
revealOnScroll('.section-header', { y: 30 });
|
|
1073
|
-
revealOnScroll('.step', { stagger: 0.15 });
|
|
1074
|
-
revealOnScroll('.testimonial-card', { stagger: 0.1 });
|
|
1075
|
-
revealOnScroll('.cta-final__title', { y: 20 });
|
|
1076
|
-
cardsStaggerIn('.features');
|
|
1077
|
-
cardsStaggerIn('.services');
|
|
1078
|
-
parallaxLight('.hero__bg img');
|
|
1079
|
-
animateCounters();
|
|
1080
|
-
initGlowCards();
|
|
1081
|
-
});
|
|
1082
|
-
```
|
|
1083
|
-
|
|
1084
|
-
### Anti-patterns to avoid
|
|
1085
|
-
- Do NOT put all scroll animations in one giant master timeline
|
|
1086
|
-
- Do NOT animate `width`, `height`, or `padding` — only `transform` and `opacity`
|
|
1087
|
-
- Do NOT run heavy GSAP work in `scroll` event — always use ScrollTrigger
|
|
1088
|
-
- Always `once: true` for entrance animations (don't re-trigger on scroll up)
|
|
1089
|
-
- Disable GSAP on `prefers-reduced-motion`:
|
|
1090
|
-
|
|
1091
|
-
```js
|
|
1092
|
-
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
|
1093
|
-
gsap.globalTimeline.timeScale(0); // or skip init entirely
|
|
1094
|
-
}
|
|
1095
|
-
```
|
|
34
|
+
Reference files are in `.aioson/skills/static/static-html-patterns/`.
|
|
1096
35
|
|
|
1097
36
|
---
|
|
1098
37
|
|
|
1099
|
-
##
|
|
1100
|
-
|
|
1101
|
-
Source: swiperjs.com/swiper-api
|
|
1102
|
-
|
|
1103
|
-
### CDN
|
|
1104
|
-
|
|
1105
|
-
```html
|
|
1106
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css">
|
|
1107
|
-
<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js" defer></script>
|
|
1108
|
-
```
|
|
38
|
+
## Quick rules (always active)
|
|
1109
39
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
<div class="swiper-slide"><!-- content --></div>
|
|
1116
|
-
<div class="swiper-slide"><!-- content --></div>
|
|
1117
|
-
</div>
|
|
1118
|
-
<div class="swiper-pagination" aria-hidden="true"></div>
|
|
1119
|
-
<button class="swiper-button-prev" aria-label="Previous slide"></button>
|
|
1120
|
-
<button class="swiper-button-next" aria-label="Next slide"></button>
|
|
1121
|
-
</div>
|
|
1122
|
-
```
|
|
1123
|
-
|
|
1124
|
-
### Universal Init (handles multiple sliders via data-attribute)
|
|
1125
|
-
|
|
1126
|
-
```js
|
|
1127
|
-
document.querySelectorAll('.swiper').forEach(el => {
|
|
1128
|
-
const options = el.dataset.swiperOptions ? JSON.parse(el.dataset.swiperOptions) : {};
|
|
1129
|
-
new Swiper(el, {
|
|
1130
|
-
loop: true,
|
|
1131
|
-
navigation: { nextEl: el.querySelector('.swiper-button-next'), prevEl: el.querySelector('.swiper-button-prev') },
|
|
1132
|
-
pagination: { el: el.querySelector('.swiper-pagination'), clickable: true },
|
|
1133
|
-
a11y: { prevSlideMessage: 'Previous slide', nextSlideMessage: 'Next slide' },
|
|
1134
|
-
breakpoints: {
|
|
1135
|
-
768: { slidesPerView: 2, spaceBetween: 24 },
|
|
1136
|
-
1024: { slidesPerView: 3, spaceBetween: 32 },
|
|
1137
|
-
},
|
|
1138
|
-
...options, // data-attribute options override defaults
|
|
1139
|
-
});
|
|
1140
|
-
});
|
|
1141
|
-
```
|
|
1142
|
-
|
|
1143
|
-
### CSS: fix slider CLS (layout shift)
|
|
1144
|
-
|
|
1145
|
-
```css
|
|
1146
|
-
.swiper { overflow: hidden; }
|
|
1147
|
-
.swiper-wrapper { display: flex; align-items: stretch; }
|
|
1148
|
-
.swiper-slide { height: auto; } /* equal height cards */
|
|
1149
|
-
```
|
|
40
|
+
- **Hero law:** the hero is NEVER a grid of cards. Full viewport, animated background, ONE headline, TWO buttons. See `structure.md` Section 0.
|
|
41
|
+
- **Bold & Cinematic mandatory trio:** animated mesh + animated gradient text + 3D card tilt. All three required. See `css-tokens.md` Section 2a-extra.
|
|
42
|
+
- **Three.js is always additive** — it enhances background/scene layer only. The CSS/design skill tokens govern everything else.
|
|
43
|
+
- **No placeholder text in final output.** Real copy or nothing.
|
|
44
|
+
- **`prefers-reduced-motion: reduce`** must disable all animations, every time.
|
|
1150
45
|
|
|
1151
46
|
---
|
|
1152
47
|
|
|
1153
|
-
##
|
|
1154
|
-
|
|
1155
|
-
```
|
|
1156
|
-
assets/scss/
|
|
1157
|
-
base/
|
|
1158
|
-
_reset.scss ← minimal reset + box-model
|
|
1159
|
-
_typography.scss ← font imports, type scale, body
|
|
1160
|
-
_helpers.scss ← .sr-only, .reveal, .gradient-text, .container
|
|
1161
|
-
tokens/
|
|
1162
|
-
_colors.scss ← CSS custom properties :root block
|
|
1163
|
-
_spacing.scss ← --space-* tokens
|
|
1164
|
-
_typography.scss ← --font-*, --text-* tokens
|
|
1165
|
-
_motion.scss ← --ease-*, --duration-* tokens
|
|
1166
|
-
layout/
|
|
1167
|
-
_header.scss
|
|
1168
|
-
_footer.scss
|
|
1169
|
-
_grid.scss
|
|
1170
|
-
components/
|
|
1171
|
-
_buttons.scss
|
|
1172
|
-
_cards.scss
|
|
1173
|
-
_forms.scss
|
|
1174
|
-
_modal.scss
|
|
1175
|
-
_accordion.scss
|
|
1176
|
-
_slider.scss
|
|
1177
|
-
sections/
|
|
1178
|
-
_hero.scss
|
|
1179
|
-
_features.scss
|
|
1180
|
-
_how-it-works.scss
|
|
1181
|
-
_testimonials.scss
|
|
1182
|
-
_pricing.scss
|
|
1183
|
-
_faq.scss
|
|
1184
|
-
_cta-final.scss
|
|
1185
|
-
main.scss ← @forward all partials in order
|
|
1186
|
-
```
|
|
48
|
+
## 15. When CSS Is Not Enough — Three.js WebGL Patterns
|
|
1187
49
|
|
|
1188
|
-
|
|
50
|
+
The patterns above (Sections 1–14) cover 95% of landing page visual needs.
|
|
51
|
+
When the user explicitly requests particle systems, WebGL scenes, holographic effects,
|
|
52
|
+
interactive 3D objects, or scroll-driven 3D camera movement:
|
|
1189
53
|
|
|
1190
|
-
|
|
54
|
+
**Load `.aioson/skills/static/threejs-patterns.md` instead.**
|
|
1191
55
|
|
|
1192
|
-
|
|
56
|
+
This is on-demand — never auto-loaded. The triggers are:
|
|
57
|
+
- "3D", "WebGL", "three.js", "Three.js"
|
|
58
|
+
- "partículas", "particles", "particle system"
|
|
59
|
+
- "cena 3D", "3D scene", "objeto 3D interativo"
|
|
60
|
+
- "holográfico", "holographic", "hologram effect"
|
|
61
|
+
- "floating objects", "3D cards", "3D background"
|
|
62
|
+
- Any explicit request for WebGL or Three.js CDN patterns
|
|
1193
63
|
|
|
1194
|
-
|
|
64
|
+
**Decision guide — CSS vs Three.js:**
|
|
1195
65
|
|
|
1196
|
-
|
|
|
66
|
+
| Effect needed | CSS approach | Three.js needed? |
|
|
1197
67
|
|---|---|---|
|
|
1198
|
-
|
|
|
1199
|
-
|
|
|
1200
|
-
|
|
|
1201
|
-
|
|
|
1202
|
-
|
|
|
1203
|
-
|
|
|
1204
|
-
|
|
|
1205
|
-
|
|
|
1206
|
-
|
|
|
1207
|
-
|
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
**For MICRO landing pages (single page, simple product):** sections 1, 2, 4, 9, 12, 13.
|
|
1213
|
-
|
|
1214
|
-
---
|
|
1215
|
-
|
|
1216
|
-
## 13. Pre-delivery Checklist
|
|
1217
|
-
|
|
1218
|
-
- [ ] Mobile menu opens/closes, body scroll locked when open
|
|
1219
|
-
- [ ] Sliders have correct breakpoints and accessible buttons
|
|
1220
|
-
- [ ] GSAP scroll animations work on mobile (use `start: 'top 85%'` for shorter viewports)
|
|
1221
|
-
- [ ] Hero image loads eagerly with `fetchpriority="high"`, all others `loading="lazy"`
|
|
1222
|
-
- [ ] No layout shift (CLS): img/video elements have explicit width+height
|
|
1223
|
-
- [ ] `prefers-reduced-motion: reduce` disables all animations
|
|
1224
|
-
- [ ] All interactive elements reachable by keyboard
|
|
1225
|
-
- [ ] Color contrast ≥ 4.5:1 checked
|
|
1226
|
-
- [ ] `<title>` and `<meta description>` are real content (not placeholders)
|
|
1227
|
-
- [ ] Open Graph meta tags present (`og:title`, `og:description`, `og:image`)
|
|
1228
|
-
- [ ] No placeholder text remains anywhere in the HTML
|
|
1229
|
-
|
|
1230
|
-
---
|
|
1231
|
-
|
|
1232
|
-
## 14. Premium Template Patterns (Aigocy-style)
|
|
1233
|
-
|
|
1234
|
-
Real patterns extracted from a production AI agency template (ThemeForest #61450410).
|
|
1235
|
-
Use these to elevate landing pages from "nice" to "award-worthy".
|
|
1236
|
-
|
|
1237
|
-
---
|
|
1238
|
-
|
|
1239
|
-
### 14a. effectFade Animations (signature 3D entrance)
|
|
1240
|
-
|
|
1241
|
-
Two animation modes used by the Aigocy template — add these classes to any element
|
|
1242
|
-
and trigger via GSAP ScrollTrigger or IntersectionObserver.
|
|
1243
|
-
|
|
1244
|
-
**HTML markup:**
|
|
1245
|
-
```html
|
|
1246
|
-
<!-- Simple fade up — most common -->
|
|
1247
|
-
<h2 class="effectFade fadeUp" data-delay="0">Headline</h2>
|
|
1248
|
-
<p class="effectFade fadeUp" data-delay="0.15">Supporting text</p>
|
|
1249
|
-
|
|
1250
|
-
<!-- 3D perspective rotate — signature "cinematic" entrance -->
|
|
1251
|
-
<div class="effectFade fadeRotateX" data-delay="0.1">Card content</div>
|
|
1252
|
-
```
|
|
1253
|
-
|
|
1254
|
-
**CSS:**
|
|
1255
|
-
```css
|
|
1256
|
-
/* Base state (invisible, ready to animate in) */
|
|
1257
|
-
.effectFade { opacity: 0; }
|
|
1258
|
-
.effectFade.fadeUp { transform: translateY(50px); }
|
|
1259
|
-
.effectFade.fadeRotateX {
|
|
1260
|
-
transform: perspective(800px) rotateX(25deg) translateY(40px);
|
|
1261
|
-
transform-origin: 50% 0%;
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
/* Animated state (JS adds .animated class) */
|
|
1265
|
-
.effectFade.animated {
|
|
1266
|
-
opacity: 1;
|
|
1267
|
-
transform: none;
|
|
1268
|
-
transition: opacity 0.7s ease, transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
|
|
1269
|
-
}
|
|
1270
|
-
```
|
|
1271
|
-
|
|
1272
|
-
**JS (GSAP + data-delay stagger):**
|
|
1273
|
-
```js
|
|
1274
|
-
// Use data-delay for precise per-element stagger control
|
|
1275
|
-
gsap.utils.toArray('.effectFade').forEach(el => {
|
|
1276
|
-
const delay = parseFloat(el.dataset.delay ?? '0');
|
|
1277
|
-
gsap.fromTo(el,
|
|
1278
|
-
{ opacity: 0, y: el.classList.contains('fadeUp') ? 50 : 0,
|
|
1279
|
-
rotateX: el.classList.contains('fadeRotateX') ? 25 : 0,
|
|
1280
|
-
transformPerspective: 800, transformOrigin: '50% 0%' },
|
|
1281
|
-
{
|
|
1282
|
-
opacity: 1, y: 0, rotateX: 0,
|
|
1283
|
-
duration: 0.8, delay, ease: 'power3.out',
|
|
1284
|
-
scrollTrigger: { trigger: el, start: 'top 85%', once: true }
|
|
1285
|
-
}
|
|
1286
|
-
);
|
|
1287
|
-
});
|
|
1288
|
-
```
|
|
1289
|
-
|
|
1290
|
-
---
|
|
1291
|
-
|
|
1292
|
-
### 14b. Infinite Logo Marquee (CSS only, no library)
|
|
1293
|
-
|
|
1294
|
-
Infinitely scrolling partner/client logo bar. Works with just CSS — no JS needed.
|
|
1295
|
-
Duplicating the list items (`data-clone` attribute in Aigocy) prevents gaps.
|
|
1296
|
-
|
|
1297
|
-
**HTML:**
|
|
1298
|
-
```html
|
|
1299
|
-
<section class="logos-marquee" aria-label="Trusted by">
|
|
1300
|
-
<div class="marquee-track">
|
|
1301
|
-
<!-- Original items -->
|
|
1302
|
-
<ul class="marquee-list" aria-hidden="false">
|
|
1303
|
-
<li><img src="logo-1.svg" alt="Company A" height="32"></li>
|
|
1304
|
-
<li><img src="logo-2.svg" alt="Company B" height="32"></li>
|
|
1305
|
-
<li><img src="logo-3.svg" alt="Company C" height="32"></li>
|
|
1306
|
-
<li><img src="logo-4.svg" alt="Company D" height="32"></li>
|
|
1307
|
-
<li><img src="logo-5.svg" alt="Company E" height="32"></li>
|
|
1308
|
-
</ul>
|
|
1309
|
-
<!-- Cloned items for seamless loop (aria-hidden) -->
|
|
1310
|
-
<ul class="marquee-list" aria-hidden="true">
|
|
1311
|
-
<!-- same items, duplicated -->
|
|
1312
|
-
</ul>
|
|
1313
|
-
</div>
|
|
1314
|
-
</section>
|
|
1315
|
-
```
|
|
1316
|
-
|
|
1317
|
-
**CSS:**
|
|
1318
|
-
```css
|
|
1319
|
-
.logos-marquee { overflow: hidden; padding: var(--space-xl) 0; }
|
|
1320
|
-
|
|
1321
|
-
.marquee-track {
|
|
1322
|
-
display: flex;
|
|
1323
|
-
width: max-content;
|
|
1324
|
-
animation: infiniteSlide 24s linear infinite;
|
|
1325
|
-
}
|
|
1326
|
-
|
|
1327
|
-
.marquee-list {
|
|
1328
|
-
display: flex; align-items: center; gap: 64px;
|
|
1329
|
-
list-style: none; padding: 0 32px;
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
.marquee-list img {
|
|
1333
|
-
height: 32px; width: auto;
|
|
1334
|
-
filter: grayscale(1) opacity(0.5);
|
|
1335
|
-
transition: filter 0.3s ease;
|
|
1336
|
-
}
|
|
1337
|
-
.marquee-list img:hover {
|
|
1338
|
-
filter: grayscale(0) opacity(1);
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
@keyframes infiniteSlide {
|
|
1342
|
-
from { transform: translateX(0); }
|
|
1343
|
-
to { transform: translateX(-50%); } /* -50% because track = 2× list width */
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
/* Pause on hover for accessibility */
|
|
1347
|
-
.logos-marquee:hover .marquee-track { animation-play-state: paused; }
|
|
1348
|
-
|
|
1349
|
-
@media (prefers-reduced-motion: reduce) {
|
|
1350
|
-
.marquee-track { animation: none; }
|
|
1351
|
-
}
|
|
1352
|
-
```
|
|
1353
|
-
|
|
1354
|
-
**JS (optional: auto-clone):**
|
|
1355
|
-
```js
|
|
1356
|
-
// Auto-clone the list so you only maintain one set of logos in HTML
|
|
1357
|
-
document.querySelectorAll('.marquee-track').forEach(track => {
|
|
1358
|
-
const list = track.querySelector('.marquee-list');
|
|
1359
|
-
const clone = list.cloneNode(true);
|
|
1360
|
-
clone.setAttribute('aria-hidden', 'true');
|
|
1361
|
-
track.appendChild(clone);
|
|
1362
|
-
});
|
|
1363
|
-
```
|
|
1364
|
-
|
|
1365
|
-
---
|
|
1366
|
-
|
|
1367
|
-
### 14c. SVG Animated Paths (hub-and-spoke diagram)
|
|
1368
|
-
|
|
1369
|
-
Dots traveling along SVG paths connecting a center image to surrounding icons.
|
|
1370
|
-
Pure SMIL animation — no JS or GSAP needed. Great for "how it works" or "integrations" sections.
|
|
1371
|
-
|
|
1372
|
-
**HTML:**
|
|
1373
|
-
```html
|
|
1374
|
-
<div class="tools-hub" aria-hidden="true">
|
|
1375
|
-
<!-- Center image -->
|
|
1376
|
-
<div class="hub-center">
|
|
1377
|
-
<img src="product-logo.svg" alt="">
|
|
1378
|
-
</div>
|
|
1379
|
-
|
|
1380
|
-
<!-- Surrounding tool icons (positioned absolutely) -->
|
|
1381
|
-
<div class="tool-item tool-item--1"><img src="icon-1.svg" alt=""></div>
|
|
1382
|
-
<div class="tool-item tool-item--2"><img src="icon-2.svg" alt=""></div>
|
|
1383
|
-
<div class="tool-item tool-item--3"><img src="icon-3.svg" alt=""></div>
|
|
1384
|
-
|
|
1385
|
-
<!-- SVG paths with animated dots -->
|
|
1386
|
-
<svg class="hub-svg" viewBox="0 0 600 600" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1387
|
-
<!-- Path from center to tool-1 -->
|
|
1388
|
-
<path id="path-1" d="M300 300 C 240 240, 160 200, 100 160" stroke="hsla(265,80%,65%,0.3)" stroke-width="1" fill="none"/>
|
|
1389
|
-
<circle r="4" fill="hsl(265,80%,65%)">
|
|
1390
|
-
<animateMotion dur="3s" repeatCount="indefinite" begin="0s">
|
|
1391
|
-
<mpath href="#path-1"/>
|
|
1392
|
-
</animateMotion>
|
|
1393
|
-
</circle>
|
|
1394
|
-
|
|
1395
|
-
<!-- Path from center to tool-2 -->
|
|
1396
|
-
<path id="path-2" d="M300 300 C 360 240, 440 200, 500 160" stroke="hsla(265,80%,65%,0.3)" stroke-width="1" fill="none"/>
|
|
1397
|
-
<circle r="4" fill="hsl(310,75%,60%)">
|
|
1398
|
-
<animateMotion dur="4s" repeatCount="indefinite" begin="1s">
|
|
1399
|
-
<mpath href="#path-2"/>
|
|
1400
|
-
</animateMotion>
|
|
1401
|
-
</circle>
|
|
1402
|
-
</svg>
|
|
1403
|
-
</div>
|
|
1404
|
-
```
|
|
1405
|
-
|
|
1406
|
-
**CSS:**
|
|
1407
|
-
```css
|
|
1408
|
-
.tools-hub {
|
|
1409
|
-
position: relative; width: 600px; height: 600px;
|
|
1410
|
-
margin: 0 auto;
|
|
1411
|
-
}
|
|
1412
|
-
.hub-center {
|
|
1413
|
-
position: absolute; top: 50%; left: 50%;
|
|
1414
|
-
transform: translate(-50%, -50%);
|
|
1415
|
-
width: 120px; height: 120px;
|
|
1416
|
-
border-radius: 50%;
|
|
1417
|
-
background: var(--bg-surface);
|
|
1418
|
-
border: 1px solid var(--border-subtle);
|
|
1419
|
-
display: flex; align-items: center; justify-content: center;
|
|
1420
|
-
}
|
|
1421
|
-
.tool-item {
|
|
1422
|
-
position: absolute;
|
|
1423
|
-
width: 64px; height: 64px;
|
|
1424
|
-
border-radius: var(--radius-md);
|
|
1425
|
-
background: var(--bg-elevated);
|
|
1426
|
-
border: 1px solid var(--border-faint);
|
|
1427
|
-
display: flex; align-items: center; justify-content: center;
|
|
1428
|
-
}
|
|
1429
|
-
/* Position items around the hub */
|
|
1430
|
-
.tool-item--1 { top: 8%; left: 8%; }
|
|
1431
|
-
.tool-item--2 { top: 8%; right: 8%; }
|
|
1432
|
-
.tool-item--3 { bottom: 8%; left: 50%; transform: translateX(-50%); }
|
|
1433
|
-
|
|
1434
|
-
.hub-svg {
|
|
1435
|
-
position: absolute; inset: 0;
|
|
1436
|
-
width: 100%; height: 100%;
|
|
1437
|
-
pointer-events: none;
|
|
1438
|
-
}
|
|
1439
|
-
|
|
1440
|
-
@media (max-width: 768px) { .tools-hub { display: none; } /* hide on mobile */ }
|
|
1441
|
-
```
|
|
1442
|
-
|
|
1443
|
-
---
|
|
1444
|
-
|
|
1445
|
-
### 14d. Scroll-to-top with Circular Progress
|
|
1446
|
-
|
|
1447
|
-
A back-to-top button that shows reading progress as a circular arc.
|
|
1448
|
-
Uses a CSS custom property `--progress-angle` updated by JS.
|
|
1449
|
-
|
|
1450
|
-
**HTML:**
|
|
1451
|
-
```html
|
|
1452
|
-
<button class="scroll-top" id="goTop" aria-label="Back to top" title="Back to top">
|
|
1453
|
-
<svg class="scroll-top__ring" viewBox="0 0 48 48" aria-hidden="true">
|
|
1454
|
-
<circle class="scroll-top__track" cx="24" cy="24" r="20" fill="none" stroke-width="2"/>
|
|
1455
|
-
<circle class="scroll-top__progress" cx="24" cy="24" r="20" fill="none" stroke-width="2"
|
|
1456
|
-
style="stroke-dasharray: 125.66; stroke-dashoffset: var(--dash-offset, 125.66)"/>
|
|
1457
|
-
</svg>
|
|
1458
|
-
<span class="scroll-top__icon" aria-hidden="true">↑</span>
|
|
1459
|
-
</button>
|
|
1460
|
-
```
|
|
1461
|
-
|
|
1462
|
-
**CSS:**
|
|
1463
|
-
```css
|
|
1464
|
-
.scroll-top {
|
|
1465
|
-
position: fixed; bottom: 32px; right: 32px; z-index: 50;
|
|
1466
|
-
width: 48px; height: 48px;
|
|
1467
|
-
border-radius: 50%;
|
|
1468
|
-
background: var(--bg-surface);
|
|
1469
|
-
border: 1px solid var(--border-subtle);
|
|
1470
|
-
display: flex; align-items: center; justify-content: center;
|
|
1471
|
-
opacity: 0; pointer-events: none;
|
|
1472
|
-
transition: opacity 0.3s ease, transform 0.2s ease;
|
|
1473
|
-
}
|
|
1474
|
-
.scroll-top.visible { opacity: 1; pointer-events: auto; }
|
|
1475
|
-
.scroll-top:hover { transform: translateY(-2px); }
|
|
1476
|
-
|
|
1477
|
-
.scroll-top__ring {
|
|
1478
|
-
position: absolute; inset: 0;
|
|
1479
|
-
transform: rotate(-90deg); /* start progress from top */
|
|
1480
|
-
}
|
|
1481
|
-
.scroll-top__track { stroke: var(--border-faint); }
|
|
1482
|
-
.scroll-top__progress {
|
|
1483
|
-
stroke: var(--accent-primary);
|
|
1484
|
-
transition: stroke-dashoffset 0.1s linear;
|
|
1485
|
-
}
|
|
1486
|
-
.scroll-top__icon {
|
|
1487
|
-
font-size: 18px; font-weight: 700;
|
|
1488
|
-
color: var(--text-primary); line-height: 1;
|
|
1489
|
-
}
|
|
1490
|
-
```
|
|
1491
|
-
|
|
1492
|
-
**JS:**
|
|
1493
|
-
```js
|
|
1494
|
-
const goTop = document.getElementById('goTop');
|
|
1495
|
-
const progressCircle = goTop?.querySelector('.scroll-top__progress');
|
|
1496
|
-
const circumference = 125.66; // 2π × r (r=20)
|
|
1497
|
-
|
|
1498
|
-
window.addEventListener('scroll', () => {
|
|
1499
|
-
const scrolled = window.scrollY;
|
|
1500
|
-
const total = document.body.scrollHeight - window.innerHeight;
|
|
1501
|
-
const progress = scrolled / total;
|
|
1502
|
-
const offset = circumference * (1 - progress);
|
|
1503
|
-
|
|
1504
|
-
goTop?.classList.toggle('visible', scrolled > 300);
|
|
1505
|
-
progressCircle?.style.setProperty('--dash-offset', offset);
|
|
1506
|
-
}, { passive: true });
|
|
1507
|
-
|
|
1508
|
-
goTop?.addEventListener('click', () =>
|
|
1509
|
-
window.scrollTo({ top: 0, behavior: 'smooth' })
|
|
1510
|
-
);
|
|
1511
|
-
```
|
|
1512
|
-
|
|
1513
|
-
---
|
|
1514
|
-
|
|
1515
|
-
### 14e. Split Swiper (synchronized text + image sliders)
|
|
1516
|
-
|
|
1517
|
-
Two separate Swiper instances that scroll together — one shows testimonial text,
|
|
1518
|
-
the other shows the matching portrait. Classic premium agency pattern.
|
|
1519
|
-
|
|
1520
|
-
**HTML:**
|
|
1521
|
-
```html
|
|
1522
|
-
<section class="split-testimonials">
|
|
1523
|
-
<div class="container split-testimonials__grid">
|
|
1524
|
-
<!-- Left: text slides -->
|
|
1525
|
-
<div class="swiper testimonials-text-swiper">
|
|
1526
|
-
<div class="swiper-wrapper">
|
|
1527
|
-
<div class="swiper-slide">
|
|
1528
|
-
<blockquote class="split-quote">
|
|
1529
|
-
<p>"This is the most impactful tool we've adopted this year. Our team velocity doubled."</p>
|
|
1530
|
-
<footer>
|
|
1531
|
-
<cite class="split-quote__name">Maria Silva</cite>
|
|
1532
|
-
<span class="split-quote__role">CTO, Acme Corp</span>
|
|
1533
|
-
</footer>
|
|
1534
|
-
</blockquote>
|
|
1535
|
-
</div>
|
|
1536
|
-
<!-- more slides -->
|
|
1537
|
-
</div>
|
|
1538
|
-
<div class="split-testimonials__controls">
|
|
1539
|
-
<button class="swiper-button-prev" aria-label="Previous testimonial"></button>
|
|
1540
|
-
<div class="swiper-pagination"></div>
|
|
1541
|
-
<button class="swiper-button-next" aria-label="Next testimonial"></button>
|
|
1542
|
-
</div>
|
|
1543
|
-
</div>
|
|
1544
|
-
|
|
1545
|
-
<!-- Right: image slides (synchronized) -->
|
|
1546
|
-
<div class="swiper testimonials-image-swiper">
|
|
1547
|
-
<div class="swiper-wrapper">
|
|
1548
|
-
<div class="swiper-slide">
|
|
1549
|
-
<img src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=480&h=560&fit=crop&crop=face"
|
|
1550
|
-
alt="Maria Silva" loading="lazy">
|
|
1551
|
-
</div>
|
|
1552
|
-
<!-- more slides -->
|
|
1553
|
-
</div>
|
|
1554
|
-
</div>
|
|
1555
|
-
</div>
|
|
1556
|
-
</section>
|
|
1557
|
-
```
|
|
1558
|
-
|
|
1559
|
-
**CSS:**
|
|
1560
|
-
```css
|
|
1561
|
-
.split-testimonials__grid {
|
|
1562
|
-
display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3xl);
|
|
1563
|
-
align-items: center;
|
|
1564
|
-
}
|
|
1565
|
-
.split-quote p {
|
|
1566
|
-
font-size: var(--text-xl); line-height: 1.7;
|
|
1567
|
-
color: var(--text-secondary); font-style: italic;
|
|
1568
|
-
margin-bottom: var(--space-xl);
|
|
1569
|
-
}
|
|
1570
|
-
.split-quote::before { content: '"'; font-size: 80px; color: var(--accent-primary); line-height: 0.6; display: block; }
|
|
1571
|
-
.split-quote__name { display: block; font-weight: 700; color: var(--text-primary); }
|
|
1572
|
-
.split-quote__role { font-size: var(--text-sm); color: var(--text-muted); }
|
|
1573
|
-
|
|
1574
|
-
.testimonials-image-swiper img {
|
|
1575
|
-
border-radius: var(--radius-lg); width: 100%; height: 480px; object-fit: cover;
|
|
1576
|
-
}
|
|
1577
|
-
|
|
1578
|
-
.split-testimonials__controls {
|
|
1579
|
-
display: flex; align-items: center; gap: var(--space-md); margin-top: var(--space-xl);
|
|
1580
|
-
}
|
|
1581
|
-
|
|
1582
|
-
@media (max-width: 768px) {
|
|
1583
|
-
.split-testimonials__grid { grid-template-columns: 1fr; }
|
|
1584
|
-
.testimonials-image-swiper { display: none; }
|
|
1585
|
-
}
|
|
1586
|
-
```
|
|
1587
|
-
|
|
1588
|
-
**JS:**
|
|
1589
|
-
```js
|
|
1590
|
-
const textSwiper = new Swiper('.testimonials-text-swiper', {
|
|
1591
|
-
loop: true,
|
|
1592
|
-
navigation: {
|
|
1593
|
-
nextEl: '.testimonials-text-swiper .swiper-button-next',
|
|
1594
|
-
prevEl: '.testimonials-text-swiper .swiper-button-prev',
|
|
1595
|
-
},
|
|
1596
|
-
pagination: { el: '.testimonials-text-swiper .swiper-pagination', clickable: true },
|
|
1597
|
-
});
|
|
1598
|
-
|
|
1599
|
-
const imageSwiper = new Swiper('.testimonials-image-swiper', {
|
|
1600
|
-
loop: true,
|
|
1601
|
-
allowTouchMove: false, // image slider is controlled only by text slider
|
|
1602
|
-
effect: 'fade', fadeEffect: { crossFade: true },
|
|
1603
|
-
});
|
|
1604
|
-
|
|
1605
|
-
// Synchronize: text controls image
|
|
1606
|
-
textSwiper.on('slideChange', () => {
|
|
1607
|
-
imageSwiper.slideTo(textSwiper.realIndex);
|
|
1608
|
-
});
|
|
1609
|
-
```
|
|
1610
|
-
|
|
1611
|
-
---
|
|
1612
|
-
|
|
1613
|
-
### 14f. Swiper with Progress Bar Navigation
|
|
1614
|
-
|
|
1615
|
-
Instead of dots, show a thin animated progress bar for long testimonial or case study sliders.
|
|
1616
|
-
|
|
1617
|
-
**HTML:**
|
|
1618
|
-
```html
|
|
1619
|
-
<div class="swiper portfolio-swiper">
|
|
1620
|
-
<div class="swiper-wrapper">
|
|
1621
|
-
<!-- slides -->
|
|
1622
|
-
</div>
|
|
1623
|
-
<div class="swiper-progress-bar" aria-hidden="true">
|
|
1624
|
-
<div class="swiper-progress-fill"></div>
|
|
1625
|
-
</div>
|
|
1626
|
-
<div class="swiper-nav">
|
|
1627
|
-
<button class="swiper-button-prev" aria-label="Previous"></button>
|
|
1628
|
-
<button class="swiper-button-next" aria-label="Next"></button>
|
|
1629
|
-
</div>
|
|
1630
|
-
</div>
|
|
1631
|
-
```
|
|
1632
|
-
|
|
1633
|
-
**CSS:**
|
|
1634
|
-
```css
|
|
1635
|
-
.swiper-progress-bar {
|
|
1636
|
-
width: 100%; height: 2px;
|
|
1637
|
-
background: var(--border-faint); border-radius: 2px;
|
|
1638
|
-
margin-top: var(--space-lg); overflow: hidden;
|
|
1639
|
-
}
|
|
1640
|
-
.swiper-progress-fill {
|
|
1641
|
-
height: 100%; background: var(--accent-primary);
|
|
1642
|
-
border-radius: 2px;
|
|
1643
|
-
transition: width 0.3s ease;
|
|
1644
|
-
}
|
|
1645
|
-
```
|
|
1646
|
-
|
|
1647
|
-
**JS:**
|
|
1648
|
-
```js
|
|
1649
|
-
const slider = new Swiper('.portfolio-swiper', {
|
|
1650
|
-
loop: false,
|
|
1651
|
-
navigation: {
|
|
1652
|
-
nextEl: '.portfolio-swiper .swiper-button-next',
|
|
1653
|
-
prevEl: '.portfolio-swiper .swiper-button-prev',
|
|
1654
|
-
},
|
|
1655
|
-
on: {
|
|
1656
|
-
init(swiper) { updateProgress(swiper); },
|
|
1657
|
-
slideChange(swiper) { updateProgress(swiper); },
|
|
1658
|
-
},
|
|
1659
|
-
});
|
|
1660
|
-
|
|
1661
|
-
function updateProgress(swiper) {
|
|
1662
|
-
const fill = document.querySelector('.swiper-progress-fill');
|
|
1663
|
-
if (!fill) return;
|
|
1664
|
-
const pct = ((swiper.activeIndex + 1) / swiper.slides.length) * 100;
|
|
1665
|
-
fill.style.width = pct + '%';
|
|
1666
|
-
}
|
|
1667
|
-
```
|
|
1668
|
-
|
|
1669
|
-
---
|
|
1670
|
-
|
|
1671
|
-
### 14g. box-white / box-black Section Alternation
|
|
1672
|
-
|
|
1673
|
-
Aigocy alternates full-width section containers between dark (`box-black`) and light (`box-white`)
|
|
1674
|
-
with decorative gradient glow images for depth. This creates the "cinematic layer cake" effect.
|
|
1675
|
-
|
|
1676
|
-
**HTML:**
|
|
1677
|
-
```html
|
|
1678
|
-
<div class="box-black">
|
|
1679
|
-
<img class="light-top" src="light-bg-top.png" alt="" aria-hidden="true">
|
|
1680
|
-
<section class="features"> ... </section>
|
|
1681
|
-
<img class="light-bot" src="light-bg-bot.png" alt="" aria-hidden="true">
|
|
1682
|
-
</div>
|
|
1683
|
-
|
|
1684
|
-
<div class="box-white">
|
|
1685
|
-
<section class="how-it-works"> ... </section>
|
|
1686
|
-
</div>
|
|
1687
|
-
```
|
|
1688
|
-
|
|
1689
|
-
**CSS (generate glow with CSS instead of images):**
|
|
1690
|
-
```css
|
|
1691
|
-
.box-black {
|
|
1692
|
-
background: var(--bg-base);
|
|
1693
|
-
position: relative; overflow: hidden;
|
|
1694
|
-
}
|
|
1695
|
-
.box-white {
|
|
1696
|
-
background: var(--bg-surface);
|
|
1697
|
-
position: relative; overflow: hidden;
|
|
1698
|
-
}
|
|
1699
|
-
|
|
1700
|
-
/* Decorative ambient glow (replaces light-top/light-bot PNG images) */
|
|
1701
|
-
.box-black::before {
|
|
1702
|
-
content: '';
|
|
1703
|
-
position: absolute; top: -200px; left: 50%;
|
|
1704
|
-
transform: translateX(-50%);
|
|
1705
|
-
width: 800px; height: 400px;
|
|
1706
|
-
background: radial-gradient(ellipse at center,
|
|
1707
|
-
hsla(265,60%,40%,0.15) 0%,
|
|
1708
|
-
transparent 70%
|
|
1709
|
-
);
|
|
1710
|
-
pointer-events: none; z-index: 0;
|
|
1711
|
-
}
|
|
1712
|
-
.box-black::after {
|
|
1713
|
-
content: '';
|
|
1714
|
-
position: absolute; bottom: -200px; left: 50%;
|
|
1715
|
-
transform: translateX(-50%);
|
|
1716
|
-
width: 800px; height: 400px;
|
|
1717
|
-
background: radial-gradient(ellipse at center,
|
|
1718
|
-
hsla(265,60%,40%,0.1) 0%,
|
|
1719
|
-
transparent 70%
|
|
1720
|
-
);
|
|
1721
|
-
pointer-events: none; z-index: 0;
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1724
|
-
/* Ensure section content is above glow */
|
|
1725
|
-
.box-black > section, .box-white > section { position: relative; z-index: 1; }
|
|
1726
|
-
```
|
|
1727
|
-
|
|
1728
|
-
---
|
|
1729
|
-
|
|
1730
|
-
### 14h. Accordion FAQ (Bootstrap collapse pattern)
|
|
1731
|
-
|
|
1732
|
-
Clean accordion FAQ that works without JS library if you use the native `<details>` element,
|
|
1733
|
-
or with Bootstrap's collapse for richer animations.
|
|
1734
|
-
|
|
1735
|
-
**HTML (native, no-library version):**
|
|
1736
|
-
```html
|
|
1737
|
-
<section class="faq" id="faq" aria-labelledby="faq-title">
|
|
1738
|
-
<div class="container">
|
|
1739
|
-
<div class="section-header">
|
|
1740
|
-
<span class="section-label">FAQ</span>
|
|
1741
|
-
<h2 class="section-title" id="faq-title">Common questions</h2>
|
|
1742
|
-
</div>
|
|
1743
|
-
<div class="faq__list">
|
|
1744
|
-
<details class="faq__item">
|
|
1745
|
-
<summary class="faq__question">
|
|
1746
|
-
How long does setup take?
|
|
1747
|
-
<span class="faq__icon" aria-hidden="true">+</span>
|
|
1748
|
-
</summary>
|
|
1749
|
-
<div class="faq__answer">
|
|
1750
|
-
<p>Setup takes under 5 minutes. Connect your account, configure your first workflow, and you're live.</p>
|
|
1751
|
-
</div>
|
|
1752
|
-
</details>
|
|
1753
|
-
<!-- repeat -->
|
|
1754
|
-
</div>
|
|
1755
|
-
</div>
|
|
1756
|
-
</section>
|
|
1757
|
-
```
|
|
1758
|
-
|
|
1759
|
-
**CSS:**
|
|
1760
|
-
```css
|
|
1761
|
-
.faq__list { max-width: 800px; margin: 0 auto; }
|
|
1762
|
-
|
|
1763
|
-
.faq__item {
|
|
1764
|
-
border-bottom: 1px solid var(--border-faint);
|
|
1765
|
-
padding: var(--space-lg) 0;
|
|
1766
|
-
}
|
|
1767
|
-
.faq__item:first-child { border-top: 1px solid var(--border-faint); }
|
|
1768
|
-
|
|
1769
|
-
.faq__question {
|
|
1770
|
-
display: flex; justify-content: space-between; align-items: center;
|
|
1771
|
-
font-size: var(--text-lg); font-weight: 600;
|
|
1772
|
-
color: var(--text-primary); cursor: pointer;
|
|
1773
|
-
list-style: none; /* hide default marker */
|
|
1774
|
-
}
|
|
1775
|
-
.faq__question::-webkit-details-marker { display: none; }
|
|
1776
|
-
|
|
1777
|
-
.faq__icon {
|
|
1778
|
-
font-size: var(--text-xl); font-weight: 300;
|
|
1779
|
-
color: var(--accent-primary);
|
|
1780
|
-
transition: transform var(--duration-base) var(--ease-out);
|
|
1781
|
-
flex-shrink: 0; margin-left: var(--space-lg);
|
|
1782
|
-
}
|
|
1783
|
-
details[open] .faq__icon { transform: rotate(45deg); }
|
|
1784
|
-
|
|
1785
|
-
.faq__answer {
|
|
1786
|
-
padding-top: var(--space-md);
|
|
1787
|
-
}
|
|
1788
|
-
.faq__answer p {
|
|
1789
|
-
font-size: var(--text-base); color: var(--text-secondary); line-height: 1.7;
|
|
1790
|
-
}
|
|
1791
|
-
```
|
|
1792
|
-
|
|
1793
|
-
---
|
|
1794
|
-
|
|
1795
|
-
### 14i. Footer with Watermark Background Logo
|
|
1796
|
-
|
|
1797
|
-
Premium footer pattern: brand name as a large faded watermark behind footer content,
|
|
1798
|
-
with dense 3-column layout (links / copyright / social).
|
|
1799
|
-
|
|
1800
|
-
**HTML:**
|
|
1801
|
-
```html
|
|
1802
|
-
<footer class="footer" role="contentinfo">
|
|
1803
|
-
<div class="footer__watermark" aria-hidden="true">ProductName</div>
|
|
1804
|
-
<div class="container footer__body">
|
|
1805
|
-
<div class="footer__col footer__col--links">
|
|
1806
|
-
<strong>Product</strong>
|
|
1807
|
-
<a href="#">Features</a>
|
|
1808
|
-
<a href="#">Pricing</a>
|
|
1809
|
-
<a href="#">Docs</a>
|
|
1810
|
-
</div>
|
|
1811
|
-
<div class="footer__col footer__col--center">
|
|
1812
|
-
<a href="/" class="footer__logo" aria-label="Home">
|
|
1813
|
-
<img src="logo.svg" alt="ProductName" height="32">
|
|
1814
|
-
</a>
|
|
1815
|
-
<p class="footer__copy">© 2026 ProductName, Inc. All rights reserved.</p>
|
|
1816
|
-
</div>
|
|
1817
|
-
<div class="footer__col footer__col--social">
|
|
1818
|
-
<strong>Follow us</strong>
|
|
1819
|
-
<div class="footer__social">
|
|
1820
|
-
<a href="#" aria-label="Twitter" class="social-link">
|
|
1821
|
-
<svg width="20" height="20" aria-hidden="true"><!-- twitter icon --></svg>
|
|
1822
|
-
Twitter
|
|
1823
|
-
</a>
|
|
1824
|
-
<a href="#" aria-label="LinkedIn" class="social-link">
|
|
1825
|
-
<svg width="20" height="20" aria-hidden="true"><!-- linkedin icon --></svg>
|
|
1826
|
-
LinkedIn
|
|
1827
|
-
</a>
|
|
1828
|
-
</div>
|
|
1829
|
-
</div>
|
|
1830
|
-
</div>
|
|
1831
|
-
</footer>
|
|
1832
|
-
```
|
|
1833
|
-
|
|
1834
|
-
**CSS:**
|
|
1835
|
-
```css
|
|
1836
|
-
.footer {
|
|
1837
|
-
position: relative; overflow: hidden;
|
|
1838
|
-
background: var(--bg-surface);
|
|
1839
|
-
border-top: 1px solid var(--border-faint);
|
|
1840
|
-
padding: var(--space-3xl) 0 var(--space-xl);
|
|
1841
|
-
}
|
|
1842
|
-
|
|
1843
|
-
/* Faded watermark behind content */
|
|
1844
|
-
.footer__watermark {
|
|
1845
|
-
position: absolute; bottom: -20px; left: 50%;
|
|
1846
|
-
transform: translateX(-50%);
|
|
1847
|
-
font-family: var(--font-display); font-size: clamp(80px, 15vw, 160px);
|
|
1848
|
-
font-weight: 900; line-height: 1;
|
|
1849
|
-
color: var(--text-primary); opacity: 0.04;
|
|
1850
|
-
white-space: nowrap; pointer-events: none; user-select: none;
|
|
1851
|
-
}
|
|
1852
|
-
|
|
1853
|
-
.footer__body {
|
|
1854
|
-
display: grid; grid-template-columns: 1fr auto 1fr;
|
|
1855
|
-
gap: var(--space-xl); align-items: start;
|
|
1856
|
-
position: relative; z-index: 1;
|
|
1857
|
-
}
|
|
1858
|
-
.footer__col { display: flex; flex-direction: column; gap: var(--space-sm); }
|
|
1859
|
-
.footer__col--center { text-align: center; align-items: center; }
|
|
1860
|
-
.footer__col--social { align-items: flex-end; }
|
|
1861
|
-
|
|
1862
|
-
.footer__col strong {
|
|
1863
|
-
font-size: var(--text-sm); font-weight: 700; text-transform: uppercase;
|
|
1864
|
-
letter-spacing: 0.08em; color: var(--text-primary); margin-bottom: var(--space-xs);
|
|
1865
|
-
}
|
|
1866
|
-
.footer__col a {
|
|
1867
|
-
font-size: var(--text-sm); color: var(--text-muted);
|
|
1868
|
-
transition: color var(--duration-fast) ease;
|
|
1869
|
-
}
|
|
1870
|
-
.footer__col a:hover { color: var(--text-primary); }
|
|
1871
|
-
|
|
1872
|
-
.social-link {
|
|
1873
|
-
display: flex; align-items: center; gap: var(--space-sm);
|
|
1874
|
-
}
|
|
1875
|
-
|
|
1876
|
-
.footer__copy {
|
|
1877
|
-
font-size: var(--text-sm); color: var(--text-muted); margin-top: var(--space-md);
|
|
1878
|
-
}
|
|
1879
|
-
|
|
1880
|
-
@media (max-width: 768px) {
|
|
1881
|
-
.footer__body { grid-template-columns: 1fr; text-align: center; }
|
|
1882
|
-
.footer__col--social { align-items: center; }
|
|
1883
|
-
.footer__watermark { display: none; }
|
|
1884
|
-
}
|
|
1885
|
-
```
|
|
1886
|
-
|
|
1887
|
-
---
|
|
1888
|
-
|
|
1889
|
-
### 14j. Canvas Cursor Trail (optional, cinematic touch)
|
|
1890
|
-
|
|
1891
|
-
A subtle canvas trail that follows the cursor — drawn as fading dots.
|
|
1892
|
-
Only activate for Bold & Cinematic direction, and skip on touch devices.
|
|
1893
|
-
|
|
1894
|
-
```js
|
|
1895
|
-
// Add <canvas id="cursorTrail" style="position:fixed;inset:0;pointer-events:none;z-index:9999"></canvas>
|
|
1896
|
-
// to <body> to use this.
|
|
1897
|
-
|
|
1898
|
-
(function initCursorTrail() {
|
|
1899
|
-
if (window.matchMedia('(hover: none)').matches) return; // skip on touch
|
|
1900
|
-
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
|
1901
|
-
|
|
1902
|
-
const canvas = document.getElementById('cursorTrail');
|
|
1903
|
-
if (!canvas) return;
|
|
1904
|
-
const ctx = canvas.getContext('2d');
|
|
1905
|
-
canvas.width = window.innerWidth;
|
|
1906
|
-
canvas.height = window.innerHeight;
|
|
1907
|
-
window.addEventListener('resize', () => {
|
|
1908
|
-
canvas.width = window.innerWidth;
|
|
1909
|
-
canvas.height = window.innerHeight;
|
|
1910
|
-
});
|
|
1911
|
-
|
|
1912
|
-
const dots = [];
|
|
1913
|
-
const MAX_DOTS = 20;
|
|
1914
|
-
const COLOR = 'hsla(265, 80%, 65%,';
|
|
1915
|
-
|
|
1916
|
-
window.addEventListener('mousemove', (e) => {
|
|
1917
|
-
dots.push({ x: e.clientX, y: e.clientY, alpha: 1 });
|
|
1918
|
-
if (dots.length > MAX_DOTS) dots.shift();
|
|
1919
|
-
}, { passive: true });
|
|
1920
|
-
|
|
1921
|
-
function draw() {
|
|
1922
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1923
|
-
dots.forEach((dot, i) => {
|
|
1924
|
-
const size = (i / dots.length) * 8 + 2;
|
|
1925
|
-
dot.alpha = (i / dots.length) * 0.6;
|
|
1926
|
-
ctx.beginPath();
|
|
1927
|
-
ctx.arc(dot.x, dot.y, size, 0, Math.PI * 2);
|
|
1928
|
-
ctx.fillStyle = `${COLOR}${dot.alpha})`;
|
|
1929
|
-
ctx.fill();
|
|
1930
|
-
});
|
|
1931
|
-
requestAnimationFrame(draw);
|
|
1932
|
-
}
|
|
1933
|
-
draw();
|
|
1934
|
-
})();
|
|
1935
|
-
```
|
|
68
|
+
| Mesh gradient background drift | `@keyframes meshDrift` | No — CSS is cleaner |
|
|
69
|
+
| Animated gradient text | `@keyframes textGradient` | No |
|
|
70
|
+
| 3D card tilt on hover | `perspective(700px) rotateY/X` | No |
|
|
71
|
+
| Floating orbs | CSS `border-radius: 50%` + blur | No |
|
|
72
|
+
| Canvas cursor trail | Canvas 2D dot array | No |
|
|
73
|
+
| Particle aurora (thousands of points) | Canvas 2D limited | **Yes** — WebGL required |
|
|
74
|
+
| Interactive 3D object (orbit/rotate) | Not possible | **Yes** |
|
|
75
|
+
| Holographic glass with bloom | Not possible | **Yes** |
|
|
76
|
+
| Scroll-driven 3D camera parallax | Not possible | **Yes** |
|
|
77
|
+
| Floating 3D card grid | Not possible | **Yes** |
|
|
78
|
+
|
|
79
|
+
Three.js patterns are CDN-only (no npm install) and always additive —
|
|
80
|
+
the CSS/design skill tokens continue to govern typography, colors, and layout.
|