diff --git a/frontend/app/globals.css b/frontend/app/globals.css
index 2743a7c1..ccc119f9 100644
--- a/frontend/app/globals.css
+++ b/frontend/app/globals.css
@@ -210,71 +210,6 @@
}
}
-@keyframes wave-slide-up {
- 0% {
- clip-path: polygon(
- 0% 100%,
- 10% 100%,
- 20% 100%,
- 30% 100%,
- 40% 100%,
- 50% 100%,
- 60% 100%,
- 70% 100%,
- 80% 100%,
- 90% 100%,
- 100% 100%,
- 100% 100%,
- 0% 100%
- );
- }
- 50% {
- clip-path: polygon(
- 0% 60%,
- 10% 50%,
- 20% 45%,
- 30% 48%,
- 40% 55%,
- 50% 50%,
- 60% 45%,
- 70% 48%,
- 80% 52%,
- 90% 50%,
- 100% 55%,
- 100% 100%,
- 0% 100%
- );
- }
- 100% {
- clip-path: polygon(
- 0% 0%,
- 10% 0%,
- 20% 0%,
- 30% 0%,
- 40% 0%,
- 50% 0%,
- 60% 0%,
- 70% 0%,
- 80% 0%,
- 90% 0%,
- 100% 0%,
- 100% 100%,
- 0% 100%
- );
- }
-}
-
-@keyframes text-fade-in {
- 0% {
- opacity: 0;
- transform: translateY(4px);
- }
- 100% {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
@keyframes card-breathe {
0% {
transform: translate(0, 0) scale(1) rotate(var(--card-rotate, 0deg));
@@ -297,36 +232,24 @@
animation: slide-up-gradient 1.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
- .animate-wave-slide-up {
- animation: wave-slide-up 1.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
- }
-
- .animate-text-fade-in {
- animation: text-fade-in 0.6s cubic-bezier(0.4, 0, 0.2, 1) forwards;
- }
-
.animate-card-breathe {
animation: card-breathe 6s ease-in-out infinite;
will-change: transform;
}
- .left-4 .animate-card-breathe,
- .md\:left-6 .animate-card-breathe,
- .lg\:left-8 .animate-card-breathe,
- .xl\:left-12 .animate-card-breathe {
- --card-x: -30px;
- --card-y: -25px;
+ .lg\:left-16.animate-card-breathe {
+ transform: rotate(-10deg);
+ --card-x: -20px;
+ --card-y: -15px;
--card-rotate: -10deg;
--card-rotate-offset: -3deg;
animation-delay: 0s;
}
- .right-4 .animate-card-breathe,
- .md\:right-6 .animate-card-breathe,
- .lg\:right-8 .animate-card-breathe,
- .xl\:right-12 .animate-card-breathe {
- --card-x: 30px;
- --card-y: 25px;
+ .lg\:right-20.animate-card-breathe {
+ transform: rotate(8deg);
+ --card-x: 20px;
+ --card-y: 15px;
--card-rotate: 8deg;
--card-rotate-offset: 3deg;
animation-delay: 0.8s;
@@ -376,7 +299,7 @@
.shop-scope {
/* keep shop rounding slightly tighter than platform */
--radius: calc(var(--radius-base) - 2px);
-
+
/* Shop header/button accent in LIGHT: no platform blue */
--accent-primary: var(--foreground);
--accent-hover: color-mix(in oklab, var(--foreground) 92%, white);
diff --git a/frontend/components/home/CodeCard.tsx b/frontend/components/home/CodeCard.tsx
index 6f3b1157..f66efbf2 100644
--- a/frontend/components/home/CodeCard.tsx
+++ b/frontend/components/home/CodeCard.tsx
@@ -9,19 +9,26 @@ interface CodeCardProps {
export function CodeCard({ fileName, snippet, className }: CodeCardProps) {
return (
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
{fileName}
+
{fileName}
-
+
+
{snippet}
diff --git a/frontend/components/home/HeroCodeCards.tsx b/frontend/components/home/HeroCodeCards.tsx
index 7c4fd1b6..8e696b93 100644
--- a/frontend/components/home/HeroCodeCards.tsx
+++ b/frontend/components/home/HeroCodeCards.tsx
@@ -5,7 +5,7 @@ export function HeroCodeCards() {
<>
type Arr1 = [
@@ -31,7 +31,7 @@ export function HeroCodeCards() {
function sum(
diff --git a/frontend/components/home/HeroSection.tsx b/frontend/components/home/HeroSection.tsx
index 78946cce..8fee2a71 100644
--- a/frontend/components/home/HeroSection.tsx
+++ b/frontend/components/home/HeroSection.tsx
@@ -26,12 +26,12 @@ sm:min-h-[calc(100vh-280px)] md:min-h-[85vh] lg:min-h-[100vh]
-
+
{t('subtitle')}
-
-
+
+
DevLovers
@@ -45,7 +45,7 @@ sm:min-h-[calc(100vh-280px)] md:min-h-[85vh] lg:min-h-[100vh]
-
+
{t('description')}
diff --git a/frontend/components/home/InteractiveCTAButton.tsx b/frontend/components/home/InteractiveCTAButton.tsx
index f6c84014..d0426479 100644
--- a/frontend/components/home/InteractiveCTAButton.tsx
+++ b/frontend/components/home/InteractiveCTAButton.tsx
@@ -3,73 +3,181 @@
import React from 'react';
import { useTranslations } from 'next-intl';
import { Link } from '@/i18n/routing';
-import { createCTAVariants } from '@/lib/home/cta-variants';
+import { motion, AnimatePresence } from 'framer-motion';
+import { Heart } from 'lucide-react';
export function InteractiveCTAButton() {
const t = useTranslations('homepage');
- const [index, setIndex] = React.useState(0);
+ const [variantIndex, setVariantIndex] = React.useState(1);
const [isHovered, setIsHovered] = React.useState(false);
- const variants = createCTAVariants(t('cta'));
- const current = variants[index];
- const nextIndex = (index + 1) % variants.length;
- const next = variants[nextIndex];
+ // Тимчасово для тестування - цифри замість текстів
+ const textVariants = [
+ `${t('cta')} 1`,
+ `${t('cta')} 2`,
+ `${t('cta')} 3`,
+ `${t('cta')} 4`,
+ `${t('cta')} 5`,
+ ];
+
+ const defaultVariant = t('cta');
+ const hoverVariant = textVariants[variantIndex];
const handleEnter = () => {
if (!window.matchMedia('(hover: hover)').matches) return;
- if (isHovered) return;
setIsHovered(true);
};
const handleLeave = () => {
if (!window.matchMedia('(hover: hover)').matches) return;
- if (!isHovered) return;
- setIndex(nextIndex);
setIsHovered(false);
+ setVariantIndex(prev => (prev + 1) % textVariants.length);
};
+ // Орбітальні частинки
+ const particles = Array.from({ length: 12 }, (_, i) => ({
+ id: i,
+ angle: (i * 360) / 8,
+ }));
+
return (
-
+
+ {/* М'яка неонова підсвітка */}
+
- {isHovered && (
-
- )}
+ {/* Орбітальні частинки - БЛИЗЬКО навколо кнопки */}
+
+ {isHovered &&
+ particles.map(particle => (
+
+
+
+ ))}
+
+ {/* Внутрішній shine overlay */}
-
-
- {isHovered ? next.text : current.text}
-
+ {/* Текст з анімацією */}
+
+
+ {!isHovered ? (
+
+ {defaultVariant}
+
+ ) : (
+
+ {hoverVariant}
+
+ )}
+
);
diff --git a/frontend/components/shared/OnlineCounterPopup.tsx b/frontend/components/shared/OnlineCounterPopup.tsx
index 206285e1..b2a79739 100644
--- a/frontend/components/shared/OnlineCounterPopup.tsx
+++ b/frontend/components/shared/OnlineCounterPopup.tsx
@@ -2,7 +2,7 @@
import { useEffect, useState } from 'react';
import { useTranslations } from 'next-intl';
-import { Users, Sparkles } from 'lucide-react';
+import { Users } from 'lucide-react';
export function OnlineCounterPopup() {
const t = useTranslations('onlineCounter');
@@ -25,14 +25,6 @@ export function OnlineCounterPopup() {
if (!online) return null;
- const getEmoji = (count: number) => {
- if (count === 1) return '🎯';
- if (count === 2) return '💼';
- if (count <= 5) return '🚀';
- if (count <= 10) return '⚡';
- return '⭐';
- };
-
const getText = (count: number) => {
if (count === 1) return t('one');
if (count === 2) return t('two');
@@ -42,7 +34,7 @@ export function OnlineCounterPopup() {
};
return (
-
+
-
+
+
-
-
-
-
+
-
-
{getEmoji(online)}
-
-
- {online}
-
-
- {getText(online)}
+
+
+
+
+
+ {online}
+
+
+ {getText(online)}
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
);