feat: dark luxury redesign with black heart branding
Complete visual overhaul: dark-only mode, rose/crimson accent system, glassmorphism header, animated hero with floating hearts and glow orbs, photo-backed cards, infinite team carousel with drag support, redesigned modals with hero images, black heart logo with rose glow silhouette. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,21 +1,29 @@
|
||||
import { siteContent } from "@/data/content";
|
||||
import { SectionHeading } from "@/components/ui/SectionHeading";
|
||||
import { Reveal } from "@/components/ui/Reveal";
|
||||
import { Heart } from "lucide-react";
|
||||
|
||||
export function About() {
|
||||
const { about } = siteContent;
|
||||
|
||||
return (
|
||||
<section id="about" className="surface-muted section-padding">
|
||||
<section id="about" className="relative section-padding bg-neutral-100 dark:bg-[#0a0a0a]">
|
||||
<div className="section-divider absolute top-0 left-0 right-0" />
|
||||
<div className="section-container">
|
||||
<Reveal>
|
||||
<SectionHeading>{about.title}</SectionHeading>
|
||||
</Reveal>
|
||||
|
||||
<div className="mt-8 max-w-3xl space-y-4">
|
||||
<div className="mt-10 max-w-3xl space-y-6">
|
||||
{about.paragraphs.map((text, i) => (
|
||||
<Reveal key={i}>
|
||||
<p className="body-text text-lg leading-relaxed">{text}</p>
|
||||
<div className="flex gap-4">
|
||||
<Heart
|
||||
size={20}
|
||||
className="mt-1 shrink-0 fill-rose-500/20 text-rose-500 dark:fill-rose-500/10 dark:text-rose-400"
|
||||
/>
|
||||
<p className="body-text text-lg leading-relaxed">{text}</p>
|
||||
</div>
|
||||
</Reveal>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Flame, Sparkles, Wind, Zap, Star, Monitor } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import { Flame, Sparkles, Wind, Zap, Star, Monitor, ArrowRight } from "lucide-react";
|
||||
import { siteContent } from "@/data/content";
|
||||
import { SectionHeading } from "@/components/ui/SectionHeading";
|
||||
import { Reveal } from "@/components/ui/Reveal";
|
||||
@@ -9,12 +10,12 @@ import { ClassModal } from "@/components/ui/ClassModal";
|
||||
import type { ClassItem } from "@/types";
|
||||
|
||||
const iconMap: Record<string, React.ReactNode> = {
|
||||
flame: <Flame size={32} />,
|
||||
sparkles: <Sparkles size={32} />,
|
||||
wind: <Wind size={32} />,
|
||||
zap: <Zap size={32} />,
|
||||
star: <Star size={32} />,
|
||||
monitor: <Monitor size={32} />,
|
||||
flame: <Flame size={20} />,
|
||||
sparkles: <Sparkles size={20} />,
|
||||
wind: <Wind size={20} />,
|
||||
zap: <Zap size={20} />,
|
||||
star: <Star size={20} />,
|
||||
monitor: <Monitor size={20} />,
|
||||
};
|
||||
|
||||
export function Classes() {
|
||||
@@ -22,22 +23,57 @@ export function Classes() {
|
||||
const [selectedClass, setSelectedClass] = useState<ClassItem | null>(null);
|
||||
|
||||
return (
|
||||
<section id="classes" className="surface-muted section-padding">
|
||||
<section id="classes" className="relative section-padding bg-neutral-100 dark:bg-[#0a0a0a]">
|
||||
<div className="section-divider absolute top-0 left-0 right-0" />
|
||||
<div className="section-container">
|
||||
<Reveal>
|
||||
<SectionHeading>{classes.title}</SectionHeading>
|
||||
</Reveal>
|
||||
|
||||
<div className="mt-12 grid gap-6 sm:grid-cols-2">
|
||||
<div className="mt-14 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{classes.items.map((item) => (
|
||||
<Reveal key={item.name} className="h-full">
|
||||
<div
|
||||
className="card h-full flex flex-col cursor-pointer transition-transform hover:scale-[1.02]"
|
||||
className="group relative h-full min-h-[280px] cursor-pointer overflow-hidden rounded-2xl"
|
||||
onClick={() => setSelectedClass(item)}
|
||||
>
|
||||
<div className="heading-text">{iconMap[item.icon]}</div>
|
||||
<h3 className="heading-text mt-4 text-xl font-semibold">{item.name}</h3>
|
||||
<p className="body-text mt-2">{item.description}</p>
|
||||
{/* Background image */}
|
||||
{item.images && item.images[0] && (
|
||||
<Image
|
||||
src={item.images[0]}
|
||||
alt={item.name}
|
||||
fill
|
||||
className="object-cover transition-transform duration-700 ease-out group-hover:scale-105"
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Dark gradient overlay */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/90 via-black/40 to-black/10 transition-all duration-500 group-hover:from-black/95 group-hover:via-black/50" />
|
||||
|
||||
{/* Rose tint on hover */}
|
||||
<div className="absolute inset-0 bg-rose-900/0 transition-all duration-500 group-hover:bg-rose-900/10" />
|
||||
|
||||
{/* Content */}
|
||||
<div className="relative flex h-full flex-col justify-end p-6">
|
||||
{/* Icon badge */}
|
||||
<div className="mb-3 inline-flex h-9 w-9 items-center justify-center rounded-lg bg-white/10 text-white backdrop-blur-sm transition-all duration-300 group-hover:bg-rose-500/20 group-hover:text-rose-300">
|
||||
{iconMap[item.icon]}
|
||||
</div>
|
||||
|
||||
<h3 className="text-xl font-semibold text-white">
|
||||
{item.name}
|
||||
</h3>
|
||||
|
||||
<p className="mt-1.5 text-sm leading-relaxed text-white/60 line-clamp-2">
|
||||
{item.description}
|
||||
</p>
|
||||
|
||||
{/* Hover arrow */}
|
||||
<div className="mt-3 flex items-center gap-1.5 text-sm font-medium text-rose-400 opacity-0 translate-y-2 transition-all duration-300 group-hover:opacity-100 group-hover:translate-y-0">
|
||||
<span>Подробнее</span>
|
||||
<ArrowRight size={14} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
))}
|
||||
|
||||
@@ -8,51 +8,65 @@ export function Contact() {
|
||||
const { contact } = siteContent;
|
||||
|
||||
return (
|
||||
<section id="contact" className="surface-base section-padding">
|
||||
<section id="contact" className="relative section-padding bg-neutral-50 dark:bg-[#050505]">
|
||||
<div className="section-divider absolute top-0 left-0 right-0" />
|
||||
<div className="section-container grid items-start gap-12 lg:grid-cols-2">
|
||||
<Reveal>
|
||||
<SectionHeading>{contact.title}</SectionHeading>
|
||||
|
||||
<div className="mt-12 space-y-6">
|
||||
<div className="mt-10 space-y-5">
|
||||
{contact.addresses.map((address, i) => (
|
||||
<div key={i} className="contact-item">
|
||||
<MapPin size={20} className="contact-icon" />
|
||||
<div key={i} className="group flex items-center gap-4">
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-rose-50 text-rose-600 transition-colors group-hover:bg-rose-100 dark:bg-rose-500/10 dark:text-rose-400 dark:group-hover:bg-rose-500/15">
|
||||
<MapPin size={18} />
|
||||
</div>
|
||||
<p className="body-text">{address}</p>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="contact-item">
|
||||
<Phone size={20} className="contact-icon" />
|
||||
<a href={`tel:${contact.phone}`} className="nav-link text-base">
|
||||
<div className="group flex items-center gap-4">
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-rose-50 text-rose-600 transition-colors group-hover:bg-rose-100 dark:bg-rose-500/10 dark:text-rose-400 dark:group-hover:bg-rose-500/15">
|
||||
<Phone size={18} />
|
||||
</div>
|
||||
<a
|
||||
href={`tel:${contact.phone}`}
|
||||
className="text-neutral-600 transition-colors hover:text-rose-600 dark:text-neutral-400 dark:hover:text-rose-400"
|
||||
>
|
||||
{contact.phone}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className="contact-item">
|
||||
<Clock size={20} className="contact-icon" />
|
||||
<div className="group flex items-center gap-4">
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-rose-50 text-rose-600 transition-colors group-hover:bg-rose-100 dark:bg-rose-500/10 dark:text-rose-400 dark:group-hover:bg-rose-500/15">
|
||||
<Clock size={18} />
|
||||
</div>
|
||||
<p className="body-text">{contact.workingHours}</p>
|
||||
</div>
|
||||
|
||||
<div className="theme-border contact-item border-t pt-6">
|
||||
<Instagram size={20} className="contact-icon" />
|
||||
<a
|
||||
href={contact.instagram}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="nav-link text-base"
|
||||
>
|
||||
{BRAND.instagramHandle}
|
||||
</a>
|
||||
<div className="border-t border-neutral-200 pt-5 dark:border-white/[0.06]">
|
||||
<div className="group flex items-center gap-4">
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-rose-50 text-rose-600 transition-colors group-hover:bg-rose-100 dark:bg-rose-500/10 dark:text-rose-400 dark:group-hover:bg-rose-500/15">
|
||||
<Instagram size={18} />
|
||||
</div>
|
||||
<a
|
||||
href={contact.instagram}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-neutral-600 transition-colors hover:text-rose-600 dark:text-neutral-400 dark:hover:text-rose-400"
|
||||
>
|
||||
{BRAND.instagramHandle}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
<Reveal>
|
||||
<div className="theme-border overflow-hidden rounded-2xl border">
|
||||
<div className="overflow-hidden rounded-2xl border border-neutral-200 shadow-sm dark:border-white/[0.06] dark:shadow-[0_0_30px_rgba(225,29,72,0.05)]">
|
||||
<iframe
|
||||
src={contact.mapEmbedUrl}
|
||||
width="100%"
|
||||
height="350"
|
||||
height="380"
|
||||
style={{ border: 0 }}
|
||||
allowFullScreen
|
||||
loading="lazy"
|
||||
|
||||
@@ -1,35 +1,99 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { siteContent } from "@/data/content";
|
||||
import { BRAND } from "@/lib/constants";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { FloatingHearts } from "@/components/ui/FloatingHearts";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
|
||||
export function Hero() {
|
||||
const { hero } = siteContent;
|
||||
|
||||
return (
|
||||
<section className="surface-base section-container flex min-h-svh items-center justify-center">
|
||||
<div className="text-center">
|
||||
<Image
|
||||
src="/images/logo.png"
|
||||
alt={BRAND.name}
|
||||
width={280}
|
||||
height={280}
|
||||
priority
|
||||
unoptimized
|
||||
className="hero-logo mx-auto mb-8 dark:invert"
|
||||
/>
|
||||
<section className="relative flex min-h-svh items-center justify-center overflow-hidden bg-[#050505]">
|
||||
{/* Animated gradient background */}
|
||||
<div className="hero-bg-gradient absolute inset-0" />
|
||||
|
||||
{/* Glow orbs */}
|
||||
<div
|
||||
className="hero-glow-orb"
|
||||
style={{
|
||||
width: "500px",
|
||||
height: "500px",
|
||||
top: "-10%",
|
||||
left: "50%",
|
||||
transform: "translateX(-50%)",
|
||||
background: "radial-gradient(circle, rgba(225, 29, 72, 0.12), transparent 70%)",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="hero-glow-orb"
|
||||
style={{
|
||||
width: "300px",
|
||||
height: "300px",
|
||||
bottom: "10%",
|
||||
right: "10%",
|
||||
background: "radial-gradient(circle, rgba(225, 29, 72, 0.08), transparent 70%)",
|
||||
animationDelay: "3s",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Floating hearts */}
|
||||
<FloatingHearts />
|
||||
|
||||
{/* Content */}
|
||||
<div className="section-container relative z-10 text-center">
|
||||
<div className="hero-logo relative mx-auto mb-10 h-[220px] w-[220px]">
|
||||
{/* Outer ambient glow */}
|
||||
<div className="absolute -inset-16 rounded-full bg-rose-500/8 blur-[60px]" />
|
||||
{/* Rose disc — makes black heart visible as silhouette */}
|
||||
<div
|
||||
className="absolute inset-2 rounded-full"
|
||||
style={{
|
||||
background: "radial-gradient(circle, rgba(225,29,72,0.45) 0%, rgba(225,29,72,0.18) 45%, transparent 70%)",
|
||||
}}
|
||||
/>
|
||||
<Image
|
||||
src="/images/logo.png"
|
||||
alt={BRAND.name}
|
||||
width={220}
|
||||
height={220}
|
||||
priority
|
||||
unoptimized
|
||||
className="relative"
|
||||
style={{
|
||||
filter:
|
||||
"drop-shadow(0 0 6px rgba(225,29,72,0.5)) drop-shadow(0 0 20px rgba(225,29,72,0.25))",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h1 className="hero-title font-display text-5xl font-bold tracking-tight sm:text-6xl lg:text-8xl">
|
||||
{hero.headline}
|
||||
<span className="gradient-text">{hero.headline}</span>
|
||||
</h1>
|
||||
<p className="hero-subtitle body-text mx-auto mt-6 max-w-md text-lg sm:text-xl">
|
||||
|
||||
<p className="hero-subtitle mx-auto mt-6 max-w-lg text-lg text-neutral-400 sm:text-xl">
|
||||
{hero.subheadline}
|
||||
</p>
|
||||
<div className="hero-cta mt-10">
|
||||
|
||||
<div className="hero-cta mt-12">
|
||||
<Button href={hero.ctaHref} size="lg">
|
||||
{hero.ctaText}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scroll indicator */}
|
||||
<div className="hero-cta absolute bottom-8 left-1/2 -translate-x-1/2">
|
||||
<a
|
||||
href="#about"
|
||||
className="flex flex-col items-center gap-1 text-neutral-600 transition-colors hover:text-rose-400"
|
||||
>
|
||||
<span className="text-xs uppercase tracking-widest">Scroll</span>
|
||||
<ChevronDown size={20} className="animate-bounce" />
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useState, useRef, useEffect, useCallback } from "react";
|
||||
import Image from "next/image";
|
||||
import { Instagram } from "lucide-react";
|
||||
import { Instagram, ChevronLeft, ChevronRight } from "lucide-react";
|
||||
import { siteContent } from "@/data/content";
|
||||
import { SectionHeading } from "@/components/ui/SectionHeading";
|
||||
import { Reveal } from "@/components/ui/Reveal";
|
||||
@@ -12,51 +12,179 @@ import type { TeamMember } from "@/types";
|
||||
export function Team() {
|
||||
const { team } = siteContent;
|
||||
const [selectedMember, setSelectedMember] = useState<TeamMember | null>(null);
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
const scrollTimer = useRef<ReturnType<typeof setTimeout>>(null);
|
||||
const isDragging = useRef(false);
|
||||
const dragStartX = useRef(0);
|
||||
const dragScrollLeft = useRef(0);
|
||||
const dragMoved = useRef(false);
|
||||
|
||||
// Render 3 copies: [clone] [original] [clone]
|
||||
const tripled = [...team.members, ...team.members, ...team.members];
|
||||
|
||||
// On mount, jump to the middle set (no animation)
|
||||
useEffect(() => {
|
||||
const el = scrollRef.current;
|
||||
if (!el) return;
|
||||
requestAnimationFrame(() => {
|
||||
const cardWidth = el.scrollWidth / 3;
|
||||
el.scrollLeft = cardWidth;
|
||||
});
|
||||
}, []);
|
||||
|
||||
// When scroll settles, check if we need to loop
|
||||
const handleScroll = useCallback(() => {
|
||||
if (scrollTimer.current) clearTimeout(scrollTimer.current);
|
||||
scrollTimer.current = setTimeout(() => {
|
||||
const el = scrollRef.current;
|
||||
if (!el) return;
|
||||
const oneSetWidth = el.scrollWidth / 3;
|
||||
if (el.scrollLeft < oneSetWidth * 0.3) {
|
||||
el.style.scrollBehavior = "auto";
|
||||
el.scrollLeft += oneSetWidth;
|
||||
el.style.scrollBehavior = "";
|
||||
}
|
||||
if (el.scrollLeft > oneSetWidth * 1.7) {
|
||||
el.style.scrollBehavior = "auto";
|
||||
el.scrollLeft -= oneSetWidth;
|
||||
el.style.scrollBehavior = "";
|
||||
}
|
||||
}, 100);
|
||||
}, []);
|
||||
|
||||
// Mouse drag handlers
|
||||
function handleMouseDown(e: React.MouseEvent) {
|
||||
const el = scrollRef.current;
|
||||
if (!el) return;
|
||||
isDragging.current = true;
|
||||
dragMoved.current = false;
|
||||
dragStartX.current = e.pageX;
|
||||
dragScrollLeft.current = el.scrollLeft;
|
||||
el.style.scrollBehavior = "auto";
|
||||
el.style.scrollSnapType = "none";
|
||||
el.style.cursor = "grabbing";
|
||||
}
|
||||
|
||||
function handleMouseMove(e: React.MouseEvent) {
|
||||
if (!isDragging.current || !scrollRef.current) return;
|
||||
e.preventDefault();
|
||||
const dx = e.pageX - dragStartX.current;
|
||||
if (Math.abs(dx) > 3) dragMoved.current = true;
|
||||
scrollRef.current.scrollLeft = dragScrollLeft.current - dx;
|
||||
}
|
||||
|
||||
function handleMouseUp() {
|
||||
if (!isDragging.current || !scrollRef.current) return;
|
||||
isDragging.current = false;
|
||||
scrollRef.current.style.scrollBehavior = "";
|
||||
scrollRef.current.style.scrollSnapType = "";
|
||||
scrollRef.current.style.cursor = "";
|
||||
}
|
||||
|
||||
function handleCardClick(member: TeamMember) {
|
||||
// Don't open modal if user was dragging
|
||||
if (dragMoved.current) return;
|
||||
setSelectedMember(member);
|
||||
}
|
||||
|
||||
function scroll(direction: "left" | "right") {
|
||||
if (!scrollRef.current) return;
|
||||
const amount = scrollRef.current.offsetWidth * 0.7;
|
||||
scrollRef.current.scrollBy({
|
||||
left: direction === "left" ? -amount : amount,
|
||||
behavior: "smooth",
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<section id="team" className="surface-base section-padding">
|
||||
<section id="team" className="relative section-padding bg-neutral-50 dark:bg-[#050505]">
|
||||
<div className="section-divider absolute top-0 left-0 right-0" />
|
||||
|
||||
<div className="section-container">
|
||||
<Reveal>
|
||||
<SectionHeading>{team.title}</SectionHeading>
|
||||
</Reveal>
|
||||
</div>
|
||||
|
||||
<div className="mt-12 grid gap-8 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{team.members.map((member, i) => (
|
||||
<Reveal key={i}>
|
||||
{/* Carousel wrapper */}
|
||||
<Reveal>
|
||||
<div className="relative mt-10">
|
||||
{/* Scroll container */}
|
||||
<div
|
||||
ref={scrollRef}
|
||||
onScroll={handleScroll}
|
||||
onMouseDown={handleMouseDown}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseUp={handleMouseUp}
|
||||
onMouseLeave={handleMouseUp}
|
||||
className="flex cursor-grab gap-4 overflow-x-auto px-6 pb-4 sm:px-8 scroll-smooth snap-x snap-mandatory select-none lg:px-[max(2rem,calc((100vw-72rem)/2+2rem))]"
|
||||
style={{ scrollbarWidth: "none" }}
|
||||
>
|
||||
{tripled.map((member, i) => (
|
||||
<div
|
||||
className="card flex h-full cursor-pointer flex-col items-center text-center transition-transform hover:scale-[1.02]"
|
||||
onClick={() => setSelectedMember(member)}
|
||||
key={`${i}-${member.name}`}
|
||||
className="group relative w-[220px] shrink-0 cursor-pointer snap-start overflow-hidden rounded-2xl sm:w-[260px]"
|
||||
onClick={() => handleCardClick(member)}
|
||||
>
|
||||
<div className="mx-auto h-32 w-32 overflow-hidden rounded-full">
|
||||
{/* Photo */}
|
||||
<div className="aspect-[3/4] w-full overflow-hidden">
|
||||
<Image
|
||||
src={member.image}
|
||||
alt={member.name}
|
||||
width={128}
|
||||
height={128}
|
||||
className="h-full w-full object-cover"
|
||||
width={260}
|
||||
height={347}
|
||||
className="h-full w-full object-cover transition-transform duration-700 ease-out group-hover:scale-105"
|
||||
/>
|
||||
</div>
|
||||
<h3 className="heading-text mt-4 text-lg font-semibold">{member.name}</h3>
|
||||
{member.instagram && (
|
||||
<span
|
||||
className="nav-link mt-1 inline-flex gap-1.5 text-sm"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Instagram size={14} className="shrink-0 mt-[3px]" />
|
||||
<a
|
||||
href={member.instagram}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
|
||||
{/* Gradient overlay */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-black/20 to-transparent opacity-80 transition-opacity duration-500 group-hover:opacity-100" />
|
||||
|
||||
{/* Rose glow on hover */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-rose-900/20 to-transparent opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
|
||||
|
||||
{/* Content */}
|
||||
<div className="absolute bottom-0 left-0 right-0 p-4 translate-y-1 transition-transform duration-500 group-hover:translate-y-0">
|
||||
<h3 className="text-base font-semibold text-white sm:text-lg">
|
||||
{member.name}
|
||||
</h3>
|
||||
{member.instagram && (
|
||||
<span
|
||||
className="mt-1 inline-flex items-center gap-1.5 text-xs text-white/60 transition-colors hover:text-rose-400 sm:text-sm"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{member.instagram.split("/").filter(Boolean).pop()}
|
||||
</a>
|
||||
</span>
|
||||
)}
|
||||
<Instagram size={12} className="shrink-0" />
|
||||
<a
|
||||
href={member.instagram}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{member.instagram.split("/").filter(Boolean).pop()}
|
||||
</a>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
))}
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Side navigation arrows */}
|
||||
<button
|
||||
onClick={() => scroll("left")}
|
||||
className="absolute left-2 top-1/2 -translate-y-1/2 hidden h-10 w-10 items-center justify-center rounded-full bg-black/50 text-white/80 backdrop-blur-sm transition-all hover:bg-rose-500/30 hover:text-white sm:flex"
|
||||
aria-label="Назад"
|
||||
>
|
||||
<ChevronLeft size={22} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => scroll("right")}
|
||||
className="absolute right-2 top-1/2 -translate-y-1/2 hidden h-10 w-10 items-center justify-center rounded-full bg-black/50 text-white/80 backdrop-blur-sm transition-all hover:bg-rose-500/30 hover:text-white sm:flex"
|
||||
aria-label="Вперёд"
|
||||
>
|
||||
<ChevronRight size={22} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
<TeamMemberModal
|
||||
member={selectedMember}
|
||||
|
||||
Reference in New Issue
Block a user