tenext redesign

This commit is contained in:
2026-08-03 14:42:01 +05:30
parent 1e3f225bed
commit 6625bb9018
78 changed files with 2798 additions and 859 deletions

View 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>
);
}

View 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>
);
}

View 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>
);
}

View 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>
);
}

View 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>
);
}

View 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>
);
}

View 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>
);
}

View File

@@ -0,0 +1,69 @@
"use client";
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/Button";
import { practiceTeams } from "@/data/site-content";
export function TeamSection() {
return (
<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="our teams"
title="Specialist teams behind every engagement"
titleClassName="text-tenext-dark"
/>
<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}
>
See open roles
</TenextButton>
</div>
{practiceTeams.map((team, i) => (
<div
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={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 =
"/images/tenext/home-9-img.png";
}}
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-transparent to-transparent opacity-80" />
</div>
<div className="absolute bottom-0 left-0 w-full p-6 text-white transition-transform duration-300 group-hover:-translate-y-2">
<h4
className="text-[20px] font-bold"
style={{ fontFamily: "var(--font-dm-sans)" }}
>
{team.name}
</h4>
<p className="text-[14px] text-tenext-teal">/ {team.focus} /</p>
</div>
</div>
))}
</div>
</PageContainer>
</SectionContainer>
);
}

View 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>
);
}