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,50 @@
import { RevealOnView } from "@/components/shared/RevealOnView";
export function BenefitsGridSection() {
return (
<section className="relative overflow-hidden bg-white px-[20px] pb-[60px] md:pb-[100px]">
<div className="mx-auto max-w-[1260px]">
<div className="grid grid-cols-1 gap-[30px] md:grid-cols-3">
{/* Card 1 */}
<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>
<ul className="flex flex-col gap-[15px] mt-[10px]">
<li className="flex items-start gap-[10px] text-[16px] text-tenext-text-muted">
<span className="mt-[5px] h-[6px] w-[6px] rounded-full bg-tenext-accent-teal shrink-0"></span>
Lowest total cost of ownership
</li>
<li className="flex items-start gap-[10px] text-[16px] text-tenext-text-muted">
<span className="mt-[5px] h-[6px] w-[6px] rounded-full bg-tenext-accent-teal shrink-0"></span>
Accelerated time to value
</li>
</ul>
</RevealOnView>
{/* Card 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>
<p className="text-[16px] leading-[1.6] text-tenext-text-muted mt-[10px]">
Seamless integration with existing systems and platforms, on a
scalable and flexible architecture engineered for the long term.
</p>
</RevealOnView>
{/* 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>
);
}

View File

@@ -0,0 +1,75 @@
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";
/** 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="insights"
title="Perspectives on cloud, data, AI, and product engineering"
titleClassName="max-w-[800px] text-tenext-dark"
/>
</div>
<div className="grid grid-cols-1 gap-[30px] md:grid-cols-2 lg:grid-cols-3">
{blogPosts.map((post, index) => (
<div
key={index}
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">
<Image
src={post.image}
alt={post.title}
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]">
<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"
>
Learn more
<ArrowUpRight className="h-[18px] w-[18px]" />
</Link>
</div>
</div>
</div>
))}
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,115 @@
import Image from "next/image";
import { CardHeading, IconButton } from "@/components/shared/CardShared";
import { ChartIcon } from "@/components/shared/icons/ChartIcon";
import { RevealOnView } from "@/components/shared/RevealOnView";
import { valueProps } from "@/data/site-content";
export function CardsGrid() {
return (
<section className="px-[20px] pb-[20px]">
<div className="grid grid-cols-1 gap-[20px] md:grid-cols-2 xl:grid-cols-[1fr_1fr_0.73fr]">
{/* Card 1 */}
<RevealOnView delay={0}>
<div className="tenext-card group relative flex h-full flex-col justify-between overflow-hidden rounded-[25px] bg-tenext-card-purple p-[40px_35px_45px_35px] lg:p-[50px_45px_50px_45px]">
<Image
src="/images/tenext/assistant-artificial-intelligence-min.png"
alt=""
className="pointer-events-none absolute right-[-10px] top-[-10px] h-auto w-[150px] object-contain object-right-top transition-transform duration-500 group-hover:scale-105 lg:w-[190px]"
width={220}
height={274}
/>
<div className="relative z-10 flex gap-[6px]">
<span className="rounded-[15px] border border-white px-[20px] py-[5px] text-[12px] text-white transition-colors hover:border-tenext-teal hover:text-tenext-teal">
Engineering
</span>
<span className="rounded-[15px] border border-white px-[20px] py-[5px] text-[12px] text-white transition-colors hover:border-tenext-teal hover:text-tenext-teal">
Cloud
</span>
</div>
<div className="relative z-10 mt-[66px] max-w-[460px] lg:mt-[110px]">
<CardHeading
title="Build and modernize digital products with full-stack engineering expertise"
titleClassName="text-white"
wrapperClassName="mb-0"
/>
<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 />
</div>
</RevealOnView>
{/* Card 2 */}
<RevealOnView delay={110}>
<div className="tenext-card group relative flex h-full flex-col justify-between overflow-hidden rounded-[25px] bg-tenext-card-purple-2 p-[40px_35px_45px_35px] lg:p-[50px_45px_50px_45px]">
<div className="absolute inset-0 bg-tenext-card-purple-2" />
<div className="absolute inset-0 bg-[url('/images/tenext/c0eb2845-min.png')] bg-[length:60%] bg-right-bottom bg-no-repeat transition-transform duration-500 group-hover:scale-105" />
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-[#454f88]/16" />
<div className="relative z-10 mb-[54px] max-w-[515px]">
<div className="mb-[24px] inline-flex h-[38px] w-[38px] items-center justify-center">
<ChartIcon className="h-full w-full text-white" />
</div>
<CardHeading
title="Unified cloud and data platforms for smarter enterprise decisions."
titleClassName="text-white"
wrapperClassName="mb-[18px]"
/>
<p className="max-w-[448px] text-[16px] leading-[1.85] text-white">
Consolidate data across systems with secure, scalable platforms
that turn day-to-day operations into actionable insight.
</p>
</div>
<IconButton />
</div>
</RevealOnView>
{/* Card 3 (spans 2 columns) */}
<RevealOnView className="md:col-span-2 xl:col-span-1" delay={220}>
<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]">
<div className="relative z-10 flex flex-col items-start">
<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>
{/* Card 3 - Bottom half */}
<div className="tenext-card group relative flex flex-col justify-between overflow-hidden rounded-[25px] bg-tenext-card-dark p-[40px_35px_45px_35px] lg:p-[50px_45px_45px_45px]">
<div className="absolute inset-0 bg-[url('/images/tenext/Layer_2-min.jpg')] bg-cover bg-center transition-all duration-500 group-hover:scale-105" />
<div className="relative z-10 mb-[26px]">
<CardHeading
title="Apply AI and data science to automate and augment your operations"
titleClassName="text-white max-w-[80%]"
wrapperClassName="mb-0"
/>
</div>
<div className="relative z-10">
<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>
</RevealOnView>
</div>
</section>
);
}

