Commit 081d9938 authored by Mahmoud Aglan's avatar Mahmoud Aglan

kokokokoko

parent 8c142ce1
...@@ -32,7 +32,7 @@ html { ...@@ -32,7 +32,7 @@ html {
body { body {
font-family: 'Tajawal', sans-serif; font-family: 'Tajawal', sans-serif;
font-size: var(--text-base); font-size: var(--text-base);
line-height: 1.7; line-height: 1.75;
color: var(--ink-primary); color: var(--ink-primary);
background-color: var(--bg-deep); background-color: var(--bg-deep);
overflow-x: hidden; overflow-x: hidden;
...@@ -40,14 +40,15 @@ body { ...@@ -40,14 +40,15 @@ body {
} }
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
line-height: 1.25; line-height: 1.2;
font-weight: 700; font-weight: 700;
text-wrap: balance; text-wrap: balance;
letter-spacing: -0.01em;
} }
h1 { font-size: var(--text-5xl); font-weight: 900; } h1 { font-size: var(--text-5xl); font-weight: 900; letter-spacing: -0.025em; line-height: 1.05; }
h2 { font-size: var(--text-4xl); font-weight: 800; } h2 { font-size: var(--text-4xl); font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; }
h3 { font-size: var(--text-3xl); } h3 { font-size: var(--text-3xl); letter-spacing: -0.015em; }
h4 { font-size: var(--text-2xl); } h4 { font-size: var(--text-2xl); }
h5 { font-size: var(--text-xl); } h5 { font-size: var(--text-xl); }
...@@ -86,7 +87,7 @@ ul, ol { ...@@ -86,7 +87,7 @@ ul, ol {
} }
::selection { ::selection {
background: oklch(0.570 0.158 353.3 / 0.3); background: oklch(0.550 0.180 353.3 / 0.35);
color: var(--ink-primary); color: var(--ink-primary);
} }
...@@ -109,6 +110,7 @@ ul, ol { ...@@ -109,6 +110,7 @@ ul, ol {
.section { .section {
padding-block: var(--space-section); padding-block: var(--space-section);
position: relative;
} }
.visually-hidden { .visually-hidden {
...@@ -122,3 +124,14 @@ ul, ol { ...@@ -122,3 +124,14 @@ ul, ol {
white-space: nowrap; white-space: nowrap;
border: 0; border: 0;
} }
/* Noise texture overlay for depth */
body::before {
content: '';
position: fixed;
inset: 0;
pointer-events: none;
z-index: 9999;
opacity: 0.025;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
}
This diff is collapsed.
This diff is collapsed.
/* Module detail pages */ /* Module detail pages */
.module-detail__features { .module-detail__features {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
gap: var(--space-lg); gap: var(--space-md);
} }
.module-detail__screenshot-section { .module-detail__screenshot-section {
...@@ -42,25 +42,27 @@ ...@@ -42,25 +42,27 @@
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
gap: var(--space-sm); gap: var(--space-sm);
font-size: var(--text-base); font-size: var(--text-sm);
color: var(--ink-secondary); color: var(--ink-secondary);
line-height: 1.7;
} }
.module-detail__list-item::before { .module-detail__list-item::before {
content: ''; content: '';
flex-shrink: 0; flex-shrink: 0;
width: 6px; width: 5px;
height: 6px; height: 5px;
margin-top: 0.65em; margin-top: 0.6em;
background: var(--brand-primary); background: var(--brand-primary);
border-radius: 50%; border-radius: 50%;
box-shadow: 0 0 6px oklch(0.550 0.180 353.3 / 0.4);
} }
/* Features overview page */ /* Features overview page */
.features-grid { .features-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
gap: var(--space-lg); gap: var(--space-md);
} }
.feature-item { .feature-item {
...@@ -70,27 +72,41 @@ ...@@ -70,27 +72,41 @@
padding: var(--space-xl); padding: var(--space-xl);
background: var(--bg-surface); background: var(--bg-surface);
border: 1px solid var(--border-subtle); border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg); border-radius: var(--radius-xl);
align-items: start; align-items: start;
transition: all var(--duration-slow) var(--ease-out-expo);
position: relative;
overflow: hidden;
}
.feature-item:hover {
border-color: var(--border-glow);
transform: translateY(-2px);
box-shadow: 0 8px 32px oklch(0 0 0 / 0.2);
} }
.feature-item__number { .feature-item__number {
font-size: var(--text-3xl); font-size: var(--text-2xl);
font-weight: 900; font-weight: 900;
color: var(--brand-primary-dim); background: linear-gradient(135deg, var(--brand-primary-dim), var(--brand-primary-muted));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
line-height: 1; line-height: 1;
opacity: 0.6; opacity: 0.7;
} }
.feature-item__content h4 { .feature-item__content h4 {
font-size: var(--text-lg); font-size: var(--text-base);
margin-bottom: var(--space-xs); font-weight: 700;
margin-bottom: var(--space-2xs);
color: var(--ink-primary); color: var(--ink-primary);
} }
.feature-item__content p { .feature-item__content p {
font-size: var(--text-sm); font-size: var(--text-sm);
color: var(--ink-secondary); color: var(--ink-secondary);
line-height: 1.8;
} }
/* Contact / Pricing page */ /* Contact / Pricing page */
...@@ -116,7 +132,7 @@ ...@@ -116,7 +132,7 @@
.form-group { .form-group {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: var(--space-xs); gap: var(--space-2xs);
} }
.form-group label { .form-group label {
...@@ -128,14 +144,15 @@ ...@@ -128,14 +144,15 @@
.form-group input, .form-group input,
.form-group textarea, .form-group textarea,
.form-group select { .form-group select {
padding: var(--space-md); padding: var(--space-sm) var(--space-md);
background: var(--bg-surface); background: var(--bg-surface);
border: 1px solid var(--border-default); border: 1px solid var(--border-subtle);
border-radius: var(--radius-md); border-radius: var(--radius-lg);
color: var(--ink-primary); color: var(--ink-primary);
font-family: inherit; font-family: inherit;
font-size: var(--text-base); font-size: var(--text-sm);
transition: border-color var(--duration-fast) var(--ease-out-quart); transition: all var(--duration-fast) var(--ease-out-quart);
min-height: 44px;
} }
.form-group input:focus, .form-group input:focus,
...@@ -143,19 +160,33 @@ ...@@ -143,19 +160,33 @@
.form-group select:focus { .form-group select:focus {
outline: none; outline: none;
border-color: var(--brand-primary); border-color: var(--brand-primary);
box-shadow: 0 0 0 3px oklch(0.570 0.158 353.3 / 0.15); box-shadow: 0 0 0 3px oklch(0.550 0.180 353.3 / 0.1), 0 0 20px oklch(0.550 0.180 353.3 / 0.05);
background: var(--bg-elevated);
}
.form-group input::placeholder,
.form-group textarea::placeholder {
color: var(--ink-muted);
} }
.form-group textarea { .form-group textarea {
min-height: 150px; min-height: 120px;
resize: vertical; resize: vertical;
} }
.form-group select {
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23888' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: left 12px center;
padding-left: 36px;
}
.contact-info { .contact-info {
padding: var(--space-xl); padding: var(--space-xl);
background: var(--bg-surface); background: var(--bg-surface);
border: 1px solid var(--border-subtle); border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg); border-radius: var(--radius-xl);
} }
.contact-info__item { .contact-info__item {
...@@ -170,24 +201,25 @@ ...@@ -170,24 +201,25 @@
} }
.contact-info__icon { .contact-info__icon {
width: 2.5rem; width: 2.25rem;
height: 2.5rem; height: 2.25rem;
display: grid; display: grid;
place-items: center; place-items: center;
background: oklch(0.570 0.158 353.3 / 0.1); background: oklch(0.550 0.180 353.3 / 0.08);
border: 1px solid oklch(0.550 0.180 353.3 / 0.15);
border-radius: var(--radius-md); border-radius: var(--radius-md);
color: var(--brand-primary-light); color: var(--brand-primary-light);
flex-shrink: 0; flex-shrink: 0;
} }
.contact-info__label { .contact-info__label {
font-size: var(--text-sm); font-size: var(--text-xs);
color: var(--ink-muted); color: var(--ink-muted);
margin-bottom: 2px; margin-bottom: 2px;
} }
.contact-info__value { .contact-info__value {
font-size: var(--text-base); font-size: var(--text-sm);
color: var(--ink-primary); color: var(--ink-primary);
font-weight: 500; font-weight: 500;
} }
...@@ -196,7 +228,7 @@ ...@@ -196,7 +228,7 @@
.workflow { .workflow {
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--space-md); gap: var(--space-sm);
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
padding: var(--space-xl) 0; padding: var(--space-xl) 0;
...@@ -205,19 +237,27 @@ ...@@ -205,19 +237,27 @@
.workflow__step { .workflow__step {
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--space-sm); gap: var(--space-xs);
padding: var(--space-md) var(--space-lg); padding: var(--space-sm) var(--space-md);
background: var(--bg-surface); background: var(--bg-surface);
border: 1px solid var(--border-subtle); border: 1px solid var(--border-subtle);
border-radius: var(--radius-md); border-radius: var(--radius-lg);
font-size: var(--text-sm); font-size: var(--text-sm);
font-weight: 500; font-weight: 500;
color: var(--ink-primary); color: var(--ink-primary);
transition: all var(--duration-normal) var(--ease-out-quart);
white-space: nowrap;
}
.workflow__step:hover {
border-color: var(--border-glow);
box-shadow: 0 0 16px oklch(0.550 0.180 353.3 / 0.1);
} }
.workflow__arrow { .workflow__arrow {
color: var(--brand-primary-dim); color: var(--brand-primary-dim);
font-size: var(--text-xl); font-size: var(--text-lg);
opacity: 0.6;
} }
/* Comparison table */ /* Comparison table */
...@@ -225,15 +265,15 @@ ...@@ -225,15 +265,15 @@
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
background: var(--bg-surface); background: var(--bg-surface);
border-radius: var(--radius-lg); border-radius: var(--radius-xl);
overflow: hidden; overflow: hidden;
border: 1px solid var(--border-subtle); border: 1px solid var(--border-subtle);
} }
.comparison-table th { .comparison-table th {
padding: var(--space-md) var(--space-lg); padding: var(--space-sm) var(--space-md);
background: var(--bg-elevated); background: var(--bg-elevated);
font-weight: 700; font-weight: 600;
font-size: var(--text-sm); font-size: var(--text-sm);
color: var(--ink-primary); color: var(--ink-primary);
text-align: right; text-align: right;
...@@ -241,10 +281,15 @@ ...@@ -241,10 +281,15 @@
} }
.comparison-table td { .comparison-table td {
padding: var(--space-md) var(--space-lg); padding: var(--space-sm) var(--space-md);
font-size: var(--text-sm); font-size: var(--text-sm);
color: var(--ink-secondary); color: var(--ink-secondary);
border-bottom: 1px solid var(--border-subtle); border-bottom: 1px solid oklch(1 0 0 / 0.02);
transition: background var(--duration-fast) var(--ease-out-quart);
}
.comparison-table tr:hover td {
background: oklch(1 0 0 / 0.02);
} }
.comparison-table tr:last-child td { .comparison-table tr:last-child td {
...@@ -258,5 +303,16 @@ ...@@ -258,5 +303,16 @@
.comparison-table .cross { .comparison-table .cross {
color: var(--ink-muted); color: var(--ink-muted);
opacity: 0.5; opacity: 0.4;
}
/* Gradient section dividers */
.section--gradient-top::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(90deg, transparent 10%, var(--brand-primary-dim), transparent 90%);
} }
:root { :root {
/* Brand seed: oklch(0.570 0.158 353.3) — deep rose/crimson */ /* Brand seed: oklch(0.570 0.158 353.3) — deep rose/crimson */
--brand-primary: oklch(0.570 0.158 353.3); --brand-primary: oklch(0.550 0.180 353.3);
--brand-primary-light: oklch(0.650 0.140 353.3); --brand-primary-light: oklch(0.680 0.160 353.3);
--brand-primary-dim: oklch(0.450 0.120 353.3); --brand-primary-dim: oklch(0.400 0.130 353.3);
--brand-primary-muted: oklch(0.380 0.080 353.3); --brand-primary-muted: oklch(0.320 0.090 353.3);
--brand-primary-ghost: oklch(0.570 0.158 353.3 / 0.06);
/* Backgrounds — true dark, not warm-tinted */ /* Backgrounds — deeper, colder dark */
--bg-deep: oklch(0.120 0.008 353.3); --bg-deep: oklch(0.095 0.006 280);
--bg-base: oklch(0.150 0.010 353.3); --bg-base: oklch(0.115 0.008 280);
--bg-surface: oklch(0.185 0.012 353.3); --bg-surface: oklch(0.145 0.010 280);
--bg-elevated: oklch(0.220 0.014 353.3); --bg-elevated: oklch(0.180 0.012 280);
/* Text */ /* Text */
--ink-primary: oklch(0.950 0.005 353.3); --ink-primary: oklch(0.960 0.003 280);
--ink-secondary: oklch(0.750 0.010 353.3); --ink-secondary: oklch(0.720 0.008 280);
--ink-muted: oklch(0.550 0.008 353.3); --ink-muted: oklch(0.500 0.006 280);
/* Borders */ /* Borders */
--border-subtle: oklch(0.250 0.012 353.3); --border-subtle: oklch(0.200 0.010 280);
--border-default: oklch(0.320 0.015 353.3); --border-default: oklch(0.280 0.012 280);
--border-glow: oklch(0.550 0.180 353.3 / 0.25);
/* Accent — gold for secondary highlights */ /* Accent — warm gold for secondary */
--accent-gold: oklch(0.700 0.120 85); --accent-gold: oklch(0.750 0.130 85);
--accent-gold-dim: oklch(0.550 0.090 85); --accent-gold-dim: oklch(0.550 0.090 85);
/* Functional */ /* Functional */
...@@ -32,45 +34,54 @@ ...@@ -32,45 +34,54 @@
/* Typography scale — 1.333 ratio (perfect fourth) */ /* Typography scale — 1.333 ratio (perfect fourth) */
--text-xs: clamp(0.694rem, 0.65vi + 0.5rem, 0.75rem); --text-xs: clamp(0.694rem, 0.65vi + 0.5rem, 0.75rem);
--text-sm: clamp(0.833rem, 0.8vi + 0.6rem, 0.875rem); --text-sm: clamp(0.833rem, 0.8vi + 0.6rem, 0.875rem);
--text-base: clamp(1rem, 1vi + 0.7rem, 1.063rem); --text-base: clamp(0.938rem, 0.9vi + 0.65rem, 1rem);
--text-lg: clamp(1.125rem, 1.2vi + 0.8rem, 1.25rem); --text-lg: clamp(1.063rem, 1.1vi + 0.75rem, 1.188rem);
--text-xl: clamp(1.333rem, 1.5vi + 0.9rem, 1.5rem); --text-xl: clamp(1.25rem, 1.4vi + 0.85rem, 1.375rem);
--text-2xl: clamp(1.777rem, 2.2vi + 1rem, 2.25rem); --text-2xl: clamp(1.6rem, 2vi + 0.95rem, 2rem);
--text-3xl: clamp(2.369rem, 3vi + 1.2rem, 3rem); --text-3xl: clamp(2.1rem, 2.8vi + 1.1rem, 2.75rem);
--text-4xl: clamp(3.157rem, 4vi + 1.5rem, 4rem); --text-4xl: clamp(2.8rem, 3.5vi + 1.3rem, 3.5rem);
--text-5xl: clamp(4.209rem, 5.5vi + 1.8rem, 5.5rem); --text-5xl: clamp(3.4rem, 4.5vi + 1.5rem, 4.5rem);
/* Spacing */ /* Spacing */
--space-2xs: clamp(0.125rem, 0.25vi, 0.25rem);
--space-xs: clamp(0.25rem, 0.5vi, 0.5rem); --space-xs: clamp(0.25rem, 0.5vi, 0.5rem);
--space-sm: clamp(0.5rem, 1vi, 0.75rem); --space-sm: clamp(0.5rem, 1vi, 0.75rem);
--space-md: clamp(1rem, 2vi, 1.5rem); --space-md: clamp(0.875rem, 1.5vi, 1.25rem);
--space-lg: clamp(1.5rem, 3vi, 2.5rem); --space-lg: clamp(1.25rem, 2.5vi, 2rem);
--space-xl: clamp(2.5rem, 5vi, 4rem); --space-xl: clamp(2rem, 4vi, 3rem);
--space-2xl: clamp(4rem, 8vi, 6rem); --space-2xl: clamp(3rem, 6vi, 5rem);
--space-3xl: clamp(6rem, 12vi, 10rem); --space-3xl: clamp(5rem, 10vi, 8rem);
--space-section: clamp(5rem, 10vi, 8rem); --space-section: clamp(5rem, 10vi, 8rem);
/* Radius */ /* Radius */
--radius-xs: 0.125rem;
--radius-sm: 0.25rem; --radius-sm: 0.25rem;
--radius-md: 0.5rem; --radius-md: 0.5rem;
--radius-lg: 1rem; --radius-lg: 0.875rem;
--radius-xl: 1.5rem; --radius-xl: 1.25rem;
--radius-2xl: 1.75rem;
/* Shadows */ /* Shadows */
--shadow-sm: 0 1px 3px oklch(0 0 0 / 0.3); --shadow-sm: 0 1px 3px oklch(0 0 0 / 0.4);
--shadow-md: 0 4px 12px oklch(0 0 0 / 0.4); --shadow-md: 0 4px 16px oklch(0 0 0 / 0.5);
--shadow-lg: 0 8px 32px oklch(0 0 0 / 0.5); --shadow-lg: 0 12px 48px oklch(0 0 0 / 0.6);
--shadow-glow: 0 0 40px oklch(0.570 0.158 353.3 / 0.2); --shadow-glow: 0 0 60px oklch(0.550 0.180 353.3 / 0.15);
--shadow-glow-strong: 0 0 80px oklch(0.550 0.180 353.3 / 0.25);
--shadow-inner: inset 0 1px 0 oklch(1 0 0 / 0.04);
/* Transitions */ /* Transitions */
--ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1); --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
--ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
--ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
--duration-fast: 150ms; --duration-fast: 150ms;
--duration-normal: 300ms; --duration-normal: 300ms;
--duration-slow: 500ms; --duration-slow: 500ms;
--duration-slower: 800ms;
/* Z-index scale */ /* Z-index scale */
--z-base: 0; --z-base: 0;
--z-above: 10;
--z-dropdown: 100; --z-dropdown: 100;
--z-sticky: 200; --z-sticky: 200;
--z-modal-backdrop: 300; --z-modal-backdrop: 300;
...@@ -79,7 +90,7 @@ ...@@ -79,7 +90,7 @@
--z-tooltip: 600; --z-tooltip: 600;
/* Layout */ /* Layout */
--container-max: 1280px; --container-max: 1200px;
--container-wide: 1440px; --container-wide: 1400px;
--content-max: 75ch; --content-max: 65ch;
} }
...@@ -2,6 +2,9 @@ document.addEventListener('DOMContentLoaded', () => { ...@@ -2,6 +2,9 @@ document.addEventListener('DOMContentLoaded', () => {
initNav(); initNav();
initReveal(); initReveal();
initMobileMenu(); initMobileMenu();
initParallax();
initCountUp();
initSmoothHover();
}); });
function initNav() { function initNav() {
...@@ -12,12 +15,14 @@ function initNav() { ...@@ -12,12 +15,14 @@ function initNav() {
window.addEventListener('scroll', () => { window.addEventListener('scroll', () => {
if (!ticking) { if (!ticking) {
requestAnimationFrame(() => { requestAnimationFrame(() => {
nav.classList.toggle('nav--scrolled', window.scrollY > 50); nav.classList.toggle('nav--scrolled', window.scrollY > 30);
ticking = false; ticking = false;
}); });
ticking = true; ticking = true;
} }
}, { passive: true }); }, { passive: true });
if (window.scrollY > 30) nav.classList.add('nav--scrolled');
} }
function initMobileMenu() { function initMobileMenu() {
...@@ -32,7 +37,7 @@ function initMobileMenu() { ...@@ -32,7 +37,7 @@ function initMobileMenu() {
}); });
links.addEventListener('click', (e) => { links.addEventListener('click', (e) => {
if (e.target.classList.contains('nav__link')) { if (e.target.classList.contains('nav__link') || e.target.classList.contains('nav__cta')) {
links.classList.remove('nav__links--open'); links.classList.remove('nav__links--open');
toggle.setAttribute('aria-expanded', 'false'); toggle.setAttribute('aria-expanded', 'false');
document.body.style.overflow = ''; document.body.style.overflow = '';
...@@ -41,7 +46,12 @@ function initMobileMenu() { ...@@ -41,7 +46,12 @@ function initMobileMenu() {
} }
function initReveal() { function initReveal() {
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelectorAll('[data-reveal]').forEach(el => {
el.style.opacity = '1';
});
return;
}
const observer = new IntersectionObserver( const observer = new IntersectionObserver(
(entries) => { (entries) => {
...@@ -52,21 +62,127 @@ function initReveal() { ...@@ -52,21 +62,127 @@ function initReveal() {
} }
}); });
}, },
{ threshold: 0.1, rootMargin: '0px 0px -50px 0px' } { threshold: 0.08, rootMargin: '0px 0px -60px 0px' }
); );
document.querySelectorAll('[data-reveal]').forEach((el) => { document.querySelectorAll('[data-reveal]').forEach((el, i) => {
const delay = parseInt(el.dataset.reveal) || 0;
el.style.opacity = '0'; el.style.opacity = '0';
el.style.transform = 'translateY(24px)'; el.style.transform = 'translateY(32px)';
el.style.transition = `opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1), transform 0.6s cubic-bezier(0.16, 1, 0.3, 1)`; el.style.transition = `opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1) ${delay}ms, transform 0.7s cubic-bezier(0.16, 1, 0.3, 1) ${delay}ms`;
const delay = el.dataset.reveal || '0';
el.style.transitionDelay = `${delay}ms`;
observer.observe(el); observer.observe(el);
}); });
} }
document.documentElement.addEventListener('animationend', () => {}); function initParallax() {
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
const heroVisual = document.querySelector('.hero__visual');
if (!heroVisual) return;
let ticking = false;
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(() => {
const scrolled = window.scrollY;
const rate = scrolled * 0.15;
if (scrolled < window.innerHeight) {
heroVisual.style.transform = `translateY(${rate}px)`;
}
ticking = false;
});
ticking = true;
}
}, { passive: true });
}
function initCountUp() {
const stats = document.querySelectorAll('.stat__value');
if (!stats.length) return;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
animateValue(entry.target);
observer.unobserve(entry.target);
}
});
},
{ threshold: 0.5 }
);
stats.forEach(stat => observer.observe(stat));
}
function animateValue(el) {
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
const text = el.textContent.trim();
const hasPlus = text.startsWith('+');
const hasPercent = text.endsWith('%');
const numStr = text.replace(/[^0-9.]/g, '');
const target = parseFloat(numStr);
if (isNaN(target)) return;
const duration = 1500;
const start = performance.now();
function update(now) {
const elapsed = now - start;
const progress = Math.min(elapsed / duration, 1);
const eased = 1 - Math.pow(1 - progress, 4);
const current = Math.round(eased * target);
el.textContent = (hasPlus ? '+' : '') + current + (hasPercent ? '%' : '');
if (progress < 1) {
requestAnimationFrame(update);
}
}
el.textContent = (hasPlus ? '+' : '') + '0' + (hasPercent ? '%' : '');
requestAnimationFrame(update);
}
function initSmoothHover() {
const cards = document.querySelectorAll('.module-card, .feature-card, .pain-point');
cards.forEach(card => {
card.addEventListener('mouseenter', (e) => {
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
card.style.setProperty('--mouse-x', `${x}px`);
card.style.setProperty('--mouse-y', `${y}px`);
});
card.addEventListener('mousemove', (e) => {
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
card.style.setProperty('--mouse-x', `${x}px`);
card.style.setProperty('--mouse-y', `${y}px`);
});
});
}
// Inject styles
const style = document.createElement('style'); const style = document.createElement('style');
style.textContent = `.revealed { opacity: 1 !important; transform: translateY(0) !important; }`; style.textContent = `
.revealed {
opacity: 1 !important;
transform: translateY(0) !important;
}
.module-card::before,
.feature-card::before,
.pain-point::before {
background: radial-gradient(
400px circle at var(--mouse-x, 50%) var(--mouse-y, 50%),
oklch(0.550 0.180 353.3 / 0.04),
transparent 60%
) !important;
opacity: 1 !important;
}
`;
document.head.appendChild(style); document.head.appendChild(style);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment