tenext redesign
This commit is contained in:
@@ -1,45 +0,0 @@
|
||||
import { Counter } from "@/components/shared/Counter";
|
||||
|
||||
export function MetricsSection() {
|
||||
return (
|
||||
<section className="bg-white px-[20px] py-[60px] md:py-[100px]">
|
||||
<div className="mx-auto max-w-[1260px]">
|
||||
<div className="grid grid-cols-1 gap-[50px] md:grid-cols-2 md:gap-[80px]">
|
||||
{/* Left Metric */}
|
||||
<div className="flex flex-col gap-[20px]">
|
||||
<Counter
|
||||
target={250}
|
||||
suffix="+"
|
||||
numberClassName="text-[60px] md:text-[80px] font-bold leading-none text-transparent gradient-text-purple font-[var(--font-sora)]"
|
||||
title=""
|
||||
/>
|
||||
<h3 className="text-[28px] font-bold leading-[1.3] text-tenext-dark font-[var(--font-sora)]">
|
||||
Projects delivered
|
||||
</h3>
|
||||
<p className="text-[16px] leading-[1.8] text-tenext-text-muted mt-[10px]">
|
||||
Across retail, financial services, healthcare, manufacturing, and
|
||||
education.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Right Metric */}
|
||||
<div className="flex flex-col gap-[20px]">
|
||||
<Counter
|
||||
target={15}
|
||||
suffix="+"
|
||||
numberClassName="text-[60px] md:text-[80px] font-bold leading-none text-transparent gradient-text-purple font-[var(--font-sora)]"
|
||||
title=""
|
||||
/>
|
||||
<h3 className="text-[28px] font-bold leading-[1.3] text-tenext-dark font-[var(--font-sora)]">
|
||||
Years engineering digital products
|
||||
</h3>
|
||||
<p className="text-[16px] leading-[1.8] text-tenext-text-muted mt-[10px]">
|
||||
Helping enterprises modernize and scale with measurable business
|
||||
outcomes.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
|
||||
export function AboutIntroSection() {
|
||||
return (
|
||||
<SectionContainer paddingY="lg">
|
||||
<PageContainer className="grid grid-cols-1 gap-12 lg:grid-cols-[1fr_1fr] lg:gap-[60px] xl:gap-[100px]">
|
||||
{/* Left: Text Content */}
|
||||
<div className="flex flex-col items-start justify-center pt-5">
|
||||
<span
|
||||
className="tenext-subheading mb-4 text-tenext-teal"
|
||||
style={{ fontFamily: "var(--font-sora)" }}
|
||||
>
|
||||
about
|
||||
</span>
|
||||
<h2
|
||||
className="mb-6 tracking-[-0.03em] text-white"
|
||||
style={{
|
||||
fontFamily: "var(--font-dm-sans)",
|
||||
fontSize: "clamp(32px, 4vw, 56px)",
|
||||
fontWeight: 500,
|
||||
lineHeight: 1.1,
|
||||
}}
|
||||
>
|
||||
Awesome things in working with tenext WordPress theme
|
||||
</h2>
|
||||
<p className="mb-8 text-base leading-relaxed text-tenext-text-muted">
|
||||
At XXLando, we are a leading AI services provider dedicated to
|
||||
delivering innovative solutions that leverage artificial
|
||||
intelligence to transform businesses.
|
||||
</p>
|
||||
<p className="text-base leading-relaxed text-tenext-text-muted">
|
||||
Our team of experts specializes in developing cutting-edge AI
|
||||
technologies, such as machine learning, natural language processing,
|
||||
and computer vision, to help our clients streamline operations,
|
||||
enhance decision-making.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Right: Images */}
|
||||
<div className="relative">
|
||||
<div className="relative aspect-[4/5] w-full overflow-hidden rounded-[25px] bg-tenext-card-dark">
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center"
|
||||
style={{
|
||||
backgroundImage: "url(/images/tenext/home-9-img.png)",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { Counter } from "@/components/shared/Counter";
|
||||
|
||||
export function MissionSection() {
|
||||
return (
|
||||
<SectionContainer paddingY="lg">
|
||||
<PageContainer className="grid grid-cols-1 gap-12 lg:grid-cols-[1fr_1.2fr] lg:gap-[60px] xl:gap-[100px]">
|
||||
{/* Left: Images */}
|
||||
<div className="relative aspect-square w-full md:aspect-[4/3] lg:aspect-square">
|
||||
<div className="absolute bottom-0 left-0 h-[85%] w-[85%] overflow-hidden rounded-[25px] bg-tenext-card-dark">
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center"
|
||||
style={{
|
||||
backgroundImage: "url(/images/tenext/home-9-img.png)",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="absolute right-0 top-0 h-[50%] w-[50%] overflow-hidden rounded-[25px] border-[8px] border-tenext-dark bg-tenext-card-purple">
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center"
|
||||
style={{
|
||||
backgroundImage: "url(/images/tenext/home-9-img.png)",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right: Text and Stats */}
|
||||
<div className="flex flex-col items-start justify-center pt-5">
|
||||
<span
|
||||
className="tenext-subheading mb-4 text-tenext-teal"
|
||||
style={{ fontFamily: "var(--font-sora)" }}
|
||||
>
|
||||
Mission
|
||||
</span>
|
||||
<h2
|
||||
className="mb-6 tracking-[-0.03em] text-white"
|
||||
style={{
|
||||
fontFamily: "var(--font-dm-sans)",
|
||||
fontSize: "clamp(32px, 4vw, 56px)",
|
||||
fontWeight: 500,
|
||||
lineHeight: 1.1,
|
||||
}}
|
||||
>
|
||||
we create a professional product using artificial intelligence
|
||||
</h2>
|
||||
<p className="mb-10 text-base leading-relaxed text-tenext-text-muted">
|
||||
Certainly, crafting a clear and inspiring mission statement is
|
||||
essential for a development company. It should reflect your
|
||||
company's values, purpose, and commitment to innovation.
|
||||
</p>
|
||||
|
||||
<div className="w-full rounded-[25px] border border-tenext-card-border bg-tenext-card-dark p-8 md:p-10">
|
||||
<Counter
|
||||
target={1250}
|
||||
suffix="+"
|
||||
numberClassName="text-[60px] md:text-[80px] font-bold leading-none font-[var(--font-manrope)] gradient-text-purple"
|
||||
title="Created projects"
|
||||
titleClassName="font-[var(--font-sora)] text-[11px] font-semibold tracking-[0.18em] uppercase text-tenext-text-muted mt-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
|
||||
export function PricingSection() {
|
||||
const plans = [
|
||||
{
|
||||
name: "Basic",
|
||||
target: "Great for private individuals",
|
||||
features: [
|
||||
"1 User",
|
||||
"Unlimited Projects",
|
||||
"Download prototypes",
|
||||
"1 Gb workspace",
|
||||
],
|
||||
price: "Free",
|
||||
isPopular: false,
|
||||
},
|
||||
{
|
||||
name: "Premium",
|
||||
target: "14 days free period",
|
||||
features: [
|
||||
"15 Users",
|
||||
"Unlimited Projects",
|
||||
"Download prototypes",
|
||||
"15 Gb workspace",
|
||||
],
|
||||
price: "$ 59 /mo",
|
||||
isPopular: true,
|
||||
},
|
||||
{
|
||||
name: "Unlimited",
|
||||
target: "Great for private individuals",
|
||||
features: [
|
||||
"100 Users",
|
||||
"Unlimited Projects",
|
||||
"Download prototypes",
|
||||
"100 Gb workspace",
|
||||
],
|
||||
price: "$ 199 /mo",
|
||||
isPopular: false,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<SectionContainer paddingY="lg">
|
||||
<PageContainer>
|
||||
<div className="mb-16 flex flex-col items-center justify-center text-center">
|
||||
<SectionHeading
|
||||
tag="pricing"
|
||||
title="Choose the plan that fits your needs"
|
||||
titleClassName="text-white max-w-[500px] text-center"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
|
||||
{plans.map((plan, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={`relative flex flex-col overflow-hidden rounded-[25px] border ${
|
||||
plan.isPopular
|
||||
? "border-tenext-teal bg-tenext-card-dark"
|
||||
: "border-tenext-card-border bg-tenext-dark"
|
||||
} p-10`}
|
||||
>
|
||||
{plan.isPopular && (
|
||||
<div
|
||||
className="absolute right-6 top-6 rounded-full bg-tenext-teal px-4 py-1 text-[12px] font-bold uppercase text-tenext-dark"
|
||||
style={{ fontFamily: "var(--font-sora)" }}
|
||||
>
|
||||
Popular
|
||||
</div>
|
||||
)}
|
||||
<h3
|
||||
className="mb-2 text-[24px] font-bold text-white"
|
||||
style={{ fontFamily: "var(--font-dm-sans)" }}
|
||||
>
|
||||
{plan.name}
|
||||
</h3>
|
||||
<p className="mb-8 text-[14px] text-tenext-text-muted">
|
||||
{plan.target}
|
||||
</p>
|
||||
|
||||
<ul className="mb-10 flex flex-col gap-4">
|
||||
{plan.features.map((feat, j) => (
|
||||
<li key={j} className="flex items-center gap-3 text-white">
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
className="text-tenext-teal"
|
||||
>
|
||||
<path
|
||||
d="M20 6L9 17l-5-5"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
{feat}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<div className="mt-auto">
|
||||
<div
|
||||
className="mb-6 text-[36px] font-bold text-white"
|
||||
style={{ fontFamily: "var(--font-dm-sans)" }}
|
||||
>
|
||||
{plan.price}
|
||||
</div>
|
||||
<a
|
||||
href="#"
|
||||
className={`flex w-full items-center justify-center rounded-[12px] py-4 text-[16px] font-bold transition-all ${
|
||||
plan.isPopular
|
||||
? "bg-tenext-teal text-tenext-dark hover:bg-white"
|
||||
: "border border-tenext-card-border text-white hover:border-tenext-teal hover:text-tenext-teal"
|
||||
}`}
|
||||
style={{ fontFamily: "var(--font-sora)" }}
|
||||
>
|
||||
Get started
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
|
||||
const testimonials = [
|
||||
{
|
||||
author: "Daniel Cross",
|
||||
text: "Working with tenext has been a game-changer for our business. Their AI solutions automated our repetitive tasks and let us make data-driven decisions fast.",
|
||||
},
|
||||
{
|
||||
author: "Marta Wolfe",
|
||||
text: "The onboarding was smooth and the support team responded within a day for every request we had. Genuinely impressed with the attention to detail.",
|
||||
},
|
||||
{
|
||||
author: "Rajiv Patel",
|
||||
text: "tenext's dashboard gave us actionable insights we didn't have before. Setup was fast and the documentation made customization painless.",
|
||||
},
|
||||
{
|
||||
author: "Daniel Cross",
|
||||
text: "Working with tenext has been a game-changer for our business. Their AI solutions automated our repetitive tasks and let us make data-driven decisions fast.",
|
||||
},
|
||||
{
|
||||
author: "Elena Novak",
|
||||
text: "Excellent customer support from the whole team. All of our integration questions were resolved within a day.",
|
||||
},
|
||||
{
|
||||
author: "Sam Okafor",
|
||||
text: "A perfect solution in every respect. The team is especially strong on support — we recommend it without hesitation.",
|
||||
},
|
||||
{
|
||||
author: "Priya Chandran",
|
||||
text: "Fast, reliable support and an API that's genuinely easy to customize. Great work all around.",
|
||||
},
|
||||
{
|
||||
author: "Marta Wolfe",
|
||||
text: "The onboarding was smooth and the support team responded within a day for every request we had. Genuinely impressed with the attention to detail.",
|
||||
},
|
||||
{
|
||||
author: "Tom Bennett",
|
||||
text: "Great platform and even better support. The team always found a solution even when the request was out of scope.",
|
||||
},
|
||||
{
|
||||
author: "Lucia Fernandez",
|
||||
text: "High quality documentation and a codebase that's genuinely easy to extend. Our developers picked it up in a day.",
|
||||
},
|
||||
{
|
||||
author: "Rajiv Patel",
|
||||
text: "tenext's dashboard gave us actionable insights we didn't have before. Setup was fast and the documentation made customization painless.",
|
||||
},
|
||||
{
|
||||
author: "Owen Marsh",
|
||||
text: "We evaluated several AI vendors and tenext stood out for speed of support and clarity of their onboarding process.",
|
||||
},
|
||||
];
|
||||
|
||||
export function TestimonialsSection() {
|
||||
return (
|
||||
<SectionContainer paddingY="lg" className="bg-tenext-surface-muted">
|
||||
<PageContainer>
|
||||
<div className="mb-12 max-w-[650px]">
|
||||
<SectionHeading
|
||||
tag="testimonials"
|
||||
title="User stories: hear what others love about our AI solutions"
|
||||
titleClassName="text-tenext-dark"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="columns-1 gap-6 sm:columns-2 lg:columns-4">
|
||||
{testimonials.map((t, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="mb-6 break-inside-avoid rounded-[20px] bg-white p-8"
|
||||
>
|
||||
<h5
|
||||
className="mb-4 text-[18px] font-bold text-tenext-dark"
|
||||
style={{ fontFamily: "var(--font-dm-sans)" }}
|
||||
>
|
||||
{t.author}
|
||||
</h5>
|
||||
<p className="text-[15px] leading-[1.7] text-tenext-text-muted">
|
||||
{t.text}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CheckCircle2 } from "lucide-react";
|
||||
import { RevealOnView } from "@/components/shared/RevealOnView";
|
||||
|
||||
export function BenefitsGridSection() {
|
||||
return (
|
||||
@@ -6,7 +6,7 @@ export function BenefitsGridSection() {
|
||||
<div className="mx-auto max-w-[1260px]">
|
||||
<div className="grid grid-cols-1 gap-[30px] md:grid-cols-3">
|
||||
{/* Card 1 */}
|
||||
<div className="flex flex-col gap-[20px] rounded-[25px] border border-tenext-card-border p-[40px] transition-transform duration-300 hover:-translate-y-2">
|
||||
<RevealOnView className="flex flex-col gap-[20px] rounded-[25px] border border-tenext-card-border p-[40px] transition-transform duration-300 hover:-translate-y-2">
|
||||
<h4 className="text-[22px] font-bold leading-[1.3] text-tenext-dark font-[var(--font-sora)]">
|
||||
Predictable outcomes from your IT investments
|
||||
</h4>
|
||||
@@ -20,10 +20,10 @@ export function BenefitsGridSection() {
|
||||
Accelerated time to value
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</RevealOnView>
|
||||
|
||||
{/* Card 2 */}
|
||||
<div className="flex flex-col gap-[20px] rounded-[25px] border border-tenext-card-border p-[40px] transition-transform duration-300 hover:-translate-y-2">
|
||||
<RevealOnView delay={110} className="flex flex-col gap-[20px] rounded-[25px] border border-tenext-card-border p-[40px] transition-transform duration-300 hover:-translate-y-2">
|
||||
<h4 className="text-[22px] font-bold leading-[1.3] text-tenext-dark font-[var(--font-sora)]">
|
||||
Built to fit your existing business processes
|
||||
</h4>
|
||||
@@ -31,16 +31,18 @@ export function BenefitsGridSection() {
|
||||
Seamless integration with existing systems and platforms, on a
|
||||
scalable and flexible architecture engineered for the long term.
|
||||
</p>
|
||||
</div>
|
||||
</RevealOnView>
|
||||
|
||||
{/* Card 3 (OpenAI Logo) */}
|
||||
<div className="flex items-center justify-center rounded-[25px] border border-tenext-card-border bg-[#F8F9FA] p-[40px] transition-transform duration-300 hover:-translate-y-2">
|
||||
<img
|
||||
src="/images/tenext/openai-logo-1.png"
|
||||
alt="OpenAI Logo"
|
||||
className="w-[180px] h-auto object-contain"
|
||||
/>
|
||||
</div>
|
||||
{/* Card 3 */}
|
||||
<RevealOnView delay={220} className="flex flex-col gap-[20px] rounded-[25px] border border-tenext-card-border bg-[#F8F9FA] p-[40px] transition-transform duration-300 hover:-translate-y-2">
|
||||
<h4 className="text-[22px] font-bold leading-[1.3] text-tenext-dark font-[var(--font-sora)]">
|
||||
Security and governance built in
|
||||
</h4>
|
||||
<p className="text-[16px] leading-[1.6] text-tenext-text-muted mt-[10px]">
|
||||
Access control, data governance, and compliance-ready handling are
|
||||
designed in from the first sprint — not retrofitted later.
|
||||
</p>
|
||||
</RevealOnView>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -1,40 +1,32 @@
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { ArrowUpRight } from "lucide-react";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { resources } from "@/data/site-pages";
|
||||
|
||||
const blogPosts = [
|
||||
{
|
||||
title: "How to Build a Custom AI Model for Your Business",
|
||||
image: "/images/tenext/portrait-confident-man.jpg",
|
||||
category: "AI Technology",
|
||||
date: "March 15, 2025",
|
||||
link: "/blog/custom-ai-model",
|
||||
},
|
||||
{
|
||||
title: "The Future of Machine Learning in Enterprise",
|
||||
image: "/images/tenext/Group-18301.jpg",
|
||||
category: "Machine Learning",
|
||||
date: "April 2, 2025",
|
||||
link: "/blog/machine-learning-enterprise",
|
||||
},
|
||||
{
|
||||
title: "Ethics in AI: What You Need to Know",
|
||||
image:
|
||||
"/images/tenext/3d-woman-shape-glowing-with-bright-holographic-colors-1-min.png",
|
||||
category: "AI Ethics",
|
||||
date: "April 10, 2025",
|
||||
link: "/blog/ethics-in-ai",
|
||||
},
|
||||
/** Cover images, paired to the insights in data/site-pages.ts by order. */
|
||||
const coverImages = [
|
||||
"/images/tenext/portrait-confident-man.jpg",
|
||||
"/images/tenext/Group-18301.jpg",
|
||||
"/images/tenext/3d-woman-shape-glowing-with-bright-holographic-colors-1-min.png",
|
||||
];
|
||||
|
||||
const blogPosts = resources.map((resource, i) => ({
|
||||
title: resource.title,
|
||||
description: resource.description,
|
||||
image: coverImages[i % coverImages.length],
|
||||
category: resource.category,
|
||||
link: `/resources#${resource.id}`,
|
||||
}));
|
||||
|
||||
export function BlogSection() {
|
||||
return (
|
||||
<section className="bg-[#F8F9FA] px-[20px] py-[80px] md:py-[120px]">
|
||||
<div className="mx-auto max-w-[1260px]">
|
||||
<div className="mb-[60px] flex flex-col items-center text-center">
|
||||
<SectionHeading
|
||||
tag="blog"
|
||||
title="Exploring the world of artificial intelligence with tenext blogging"
|
||||
tag="insights"
|
||||
title="Perspectives on cloud, data, AI, and product engineering"
|
||||
titleClassName="max-w-[800px] text-tenext-dark"
|
||||
/>
|
||||
</div>
|
||||
@@ -46,28 +38,30 @@ export function BlogSection() {
|
||||
className="group flex flex-col overflow-hidden rounded-[25px] border border-tenext-card-border bg-white transition-shadow duration-300 hover:shadow-xl"
|
||||
>
|
||||
<div className="relative h-[250px] w-full overflow-hidden">
|
||||
<img
|
||||
<Image
|
||||
src={post.image}
|
||||
alt={post.title}
|
||||
className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-110"
|
||||
fill
|
||||
sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
|
||||
className="object-cover transition-transform duration-500 group-hover:scale-110"
|
||||
/>
|
||||
<div className="absolute left-[20px] top-[20px] rounded-full bg-white px-[15px] py-[5px] text-[12px] font-bold tracking-wide text-tenext-dark uppercase font-[var(--font-sora)]">
|
||||
{post.category}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col p-[30px]">
|
||||
<div className="mb-[15px] text-[14px] text-tenext-text-muted">
|
||||
{post.date}
|
||||
</div>
|
||||
<h4 className="mb-[20px] text-[22px] font-bold leading-[1.3] text-tenext-dark font-[var(--font-sora)] transition-colors group-hover:text-tenext-accent-teal">
|
||||
<h4 className="mb-[12px] text-[22px] font-bold leading-[1.3] text-tenext-dark font-[var(--font-sora)] transition-colors group-hover:text-tenext-accent-teal">
|
||||
<Link href={post.link}>{post.title}</Link>
|
||||
</h4>
|
||||
<p className="mb-[20px] text-[15px] leading-[1.6] text-tenext-text-muted">
|
||||
{post.description}
|
||||
</p>
|
||||
<div className="mt-auto">
|
||||
<Link
|
||||
href={post.link}
|
||||
className="inline-flex items-center gap-[10px] text-[15px] font-bold text-tenext-dark font-[var(--font-sora)] hover:text-tenext-accent-teal"
|
||||
>
|
||||
Read more
|
||||
Learn more
|
||||
<ArrowUpRight className="h-[18px] w-[18px]" />
|
||||
</Link>
|
||||
</div>
|
||||
@@ -1,35 +1,8 @@
|
||||
import Image from "next/image";
|
||||
import { CardHeading, IconButton } from "@/components/shared/CardShared";
|
||||
import { ChartIcon } from "@/components/shared/icons/ChartIcon";
|
||||
import { Counter } from "@/components/shared/Counter";
|
||||
import { RevealOnView } from "@/components/shared/RevealOnView";
|
||||
|
||||
const socialIcons = [
|
||||
{
|
||||
src: "/images/tenext/messenger-logo-1.png",
|
||||
alt: "Messenger",
|
||||
width: 57,
|
||||
height: 59,
|
||||
},
|
||||
{
|
||||
src: "/images/tenext/skype-logo.png",
|
||||
alt: "Skype",
|
||||
width: 56,
|
||||
height: 57,
|
||||
},
|
||||
{
|
||||
src: "/images/tenext/telegram-symbol-1.png",
|
||||
alt: "Telegram",
|
||||
width: 59,
|
||||
height: 58,
|
||||
},
|
||||
{
|
||||
src: "/images/tenext/discord-1.png",
|
||||
alt: "Discord",
|
||||
width: 54,
|
||||
height: 54,
|
||||
},
|
||||
];
|
||||
import { valueProps } from "@/data/site-content";
|
||||
|
||||
export function CardsGrid() {
|
||||
return (
|
||||
@@ -62,18 +35,10 @@ export function CardsGrid() {
|
||||
wrapperClassName="mb-0"
|
||||
/>
|
||||
|
||||
<div className="mt-[36px] flex items-center gap-[20px]">
|
||||
{socialIcons.map((icon) => (
|
||||
<Image
|
||||
key={icon.alt}
|
||||
src={icon.src}
|
||||
alt={icon.alt}
|
||||
width={icon.width}
|
||||
height={icon.height}
|
||||
className="h-auto w-auto"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-[24px] max-w-[420px] text-[16px] leading-[1.7] text-white/80">
|
||||
Architecture, development, and modernization of enterprise
|
||||
applications — engineered to scale with your business.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<IconButton />
|
||||
@@ -113,29 +78,13 @@ export function CardsGrid() {
|
||||
<div className="flex h-full flex-col gap-[20px]">
|
||||
{/* Card 3 - Top half */}
|
||||
<div className="tenext-card relative flex min-h-[176px] flex-col justify-center overflow-hidden rounded-[25px] bg-tenext-card-lavender p-[40px] lg:p-[45px_50px]">
|
||||
<a
|
||||
href="#"
|
||||
className="absolute inset-0 z-20"
|
||||
aria-label="Digital transactions processed daily"
|
||||
/>
|
||||
<div className="relative z-10 flex flex-col items-start">
|
||||
<div>
|
||||
<Counter
|
||||
target={500}
|
||||
suffix="K+"
|
||||
numberClassName="font-[var(--font-manrope)] text-[82px] font-extrabold leading-none tracking-[-0.04em] text-transparent"
|
||||
style={{
|
||||
WebkitTextStroke: "1px rgba(255,255,255,0.16)",
|
||||
backgroundImage:
|
||||
"linear-gradient(180deg, rgba(255,255,255,0.44) 0%, rgba(255,255,255,0.06) 90%)",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-[4px]">
|
||||
<h4 className="font-[var(--font-manrope)] text-[16px] font-medium leading-[20px] text-white">
|
||||
Digital transactions processed daily
|
||||
</h4>
|
||||
</div>
|
||||
<h4 className="font-[var(--font-sora)] text-[24px] font-bold leading-[1.25] text-white">
|
||||
{valueProps.reliability.title}
|
||||
</h4>
|
||||
<p className="mt-[10px] text-[15px] leading-[1.6] text-white/85">
|
||||
{valueProps.reliability.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -152,13 +101,10 @@ export function CardsGrid() {
|
||||
</div>
|
||||
|
||||
<div className="relative z-10">
|
||||
<Image
|
||||
src="/images/tenext/openai-logo-1.png"
|
||||
alt="OpenAI"
|
||||
width={272}
|
||||
height={71}
|
||||
className="h-auto w-[138px] lg:w-[152px]"
|
||||
/>
|
||||
<p className="max-w-[360px] text-[16px] leading-[1.7] text-white/80">
|
||||
Data platforms and applied AI that turn enterprise data into
|
||||
decision-ready insight.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,5 +1,4 @@
|
||||
import { CardHeading, IconButton } from "@/components/shared/CardShared";
|
||||
import { Counter } from "@/components/shared/Counter";
|
||||
|
||||
export function FeaturesSection() {
|
||||
return (
|
||||
@@ -106,21 +105,23 @@ export function FeaturesSection() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-[40px] sm:flex-row sm:gap-[60px] lg:pl-[15%]">
|
||||
<Counter
|
||||
target={98}
|
||||
suffix="%"
|
||||
numberClassName="text-[60px] font-bold leading-none font-[var(--font-manrope)] text-white"
|
||||
title="Client retention"
|
||||
titleClassName="font-[var(--font-sora)] text-[11px] font-semibold tracking-[0.18em] uppercase text-tenext-text-muted mt-2"
|
||||
/>
|
||||
<Counter
|
||||
target={24}
|
||||
suffix="/7"
|
||||
numberClassName="text-[60px] font-bold leading-none font-[var(--font-manrope)] text-white"
|
||||
title="Customer support"
|
||||
titleClassName="font-[var(--font-sora)] text-[11px] font-semibold tracking-[0.18em] uppercase text-tenext-text-muted mt-2"
|
||||
/>
|
||||
<div className="flex flex-col gap-[30px] lg:pl-[15%]">
|
||||
<div>
|
||||
<h4 className="text-[20px] font-bold text-white font-[var(--font-sora)]">
|
||||
Engineering ownership
|
||||
</h4>
|
||||
<p className="mt-[8px] text-[15px] leading-[1.7] text-tenext-text-muted">
|
||||
The team that designs a system builds and supports it.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-[20px] font-bold text-white font-[var(--font-sora)]">
|
||||
Support beyond go-live
|
||||
</h4>
|
||||
<p className="mt-[8px] text-[15px] leading-[1.7] text-tenext-text-muted">
|
||||
Monitoring, optimization, and managed support after launch.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,4 +1,4 @@
|
||||
import { HeroImageScene } from "@/components/aiero/HeroImageScene";
|
||||
import { HeroImageScene } from "@/components/sections/HeroImageScene";
|
||||
import { ScrollDown } from "@/components/shared/ScrollDown";
|
||||
|
||||
export function HeroSection() {
|
||||
@@ -1,4 +1,5 @@
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { RevealOnView } from "@/components/shared/RevealOnView";
|
||||
import { ArrowLeft, ArrowRight } from "lucide-react";
|
||||
|
||||
export function HowItWorksSection() {
|
||||
@@ -50,7 +51,7 @@ export function HowItWorksSection() {
|
||||
|
||||
<div className="flex flex-col">
|
||||
{steps.map((step, index) => (
|
||||
<div key={index} className="flex flex-col">
|
||||
<RevealOnView key={index} delay={index * 80} className="flex flex-col">
|
||||
<div className="flex flex-wrap items-center gap-[15px] rounded-[15px] bg-gradient-to-r from-tenext-blue to-tenext-purple-start px-[25px] py-[14px] text-white">
|
||||
<span className="text-[14px] font-bold">{step.number}</span>
|
||||
<span className="text-[18px] font-bold font-[var(--font-sora)]">
|
||||
@@ -60,7 +61,7 @@ export function HowItWorksSection() {
|
||||
<p className="mt-[20px] mb-[25px] max-w-[720px] text-[16px] leading-[1.6] text-tenext-text-muted">
|
||||
{step.description}
|
||||
</p>
|
||||
</div>
|
||||
</RevealOnView>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
34
components/sections/MetricsSection.tsx
Normal file
34
components/sections/MetricsSection.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import { RevealOnView } from "@/components/shared/RevealOnView";
|
||||
import { differentiators } from "@/data/site-content";
|
||||
|
||||
export function MetricsSection() {
|
||||
// Show the first four differentiators as a proof grid — real commitments
|
||||
// in place of the template's unverified statistics.
|
||||
const points = differentiators.slice(0, 4);
|
||||
|
||||
return (
|
||||
<section className="bg-white px-[20px] py-[60px] md:py-[100px]">
|
||||
<div className="mx-auto max-w-[1260px]">
|
||||
<div className="grid grid-cols-1 gap-[50px] sm:grid-cols-2 md:gap-[60px]">
|
||||
{points.map((point, index) => (
|
||||
<RevealOnView
|
||||
key={point.id}
|
||||
delay={index * 90}
|
||||
className="flex flex-col gap-[14px]"
|
||||
>
|
||||
<span className="gradient-text-purple text-[22px] font-bold font-[var(--font-sora)]">
|
||||
0{index + 1}
|
||||
</span>
|
||||
<h3 className="text-[24px] font-bold leading-[1.3] text-tenext-dark font-[var(--font-sora)]">
|
||||
{point.title}
|
||||
</h3>
|
||||
<p className="text-[16px] leading-[1.8] text-tenext-text-muted">
|
||||
{point.description}
|
||||
</p>
|
||||
</RevealOnView>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +1,20 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { navigationData } from "@/data/navigation";
|
||||
import { SearchIcon } from "@/components/shared/icons/SearchIcon";
|
||||
import { SiteLogo } from "@/components/shared/SiteLogo";
|
||||
|
||||
export function Navbar() {
|
||||
interface NavbarProps {
|
||||
/**
|
||||
* "overlay" — transparent, sits over a dark hero (home page).
|
||||
* "solid" — dark background, for inner pages that open on a light
|
||||
* surface so the white logo and links stay legible.
|
||||
*/
|
||||
variant?: "overlay" | "solid";
|
||||
}
|
||||
|
||||
export function Navbar({ variant = "solid" }: NavbarProps) {
|
||||
const [isSticky, setIsSticky] = useState(false);
|
||||
const [openDropdown, setOpenDropdown] = useState<string | null>(null);
|
||||
|
||||
@@ -17,15 +26,17 @@ export function Navbar() {
|
||||
return () => window.removeEventListener("scroll", onScroll);
|
||||
}, []);
|
||||
|
||||
const idleBg = variant === "overlay" ? "bg-transparent" : "bg-tenext-dark";
|
||||
|
||||
return (
|
||||
<header
|
||||
className={`tenext-navbar z-30 mx-auto grid h-[100px] max-w-[2520px] grid-cols-[280px_1fr_360px] items-center px-[34px] transition-[background-color,border-radius,box-shadow,transform] duration-500 ${
|
||||
className={`tenext-navbar z-30 mx-auto grid h-[100px] max-w-[2520px] grid-cols-[auto_1fr_auto] items-center px-[34px] transition-[background-color,border-radius,box-shadow,transform] duration-500 ${
|
||||
isSticky
|
||||
? "fixed left-5 right-5 top-0 rounded-b-[25px] bg-[#111111] shadow-[0_12px_35px_rgba(0,0,0,0.18)]"
|
||||
: "relative bg-transparent"
|
||||
: `relative ${idleBg}`
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-[64px]">
|
||||
<div className="flex items-center gap-[24px] xl:gap-[64px]">
|
||||
<button
|
||||
className="navbar-reveal grid h-6 w-6 grid-cols-2 gap-[5px] text-white transition-colors hover:text-tenext-teal"
|
||||
aria-label="Open menu"
|
||||
@@ -41,21 +52,15 @@ export function Navbar() {
|
||||
href="/"
|
||||
className="navbar-reveal flex items-center"
|
||||
style={{ animationDelay: "120ms" }}
|
||||
aria-label="Tenext Technologies — Home"
|
||||
>
|
||||
<Image
|
||||
src="/images/tenext/logo-dark.png"
|
||||
alt="tenext"
|
||||
width={109.5}
|
||||
height={19.5}
|
||||
className="h-auto w-auto"
|
||||
priority
|
||||
/>
|
||||
<SiteLogo size={24} />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Navigation */}
|
||||
<nav
|
||||
className="hidden items-center justify-center gap-[11px] lg:flex"
|
||||
className="hidden items-center justify-center gap-[4px] lg:flex xl:gap-[11px]"
|
||||
aria-label="Primary navigation"
|
||||
>
|
||||
{navigationData.map((item, index) => (
|
||||
@@ -68,7 +73,7 @@ export function Navbar() {
|
||||
>
|
||||
<a
|
||||
href={item.href}
|
||||
className={`nav-link-swap flex h-10 items-center rounded-[10px] px-[21px] text-[13px] font-bold uppercase leading-none text-white transition-colors hover:bg-tenext-dark ${
|
||||
className={`nav-link-swap flex h-10 items-center whitespace-nowrap rounded-[10px] px-[12px] text-[13px] font-bold uppercase leading-none text-white transition-colors hover:bg-tenext-dark xl:px-[21px] ${
|
||||
item.label === "Home" ? "bg-tenext-dark" : ""
|
||||
}`}
|
||||
style={{ fontFamily: "var(--font-sora)" }}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { tenextButton as TenextButton } from "@/components/shared/AieroButton";
|
||||
import { Counter } from "@/components/shared/Counter";
|
||||
import { tenextButton as TenextButton } from "@/components/shared/Button";
|
||||
import { IconBox } from "@/components/shared/IconBox";
|
||||
import { valueProps } from "@/data/site-content";
|
||||
import {
|
||||
OrbitIcon,
|
||||
FanIcon,
|
||||
@@ -48,23 +48,13 @@ export function PossibilitiesSection() {
|
||||
Explore more
|
||||
</TenextButton>
|
||||
|
||||
<div className="mt-[80px]">
|
||||
<Counter
|
||||
target={270}
|
||||
suffix="k"
|
||||
numberClassName="text-[60px] md:text-[100px] font-extrabold leading-none font-[var(--font-manrope)] text-transparent"
|
||||
style={{
|
||||
WebkitTextStroke: "1px #E2D7F8",
|
||||
backgroundImage:
|
||||
"linear-gradient(180deg, rgba(226, 215, 248, 0.44) 0%, rgba(226, 215, 248, 0.06) 90%)",
|
||||
backgroundClip: "text",
|
||||
WebkitBackgroundClip: "text",
|
||||
}}
|
||||
title="Engineering hours delivered for clients"
|
||||
titleClassName="font-[var(--font-manrope)] text-[16px] font-bold leading-[1.4] text-tenext-dark max-w-[160px]"
|
||||
layout="row-reverse"
|
||||
gap="30px"
|
||||
/>
|
||||
<div className="mt-[80px] max-w-[420px] border-t border-tenext-card-border pt-[30px]">
|
||||
<h3 className="text-[20px] font-bold text-tenext-dark font-[var(--font-sora)]">
|
||||
{valueProps.engineering.title}
|
||||
</h3>
|
||||
<p className="mt-[10px] text-[16px] leading-[1.7] text-tenext-text-muted">
|
||||
{valueProps.engineering.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -51,36 +51,19 @@ export function TinkerSection() {
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{/* Partners row */}
|
||||
<div className="flex flex-wrap items-center justify-start gap-x-[40px] gap-y-[30px]">
|
||||
<Image
|
||||
src="/images/tenext/partners-1.png"
|
||||
alt="Partner 1"
|
||||
width={140}
|
||||
height={40}
|
||||
className="h-auto w-[140px] object-contain"
|
||||
/>
|
||||
<Image
|
||||
src="/images/tenext/partners-2.png"
|
||||
alt="Partner 2"
|
||||
width={130}
|
||||
height={40}
|
||||
className="h-auto w-[130px] object-contain"
|
||||
/>
|
||||
<Image
|
||||
src="/images/tenext/partners-3.png"
|
||||
alt="Partner 3"
|
||||
width={100}
|
||||
height={40}
|
||||
className="h-auto w-[100px] object-contain"
|
||||
/>
|
||||
<Image
|
||||
src="/images/tenext/partners-4.png"
|
||||
alt="Partner 4"
|
||||
width={140}
|
||||
height={40}
|
||||
className="h-auto w-[140px] object-contain"
|
||||
/>
|
||||
{/* Capability tags */}
|
||||
<div className="flex flex-wrap items-center justify-start gap-[12px]">
|
||||
{["Cloud", "Data & AI", "IoT", "SMAC", "DevOps", "Blockchain"].map(
|
||||
(tag) => (
|
||||
<span
|
||||
key={tag}
|
||||
className="rounded-full border border-tenext-card-border px-[22px] py-[10px] text-[15px] font-medium text-tenext-dark"
|
||||
style={{ fontFamily: "var(--font-sora)" }}
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,4 +1,5 @@
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { ArrowIcon } from "@/components/shared/icons/ArrowIcon";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
|
||||
@@ -29,7 +30,7 @@ export function WOWSection() {
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<img
|
||||
<Image
|
||||
src="/images/tenext/home-9-img.png"
|
||||
alt="Tenext"
|
||||
width={632}
|
||||
52
components/sections/about/AboutCTA.tsx
Normal file
52
components/sections/about/AboutCTA.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import { tenextButton as TenextButton } from "@/components/shared/Button";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { aboutCta } from "@/data/about";
|
||||
|
||||
/** AboutCTA — large enterprise call to action on a premium gradient panel. */
|
||||
export function AboutCTA() {
|
||||
return (
|
||||
<section className="px-5 py-[60px] md:py-[80px]">
|
||||
<div className="relative overflow-hidden rounded-[25px] bg-tenext-dark px-[7vw] py-[80px] text-center md:py-[100px]">
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<div className="absolute left-1/2 top-[-40%] h-[600px] w-[600px] -translate-x-1/2 rounded-full bg-[radial-gradient(circle,rgba(103,102,200,0.35),transparent_60%)]" />
|
||||
<div className="absolute bottom-[-50%] left-[15%] h-[420px] w-[420px] rounded-full bg-[radial-gradient(circle,rgba(69,208,189,0.16),transparent_60%)]" />
|
||||
</div>
|
||||
|
||||
<PageContainer className="relative z-10 flex flex-col items-center">
|
||||
<h2
|
||||
className="max-w-[760px] tracking-[-0.03em] text-white"
|
||||
style={{
|
||||
fontFamily: "var(--font-dm-sans)",
|
||||
fontSize: "clamp(30px, 4vw, 56px)",
|
||||
fontWeight: 600,
|
||||
lineHeight: 1.1,
|
||||
}}
|
||||
>
|
||||
{aboutCta.title}
|
||||
</h2>
|
||||
<p className="mt-[22px] max-w-[560px] text-[17px] leading-[1.75] text-white/80">
|
||||
{aboutCta.paragraph}
|
||||
</p>
|
||||
<div className="mt-[40px] flex flex-wrap items-center justify-center gap-[16px]">
|
||||
<TenextButton
|
||||
href={aboutCta.primaryCta.href}
|
||||
variant="gradient-fill"
|
||||
className="rounded-[25px] px-[36px] py-[16px] text-[15px] font-semibold"
|
||||
showArrow={false}
|
||||
>
|
||||
{aboutCta.primaryCta.label}
|
||||
</TenextButton>
|
||||
<TenextButton
|
||||
href={aboutCta.secondaryCta.href}
|
||||
variant="gradient-border"
|
||||
className="rounded-[25px] px-[36px] py-[16px] text-[15px] font-medium text-white"
|
||||
showArrow={true}
|
||||
>
|
||||
{aboutCta.secondaryCta.label}
|
||||
</TenextButton>
|
||||
</div>
|
||||
</PageContainer>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
96
components/sections/about/AboutHero.tsx
Normal file
96
components/sections/about/AboutHero.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import Link from "next/link";
|
||||
import { tenextButton as TenextButton } from "@/components/shared/Button";
|
||||
import { Icon } from "@/components/shared/Icon";
|
||||
import { aboutHero } from "@/data/about";
|
||||
|
||||
const floatIcons = ["cloud", "cpu", "database", "code", "shield", "boxes"];
|
||||
|
||||
/**
|
||||
* AboutHero — flagship enterprise hero.
|
||||
* Left: breadcrumb, headline, supporting paragraph, primary + secondary CTA.
|
||||
* Right: an asset-free glass-tile composition of capability icons (no photos).
|
||||
*/
|
||||
export function AboutHero() {
|
||||
return (
|
||||
<section className="px-5 pt-5">
|
||||
<div className="relative overflow-hidden rounded-[25px] bg-tenext-dark px-[7vw] py-[80px] md:py-[110px]">
|
||||
{/* Ambient gradient wash */}
|
||||
<div className="pointer-events-none absolute inset-0 opacity-70">
|
||||
<div className="absolute -right-[10%] -top-[30%] h-[600px] w-[600px] rounded-full bg-[radial-gradient(circle,rgba(130,88,200,0.35),transparent_60%)]" />
|
||||
<div className="absolute -bottom-[40%] left-[10%] h-[500px] w-[500px] rounded-full bg-[radial-gradient(circle,rgba(69,208,189,0.18),transparent_60%)]" />
|
||||
</div>
|
||||
|
||||
<div className="relative z-10 grid grid-cols-1 items-center gap-[50px] lg:grid-cols-[1.1fr_0.9fr]">
|
||||
{/* Content */}
|
||||
<div>
|
||||
<nav aria-label="Breadcrumb" className="mb-[26px]">
|
||||
<ol className="flex items-center gap-2 text-[13px] text-white/60">
|
||||
<li>
|
||||
<Link href="/" className="transition-colors hover:text-tenext-teal">
|
||||
Home
|
||||
</Link>
|
||||
</li>
|
||||
<li className="h-1 w-1 rounded-full bg-tenext-teal" />
|
||||
<li className="text-white">About us</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<span className="tenext-subheading mb-[18px] text-tenext-teal" style={{ fontFamily: "var(--font-sora)" }}>
|
||||
{aboutHero.eyebrow}
|
||||
</span>
|
||||
|
||||
<h1
|
||||
className="max-w-[640px] tracking-[-0.03em] text-white"
|
||||
style={{
|
||||
fontFamily: "var(--font-dm-sans)",
|
||||
fontSize: "clamp(38px, 5vw, 72px)",
|
||||
fontWeight: 600,
|
||||
lineHeight: 1.06,
|
||||
}}
|
||||
>
|
||||
{aboutHero.title}
|
||||
</h1>
|
||||
|
||||
<p className="mt-[26px] max-w-[540px] text-[17px] leading-[1.75] text-white/80">
|
||||
{aboutHero.paragraph}
|
||||
</p>
|
||||
|
||||
<div className="mt-[40px] flex flex-wrap items-center gap-[16px]">
|
||||
<TenextButton
|
||||
href={aboutHero.primaryCta.href}
|
||||
variant="gradient-fill"
|
||||
className="rounded-[25px] px-[34px] py-[15px] text-[15px] font-semibold"
|
||||
showArrow={false}
|
||||
>
|
||||
{aboutHero.primaryCta.label}
|
||||
</TenextButton>
|
||||
<TenextButton
|
||||
href={aboutHero.secondaryCta.href}
|
||||
variant="gradient-border"
|
||||
className="rounded-[25px] px-[34px] py-[15px] text-[15px] font-medium text-white"
|
||||
showArrow={true}
|
||||
>
|
||||
{aboutHero.secondaryCta.label}
|
||||
</TenextButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Icon composition */}
|
||||
<div className="relative hidden lg:block" aria-hidden="true">
|
||||
<div className="grid grid-cols-3 gap-[16px]">
|
||||
{floatIcons.map((name, i) => (
|
||||
<div
|
||||
key={name}
|
||||
className="flex aspect-square items-center justify-center rounded-[22px] border border-white/10 bg-white/[0.04] text-tenext-teal backdrop-blur-sm transition-transform duration-500 hover:-translate-y-1"
|
||||
style={{ transform: `translateY(${i % 2 === 0 ? "-12px" : "12px"})` }}
|
||||
>
|
||||
<Icon name={name} className="h-[34px] w-[34px]" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
57
components/sections/about/AboutIndustries.tsx
Normal file
57
components/sections/about/AboutIndustries.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import Link from "next/link";
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { RevealOnView } from "@/components/shared/RevealOnView";
|
||||
import { ArrowIcon } from "@/components/shared/icons/ArrowIcon";
|
||||
import { Icon } from "@/components/shared/Icon";
|
||||
import { industries } from "@/data/site-pages";
|
||||
import { industryIcons } from "@/data/about";
|
||||
|
||||
/** AboutIndustries — premium industry cards (replaces the plain text list). */
|
||||
export function AboutIndustries() {
|
||||
return (
|
||||
<SectionContainer paddingY="lg" className="bg-white px-[20px]">
|
||||
<PageContainer>
|
||||
<SectionHeading
|
||||
tag="industries"
|
||||
title="Depth across the industries you operate in"
|
||||
description="We bring domain understanding and engineering rigor to the sectors where Tenext delivers transformation."
|
||||
titleClassName="text-tenext-dark max-w-[720px]"
|
||||
descriptionClassName="max-w-[620px]"
|
||||
className="mb-[50px]"
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-1 gap-[20px] sm:grid-cols-2 lg:grid-cols-3">
|
||||
{industries.map((industry, index) => (
|
||||
<RevealOnView key={industry.id} delay={index * 80}>
|
||||
<Link
|
||||
href={`/industries#${industry.id}`}
|
||||
className="group relative flex h-full flex-col justify-between overflow-hidden rounded-[25px] border border-tenext-card-border bg-tenext-dark p-[35px] transition-all duration-300 hover:-translate-y-2 hover:shadow-[0_22px_55px_rgba(31,31,31,0.22)]"
|
||||
>
|
||||
<div className="pointer-events-none absolute -right-[20%] -top-[30%] h-[240px] w-[240px] rounded-full bg-[radial-gradient(circle,rgba(69,208,189,0.16),transparent_65%)] opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
|
||||
|
||||
<span className="relative flex h-[60px] w-[60px] items-center justify-center rounded-[16px] bg-white/[0.06] text-tenext-teal">
|
||||
<Icon name={industryIcons[industry.id] ?? "building"} className="h-[28px] w-[28px]" />
|
||||
</span>
|
||||
|
||||
<div className="relative mt-[70px]">
|
||||
<h3 className="font-[var(--font-dm-sans)] text-[22px] font-bold text-white">
|
||||
{industry.title}
|
||||
</h3>
|
||||
<p className="mt-[12px] text-[15px] leading-[1.7] text-tenext-text-muted">
|
||||
{industry.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<span className="relative mt-[24px] flex h-[42px] w-[42px] items-center justify-center rounded-full border border-white/15 text-white transition-colors duration-300 group-hover:bg-tenext-teal group-hover:text-tenext-dark">
|
||||
<ArrowIcon className="h-[14px] w-[14px]" />
|
||||
</span>
|
||||
</Link>
|
||||
</RevealOnView>
|
||||
))}
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
66
components/sections/about/AboutPracticeTeams.tsx
Normal file
66
components/sections/about/AboutPracticeTeams.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { RevealOnView } from "@/components/shared/RevealOnView";
|
||||
import { tenextButton as TenextButton } from "@/components/shared/Button";
|
||||
import { Icon } from "@/components/shared/Icon";
|
||||
import { practiceTeamCards } from "@/data/about";
|
||||
|
||||
/**
|
||||
* AboutPracticeTeams — the disciplines that staff an engagement.
|
||||
* Each card has a unique gradient header and icon (no repeated artwork,
|
||||
* no invented individuals).
|
||||
*/
|
||||
export function AboutPracticeTeams() {
|
||||
return (
|
||||
<SectionContainer paddingY="lg" className="bg-white px-[20px]">
|
||||
<PageContainer>
|
||||
<div className="mb-[50px] flex flex-col gap-[24px] md:flex-row md:items-end md:justify-between">
|
||||
<SectionHeading
|
||||
tag="practice teams"
|
||||
title="Specialist teams behind every engagement"
|
||||
description="Engagements are staffed from practices that work together — so the people who design a system are the ones who build and support it."
|
||||
titleClassName="text-tenext-dark max-w-[640px]"
|
||||
descriptionClassName="max-w-[560px]"
|
||||
/>
|
||||
<TenextButton
|
||||
href="/careers"
|
||||
variant="simple"
|
||||
className="shrink-0 text-[15px] font-semibold text-tenext-dark"
|
||||
showArrow={true}
|
||||
>
|
||||
See open roles
|
||||
</TenextButton>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-[20px] sm:grid-cols-2 lg:grid-cols-3">
|
||||
{practiceTeamCards.map((team, index) => (
|
||||
<RevealOnView key={team.name} delay={index * 80}>
|
||||
<div className="group flex h-full flex-col overflow-hidden rounded-[25px] border border-tenext-card-border transition-all duration-300 hover:-translate-y-2 hover:shadow-[0_22px_55px_rgba(31,31,31,0.12)]">
|
||||
{/* Unique gradient header */}
|
||||
<div className={`relative h-[130px] bg-gradient-to-br ${team.gradient}`}>
|
||||
<div className="absolute inset-0 opacity-30 [background-image:radial-gradient(rgba(255,255,255,0.5)_1px,transparent_1px)] [background-size:16px_16px]" />
|
||||
<span className="absolute bottom-[-26px] left-[30px] flex h-[54px] w-[54px] items-center justify-center rounded-[16px] border border-white/20 bg-tenext-dark text-tenext-teal transition-transform duration-500 group-hover:-translate-y-1">
|
||||
<Icon name={team.icon} className="h-[26px] w-[26px]" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-1 flex-col p-[30px] pt-[40px]">
|
||||
<h3 className="font-[var(--font-dm-sans)] text-[20px] font-bold text-tenext-dark">
|
||||
{team.name}
|
||||
</h3>
|
||||
<p className="mt-[4px] text-[14px] font-semibold text-tenext-teal">
|
||||
/ {team.focus} /
|
||||
</p>
|
||||
<p className="mt-[14px] text-[15px] leading-[1.7] text-tenext-text-muted">
|
||||
{team.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</RevealOnView>
|
||||
))}
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
48
components/sections/about/DeliveryModel.tsx
Normal file
48
components/sections/about/DeliveryModel.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { RevealOnView } from "@/components/shared/RevealOnView";
|
||||
import { Icon } from "@/components/shared/Icon";
|
||||
import { deliverySteps } from "@/data/about";
|
||||
|
||||
/** DeliveryModel — connected timeline: Discover → … → Support. */
|
||||
export function DeliveryModel() {
|
||||
return (
|
||||
<SectionContainer paddingY="lg" className="bg-tenext-dark px-[20px]">
|
||||
<PageContainer>
|
||||
<SectionHeading
|
||||
tag="delivery model"
|
||||
title="A transparent path from idea to lasting impact"
|
||||
description="Every engagement moves through the same disciplined flow, so progress and cost stay visible at each step."
|
||||
titleClassName="text-white max-w-[720px]"
|
||||
descriptionClassName="max-w-[620px] text-tenext-text-muted"
|
||||
className="mb-[60px]"
|
||||
/>
|
||||
|
||||
<div className="relative grid grid-cols-1 gap-[20px] sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6">
|
||||
{/* Connecting line (desktop) */}
|
||||
<div className="pointer-events-none absolute left-0 right-0 top-[36px] hidden h-px bg-gradient-to-r from-tenext-teal/10 via-tenext-teal/40 to-tenext-teal/10 xl:block" />
|
||||
|
||||
{deliverySteps.map((step, index) => (
|
||||
<RevealOnView key={step.title} delay={index * 90} className="relative">
|
||||
<div className="flex flex-col items-start gap-[16px]">
|
||||
<div className="relative z-10 flex h-[72px] w-[72px] items-center justify-center rounded-[20px] border border-white/10 bg-tenext-dark text-tenext-teal">
|
||||
<Icon name={step.icon} className="h-[30px] w-[30px]" />
|
||||
<span className="absolute -right-2 -top-2 flex h-[26px] w-[26px] items-center justify-center rounded-full bg-tenext-teal text-[12px] font-bold text-tenext-dark">
|
||||
{index + 1}
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="font-[var(--font-sora)] text-[18px] font-bold text-white">
|
||||
{step.title}
|
||||
</h3>
|
||||
<p className="text-[14px] leading-[1.65] text-tenext-text-muted">
|
||||
{step.description}
|
||||
</p>
|
||||
</div>
|
||||
</RevealOnView>
|
||||
))}
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
85
components/sections/about/IconCardGrid.tsx
Normal file
85
components/sections/about/IconCardGrid.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { RevealOnView } from "@/components/shared/RevealOnView";
|
||||
import { Icon } from "@/components/shared/Icon";
|
||||
import { IconCard } from "@/data/about";
|
||||
|
||||
interface IconCardGridProps {
|
||||
id?: string;
|
||||
eyebrow?: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
items: IconCard[];
|
||||
columns?: 2 | 3 | 4;
|
||||
theme?: "light" | "surface" | "dark";
|
||||
}
|
||||
|
||||
const colClass: Record<number, string> = {
|
||||
2: "sm:grid-cols-2",
|
||||
3: "sm:grid-cols-2 lg:grid-cols-3",
|
||||
4: "sm:grid-cols-2 lg:grid-cols-4",
|
||||
};
|
||||
|
||||
/**
|
||||
* IconCardGrid — reusable premium icon-card section for the About page.
|
||||
* Powers Mission/Vision/Values, Why Tenext, Capabilities, Technology
|
||||
* Ecosystem, and Enterprise Trust with a single, consistent card.
|
||||
*/
|
||||
export function IconCardGrid({
|
||||
id,
|
||||
eyebrow,
|
||||
title,
|
||||
description,
|
||||
items,
|
||||
columns = 3,
|
||||
theme = "light",
|
||||
}: IconCardGridProps) {
|
||||
const isDark = theme === "dark";
|
||||
const sectionBg =
|
||||
theme === "dark"
|
||||
? "bg-tenext-dark"
|
||||
: theme === "surface"
|
||||
? "bg-tenext-surface-muted"
|
||||
: "bg-white";
|
||||
|
||||
const cardBase = isDark
|
||||
? "border-white/10 bg-white/[0.03] hover:border-tenext-teal/40"
|
||||
: "border-tenext-card-border bg-white hover:border-tenext-teal/50";
|
||||
const titleColor = isDark ? "text-white" : "text-tenext-dark";
|
||||
|
||||
return (
|
||||
<SectionContainer id={id} paddingY="lg" className={`${sectionBg} px-[20px] scroll-mt-[110px]`}>
|
||||
<PageContainer>
|
||||
<SectionHeading
|
||||
tag={eyebrow}
|
||||
title={title}
|
||||
description={description}
|
||||
titleClassName={`${titleColor} max-w-[760px]`}
|
||||
descriptionClassName={`max-w-[640px] ${isDark ? "text-tenext-text-muted" : ""}`}
|
||||
className="mb-[50px]"
|
||||
/>
|
||||
|
||||
<div className={`grid grid-cols-1 gap-[20px] ${colClass[columns]}`}>
|
||||
{items.map((item, index) => (
|
||||
<RevealOnView key={item.title} delay={index * 80}>
|
||||
<div
|
||||
className={`group flex h-full flex-col gap-[16px] rounded-[25px] border p-[35px] transition-all duration-300 hover:-translate-y-2 hover:shadow-[0_22px_55px_rgba(31,31,31,0.12)] ${cardBase}`}
|
||||
>
|
||||
<span className="flex h-[54px] w-[54px] items-center justify-center rounded-[15px] bg-tenext-teal/10 text-tenext-teal transition-colors duration-300 group-hover:bg-tenext-teal group-hover:text-tenext-dark">
|
||||
<Icon name={item.icon} className="h-[26px] w-[26px]" />
|
||||
</span>
|
||||
<h3 className={`font-[var(--font-sora)] text-[20px] font-bold leading-[1.3] ${titleColor}`}>
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="text-[15px] leading-[1.7] text-tenext-text-muted">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
</RevealOnView>
|
||||
))}
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
60
components/sections/about/OurStory.tsx
Normal file
60
components/sections/about/OurStory.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { RevealOnView } from "@/components/shared/RevealOnView";
|
||||
import { Icon } from "@/components/shared/Icon";
|
||||
import { ourStory } from "@/data/about";
|
||||
|
||||
const focusAreas = [
|
||||
{ icon: "code", label: "Engineering" },
|
||||
{ icon: "cloud", label: "Cloud" },
|
||||
{ icon: "cpu", label: "AI" },
|
||||
{ icon: "database", label: "Data" },
|
||||
{ icon: "workflow", label: "Digital Transformation" },
|
||||
{ icon: "chart", label: "Business Outcomes" },
|
||||
];
|
||||
|
||||
/** OurStory — company narrative with a focus-area rail. */
|
||||
export function OurStory() {
|
||||
return (
|
||||
<SectionContainer paddingY="lg" className="bg-tenext-surface-muted px-[20px]">
|
||||
<PageContainer>
|
||||
<div className="grid grid-cols-1 gap-[50px] lg:grid-cols-[0.85fr_1.15fr] lg:gap-[80px]">
|
||||
<RevealOnView>
|
||||
<SectionHeading
|
||||
tag={ourStory.eyebrow}
|
||||
title={ourStory.title}
|
||||
titleClassName="text-tenext-dark"
|
||||
/>
|
||||
<div className="mt-[36px] grid grid-cols-2 gap-[14px]">
|
||||
{focusAreas.map((area) => (
|
||||
<div
|
||||
key={area.label}
|
||||
className="flex items-center gap-[12px] rounded-[15px] border border-tenext-card-border bg-white px-[18px] py-[14px]"
|
||||
>
|
||||
<span className="text-tenext-teal">
|
||||
<Icon name={area.icon} className="h-[20px] w-[20px]" />
|
||||
</span>
|
||||
<span className="text-[14px] font-semibold text-tenext-dark font-[var(--font-sora)]">
|
||||
{area.label}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</RevealOnView>
|
||||
|
||||
<RevealOnView delay={120} className="flex flex-col gap-[24px]">
|
||||
{ourStory.paragraphs.map((paragraph, i) => (
|
||||
<p
|
||||
key={i}
|
||||
className={`leading-[1.85] text-tenext-text-muted ${i === 0 ? "text-[19px] text-tenext-dark" : "text-[16px]"}`}
|
||||
>
|
||||
{paragraph}
|
||||
</p>
|
||||
))}
|
||||
</RevealOnView>
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
@@ -3,82 +3,46 @@
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { tenextButton as TenextButton } from "@/components/shared/AieroButton";
|
||||
import { Counter } from "@/components/shared/Counter";
|
||||
|
||||
const teamMembers = [
|
||||
{
|
||||
name: "Alan Begham",
|
||||
role: "CEO",
|
||||
image: "/images/tenext/waist-up-shot-handsome-calm.jpg",
|
||||
},
|
||||
{
|
||||
name: "Arthur Dowson",
|
||||
role: "AI Programmer",
|
||||
image: "/images/tenext/funny-curious-man-makes.jpg",
|
||||
},
|
||||
{
|
||||
name: "Dan Smith",
|
||||
role: "Manager",
|
||||
image: "/images/tenext/portrait-confident-man.jpg",
|
||||
},
|
||||
{
|
||||
name: "Brandon Adams",
|
||||
role: "HR",
|
||||
image: "/images/tenext/confident-ginger-man-with-trendy.jpg",
|
||||
},
|
||||
{
|
||||
name: "Alan Begham",
|
||||
role: "CEO Neuro",
|
||||
image: "/images/tenext/waist-up-shot-handsome-calm.jpg",
|
||||
},
|
||||
];
|
||||
import { tenextButton as TenextButton } from "@/components/shared/Button";
|
||||
import { practiceTeams } from "@/data/site-content";
|
||||
|
||||
export function TeamSection() {
|
||||
return (
|
||||
<SectionContainer paddingY="lg">
|
||||
<SectionContainer id="teams" paddingY="lg" className="scroll-mt-[120px]">
|
||||
<PageContainer>
|
||||
<div className="columns-1 gap-6 sm:columns-2 lg:columns-4">
|
||||
<div className="mb-6 flex break-inside-avoid flex-col">
|
||||
<SectionHeading
|
||||
tag="team"
|
||||
title="The Neural Network experts: uniting talent for intelligent solutions"
|
||||
tag="our teams"
|
||||
title="Specialist teams behind every engagement"
|
||||
titleClassName="text-tenext-dark"
|
||||
/>
|
||||
<div className="mt-[40px]">
|
||||
<Counter
|
||||
target={500}
|
||||
prefix="+"
|
||||
numberClassName="text-[60px] font-extrabold leading-none font-[var(--font-manrope)] text-transparent"
|
||||
style={{
|
||||
WebkitTextStroke: "1px #E2D7F8",
|
||||
backgroundImage:
|
||||
"linear-gradient(180deg, rgba(226, 215, 248, 0.44) 0%, rgba(226, 215, 248, 0.06) 90%)",
|
||||
backgroundClip: "text",
|
||||
WebkitBackgroundClip: "text",
|
||||
}}
|
||||
title="Awesome team members"
|
||||
titleClassName="mt-[15px] text-[16px] font-bold text-tenext-dark"
|
||||
/>
|
||||
</div>
|
||||
<p className="mt-[24px] text-[16px] leading-[1.8] text-tenext-text-muted">
|
||||
Engagements are staffed from practices that work together —
|
||||
engineering, cloud, data, mobility, and commerce — so the people
|
||||
who design a system are the ones who build and support it.
|
||||
</p>
|
||||
<TenextButton
|
||||
href="/careers"
|
||||
variant="simple"
|
||||
className="mt-[25px] text-[15px] font-medium text-tenext-dark"
|
||||
showArrow={true}
|
||||
>
|
||||
Explore more
|
||||
See open roles
|
||||
</TenextButton>
|
||||
</div>
|
||||
|
||||
{teamMembers.map((member, i) => (
|
||||
{practiceTeams.map((team, i) => (
|
||||
<div
|
||||
key={i}
|
||||
key={`${team.name}-${i}`}
|
||||
className="group relative mb-6 break-inside-avoid overflow-hidden rounded-[25px] bg-tenext-card-dark"
|
||||
>
|
||||
<div className="relative aspect-[3/4] w-full">
|
||||
<img
|
||||
src={member.image}
|
||||
alt={member.name}
|
||||
src={team.image}
|
||||
alt=""
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-105"
|
||||
onError={(e) => {
|
||||
(e.target as HTMLImageElement).src =
|
||||
@@ -92,11 +56,9 @@ export function TeamSection() {
|
||||
className="text-[20px] font-bold"
|
||||
style={{ fontFamily: "var(--font-dm-sans)" }}
|
||||
>
|
||||
{member.name}
|
||||
{team.name}
|
||||
</h4>
|
||||
<p className="text-[14px] text-tenext-teal">
|
||||
/ {member.role} /
|
||||
</p>
|
||||
<p className="text-[14px] text-tenext-teal">/ {team.focus} /</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
58
components/sections/about/WhoWeAre.tsx
Normal file
58
components/sections/about/WhoWeAre.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { RevealOnView } from "@/components/shared/RevealOnView";
|
||||
import { Icon } from "@/components/shared/Icon";
|
||||
import { whoWeAre } from "@/data/about";
|
||||
|
||||
/** WhoWeAre — balanced two-column: positioning statement + what/who/why. */
|
||||
export function WhoWeAre() {
|
||||
return (
|
||||
<SectionContainer paddingY="lg" className="bg-white px-[20px]">
|
||||
<PageContainer>
|
||||
<div className="grid grid-cols-1 gap-[50px] lg:grid-cols-2 lg:gap-[80px]">
|
||||
{/* Left */}
|
||||
<RevealOnView>
|
||||
<span className="tenext-subheading mb-[16px] text-tenext-teal" style={{ fontFamily: "var(--font-sora)" }}>
|
||||
{whoWeAre.eyebrow}
|
||||
</span>
|
||||
<h2
|
||||
className="max-w-[480px] tracking-[-0.03em] text-tenext-dark"
|
||||
style={{
|
||||
fontFamily: "var(--font-dm-sans)",
|
||||
fontSize: "clamp(30px, 3.6vw, 48px)",
|
||||
fontWeight: 500,
|
||||
lineHeight: 1.12,
|
||||
}}
|
||||
>
|
||||
{whoWeAre.title}
|
||||
</h2>
|
||||
<p className="mt-[24px] max-w-[460px] text-[17px] leading-[1.75] text-tenext-text-muted">
|
||||
{whoWeAre.lead}
|
||||
</p>
|
||||
</RevealOnView>
|
||||
|
||||
{/* Right */}
|
||||
<div className="flex flex-col gap-[24px]">
|
||||
{whoWeAre.points.map((point, index) => (
|
||||
<RevealOnView key={point.title} delay={index * 90}>
|
||||
<div className="flex gap-[22px] rounded-[25px] border border-tenext-card-border p-[30px] transition-transform duration-300 hover:-translate-y-1">
|
||||
<span className="flex h-[54px] w-[54px] shrink-0 items-center justify-center rounded-[15px] bg-tenext-teal/10 text-tenext-teal">
|
||||
<Icon name={point.icon} className="h-[26px] w-[26px]" />
|
||||
</span>
|
||||
<div>
|
||||
<h3 className="mb-[8px] font-[var(--font-sora)] text-[19px] font-bold text-tenext-dark">
|
||||
{point.title}
|
||||
</h3>
|
||||
<p className="text-[15px] leading-[1.7] text-tenext-text-muted">
|
||||
{point.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</RevealOnView>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
@@ -1,17 +1,22 @@
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { siteConfig } from "@/data/site-config";
|
||||
|
||||
export function MapSection() {
|
||||
const query = encodeURIComponent(
|
||||
`${siteConfig.address.line1}, ${siteConfig.address.line2}`
|
||||
);
|
||||
|
||||
return (
|
||||
<SectionContainer paddingY="none" className="h-[500px] w-full">
|
||||
<iframe
|
||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d193595.15830869428!2d-74.11976397304603!3d40.69766374874431!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x89c24fa5d33f083b%3A0xc80b8f06e177fe62!2sNew%20York%2C%20NY%2C%20USA!5e0!3m2!1sen!2s!4v1716301234567!5m2!1sen!2s"
|
||||
src={`https://www.google.com/maps?q=${query}&output=embed`}
|
||||
width="100%"
|
||||
height="100%"
|
||||
style={{ border: 0 }}
|
||||
allowFullScreen={false}
|
||||
loading="lazy"
|
||||
referrerPolicy="no-referrer-when-downgrade"
|
||||
title="Google Map"
|
||||
title={`${siteConfig.legalName} — Coimbatore`}
|
||||
/>
|
||||
</SectionContainer>
|
||||
);
|
||||
50
components/sections/services/DeliveryPrinciplesSection.tsx
Normal file
50
components/sections/services/DeliveryPrinciplesSection.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { deliveryPrinciples } from "@/data/site-content";
|
||||
|
||||
/**
|
||||
* DeliveryPrinciplesSection — masonry grid of the commitments that keep
|
||||
* delivery predictable.
|
||||
*
|
||||
* Shared by: Home and Services.
|
||||
*
|
||||
* This slot held stock client testimonials in the original build. Tenext
|
||||
* does not publish named client quotes, so it presents how the company
|
||||
* works instead. If real, attributable testimonials become available,
|
||||
* this section is the place to reinstate them.
|
||||
*/
|
||||
export function DeliveryPrinciplesSection() {
|
||||
return (
|
||||
<SectionContainer paddingY="lg" className="bg-tenext-surface-muted">
|
||||
<PageContainer>
|
||||
<div className="mb-12 max-w-[650px]">
|
||||
<SectionHeading
|
||||
tag="how we work"
|
||||
title="The principles that keep delivery predictable"
|
||||
titleClassName="text-tenext-dark"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="columns-1 gap-6 sm:columns-2 lg:columns-4">
|
||||
{deliveryPrinciples.map((principle) => (
|
||||
<div
|
||||
key={principle.id}
|
||||
className="mb-6 break-inside-avoid rounded-[20px] bg-white p-8"
|
||||
>
|
||||
<h5
|
||||
className="mb-4 text-[18px] font-bold text-tenext-dark"
|
||||
style={{ fontFamily: "var(--font-dm-sans)" }}
|
||||
>
|
||||
{principle.title}
|
||||
</h5>
|
||||
<p className="text-[15px] leading-[1.7] text-tenext-text-muted">
|
||||
{principle.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
83
components/sections/services/EngagementModelsSection.tsx
Normal file
83
components/sections/services/EngagementModelsSection.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { engagementModels } from "@/data/site-content";
|
||||
|
||||
/**
|
||||
* EngagementModelsSection — the three ways enterprises work with Tenext.
|
||||
*
|
||||
* This slot held the template's SaaS pricing tiers. Tenext quotes
|
||||
* commercial terms per engagement, so no prices are published; each card
|
||||
* routes to the contact form instead.
|
||||
*/
|
||||
export function EngagementModelsSection() {
|
||||
return (
|
||||
<SectionContainer paddingY="lg">
|
||||
<PageContainer>
|
||||
<div className="mb-16 flex flex-col items-center justify-center text-center">
|
||||
<SectionHeading
|
||||
tag="engagement models"
|
||||
title="Ways to work with us"
|
||||
titleClassName="text-white max-w-[500px] text-center"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
|
||||
{engagementModels.map((model) => (
|
||||
<div
|
||||
key={model.name}
|
||||
className="relative flex flex-col overflow-hidden rounded-[25px] border border-tenext-card-border bg-tenext-dark p-10 transition-colors hover:border-tenext-teal"
|
||||
>
|
||||
<h3
|
||||
className="mb-4 text-[24px] font-bold text-white"
|
||||
style={{ fontFamily: "var(--font-dm-sans)" }}
|
||||
>
|
||||
{model.name}
|
||||
</h3>
|
||||
<p className="mb-8 text-[15px] leading-[1.7] text-tenext-text-muted">
|
||||
{model.summary}
|
||||
</p>
|
||||
|
||||
<ul className="mb-10 flex flex-col gap-4">
|
||||
{model.includes.map((item) => (
|
||||
<li
|
||||
key={item}
|
||||
className="flex items-start gap-3 text-[15px] text-white"
|
||||
>
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
className="mt-[3px] shrink-0 text-tenext-teal"
|
||||
aria-hidden
|
||||
>
|
||||
<path
|
||||
d="M20 6L9 17l-5-5"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<div className="mt-auto">
|
||||
<a
|
||||
href="/contacts"
|
||||
className="flex w-full items-center justify-center rounded-[12px] border border-tenext-card-border py-4 text-[16px] font-bold text-white transition-all hover:border-tenext-teal hover:text-tenext-teal"
|
||||
style={{ fontFamily: "var(--font-sora)" }}
|
||||
>
|
||||
Talk to an expert
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
@@ -1,38 +1,28 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { ArrowIcon } from "@/components/shared/icons/ArrowIcon";
|
||||
|
||||
const services = [
|
||||
{
|
||||
title: "Neural Network Development",
|
||||
desc: "Custom design and development of neural network architectures tailored to your specific business needs",
|
||||
},
|
||||
{
|
||||
title: "Training & Optimization",
|
||||
desc: "Fine-tuning and optimizing neural network models to improve accuracy, speed, and efficiency",
|
||||
},
|
||||
{
|
||||
title: "Neural Network Integration",
|
||||
desc: "Expert guidance and strategic advice on integrating neural networks into your existing systems",
|
||||
},
|
||||
];
|
||||
import { services } from "@/data/site-content";
|
||||
|
||||
export function ServiceCardsGrid() {
|
||||
return (
|
||||
<SectionContainer paddingY="lg">
|
||||
<PageContainer>
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||
{services.map((svc, i) => (
|
||||
{services.map((svc) => (
|
||||
<div
|
||||
key={i}
|
||||
className="group relative flex h-full min-h-[340px] flex-col justify-between overflow-hidden rounded-[25px] border border-tenext-card-border bg-tenext-card-dark p-10 transition-all hover:bg-tenext-card-purple"
|
||||
key={svc.id}
|
||||
id={svc.id}
|
||||
className="group relative flex h-full min-h-[340px] scroll-mt-[120px] flex-col justify-between overflow-hidden rounded-[25px] border border-tenext-card-border bg-tenext-card-dark p-10 transition-all hover:bg-tenext-card-purple"
|
||||
>
|
||||
<div className="mb-6 h-[60px] w-[60px] rounded-full bg-tenext-card-purple2 p-4">
|
||||
<img
|
||||
<Image
|
||||
src="/images/tenext/3x.png"
|
||||
alt="Icon"
|
||||
alt=""
|
||||
width={60}
|
||||
height={60}
|
||||
className="h-full w-full object-contain"
|
||||
onError={(e) => {
|
||||
(e.target as HTMLImageElement).src =
|
||||
@@ -48,7 +38,9 @@ export function ServiceCardsGrid() {
|
||||
>
|
||||
{svc.title}
|
||||
</h4>
|
||||
<p className="text-[16px] text-tenext-text-muted">{svc.desc}</p>
|
||||
<p className="text-[16px] text-tenext-text-muted">
|
||||
{svc.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-0 right-0 flex h-[60px] w-[60px] items-center justify-center rounded-tl-[25px] bg-white text-tenext-dark transition-all duration-300 group-hover:bg-tenext-teal group-hover:text-white">
|
||||
@@ -2,35 +2,9 @@ import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { IconBox } from "@/components/shared/IconBox";
|
||||
import { differentiators } from "@/data/site-content";
|
||||
|
||||
export function ServiceFeaturesSection() {
|
||||
const features = [
|
||||
{
|
||||
title: "AI Technology",
|
||||
desc: "Emphasize the expertise and knowledge of your team in developing and implementing neural networks.",
|
||||
},
|
||||
{
|
||||
title: "Tailored solutions",
|
||||
desc: "Mention your ability to create customized neural network solutions that specifically address your clients.",
|
||||
},
|
||||
{
|
||||
title: "Cutting-edge technology",
|
||||
desc: "Highlight that you use the latest and most advanced neural network frameworks and technologies.",
|
||||
},
|
||||
{
|
||||
title: "AI consultancy & strategy",
|
||||
desc: "Emphasize the expertise and knowledge of your team in developing and implementing neural networks.",
|
||||
},
|
||||
{
|
||||
title: "Computer vision",
|
||||
desc: "Mention your ability to create customized neural network solutions that specifically address your clients.",
|
||||
},
|
||||
{
|
||||
title: "Deployment & Integration",
|
||||
desc: "Highlight that you use the latest and most advanced neural network frameworks and technologies.",
|
||||
},
|
||||
];
|
||||
|
||||
const DefaultIcon = () => (
|
||||
<div className="flex h-full w-full items-center justify-center rounded-[18px] bg-tenext-card-purple">
|
||||
<svg
|
||||
@@ -56,19 +30,19 @@ export function ServiceFeaturesSection() {
|
||||
<PageContainer>
|
||||
<div className="mb-16">
|
||||
<SectionHeading
|
||||
tag="features"
|
||||
title="The unique selling points & advantages of our service"
|
||||
tag="why tenext"
|
||||
title="What enterprises get from working with us"
|
||||
titleClassName="text-white max-w-[700px]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-x-12 gap-y-12 md:grid-cols-2 lg:grid-cols-3">
|
||||
{features.map((feat, i) => (
|
||||
{differentiators.map((item, i) => (
|
||||
<IconBox
|
||||
key={i}
|
||||
key={item.id}
|
||||
icon={<DefaultIcon />}
|
||||
title={feat.title}
|
||||
description={feat.desc}
|
||||
title={item.title}
|
||||
description={item.description}
|
||||
hasBorder={i < 3} // The original has a border for the first row
|
||||
/>
|
||||
))}
|
||||
64
components/shared/AnchoredCardGrid.tsx
Normal file
64
components/shared/AnchoredCardGrid.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { RevealOnView } from "@/components/shared/RevealOnView";
|
||||
import { CardItem } from "@/data/site-pages";
|
||||
|
||||
interface AnchoredCardGridProps {
|
||||
tag?: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
items: CardItem[];
|
||||
/** Number of columns at lg breakpoint */
|
||||
columns?: 2 | 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* AnchoredCardGrid — data-driven grid of bordered cards.
|
||||
*
|
||||
* Each card carries an `id` so navbar hash links (e.g. /solutions#devops)
|
||||
* scroll to it. Shared by the Solutions and Industries pages; composes the
|
||||
* existing SectionContainer / PageContainer / SectionHeading primitives.
|
||||
*/
|
||||
export function AnchoredCardGrid({
|
||||
tag,
|
||||
title,
|
||||
description,
|
||||
items,
|
||||
columns = 3,
|
||||
}: AnchoredCardGridProps) {
|
||||
const colClass = columns === 2 ? "md:grid-cols-2" : "md:grid-cols-2 lg:grid-cols-3";
|
||||
|
||||
return (
|
||||
<SectionContainer paddingY="lg" className="bg-white px-[20px]">
|
||||
<PageContainer>
|
||||
<SectionHeading
|
||||
tag={tag}
|
||||
title={title}
|
||||
description={description}
|
||||
titleClassName="text-tenext-dark max-w-[720px]"
|
||||
descriptionClassName="max-w-[620px]"
|
||||
className="mb-[50px]"
|
||||
/>
|
||||
|
||||
<div className={`grid grid-cols-1 gap-[20px] ${colClass}`}>
|
||||
{items.map((item, index) => (
|
||||
<RevealOnView key={item.id} delay={index * 90}>
|
||||
<div
|
||||
id={item.id}
|
||||
className="flex h-full scroll-mt-[120px] flex-col gap-[15px] rounded-[25px] border border-tenext-card-border p-[40px] transition-transform duration-300 hover:-translate-y-2"
|
||||
>
|
||||
<h3 className="font-[var(--font-sora)] text-[22px] font-bold leading-[1.3] text-tenext-dark">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="text-[16px] leading-[1.7] text-tenext-text-muted">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
</RevealOnView>
|
||||
))}
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { type FormEvent, useState } from "react";
|
||||
import { siteConfig } from "@/data/site-config";
|
||||
import { ctaContent } from "@/data/site-content";
|
||||
import { SectionHeading } from "@/components/shared/SectionHeading";
|
||||
import { SocialIcons } from "@/components/shared/SocialIcons";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
@@ -42,10 +43,10 @@ export function ContactFormSection() {
|
||||
{/* ── Left: Info column ── */}
|
||||
<div className="flex flex-col">
|
||||
<SectionHeading
|
||||
tag="get in touch"
|
||||
title="We are always ready to help you and answer your questions"
|
||||
tag={ctaContent.contact.tag}
|
||||
title={ctaContent.contact.title}
|
||||
titleClassName="text-white"
|
||||
description="Pacific hake false trevally queen parrotfish black prickleback mosshead warbonnet sweeper! Greenling sleeper."
|
||||
description={ctaContent.contact.description}
|
||||
/>
|
||||
|
||||
{/* Contact details grid */}
|
||||
@@ -62,12 +63,6 @@ export function ContactFormSection() {
|
||||
>
|
||||
{siteConfig.phone}
|
||||
</a>
|
||||
<a
|
||||
href="tel:+11800234567"
|
||||
className="text-[15px] text-tenext-text-muted transition-colors hover:text-tenext-teal"
|
||||
>
|
||||
+ (123) 1800-234-5678
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { siteConfig } from "@/data/site-config";
|
||||
import { SocialIcons } from "@/components/shared/SocialIcons";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SiteLogo } from "@/components/shared/SiteLogo";
|
||||
|
||||
/**
|
||||
* Footer — shared site-wide footer.
|
||||
@@ -23,14 +23,8 @@ export function Footer() {
|
||||
<div className="grid grid-cols-1 gap-12 md:grid-cols-2 lg:grid-cols-[1.5fr_1fr_1fr]">
|
||||
{/* Brand column */}
|
||||
<div className="flex flex-col items-start gap-8">
|
||||
<Link href="/" aria-label="Home">
|
||||
<Image
|
||||
src="/images/tenext/logo-dark.png"
|
||||
alt={siteConfig.name}
|
||||
width={146}
|
||||
height={26}
|
||||
className="h-auto w-auto brightness-0 invert"
|
||||
/>
|
||||
<Link href="/" aria-label={`${siteConfig.legalName} — Home`}>
|
||||
<SiteLogo size={28} />
|
||||
</Link>
|
||||
|
||||
<SocialIcons links={siteConfig.socials} />
|
||||
|
||||
79
components/shared/Icon.tsx
Normal file
79
components/shared/Icon.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import {
|
||||
Cloud,
|
||||
Cpu,
|
||||
Database,
|
||||
Code2,
|
||||
Smartphone,
|
||||
Boxes,
|
||||
GitBranch,
|
||||
ShieldCheck,
|
||||
LineChart,
|
||||
Rocket,
|
||||
Target,
|
||||
Eye,
|
||||
Compass,
|
||||
Building2,
|
||||
Landmark,
|
||||
HeartPulse,
|
||||
Factory,
|
||||
GraduationCap,
|
||||
ShoppingBag,
|
||||
Layers,
|
||||
Workflow,
|
||||
Users,
|
||||
Sparkles,
|
||||
Handshake,
|
||||
BadgeCheck,
|
||||
Search,
|
||||
PenTool,
|
||||
Hammer,
|
||||
RefreshCw,
|
||||
TrendingUp,
|
||||
Headset,
|
||||
type LucideIcon,
|
||||
} from "lucide-react";
|
||||
|
||||
const map: Record<string, LucideIcon> = {
|
||||
cloud: Cloud,
|
||||
cpu: Cpu,
|
||||
database: Database,
|
||||
code: Code2,
|
||||
mobile: Smartphone,
|
||||
boxes: Boxes,
|
||||
devops: GitBranch,
|
||||
shield: ShieldCheck,
|
||||
chart: LineChart,
|
||||
rocket: Rocket,
|
||||
target: Target,
|
||||
eye: Eye,
|
||||
compass: Compass,
|
||||
building: Building2,
|
||||
landmark: Landmark,
|
||||
health: HeartPulse,
|
||||
factory: Factory,
|
||||
education: GraduationCap,
|
||||
retail: ShoppingBag,
|
||||
layers: Layers,
|
||||
workflow: Workflow,
|
||||
users: Users,
|
||||
sparkles: Sparkles,
|
||||
handshake: Handshake,
|
||||
badge: BadgeCheck,
|
||||
discover: Search,
|
||||
design: PenTool,
|
||||
build: Hammer,
|
||||
modernize: RefreshCw,
|
||||
scale: TrendingUp,
|
||||
support: Headset,
|
||||
};
|
||||
|
||||
interface IconProps {
|
||||
name: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/** Renders a named lucide icon. Keeps content data serializable (string keys). */
|
||||
export function Icon({ name, className = "h-6 w-6" }: IconProps) {
|
||||
const Cmp = map[name] ?? Sparkles;
|
||||
return <Cmp className={className} strokeWidth={1.6} />;
|
||||
}
|
||||
42
components/shared/LegalContent.tsx
Normal file
42
components/shared/LegalContent.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { RevealOnView } from "@/components/shared/RevealOnView";
|
||||
import { LegalSection, legalEffectiveDate } from "@/data/legal";
|
||||
|
||||
interface LegalContentProps {
|
||||
sections: LegalSection[];
|
||||
}
|
||||
|
||||
/**
|
||||
* LegalContent — shared renderer for Privacy and Terms pages.
|
||||
* Uses the site's spacing, container, typography, and reveal animation.
|
||||
*/
|
||||
export function LegalContent({ sections }: LegalContentProps) {
|
||||
return (
|
||||
<SectionContainer paddingY="lg" className="bg-white px-[20px]">
|
||||
<PageContainer className="max-w-[820px]">
|
||||
<p className="mb-[40px] text-[14px] font-semibold uppercase tracking-[0.1em] text-tenext-teal">
|
||||
Effective {legalEffectiveDate}
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col gap-[40px]">
|
||||
{sections.map((section, index) => (
|
||||
<RevealOnView key={section.heading} delay={index * 60}>
|
||||
<h2 className="mb-[16px] font-[var(--font-sora)] text-[24px] font-bold leading-[1.25] text-tenext-dark">
|
||||
{section.heading}
|
||||
</h2>
|
||||
{section.body.map((paragraph, i) => (
|
||||
<p
|
||||
key={i}
|
||||
className="mb-[14px] text-[16px] leading-[1.8] text-tenext-text-muted"
|
||||
>
|
||||
{paragraph}
|
||||
</p>
|
||||
))}
|
||||
</RevealOnView>
|
||||
))}
|
||||
</div>
|
||||
</PageContainer>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import { siteConfig } from "@/data/site-config";
|
||||
|
||||
interface BreadcrumbItem {
|
||||
label: string;
|
||||
href?: string;
|
||||
@@ -23,8 +25,23 @@ interface PageTitleBannerProps {
|
||||
* - Top-left and bottom-right rounded corner decorations
|
||||
*/
|
||||
export function PageTitleBanner({ title, breadcrumbs }: PageTitleBannerProps) {
|
||||
const breadcrumbJsonLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
itemListElement: breadcrumbs.map((crumb, index) => ({
|
||||
"@type": "ListItem",
|
||||
position: index + 1,
|
||||
name: crumb.label,
|
||||
...(crumb.href ? { item: `${siteConfig.url}${crumb.href}` } : {}),
|
||||
})),
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative mx-5 overflow-hidden rounded-[25px] bg-tenext-dark">
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbJsonLd) }}
|
||||
/>
|
||||
{/* Background image */}
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center opacity-80"
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
"use client";
|
||||
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { SectionContainer } from "@/components/shared/SectionContainer";
|
||||
import { industries } from "@/data/site-pages";
|
||||
|
||||
/**
|
||||
* Industries trust strip.
|
||||
*
|
||||
* Replaces the template's fabricated partner-logo carousel. Tenext does
|
||||
* not publish client logos here, so this presents the real industries it
|
||||
* serves. Swap in a genuine client-logo row once approved logos exist.
|
||||
*/
|
||||
export function PartnerLogosSection() {
|
||||
const logos = [
|
||||
"/images/tenext/partners-1.png",
|
||||
"/images/tenext/partners-2.png",
|
||||
"/images/tenext/partners-1.png",
|
||||
"/images/tenext/partners-2.png",
|
||||
"/images/tenext/partners-1.png",
|
||||
"/images/tenext/partners-2.png",
|
||||
];
|
||||
|
||||
return (
|
||||
<SectionContainer
|
||||
paddingY="lg"
|
||||
@@ -28,25 +25,18 @@ export function PartnerLogosSection() {
|
||||
lineHeight: 1.2,
|
||||
}}
|
||||
>
|
||||
Our trusted collaborators in progress and success
|
||||
Trusted to deliver across the industries we serve
|
||||
</h3>
|
||||
|
||||
<div className="flex flex-wrap justify-center gap-8 md:gap-16 lg:gap-24 opacity-60">
|
||||
{logos.map((src, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex h-12 items-center justify-center grayscale transition-all hover:grayscale-0"
|
||||
<div className="flex flex-wrap items-center justify-center gap-x-10 gap-y-6 md:gap-x-16">
|
||||
{industries.map((industry) => (
|
||||
<span
|
||||
key={industry.id}
|
||||
className="text-[18px] font-semibold text-white/70 transition-colors hover:text-tenext-teal md:text-[22px]"
|
||||
style={{ fontFamily: "var(--font-sora)" }}
|
||||
>
|
||||
<img
|
||||
src={src}
|
||||
alt={`Partner ${index + 1}`}
|
||||
className="h-full w-auto object-contain"
|
||||
onError={(e) => {
|
||||
(e.target as HTMLImageElement).src =
|
||||
"/images/tenext/logo-dark.png";
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{industry.title}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</PageContainer>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { tenextButton as TenextButton } from "@/components/shared/AieroButton";
|
||||
import { tenextButton as TenextButton } from "@/components/shared/Button";
|
||||
import { PageContainer } from "@/components/shared/PageContainer";
|
||||
import { ctaContent } from "@/data/site-content";
|
||||
|
||||
/**
|
||||
* PreFooterCTA — "Elevate your business with our innovative solutions" banner.
|
||||
* PreFooterCTA — closing conversion banner.
|
||||
*
|
||||
* Shared across: Home, About, Services, Contacts.
|
||||
*
|
||||
@@ -25,7 +26,7 @@ export function PreFooterCTA() {
|
||||
lineHeight: 1.15,
|
||||
}}
|
||||
>
|
||||
Elevate your business with our innovative solutions
|
||||
{ctaContent.preFooter.heading}
|
||||
</h2>
|
||||
|
||||
{/* CTA */}
|
||||
@@ -34,7 +35,7 @@ export function PreFooterCTA() {
|
||||
variant="simple"
|
||||
className="shrink-0 text-[15px] font-semibold text-tenext-teal"
|
||||
>
|
||||
Get in touch
|
||||
{ctaContent.preFooter.linkLabel}
|
||||
</TenextButton>
|
||||
</PageContainer>
|
||||
</section>
|
||||
|
||||
24
components/shared/SiteLogo.tsx
Normal file
24
components/shared/SiteLogo.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
interface SiteLogoProps {
|
||||
/** Extra classes (e.g. color overrides) */
|
||||
className?: string;
|
||||
/** Wordmark font-size in px — matches the slot it replaces */
|
||||
size?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* SiteLogo — Tenext Technologies wordmark.
|
||||
*
|
||||
* Temporary text logo in the project's Sora typography, used until an
|
||||
* official logo asset is supplied. Rendered on dark surfaces (navbar,
|
||||
* footer), so it defaults to white with a teal accent dot.
|
||||
*/
|
||||
export function SiteLogo({ className = "", size = 22 }: SiteLogoProps) {
|
||||
return (
|
||||
<span
|
||||
className={`font-bold leading-none tracking-[-0.02em] text-white ${className}`}
|
||||
style={{ fontFamily: "var(--font-sora)", fontSize: `${size}px` }}
|
||||
>
|
||||
Tenext<span className="text-tenext-teal">.</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user