View File

@@ -0,0 +1,132 @@
import { CardHeading, IconButton } from "@/components/shared/CardShared";
export function FeaturesSection() {
return (
<section className="bg-white px-[20px] pb-[100px] pt-[150px]">
<div className="mx-auto max-w-[1260px]">
{/* Top text and separator */}
<div className="mb-[70px] pr-[10%]">
<div className="mb-[20px] h-px w-[130px] bg-tenext-card-border" />
<h2
className="max-w-[700px] tracking-[-0.03em] text-tenext-dark"
style={{
fontFamily: "var(--font-sora)",
fontSize: "clamp(32px, 4vw, 56px)",
fontWeight: 700,
lineHeight: 1.1,
}}
>
Engineered for outcomes, built for scale
</h2>
</div>
{/* Feature Cards Grid */}
<div className="grid grid-cols-1 gap-[20px] lg:grid-cols-2">
{/* Card 1 - Left */}
<div className="relative flex flex-col justify-between overflow-hidden rounded-[25px] border border-tenext-card-border bg-tenext-card-dark p-[40px_35px_45px_35px] lg:p-[22%_9%_20%_9%]">
<div
className="absolute inset-0 bg-[url('/images/tenext/home-9-img.png')] bg-bottom bg-no-repeat transition-all duration-300 hover:scale-105"
style={{ backgroundSize: "100% auto" }}
/>
<div className="absolute inset-0 bg-gradient-to-t from-[#0D0D0D99] to-transparent to-[20%]" />
<div className="relative z-10 mt-auto">
<CardHeading
title="Integrate data across your enterprise to uncover deep insight"
titleClassName="text-white"
/>
<ul className="mt-[20px] flex flex-col gap-3">
<li className="flex items-center gap-3 text-tenext-text-muted">
<span className="flex h-1 w-1 rounded-full bg-tenext-text-muted" />
Advanced analytics processing
</li>
<li className="flex items-center gap-3 text-tenext-text-muted">
<span className="flex h-1 w-1 rounded-full bg-tenext-text-muted" />
Real-time data synchronization
</li>
<li className="flex items-center gap-3 text-tenext-text-muted">
<span className="flex h-1 w-1 rounded-full bg-tenext-text-muted" />
Secure API endpoints
</li>
</ul>
</div>
<IconButton />
</div>
{/* Card 2 - Right */}
<div className="relative flex flex-col justify-between overflow-hidden rounded-[25px] border border-tenext-card-border bg-tenext-card-dark p-[40px_35px_45px_35px] lg:p-[10%_9%_11%_9%]">
<div className="absolute inset-0 bg-[url('/images/tenext/Dots.png')] bg-[length:auto] bg-[50%_20px] bg-no-repeat opacity-20" />
<div className="relative z-10 flex h-[42px] w-[42px] items-center justify-center text-white">
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="h-full w-full"
>
<path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6" />
</svg>
</div>
<div className="relative z-10 mt-[60px] lg:mt-[100px]">
<CardHeading
title="Data privacy and security with robust measures"
titleClassName="text-white"
/>
<p className="text-[16px] text-tenext-text-muted">
Enterprise-grade security and governance built into every
engagement from secure architecture and access controls to
compliance-ready data handling.
</p>
</div>
<IconButton />
</div>
{/* Card 3 - Bottom Full Width */}
<div className="relative col-span-1 overflow-hidden rounded-[25px] border border-tenext-card-border bg-tenext-card-dark lg:col-span-2">
<div
className="absolute inset-0 bg-[url('/images/tenext/3d-woman-shape-glowing-with-bright-holographic-colors-1-min.png')] bg-right-bottom bg-no-repeat transition-all duration-300 hover:scale-105"
style={{ backgroundSize: "83% auto" }}
/>
<div className="relative z-10 grid grid-cols-1 gap-[40px] p-[40px_35px] lg:grid-cols-2 lg:p-[80px_60px]">
<div>
<CardHeading
subtitle="Technology"
title="Tailored solutions specifically to your needs"
titleClassName="text-white"
subtitleClassName="text-tenext-teal"
/>
</div>
<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>
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,214 @@
"use client";
import { useEffect, useRef } from "react";
import { Mesh, Plane, Program, Renderer, Texture } from "ogl";
const vertex = `
attribute vec2 uv;
attribute vec2 position;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(position, 0.0, 1.0);
}
`;
const fragment = `
precision highp float;
uniform sampler2D tMap;
uniform vec2 uResolution;
uniform vec2 uImageResolution;
uniform vec2 uPointer;
uniform vec2 uVelocity;
uniform float uStrength;
varying vec2 vUv;
vec2 coverUv(vec2 uv, vec2 screen, vec2 image) {
float screenRatio = screen.x / screen.y;
float imageRatio = image.x / image.y;
vec2 scale = vec2(1.0);
if (screenRatio > imageRatio) {
scale.y = imageRatio / screenRatio;
} else {
scale.x = screenRatio / imageRatio;
}
return (uv - 0.5) * scale + 0.5;
}
void main() {
vec2 uv = coverUv(vUv, uResolution, uImageResolution);
vec2 pointerDelta = uv - uPointer;
float distanceFromPointer = length(pointerDelta);
float cursorMask = smoothstep(0.36, 0.0, distanceFromPointer);
float innerMask = smoothstep(0.16, 0.0, distanceFromPointer);
vec2 pull = normalize(pointerDelta + 0.0001) * innerMask * 0.0035;
vec2 distortion = ((uVelocity * 0.075) - pull) * cursorMask * uStrength;
uv += distortion;
float red = texture2D(tMap, uv + distortion * 0.12).r;
float green = texture2D(tMap, uv).g;
float blue = texture2D(tMap, uv - distortion * 0.1).b;
gl_FragColor = vec4(red, green, blue, 1.0);
}
`;
interface HeroImageSceneProps {
imageSrc: string;
}
export function HeroImageScene({ imageSrc }: HeroImageSceneProps) {
const rootRef = useRef<HTMLDivElement>(null);
const pointerRef = useRef({ x: 0.5, y: 0.5 });
const velocityRef = useRef({ x: 0, y: 0 });
const strengthRef = useRef(0);
const lastMoveTimeRef = useRef(0);
useEffect(() => {
const root = rootRef.current;
if (!root) return;
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
if (reduceMotion.matches) return;
const renderer = new Renderer({
alpha: true,
antialias: true,
dpr: Math.min(window.devicePixelRatio, 2),
});
const gl = renderer.gl;
root.appendChild(gl.canvas);
gl.canvas.className = "absolute inset-0 h-full w-full";
gl.clearColor(0, 0, 0, 0);
const texture = new Texture(gl, {
generateMipmaps: false,
minFilter: gl.LINEAR,
magFilter: gl.LINEAR,
});
const image = new Image();
image.src = imageSrc;
image.onload = () => {
texture.image = image;
texture.needsUpdate = true;
};
const program = new Program(gl, {
vertex,
fragment,
uniforms: {
tMap: { value: texture },
uResolution: { value: [1, 1] },
uImageResolution: { value: [1883, 855] },
uPointer: { value: [0.5, 0.5] },
uVelocity: { value: [0, 0] },
uStrength: { value: 0 },
},
transparent: true,
});
const mesh = new Mesh(gl, {
geometry: new Plane(gl, { width: 2, height: 2 }),
program,
});
let animationFrame = 0;
let width = 1;
let height = 1;
const resize = () => {
const rect = root.getBoundingClientRect();
width = Math.max(1, rect.width);
height = Math.max(1, rect.height);
renderer.setSize(width, height);
program.uniforms.uResolution.value = [width, height];
};
const onPointerMove = (event: PointerEvent) => {
const rect = root.getBoundingClientRect();
const isInside =
event.clientX >= rect.left &&
event.clientX <= rect.right &&
event.clientY >= rect.top &&
event.clientY <= rect.bottom;
if (!isInside) {
velocityRef.current = { x: 0, y: 0 };
return;
}
const nextPointer = {
x: (event.clientX - rect.left) / rect.width,
y: 1 - (event.clientY - rect.top) / rect.height,
};
const now = performance.now();
const elapsed = Math.max(16, now - lastMoveTimeRef.current);
lastMoveTimeRef.current = now;
velocityRef.current = {
x: ((nextPointer.x - pointerRef.current.x) / elapsed) * 16.67,
y: ((nextPointer.y - pointerRef.current.y) / elapsed) * 16.67,
};
pointerRef.current = nextPointer;
strengthRef.current = Math.min(1, strengthRef.current + 0.72);
};
const onPointerLeave = () => {
velocityRef.current = { x: 0, y: 0 };
};
const render = () => {
strengthRef.current *= 0.86;
velocityRef.current = {
x: velocityRef.current.x * 0.74,
y: velocityRef.current.y * 0.74,
};
program.uniforms.uPointer.value = [
pointerRef.current.x,
pointerRef.current.y,
];
program.uniforms.uVelocity.value = [
velocityRef.current.x,
velocityRef.current.y,
];
program.uniforms.uStrength.value = strengthRef.current;
renderer.render({ scene: mesh });
animationFrame = requestAnimationFrame(render);
};
const observer = new ResizeObserver(resize);
observer.observe(root);
window.addEventListener("pointermove", onPointerMove);
root.addEventListener("pointerleave", onPointerLeave);
resize();
animationFrame = requestAnimationFrame(render);
return () => {
cancelAnimationFrame(animationFrame);
observer.disconnect();
window.removeEventListener("pointermove", onPointerMove);
root.removeEventListener("pointerleave", onPointerLeave);
gl.canvas.remove();
};
}, [imageSrc]);
return (
<div
ref={rootRef}
aria-hidden="true"
className="hero-ogl-scene absolute inset-[-18px]"
>
<div
className="absolute inset-0 bg-cover bg-center"
style={{ backgroundImage: `url(${imageSrc})` }}
/>
</div>
);
}

View File

@@ -0,0 +1,81 @@
import { HeroImageScene } from "@/components/sections/HeroImageScene";
import { ScrollDown } from "@/components/shared/ScrollDown";
export function HeroSection() {
return (
<section className="relative px-5 py-5">
{/* Scroll Down button — vertical, left side */}
<div className="scroll-widget absolute left-0 top-[40%] z-20 hidden xl:block">
<ScrollDown />
</div>
{/* Hero container with background */}
<div
className="relative overflow-hidden rounded-[25px] bg-tenext-dark"
style={{
minHeight: "min(858px, calc(100vw * 0.447))",
padding: "14.3% 0 8.1% 0",
}}
>
<HeroImageScene imageSrc="/images/tenext/home-9-top-bg-min.jpg" />
{/* Hero content */}
<div className="relative z-10 w-full px-[12.7vw]">
<div className="flex flex-col items-start">
{/* Heading */}
<h1
className="hero-reveal mb-[24px] max-w-[1280px] text-left tracking-[-0.03em] text-white"
style={{
fontFamily: "var(--font-manrope)",
fontSize: "clamp(42px, 4.43vw, 85px)",
fontWeight: 400,
lineHeight: 1.06,
}}
>
Engineering predictable outcomes from your digital investments
</h1>
{/* Subtitle */}
<div
className="hero-reveal max-w-[660px]"
style={{ animationDelay: "760ms" }}
>
<p className="text-[16px] font-semibold leading-[1.9] text-white">
Tenext helps enterprises transform with cloud, data, AI, and
product engineering built to lower total cost of ownership and
accelerate time to value.
</p>
</div>
{/* CTA Button */}
<div
className="hero-reveal mt-[42px]"
style={{ animationDelay: "940ms" }}
>
<a
href="/contacts"
className="tenext-button tenext-button-solid inline-flex items-center gap-2 rounded-[25px] border border-tenext-red bg-tenext-red px-[30px] py-[14px] text-[16px] text-white transition-all hover:-translate-y-0.5 hover:border-tenext-red-hover hover:bg-tenext-red-hover hover:shadow-[0_15px_30px_rgba(239,100,100,0.28)]"
style={{ minWidth: "216px", fontFamily: "var(--font-sora)" }}
>
Talk to an expert
<svg width="10" height="10" viewBox="0 0 12 12" fill="none">
<path
d="M1 11L11 1M11 1H3M11 1V9"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
<span className="button-inner" />
</a>
</div>
</div>
</div>
{/* Scroll anchor */}
<div id="scroll-down" className="absolute bottom-0" />
</div>
</section>
);
}

View File

@@ -0,0 +1,70 @@
import { SectionHeading } from "@/components/shared/SectionHeading";
import { RevealOnView } from "@/components/shared/RevealOnView";
import { ArrowLeft, ArrowRight } from "lucide-react";
export function HowItWorksSection() {
const steps = [
{
number: "01",
title: "Discover & Diagnose",
description:
"We assess your systems, processes, and goals to identify where technology can deliver the highest business value.",
},
{
number: "02",
title: "Design",
description:
"We architect a focused solution that fits your existing landscape, balancing cost, scale, and time to value.",
},
{
number: "03",
title: "Build & Integrate",
description:
"Our engineering teams build, integrate, and test — connecting new capabilities to the systems you already run.",
},
{
number: "04",
title: "Deploy & Optimize",
description:
"We deploy with confidence and keep improving through monitoring, support, and continuous optimization.",
},
];
return (
<section className="bg-white px-[20px] py-[60px] md:py-[100px]">
<div className="mx-auto max-w-[1260px]">
<div className="flex flex-col md:flex-row md:items-end justify-between gap-[30px] mb-[60px]">
<SectionHeading
tag="how it works"
title="A transparent path from idea to measurable impact"
titleClassName="max-w-[700px] text-tenext-dark"
/>
<div className="flex gap-[15px]">
<button className="flex h-[50px] w-[50px] items-center justify-center rounded-full border border-tenext-card-border text-tenext-dark transition-colors hover:bg-tenext-card-border">
<ArrowLeft size={20} />
</button>
<button className="flex h-[50px] w-[50px] items-center justify-center rounded-full border border-tenext-card-border text-tenext-dark transition-colors hover:bg-tenext-card-border">
<ArrowRight size={20} />
</button>
</div>
</div>
<div className="flex flex-col">
{steps.map((step, index) => (
<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)]">
{step.title}
</span>
</div>
<p className="mt-[20px] mb-[25px] max-w-[720px] text-[16px] leading-[1.6] text-tenext-text-muted">
{step.description}
</p>
</RevealOnView>
))}
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,39 @@
interface MarqueeStripProps {
text?: string;
className?: string;
}
export function MarqueeStrip({
text = "Artificial Intelligence",
className = "",
}: MarqueeStripProps) {
const marqueeItems = Array.from({ length: 6 });
return (
<div
className={`relative z-10 mx-[-5px] mb-[-20px] mt-0 overflow-hidden bg-gradient-to-r from-tenext-teal to-tenext-blue py-[42px] ${className}`}
style={{ transform: "rotate(-2.07deg)" }}
>
<div className="marquee-track flex w-max whitespace-nowrap">
{[0, 1].map((track) => (
<div key={track} className="flex shrink-0 items-center">
{marqueeItems.map((_, i) => (
<div
key={`${track}-${i}`}
className="flex items-center gap-8 pr-8"
>
<span
className="marquee-text text-white"
style={{ fontFamily: "var(--font-sora)" }}
>
{text}
</span>
<span className="flex h-3 w-3 rounded-full bg-white opacity-50" />
</div>
))}
</div>
))}
</div>
</div>
);
}

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

View File

@@ -0,0 +1,175 @@
"use client";
import { useEffect, useState } from "react";
import { navigationData } from "@/data/navigation";
import { SearchIcon } from "@/components/shared/icons/SearchIcon";
import { SiteLogo } from "@/components/shared/SiteLogo";
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);
useEffect(() => {
const onScroll = () => setIsSticky(window.scrollY > 120);
onScroll();
window.addEventListener("scroll", onScroll, { passive: true });
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-[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 ${idleBg}`
}`}
>
<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"
>
<span className="h-[7px] w-[7px] rounded-[2px] border-2 border-current" />
<span className="h-[7px] w-[7px] rounded-[2px] border-2 border-current" />
<span className="h-[7px] w-[7px] rounded-[2px] border-2 border-current" />
<span className="h-[7px] w-[7px] rounded-[2px] border-2 border-current" />
</button>
{/* Logo */}
<a
href="/"
className="navbar-reveal flex items-center"
style={{ animationDelay: "120ms" }}
aria-label="Tenext Technologies — Home"
>
<SiteLogo size={24} />
</a>
</div>
{/* Navigation */}
<nav
className="hidden items-center justify-center gap-[4px] lg:flex xl:gap-[11px]"
aria-label="Primary navigation"
>
{navigationData.map((item, index) => (
<div
key={item.label}
className="navbar-reveal relative"
style={{ animationDelay: `${140 + index * 70}ms` }}
onMouseEnter={() => setOpenDropdown(item.label)}
onMouseLeave={() => setOpenDropdown(null)}
>
<a
href={item.href}
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)" }}
>
<span className="text-active">{item.label}</span>
<span aria-hidden>{item.label}</span>
{item.children && (
<svg
className="ml-[12px] h-[5px] w-[5px] opacity-90"
viewBox="0 0 5 5"
fill="none"
>
<path
d="M4.35 0.9L3.75 4.05L0.65 3.45"
stroke="currentColor"
strokeWidth="1.1"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)}
</a>
{/* Dropdown */}
{item.children && openDropdown === item.label && (
<div className="absolute left-0 top-full z-50 min-w-[286px] origin-top rounded-[20px] border border-tenext-card-border bg-[#111111] px-[45px] py-[30px] shadow-2xl">
{item.children.map((child, childIndex) => (
<a
key={child.label}
href={child.href}
className="dropdown-reveal block py-[10px] pr-5 text-[14px] font-medium text-white/80 transition-all hover:pl-5 hover:text-tenext-teal"
style={{
animationDelay: `${childIndex * 45}ms`,
fontFamily: "var(--font-sora)",
}}
>
{child.label}
</a>
))}
</div>
)}
</div>
))}
</nav>
{/* Right Icons */}
<div
className="navbar-reveal flex items-center justify-end gap-[10px]"
style={{ animationDelay: "620ms" }}
>
<button
className="hidden p-[8px] text-white transition-colors hover:text-tenext-teal md:block"
aria-label="Search"
>
<SearchIcon className="h-[18px] w-[18px]" />
</button>
<a
href="#"
className="hidden items-center gap-[8px] p-[8px] text-[13px] font-bold uppercase leading-none text-white transition-colors hover:text-tenext-teal md:flex"
style={{ fontFamily: "var(--font-sora)" }}
>
<svg className="h-4 w-4" viewBox="0 0 16 16" fill="none">
<circle
cx="8"
cy="5"
r="3.5"
stroke="currentColor"
strokeWidth="1.3"
/>
<path
d="M2 14.5C2 11.5 4.5 9.5 8 9.5C11.5 9.5 14 11.5 14 14.5"
stroke="currentColor"
strokeWidth="1.3"
strokeLinecap="round"
/>
</svg>
Log in
</a>
<a
href="/contacts"
className="tenext-button tenext-button-gradient-border min-w-[188px] justify-center rounded-full px-[24px] py-[21px] text-[16px] font-semibold leading-none text-white"
style={{ fontFamily: "var(--font-sora)" }}
>
Talk to an expert
<span className="button-inner" />
</a>
{/* Mobile menu button */}
<button className="flex flex-col gap-[5px] lg:hidden" aria-label="Menu">
<span className="h-[2px] w-[22px] bg-white" />
<span className="h-[2px] w-[22px] bg-white" />
<span className="h-[2px] w-[22px] bg-white" />
</button>
</div>
</header>
);
}

View File

@@ -0,0 +1,95 @@
import { tenextButton as TenextButton } from "@/components/shared/Button";
import { IconBox } from "@/components/shared/IconBox";
import { valueProps } from "@/data/site-content";
import {
OrbitIcon,
FanIcon,
CirclesIcon,
ExpandIcon,
} from "@/components/shared/icons/PossibilityIcons";
export function PossibilitiesSection() {
return (
<section className="px-[20px] py-[60px] md:py-[100px]">
<div className="mx-auto grid max-w-[1260px] grid-cols-1 gap-[50px] lg:grid-cols-[1fr_1fr]">
{/* Left Column */}
<div className="flex flex-col items-start pr-[10%] pt-[20px]">
<span
className="tenext-subheading mb-[16px] text-tenext-dark uppercase tracking-[0.1em]"
style={{ fontFamily: "var(--font-sora)" }}
>
[ what we do ]
</span>
<h2
className="mb-[24px] max-w-[500px] tracking-[-0.03em] text-tenext-dark"
style={{
fontFamily: "var(--font-dm-sans)",
fontSize: "clamp(32px, 4vw, 56px)",
fontWeight: 500,
lineHeight: 1.1,
}}
>
Services that move the business, not just the technology
</h2>
<p className="mb-[40px] max-w-[480px] text-[16px] leading-[1.8] text-tenext-text-muted">
Tenext Technologies partners with enterprises to engineer, migrate,
and scale digital platforms. We integrate solutions with your
existing systems and processes to deliver predictable outcomes,
lower total cost of ownership, and accelerate time to value.
</p>
<TenextButton
variant="gradient-border"
className="rounded-[25px] px-[35px] py-[15px] text-[15px] font-medium"
showArrow={true}
>
Explore more
</TenextButton>
<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>
{/* Right Column */}
<div className="flex flex-col gap-[30px] lg:pl-[10%]">
<IconBox
icon={<OrbitIcon className="h-full w-full" />}
title="Technology Engineering"
description="Full-stack product engineering — architecture, development, and modernization of enterprise applications built to scale."
hasBorder={true}
theme="light"
/>
<IconBox
icon={<FanIcon className="h-full w-full" />}
title="Cloud & Enterprise Platforms"
description="Cloud migration, platform engineering, and DevOps that lower total cost of ownership and keep systems reliable."
hasBorder={true}
theme="light"
/>
<IconBox
icon={<CirclesIcon className="h-full w-full" />}
title="AI & Data Science"
description="Data platforms, analytics, and applied AI that turn enterprise data into automation and decision-ready insight."
hasBorder={true}
theme="light"
/>
<IconBox
icon={<ExpandIcon className="h-full w-full" />}
title="Digital Commerce & Mobility"
description="Commerce platforms and enterprise mobile applications that deliver seamless customer and workforce experiences."
hasBorder={true}
theme="light"
/>
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,72 @@
import Image from "next/image";
export function TinkerSection() {
return (
<section className="relative px-[20px] py-[60px] md:py-[100px] overflow-hidden">
<div className="mx-auto flex max-w-[1340px] flex-col gap-[50px] lg:flex-row lg:items-center lg:gap-0">
{/* Left Column - Images */}
<div className="relative flex w-full flex-col lg:mt-[30px] lg:w-[22%]">
{/* Background Glow (elementor-absolute) */}
<div className="absolute left-0 top-0 z-0 pointer-events-none min-[576px]:left-[-40vw] min-[576px]:top-[-19.252vw]">
<Image
src="/images/tenext/Group-18433.png"
alt=""
width={1283}
height={1471}
className="h-auto w-auto max-w-[100vw] object-contain opacity-80"
aria-hidden="true"
unoptimized
/>
</div>
{/* Main Vector Image */}
<div className="relative z-10 min-[576px]:ml-[-26vw]">
<Image
src="/images/tenext/Vector-13.png"
alt="Tenext technology stack"
width={670}
height={694}
className="w-full h-auto max-w-[800px] object-contain"
/>
</div>
</div>
{/* Right Column - Text & Partners */}
<div className="relative z-10 flex w-full flex-col lg:w-[78%]">
<div className="min-[576px]:mr-[-4%]">
<h2
className="mb-[60px] text-tenext-dark tracking-[-0.03em]"
style={{
fontFamily: "var(--font-dm-sans)",
fontSize: "clamp(36px, 4.5vw, 58px)",
fontWeight: 500,
lineHeight: 1.1,
}}
>
Modern technology,{" "}
<span className="gradient-text-purple">
integrated with the systems
</span>{" "}
you already run cloud, data, IoT, DevOps, and blockchain.
</h2>
</div>
{/* 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>
</section>
);
}

View File

@@ -0,0 +1,74 @@
import Link from "next/link";
import Image from "next/image";
import { ArrowIcon } from "@/components/shared/icons/ArrowIcon";
import { PageContainer } from "@/components/shared/PageContainer";
export function WOWSection() {
return (
<section className="relative z-20 px-[20px]">
<div className="relative z-20 mx-auto max-w-[1340px] overflow-hidden rounded-t-[20px] bg-tenext-dark pt-[30px] pb-[60px] md:pt-[40px] md:pb-[80px]">
<PageContainer>
<div className="grid grid-cols-1 gap-[40px] lg:grid-cols-2 lg:gap-[60px]">
<div className="flex flex-col justify-between">
<div className="mb-[35px] md:mb-[70px] md:pr-[10%]">
<span
className="mb-[18px] block text-[12px] font-semibold uppercase tracking-[0.1em] text-white"
style={{ fontFamily: "var(--font-sora)" }}
>
[ about ]
</span>
<h2
className="tracking-[-0.03em] text-white"
style={{
fontFamily: "var(--font-dm-sans)",
fontSize: "clamp(44px, 5vw, 80px)",
fontWeight: 500,
lineHeight: 1.1,
}}
>
Why enterprises choose Tenext
</h2>
</div>
<Image
src="/images/tenext/home-9-img.png"
alt="Tenext"
width={632}
height={158}
className="h-auto w-full max-w-[632px] object-contain"
/>
</div>
<div className="flex flex-col justify-between">
<div className="max-w-[560px] text-white">
<p className="text-[16px] font-bold leading-[1.7]">
Tenext Technologies helps enterprises turn digital
transformation into predictable business outcomes. We combine
engineering depth with a diagnostic, outcome-first approach
so every investment maps to measurable value.
</p>
<p className="mt-[27px] text-[16px] font-medium leading-[1.7]">
Our teams integrate solutions with your existing systems and
processes, delivering the lowest total cost of ownership and
accelerated time to value across cloud, data, AI, product
engineering, and digital commerce.
</p>
</div>
<div className="mt-[40px] md:mt-[60px]">
<Link
href="/services"
className="tenext-button tenext-button-gradient-border group rounded-full px-[35px] py-[15px] font-[var(--font-sora)] text-[15px] font-semibold tracking-wide text-white transition-all"
>
<span className="button-inner" />
Explore more
<ArrowIcon className="ml-2 h-[12px] w-[12px] transition-transform duration-300 group-hover:translate-x-1 group-hover:-translate-y-1" />
</Link>
</div>
</div>
</div>
</PageContainer>
</div>
</section>
);
}

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

View File

@@ -0,0 +1,23 @@
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?q=${query}&output=embed`}
width="100%"
height="100%"
style={{ border: 0 }}
allowFullScreen={false}
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
title={`${siteConfig.legalName} — Coimbatore`}
/>
</SectionContainer>
);
}

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

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

View File

@@ -0,0 +1,55 @@
"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";
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) => (
<div
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">
<Image
src="/images/tenext/3x.png"
alt=""
width={60}
height={60}
className="h-full w-full object-contain"
onError={(e) => {
(e.target as HTMLImageElement).src =
"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23fff'><path d='M12 2L2 22h20L12 2z'/></svg>";
}}
/>
</div>
<div>
<h4
className="mb-4 text-[22px] font-bold text-white transition-colors group-hover:text-tenext-teal"
style={{ fontFamily: "var(--font-dm-sans)" }}
>
{svc.title}
</h4>
<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">
<ArrowIcon className="h-4 w-4" />
</div>
</div>
))}
</div>
</PageContainer>
</SectionContainer>
);
}

View File

@@ -0,0 +1,53 @@
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 DefaultIcon = () => (
<div className="flex h-full w-full items-center justify-center rounded-[18px] bg-tenext-card-purple">
<svg
width="32"
height="32"
viewBox="0 0 24 24"
fill="none"
className="text-white"
>
<path
d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</div>
);
return (
<SectionContainer paddingY="lg">
<PageContainer>
<div className="mb-16">
<SectionHeading
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">
{differentiators.map((item, i) => (
<IconBox
key={item.id}
icon={<DefaultIcon />}
title={item.title}
description={item.description}
hasBorder={i < 3} // The original has a border for the first row
/>
))}
</div>
</PageContainer>
</SectionContainer>
);
}