blog: updated blog

This commit is contained in:
sankalp committed 2026-09-25 19:48:24 +05:45
1 parent ab7aadbbc8
commit 04138d833f
15 files changed
+1013 -647

No files matched your search

+424
View File
@@ -0,0 +1,424 @@
Redesign the existing company portfolio website using a premium editorial / modern digital-agency design language.
IMPORTANT:
- The existing project already contains the company's content, pages, functionality, assets, routes, components, and business information.
- Do NOT rebuild the project from scratch.
- Do NOT remove existing functionality.
- First inspect and understand the entire existing codebase, including all pages, components, content, images, assets, routes, responsive behavior, and existing design system.
- Preserve the company's actual content and business information unless something clearly needs restructuring for the new visual hierarchy.
- The primary goal is a COMPLETE VISUAL AND UX REDESIGN.
- Do not make it look like a generic SaaS template or an AI-generated website.
## DESIGN DIRECTION
Use a sophisticated:
"Premium Editorial + Swiss Minimalism + Contemporary Digital Agency"
aesthetic.
The website should feel like a high-end international creative agency / architecture studio / luxury brand website rather than a conventional corporate website.
The visual language should combine:
- Swiss-inspired typography
- Editorial magazine layouts
- Premium corporate branding
- Large-scale typography
- Asymmetric compositions
- Strong grid systems
- Generous whitespace
- Large immersive photography
- Minimal UI
- Sophisticated motion
- Strong visual hierarchy
- Intentional negative space
- Subtle organic shapes
- Restrained use of color
- High-quality transitions and micro-interactions
The final result should feel expensive, intentional, confident, and highly designed.
## TYPOGRAPHY
Typography is one of the most important parts of the redesign.
Use typography as a major visual element rather than simply displaying text.
Use:
- Extremely large display headings
- Strong contrast between display and body typography
- Large section titles
- Tight but carefully controlled heading line-height
- Clear typographic hierarchy
- Editorial-style text blocks
- Occasional oversized numbers/statistics
- Small uppercase labels with subtle letter spacing
- Short, confident headlines
Avoid excessive font weights and unnecessary decorative typography.
The typography should feel modern, sophisticated, and editorial.
## LAYOUT
Do NOT make every section centered.
Use a strong responsive grid with intentional asymmetry.
Use compositions such as:
- Text aligned to one side with large imagery on the other
- Full-width images
- Oversized headings extending across multiple grid columns
- Offset content blocks
- Uneven image/text ratios
- Large whitespace areas
- Overlapping elements when appropriate
- Editorial multi-column layouts
- Large visual pauses between sections
The page should feel composed rather than assembled from UI components.
Do not make every section look like:
heading → paragraph → three cards.
## HERO
Create a visually dominant hero section.
The hero should immediately communicate the company's identity.
Use:
- Very large typography
- Strong composition
- High-quality company imagery
- Minimal supporting text
- Minimal CTA treatment
- Plenty of negative space
- Subtle entrance animation
Avoid the typical SaaS hero pattern.
Do not use a huge gradient background with floating cards.
The hero should feel like the opening spread of a premium magazine.
## NAVIGATION
Create a minimal, sophisticated navigation.
Keep the navigation visually quiet.
Use:
- Simple logo
- Minimal navigation links
- Strong spacing
- Subtle hover interactions
- Optional menu interaction on smaller screens
- Sticky/floating behavior only if it improves the experience
Do not overcrowd the navbar.
Navigation should never compete with the content.
## IMAGERY
Treat images as part of the design rather than simple content containers.
Use:
- Large editorial photographs
- Full-width imagery
- Carefully cropped images
- Different aspect ratios
- Asymmetric image compositions
- Subtle border radius where appropriate
- Image reveal animations
- Hover transformations that are subtle and sophisticated
Avoid putting every image inside a standard rounded rectangular card.
If the existing project already has images, reuse them intelligently.
Do not replace real company imagery with random stock imagery unless absolutely necessary.
## SECTIONS
Reorganize the visual presentation of existing content into a strong editorial narrative.
Possible visual rhythm:
1. Minimal navigation
2. Massive hero statement
3. Introductory company statement
4. Large visual / company image
5. Company capabilities or services
6. Featured projects
7. Individual project showcases
8. Company statistics / achievements
9. About/company story
10. Process or expertise
11. Clients / partners
12. Testimonials if they already exist
13. Strong CTA
14. Minimal footer
Do not blindly follow this order.
Analyze the existing company's content and determine the most natural narrative.
## PROJECT / PORTFOLIO SECTION
Projects should feel like editorial case studies.
Avoid generic grids of identical cards.
Instead use:
- Large featured project
- Different image sizes
- Asymmetric layouts
- Project number/category labels
- Large project titles
- Metadata presented subtly
- Image hover interactions
- Alternating compositions
Example visual rhythm:
Large project
↓
Two smaller projects
↓
Large offset project
↓
Full-width project
↓
Next major section
The portfolio should feel curated rather than like a database.
## SERVICES / CAPABILITIES
Do not create generic SaaS feature cards.
Instead present services using editorial typography.
For example:
01 — SERVICE NAME
Short description
02 — SERVICE NAME
Short description
03 — SERVICE NAME
Short description
Allow typography, spacing, dividers, and interaction to create the hierarchy.
If cards are appropriate for the existing content, make them editorial rather than conventional UI cards.
## MOTION
Use sophisticated motion throughout the website.
Animations should feel intentional and restrained.
Use:
- Text reveal animations
- Image reveal animations
- Fade/slide transitions
- Subtle scale transformations
- Hover interactions
- Staggered content reveals
- Smooth section transitions
- Marquee/scrolling elements where appropriate
- Subtle parallax where it genuinely improves the composition
Motion should support the design rather than become a spectacle.
Avoid:
- Excessive bouncing
- Random animations
- Constant floating elements
- Overly aggressive parallax
- Long loading animations
- Animations that hurt usability
Respect prefers-reduced-motion.
## MARQUEE / SCROLLING ELEMENTS
Where appropriate, introduce editorial scrolling elements such as:
COMPANY • SERVICES • PROJECTS • EXPERTISE • COMPANY • SERVICES • PROJECTS
Use them sparingly.
They should feel like part of the visual identity rather than a gimmick.
## COLORS
Use the company's existing brand colors as the foundation.
Do not blindly introduce purple/blue gradients.
Prefer:
- Strong neutral base
- Black/near-black
- White/off-white
- Existing brand accent
- Very limited secondary colors
Color should support typography and imagery.
If the existing brand palette is poor, refine it rather than completely replacing the brand identity.
## BORDERS / SHADOWS / CARDS
Use visual restraint.
Prefer:
- Thin borders
- Dividers
- Whitespace
- Typography
- Image composition
Avoid excessive:
- Box shadows
- Glassmorphism
- Gradient borders
- Floating cards
- Pills
- Huge border radiuses
Not every element needs a container.
## FOOTER
Create a strong editorial footer.
The footer should feel like the final page of a magazine rather than a standard corporate footer.
Use:
- Large company statement
- Contact information
- Important navigation
- Social links if already present
- Location information if relevant
- Large typography
- Minimal legal links
- Strong whitespace
## RESPONSIVE DESIGN
The design must be genuinely responsive.
Do not simply shrink the desktop version.
Create intentional layouts for:
- Large desktop
- Laptop
- Tablet
- Mobile
On mobile:
- Preserve the typography hierarchy
- Maintain the editorial feel
- Recompose asymmetric layouts
- Carefully control oversized typography
- Prevent horizontal overflow
- Maintain image quality
- Keep navigation simple
- Preserve whitespace without wasting viewport space
## UX
Despite the highly visual design, usability must remain excellent.
Ensure:
- Clear navigation
- Accessible contrast
- Keyboard accessibility
- Proper semantic HTML
- Visible focus states
- Accessible buttons and links
- Proper heading hierarchy
- Fast loading
- Optimized images
- No unnecessary JavaScript
- No unnecessary dependencies
The website should look artistic without sacrificing usability.
## IMPORTANT ANTI-PATTERNS
Do NOT produce:
- Generic SaaS design
- Generic corporate template
- AI-looking website
- Purple gradient hero
- Glassmorphism
- Excessive rounded cards
- Dashboard-style layouts
- Repeated 3-column cards
- Excessive shadows
- Excessive pills
- Giant CTA buttons everywhere
- Centered content in every section
- Same-sized cards everywhere
- Random decorative blobs
- Unnecessary icons
- Excessive animations
- Stock-template appearance
## IMPLEMENTATION
Before changing code:
1. Inspect the entire existing project.
2. Identify the current architecture.
3. Identify reusable components.
4. Identify existing routes/pages.
5. Identify existing assets and images.
6. Identify the company's actual brand colors.
7. Identify existing functionality that must remain.
8. Identify opportunities to improve the information hierarchy.
9. Create a coherent design system based on the editorial direction.
10. Then implement the redesign systematically.
Do not rewrite working functionality unnecessarily.
Reuse existing components when technically appropriate, but redesign their visual presentation where necessary.
Keep the code clean, maintainable, responsive, and production-ready.
The final website should feel like a website designed by a high-end digital agency, not a collection of UI components.
MOST IMPORTANT:
The goal is not to copy another website.
The goal is to reproduce the same DESIGN PHILOSOPHY:
large typography + editorial composition + asymmetric grid + premium imagery + whitespace + restrained UI + sophisticated motion + strong visual identity.
Make the existing company feel like a premium, established, internationally credible brand through visual design alone.
@@ -59,10 +59,10 @@ export function ClientsMarquee({
<img
src={client.logo}
alt={client.name}
className="h-16 w-32 object-contain filter grayscale transition-all duration-300 group-hover:grayscale-0 group-hover:scale-110 opacity-70 group-hover:opacity-100"
className="h-16 w-32 object-contain transition-all duration-300 hover:scale-110 opacity-90 hover:opacity-100"
/>
) : (
<span className="text-xl font-bold tracking-widest text-muted-foreground transition-colors group-hover:text-brand">
<span className="text-xl font-bold tracking-widest text-muted-foreground transition-colors group-hover:text-foreground">
{client.name}
</span>
)}
+36 -45
View File
@@ -20,74 +20,65 @@ export function Footer() {
return (
<footer className="relative z-10 bg-[#0A0A0A] text-white pt-24 overflow-hidden border-t border-white/5">
<footer className="relative z-10 bg-ink text-background pt-32 overflow-hidden">
<div className="mx-auto max-w-7xl px-6 lg:px-8 relative z-10">
<div className="flex flex-col lg:flex-row gap-16 lg:gap-24 mb-20 lg:mb-32">
<div className="flex flex-col lg:flex-row gap-16 lg:gap-24 mb-32">
{/* Logo and Copyright */}
<div className="flex flex-col lg:w-[35%] shrink-0">
<div className="flex items-center gap-3">
{org?.logo ? (
<img src={org.logo} alt={org?.name || "Udhamsil Nepal"} className="h-9 w-auto object-contain bg-white rounded p-1" />
) : (
<span className="grid h-9 w-9 place-items-center bg-white font-display text-sm font-bold text-black rounded">
{org?.name ? org.name.charAt(0) : "U"}
</span>
)}
<span className="font-display text-lg font-bold">{org?.name || "Udhamsil Nepal"}</span>
<span className="font-display text-2xl font-bold tracking-tight">{org?.name || "UDHAMSIL"}</span>
</div>
<p className="mt-5 text-[13px] text-white/40">
© copyright {org?.name || "Udhamsil Nepal"} {new Date().getFullYear()}.<br />All rights reserved.
<p className="mt-8 text-xs font-medium uppercase tracking-widest text-background/40">
© {new Date().getFullYear()} {org?.name || "Udhamsil Nepal"}.<br />All rights reserved.
</p>
</div>
{/* Links Columns */}
<div className="flex-1 grid grid-cols-2 md:grid-cols-4 gap-10">
<div className="flex-1 grid grid-cols-2 md:grid-cols-4 gap-12">
{/* Pages */}
<div className="flex flex-col gap-6">
<h4 className="text-sm font-semibold text-white">PAGES</h4>
<nav className="flex flex-col gap-4 text-[13px] text-white/50">
<Link to="/about" className="hover:text-white transition-colors">About Us</Link>
<Link to="/products" className="hover:text-white transition-colors">Products</Link>
<Link to="/projects-events" className="hover:text-white transition-colors">Projects &amp; Events</Link>
<Link to="/team" className="hover:text-white transition-colors">Team</Link>
<Link to="/career" className="hover:text-white transition-colors">Career</Link>
<div className="flex flex-col gap-8">
<h4 className="text-xs font-bold uppercase tracking-widest text-background/30">Index</h4>
<nav className="flex flex-col gap-4 text-sm font-medium text-background/70">
<Link to="/about" className="hover:text-background transition-colors">About</Link>
<Link to="/products" className="hover:text-background transition-colors">Products</Link>
<Link to="/projects-events" className="hover:text-background transition-colors">Projects</Link>
<Link to="/team" className="hover:text-background transition-colors">Team</Link>
<Link to="/career" className="hover:text-background transition-colors">Careers</Link>
</nav>
</div>
{/* Socials */}
<div className="flex flex-col gap-6">
<h4 className="text-sm font-semibold text-white">SOCIALS</h4>
<nav className="flex flex-col gap-4 text-[13px] text-white/50">
{org?.facebook && <a href={org.facebook} target="_blank" rel="noopener noreferrer" className="hover:text-white transition-colors">Facebook</a>}
{org?.instagram && <a href={org.instagram} target="_blank" rel="noopener noreferrer" className="hover:text-white transition-colors">Instagram</a>}
{org?.linkedin && <a href={org.linkedin} target="_blank" rel="noopener noreferrer" className="hover:text-white transition-colors">LinkedIn</a>}
{org?.youtube && <a href={org.youtube} target="_blank" rel="noopener noreferrer" className="hover:text-white transition-colors">YouTube</a>}
{org?.tiktok && <a href={org.tiktok} target="_blank" rel="noopener noreferrer" className="hover:text-white transition-colors">TikTok</a>}
<div className="flex flex-col gap-8">
<h4 className="text-xs font-bold uppercase tracking-widest text-background/30">Network</h4>
<nav className="flex flex-col gap-4 text-sm font-medium text-background/70">
{org?.facebook && <a href={org.facebook} target="_blank" rel="noopener noreferrer" className="hover:text-background transition-colors">Facebook</a>}
{org?.instagram && <a href={org.instagram} target="_blank" rel="noopener noreferrer" className="hover:text-background transition-colors">Instagram</a>}
{org?.linkedin && <a href={org.linkedin} target="_blank" rel="noopener noreferrer" className="hover:text-background transition-colors">LinkedIn</a>}
{org?.youtube && <a href={org.youtube} target="_blank" rel="noopener noreferrer" className="hover:text-background transition-colors">YouTube</a>}
{org?.tiktok && <a href={org.tiktok} target="_blank" rel="noopener noreferrer" className="hover:text-background transition-colors">TikTok</a>}
{(!org || (!org.facebook && !org.instagram && !org.linkedin && !org.youtube && !org.tiktok)) && (
<>
<span className="opacity-50 hover:text-white cursor-pointer transition-colors">Facebook</span>
<span className="opacity-50 hover:text-white cursor-pointer transition-colors">Instagram</span>
<span className="opacity-50 hover:text-white cursor-pointer transition-colors">LinkedIn</span>
<span className="opacity-50 hover:text-background cursor-pointer transition-colors">Instagram</span>
<span className="opacity-50 hover:text-background cursor-pointer transition-colors">LinkedIn</span>
</>
)}
</nav>
</div>
{/* Legal */}
<div className="flex flex-col gap-6">
<h4 className="text-sm font-semibold text-white">LEGAL</h4>
<nav className="flex flex-col gap-4 text-[13px] text-white/50">
<Link to="#" className="hover:text-white transition-colors">Privacy Policy</Link>
<Link to="#" className="hover:text-white transition-colors">Terms of Service</Link>
<Link to="#" className="hover:text-white transition-colors">Cookie Policy</Link>
<div className="flex flex-col gap-8">
<h4 className="text-xs font-bold uppercase tracking-widest text-background/30">Legal</h4>
<nav className="flex flex-col gap-4 text-sm font-medium text-background/70">
<Link to="#" className="hover:text-background transition-colors">Privacy</Link>
<Link to="#" className="hover:text-background transition-colors">Terms</Link>
</nav>
</div>
{/* Contact */}
<div className="flex flex-col gap-6">
<h4 className="text-sm font-semibold text-white">CONTACT</h4>
<nav className="flex flex-col gap-4 text-[13px] text-white/50">
<Link to="/contact" className="hover:text-white transition-colors">Contact Us</Link>
<div className="flex flex-col gap-8">
<h4 className="text-xs font-bold uppercase tracking-widest text-background/30">Contact</h4>
<nav className="flex flex-col gap-4 text-sm font-medium text-background/70">
<Link to="/contact" className="hover:text-background transition-colors">Get in touch</Link>
<span title={org?.primary_email || "info@udhamsilnepal.com"}>{org?.primary_email || "info@udhamsilnepal.com"}</span>
<span>{org?.phone_number || "+977-1234567890"}</span>
</nav>
@@ -99,10 +90,10 @@ export function Footer() {
{/* Massive Bottom Text */}
<div className="w-full flex justify-center overflow-hidden pointer-events-none select-none px-4">
<h1
className="font-black tracking-tighter text-white/[0.03] uppercase whitespace-nowrap"
style={{ fontSize: "clamp(3rem, 11vw, 15rem)", lineHeight: 0.8, transform: "translateY(10%)" }}
className="font-display font-black tracking-tighter text-background/5 uppercase whitespace-nowrap"
style={{ fontSize: "clamp(3rem, 9.5vw, 15rem)", lineHeight: 0.75, transform: "translateY(15%)" }}
>
{org?.name ? org.name.replace('Global Trade Company', '').trim() : "UDHAMSIL NEPAL"}
{org?.name ? org.name.replace('Global Trade Company', '').trim() : "UDHAMSIL"}
</h1>
</div>
</footer>
+10 -16
View File
@@ -26,30 +26,24 @@ export function Header() {
const [open, setOpen] = useState(false);
return (
<header className="fixed top-0 inset-x-0 w-full z-50 border-b border-border bg-background/95 backdrop-blur-md transition-all duration-300">
<header className="fixed top-0 inset-x-0 w-full z-50 bg-background/90 backdrop-blur-md transition-all duration-300">
<div className="mx-auto max-w-7xl px-4 sm:px-6">
<nav className="flex h-20 items-center justify-between gap-4">
<Link to="/" className="flex items-center gap-3">
<span className="grid h-10 w-10 place-items-center bg-brand font-display font-bold text-primary-foreground">
U
</span>
<nav className="flex h-24 items-center justify-between gap-4">
<Link to="/" className="flex items-center gap-4">
<span className="leading-tight">
<span className="block font-display text-[14px]">UDHAMSIL NEPAL</span>
<span className="block text-[10px] uppercase text-muted-foreground">
Global Trade Co.
</span>
<span className="block font-display text-lg tracking-wide">UDHAMSIL</span>
</span>
</Link>
<div className="hidden h-full items-center gap-7 text-sm font-semibold text-muted-foreground lg:flex">
<div className="hidden h-full items-center gap-8 text-xs font-medium uppercase tracking-widest text-muted-foreground lg:flex">
{links.map((l) => (
<NavLink
key={l.to}
to={l.to}
end={l.to === "/"}
className={({ isActive }) =>
`flex h-full items-center border-b-2 transition-colors hover:text-brand ${
isActive ? "border-brand text-ink" : "border-transparent"
`flex h-full items-center transition-colors hover:text-foreground ${
isActive ? "text-foreground font-bold" : ""
}`
}
>
@@ -58,12 +52,12 @@ export function Header() {
))}
</div>
<div className="flex items-center gap-2">
<div className="flex items-center gap-4">
<Link
to="/contact"
className="hidden rounded-full bg-brand px-6 py-2.5 text-sm font-bold text-primary-foreground shadow-sm transition-all hover:scale-105 hover:bg-brand/90 sm:inline-block"
className="hidden text-xs font-bold uppercase tracking-widest text-foreground transition-opacity hover:opacity-70 sm:inline-block"
>
Get a Quote
Contact
</Link>
<Sheet open={open} onOpenChange={setOpen}>
<SheetTrigger asChild>
@@ -18,92 +18,127 @@ interface Organization {
export function OrbitalVisualization({ nodes }: { nodes: NodeData[] }) {
const { data: org } = useApi<Organization>("org/organization");
const RADIUS = {
mobile: 140,
desktop: 220,
};
// On desktop, radius is 430, box is 940, icon is 80
// On mobile, radius is 140, box is 320, icon is 50
const RADIUS = { desktop: 430, mobile: 140 };
const BOX = { desktop: 940, mobile: 320 };
const ICON = { desktop: 80, mobile: 50 };
return (
<div className="relative mx-auto flex h-[500px] w-full max-w-3xl items-center justify-center overflow-hidden lg:h-[600px]">
{/* Background Orbit Rings */}
<div className="absolute h-[280px] w-[280px] rounded-full border border-dashed border-border/40 lg:h-[440px] lg:w-[440px]" />
<div className="absolute h-[180px] w-[180px] rounded-full border border-border/20 lg:h-[260px] lg:w-[260px]" />
{/* Central Node */}
<div className="relative z-10 flex h-24 w-24 flex-col items-center justify-center rounded-full border-2 border-brand/30 bg-background shadow-[0_0_40px_rgba(var(--brand-rgb),0.15)] lg:h-32 lg:w-32">
<div className="absolute inset-0 rounded-full animate-ping bg-brand/10 opacity-75" style={{ animationDuration: '3s' }} />
{org?.logo ? (
<img src={org.logo} alt={org?.name || "Organization"} className="h-12 w-12 lg:h-16 lg:w-16 object-contain" />
) : (
<span className="font-display text-3xl font-black text-foreground">{org?.name ? org.name.charAt(0) : "UN"}</span>
)}
<div className="relative mx-auto flex w-full flex-col items-center justify-center overflow-hidden">
{/* Desktop Orbit */}
<div className="relative z-0 hidden w-full max-w-[1000px] flex-col items-center justify-center overflow-clip h-[505px] md:flex">
<div className="absolute left-1/2 top-0 -translate-x-1/2" style={{ width: BOX.desktop, height: BOX.desktop }}>
{/* Dashed track */}
<div
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full border border-dashed border-muted-foreground/30"
style={{ width: RADIUS.desktop * 2, height: RADIUS.desktop * 2 }}
/>
<motion.div
className="h-full w-full"
initial={{ rotate: 0 }}
animate={{ rotate: 360 }}
transition={{ duration: 70, repeat: Infinity, ease: "linear" }}
>
{nodes.map((node, i) => {
const rad = ((i * 360) / nodes.length - 90) * (Math.PI / 180);
const x = BOX.desktop / 2 + RADIUS.desktop * Math.sin(rad) - ICON.desktop / 2;
const y = BOX.desktop / 2 - RADIUS.desktop * Math.cos(rad) - ICON.desktop / 2;
return (
<motion.div
key={node.id}
className="absolute flex items-center justify-center overflow-clip rounded-full bg-background shadow-[0_8px_20px_-8px_rgba(0,0,0,0.15)] ring-1 ring-border p-3"
style={{ left: x, top: y, width: ICON.desktop, height: ICON.desktop }}
initial={{ rotate: 0 }}
animate={{ rotate: -360 }}
transition={{ duration: 70, repeat: Infinity, ease: "linear" }}
>
<NodeCard node={node} />
</motion.div>
);
})}
</motion.div>
</div>
{/* Central Logo */}
<div className="relative mt-[110px] flex max-w-[520px] flex-col items-center gap-[30px]">
<span className="relative flex size-[130px] items-center justify-center rounded-full bg-background shadow-[0_12px_30px_rgba(0,0,0,0.1)]">
<span aria-hidden className="absolute -inset-6 rounded-full ring-1 ring-border/50" />
<span aria-hidden className="absolute -inset-12 rounded-full ring-1 ring-border/30" />
{org?.logo ? (
<img src={org.logo} alt={org?.name || "Organization"} className="size-[55%] object-contain" />
) : (
<span className="font-display text-4xl font-black text-foreground">{org?.name ? org.name.charAt(0) : "UN"}</span>
)}
</span>
</div>
</div>
{/* Orbiting Nodes */}
<motion.div
className="absolute left-1/2 top-1/2 z-20 h-0 w-0"
initial={{ rotate: 0 }}
animate={{ rotate: 360 }}
transition={{ duration: 60, repeat: Infinity, ease: "linear" }}
>
{nodes.map((node, i) => {
const angle = (i / nodes.length) * 360;
// Use standard trigonometry for positioning.
// 0 degrees is right (positive X).
const rad = (angle * Math.PI) / 180;
{/* Mobile Orbit */}
<div className="relative z-0 flex w-full flex-col items-center gap-[30px] md:hidden pt-8 pb-16">
<div className="relative aspect-square w-full max-w-[340px]">
<div className="absolute inset-0">
{/* Dashed track */}
<div
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full border border-dashed border-muted-foreground/30"
style={{ width: "80%", height: "80%" }}
/>
<motion.div
className="h-full w-full"
initial={{ rotate: 0 }}
animate={{ rotate: 360 }}
transition={{ duration: 70, repeat: Infinity, ease: "linear" }}
>
{nodes.map((node, i) => {
const rad = ((i * 360) / nodes.length - 90) * (Math.PI / 180);
const r = 40; // 40%
const x = 50 + r * Math.sin(rad);
const y = 50 - r * Math.cos(rad);
return (
<motion.div
key={node.id}
className="absolute flex items-center justify-center overflow-clip rounded-full bg-background shadow-[0_8px_20px_-8px_rgba(0,0,0,0.15)] ring-1 ring-border p-2 -translate-x-1/2 -translate-y-1/2"
style={{ left: `${x}%`, top: `${y}%`, width: ICON.mobile, height: ICON.mobile }}
initial={{ rotate: 0 }}
animate={{ rotate: -360 }}
transition={{ duration: 70, repeat: Infinity, ease: "linear" }}
>
<NodeCard node={node} />
</motion.div>
);
})}
</motion.div>
</div>
return (
<React.Fragment key={node.id}>
{/* Desktop position */}
<motion.div
className="absolute hidden -translate-x-1/2 -translate-y-1/2 md:block"
style={{
x: RADIUS.desktop * Math.cos(rad),
y: RADIUS.desktop * Math.sin(rad),
}}
initial={{ rotate: 0 }}
animate={{ rotate: -360 }}
transition={{ duration: 60, repeat: Infinity, ease: "linear" }}
>
<NodeCard node={node} />
</motion.div>
{/* Mobile position */}
<motion.div
className="absolute -translate-x-1/2 -translate-y-1/2 md:hidden"
style={{
x: RADIUS.mobile * Math.cos(rad),
y: RADIUS.mobile * Math.sin(rad),
}}
initial={{ rotate: 0 }}
animate={{ rotate: -360 }}
transition={{ duration: 60, repeat: Infinity, ease: "linear" }}
>
<NodeCard node={node} />
</motion.div>
</React.Fragment>
);
})}
</motion.div>
{/* Central Logo Mobile */}
<span className="absolute inset-0 m-auto flex size-20 items-center justify-center rounded-full bg-background shadow-[0_12px_30px_rgba(0,0,0,0.1)]">
<span aria-hidden className="absolute -inset-4 rounded-full ring-1 ring-border/50" />
<span aria-hidden className="absolute -inset-8 rounded-full ring-1 ring-border/30" />
{org?.logo ? (
<img src={org.logo} alt={org?.name || "Organization"} className="size-[55%] object-contain" />
) : (
<span className="font-display text-2xl font-black text-foreground">{org?.name ? org.name.charAt(0) : "UN"}</span>
)}
</span>
</div>
</div>
</div>
);
}
function NodeCard({ node }: { node: NodeData }) {
const content = (
<div className="group relative flex cursor-pointer items-center justify-center rounded-full border border-border/60 bg-card/80 p-1.5 shadow-lg backdrop-blur-md transition-all hover:border-brand hover:bg-card">
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-muted text-accent">
{node.logo ? (
<img src={node.logo} alt={node.name} className="h-6 w-6 object-contain" />
) : (
<Settings2 className="h-5 w-5" />
)}
</div>
<div className="group relative flex h-full w-full cursor-pointer items-center justify-center transition-transform hover:scale-110">
{node.logo ? (
<img src={node.logo} alt={node.name} className="size-full object-contain" />
) : (
<Settings2 className="h-5 w-5 text-muted-foreground" />
)}
{/* Tooltip */}
<div className="pointer-events-none absolute -bottom-10 left-1/2 -translate-x-1/2 whitespace-nowrap rounded bg-foreground px-2.5 py-1.5 text-xs font-semibold text-background opacity-0 shadow-xl transition-opacity group-hover:opacity-100">
<div className="pointer-events-none absolute -bottom-10 left-1/2 -translate-x-1/2 whitespace-nowrap bg-foreground px-2 py-1 text-[10px] font-bold uppercase tracking-widest text-background opacity-0 shadow-xl transition-opacity group-hover:opacity-100">
{node.name}
</div>
</div>
@@ -111,11 +146,11 @@ function NodeCard({ node }: { node: NodeData }) {
if (node.website_link) {
return (
<a href={node.website_link} target="_blank" rel="noreferrer" className="block outline-none hover:scale-110 transition-transform">
<a href={node.website_link} target="_blank" rel="noreferrer" className="block outline-none hover:-translate-y-1 transition-transform">
{content}
</a>
);
}
return <div className="hover:scale-110 transition-transform">{content}</div>;
return <div className="hover:-translate-y-1 transition-transform">{content}</div>;
}
+10 -8
View File
@@ -13,16 +13,18 @@ export function PageHero({
}) {
return (
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 pb-16 pt-24 md:pb-24 md:pt-32">
<Parallax speed={0.06}>
<div className="rise flex items-center gap-4 text-xs font-bold uppercase text-brand">
<span className="h-px w-12 bg-brand" /> {eyebrow}
<div className="mx-auto max-w-7xl px-6 pb-16 pt-32 md:pb-24 md:pt-48">
<Parallax speed={0.05}>
<div className="rise flex items-center gap-4 text-xs font-bold uppercase tracking-widest text-muted-foreground mb-8">
{eyebrow} <span className="h-px w-12 bg-border" />
</div>
<h1 className="rise-2 mt-7 max-w-5xl text-4xl leading-[1.06] md:text-7xl">
{title} {highlight && <span className="text-gradient">{highlight}</span>}
<h1 className="rise-2 font-display text-[10vw] sm:text-[8vw] lg:text-[7rem] leading-[0.85] tracking-tighter uppercase mb-16">
{title} {highlight && <span className="text-brand block">{highlight}</span>}
</h1>
<div className="rise-3 mt-8 grid border-t border-border pt-6 md:grid-cols-12">
<p className="max-w-2xl text-lg text-muted-foreground md:col-start-6 md:col-span-7">{description}</p>
<div className="rise-3 grid grid-cols-1 md:grid-cols-12 gap-8 border-t border-border pt-8">
<p className="md:col-start-7 md:col-span-6 text-sm font-medium leading-relaxed text-foreground uppercase tracking-widest">
{description}
</p>
</div>
</Parallax>
</div>
@@ -25,18 +25,17 @@ export function TestimonialsMarquee({
useEffect(() => {
if (testimonials.length === 0) return;
// We duplicate the array enough times to ensure smooth infinite scroll
// A single setWidth is just one set of testimonials
const setWidth = testimonials.length * (CARD_WIDTH + GAP);
controls1.current = animate(x1, [-setWidth, 0], {
// Row 1: moves left (0 to -setWidth)
controls1.current = animate(x1, [0, -setWidth], {
duration: 40,
ease: "linear",
repeat: Infinity,
});
// Start x2 shifted by half a set width, moving the same direction (left to right)
controls2.current = animate(x2, [-setWidth - (setWidth / 2), -setWidth / 2], {
// Row 2: moves right (-setWidth to 0)
controls2.current = animate(x2, [-setWidth, 0], {
duration: 40,
ease: "linear",
repeat: Infinity,
@@ -46,26 +45,21 @@ export function TestimonialsMarquee({
controls1.current?.stop();
controls2.current?.stop();
};
}, [testimonials, x1, x2]);
}, [testimonials.length, x1, x2]);
if (testimonials.length === 0) return null;
// We need enough items to fill the screen twice over to ensure it doesn't run out during animation.
const items = [...testimonials, ...testimonials, ...testimonials, ...testimonials, ...testimonials];
return (
<section className="relative z-10 overflow-hidden bg-mist/30 py-24 text-foreground border-y border-border/50">
<div className="mx-auto mb-16 max-w-7xl px-6">
<div className="flex flex-col justify-between gap-5 md:flex-row md:items-end">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-accent">Client voices</p>
<h2 className="mt-3 text-4xl font-bold">Confidence earned on the ground.</h2>
</div>
</div>
<section className="relative z-10 overflow-hidden bg-background py-32 border-t border-border text-foreground">
<div className="mx-auto mb-24 max-w-7xl px-6 text-center">
<p className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4">Client voices</p>
<h2 className="text-4xl font-display font-black tracking-tighter uppercase md:text-6xl">Confidence earned on the ground.</h2>
</div>
<div
className="mask-edges relative mx-auto flex flex-col w-full overflow-hidden"
className="mask-edges relative mx-auto flex flex-col w-full overflow-hidden gap-6"
style={{ overflowAnchor: "none" }}
onMouseEnter={() => {
controls1.current?.pause();
@@ -78,8 +72,8 @@ export function TestimonialsMarquee({
>
{/* ROW 1 */}
<motion.div
style={{ x: x1 }}
className="flex items-stretch w-max"
style={{ x: x1, gap: GAP }}
className="flex items-stretch w-max ml-4"
>
{items.map((t, i) => (
<TestimonialCard key={`r1-${t.id}-${i}`} t={t} />
@@ -88,8 +82,8 @@ export function TestimonialsMarquee({
{/* ROW 2 */}
<motion.div
style={{ x: x2 }}
className="flex items-stretch w-max"
style={{ x: x2, gap: GAP }}
className="flex items-stretch w-max ml-4"
>
{items.map((t, i) => (
<TestimonialCard key={`r2-${t.id}-${i}`} t={t} />
@@ -114,31 +108,27 @@ export function TestimonialsMarquee({
function TestimonialCard({ t }: { t: Testimonial }) {
return (
<article
className="flex min-h-[260px] w-[480px] shrink-0 flex-col justify-between border border-border/50 bg-card p-8 shadow-sm transition-colors hover:bg-muted/30 m-3 rounded-3xl ml-4"
className="flex min-h-[260px] w-[400px] md:w-[480px] shrink-0 flex-col gap-6 border border-border bg-muted/10 p-8 transition-colors hover:bg-muted/30"
>
<div>
<div className="flex items-center gap-2 mb-6 text-accent">
<div className="flex gap-1">
{[0, 1, 2, 3, 4].map((star) => <Star key={star} className="h-4 w-4 fill-accent" aria-hidden="true" />)}
</div>
</div>
<blockquote className="text-[17px] font-medium leading-[1.6] tracking-tight text-foreground">
{t.testimonial}
</blockquote>
</div>
<footer className="mt-8 flex items-center gap-4">
<div className="flex flex-wrap items-center gap-4 border-b border-border/50 pb-6">
{t.image ? (
<img src={t.image} alt={t.name} className="h-11 w-11 rounded-lg object-cover ring-1 ring-border/50" />
<img src={t.image} alt={t.name} className="h-12 w-12 rounded-full object-cover grayscale" />
) : (
<div className="grid h-11 w-11 place-items-center rounded-lg bg-muted ring-1 ring-border/50 text-lg font-bold text-muted-foreground">
<div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-full bg-foreground font-display text-lg font-bold text-background">
{t.name.charAt(0)}
</div>
)}
<div>
<p className="text-[15px] font-semibold text-foreground">{t.name}</p>
<p className="text-[13px] text-muted-foreground">{t.organization}</p>
<div className="flex min-w-[150px] flex-1 flex-col gap-1">
<p className="text-base font-bold uppercase tracking-wide text-foreground">{t.name}</p>
<p className="text-xs font-semibold uppercase tracking-widest text-muted-foreground">{t.organization || "Google review"}</p>
</div>
</footer>
<div className="ml-auto flex gap-1">
{[0, 1, 2, 3, 4].map((star) => <Star key={star} className="h-4 w-4 fill-foreground text-foreground" aria-hidden="true" />)}
</div>
</div>
<blockquote className="text-lg font-medium leading-relaxed text-muted-foreground">
"{t.testimonial}"
</blockquote>
</article>
);
}
+44 -71
View File
@@ -67,25 +67,23 @@ function About() {
{about && (
<section className="relative z-10">
<div className="mx-auto grid max-w-7xl items-center gap-12 px-6 pb-24 lg:grid-cols-12">
<div className="mx-auto grid max-w-7xl items-center gap-16 px-6 pb-32 lg:grid-cols-12">
<div className="lg:col-span-5">
<Parallax speed={0.1}>
<div className="group overflow-hidden rounded-3xl border border-border/50 bg-card p-2 shadow-2xl transition-all hover:shadow-brand/10">
<div className="group overflow-hidden bg-muted aspect-[4/5] w-full">
<img
src={about.cover_image }
src={about.cover_image}
loading="lazy"
width={1024}
height={1152}
alt={about.title}
className="aspect-[4/5] w-full rounded-2xl object-cover transition duration-700 group-hover:scale-105"
className="w-full h-full object-cover grayscale transition duration-1000 group-hover:grayscale-0 group-hover:scale-105"
/>
</div>
</Parallax>
</div>
<div className="lg:col-span-7">
<div className="lg:col-span-7 lg:pl-12">
<Reveal>
<h2 className="text-4xl font-black tracking-tight md:text-5xl">{about.title}</h2>
<div className="mt-5 text-muted-foreground prose prose-invert" dangerouslySetInnerHTML={{ __html: about.about_us }} />
<h2 className="text-4xl font-display font-black tracking-tighter uppercase md:text-6xl">{about.title}</h2>
<div className="mt-8 text-base leading-relaxed text-muted-foreground prose prose-invert max-w-2xl" dangerouslySetInnerHTML={{ __html: about.about_us }} />
</Reveal>
</div>
</div>
@@ -93,90 +91,65 @@ function About() {
)}
{vision && (
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 pb-24">
<section className="relative z-10 border-t border-border mt-16 pt-32">
<div className="mx-auto max-w-7xl px-6 pb-32">
<Reveal>
<p className="inline-flex items-center gap-2 rounded-full bg-brand/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-brand">Vision</p>
<h2 className="mt-3 text-4xl font-black tracking-tight md:text-5xl">{vision.title}</h2>
</Reveal>
<div className="mt-10 grid items-center gap-10 lg:grid-cols-12">
<div className="lg:col-span-7">
<Reveal>
<div className="border-l-4 border-brand bg-mist p-10">
<span className="inline-flex h-12 w-12 items-center justify-center border border-brand/30 bg-background text-brand">
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>
</span>
<div className="mt-6 text-xl font-medium leading-relaxed md:text-2xl prose prose-invert" dangerouslySetInnerHTML={{ __html: vision.vision }} />
</div>
</Reveal>
</div>
{vision.subtitle && (
<div className="lg:col-span-5">
<Parallax speed={0.08}>
<Reveal delay={100}>
<p className="text-muted-foreground">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12">
<div className="lg:col-span-4">
<p className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4">01 — Vision</p>
<h2 className="text-4xl font-display font-black tracking-tighter uppercase">{vision.title}</h2>
{vision.subtitle && (
<p className="mt-6 text-sm font-medium text-foreground uppercase tracking-widest">
{vision.subtitle}
</p>
</Reveal>
</Parallax>
)}
</div>
<div className="lg:col-span-8 lg:pl-12">
<div className="text-2xl md:text-4xl font-display font-bold uppercase tracking-tight leading-tight text-foreground/80 prose prose-invert" dangerouslySetInnerHTML={{ __html: vision.vision }} />
</div>
</div>
)}
</div>
</Reveal>
</div>
</section>
)}
{mision && (
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 pb-24">
<section className="relative z-10 border-t border-border pt-32">
<div className="mx-auto max-w-7xl px-6 pb-32">
<Reveal>
<p className="inline-flex items-center gap-2 rounded-full bg-brand/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-brand">Mission</p>
<h2 className="mt-3 text-4xl font-black tracking-tight md:text-5xl">{mision.title}</h2>
</Reveal>
<div className="mt-10 grid items-center gap-10 lg:grid-cols-12">
{mision.subtitle && (
<div className="order-2 lg:order-1 lg:col-span-5">
<Parallax speed={0.06}>
<Reveal delay={100}>
<p className="text-muted-foreground">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12">
<div className="lg:col-span-4">
<p className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4">02 — Mission</p>
<h2 className="text-4xl font-display font-black tracking-tighter uppercase">{mision.title}</h2>
{mision.subtitle && (
<p className="mt-6 text-sm font-medium text-foreground uppercase tracking-widest">
{mision.subtitle}
</p>
</Reveal>
</Parallax>
)}
</div>
<div className="lg:col-span-8 lg:pl-12">
<div className="text-2xl md:text-4xl font-display font-bold uppercase tracking-tight leading-tight text-foreground/80 prose prose-invert" dangerouslySetInnerHTML={{ __html: mision.mision }} />
</div>
</div>
)}
<div className="order-1 lg:order-2 lg:col-span-7">
<Reveal>
<div className="border-r-4 border-brand bg-mist p-10">
<span className="inline-flex h-12 w-12 items-center justify-center border border-brand/30 bg-background text-brand">
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></svg>
</span>
<div className="mt-6 text-xl font-medium leading-relaxed md:text-2xl prose prose-invert" dangerouslySetInnerHTML={{ __html: mision.mision }} />
</div>
</Reveal>
</div>
</div>
</Reveal>
</div>
</section>
)}
{values && values.length > 0 && (
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 pb-24">
<section className="relative z-10 border-t border-border pt-32">
<div className="mx-auto max-w-7xl px-6 pb-32">
<Reveal>
<p className="inline-flex items-center gap-2 rounded-full bg-brand/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-brand">Values</p>
<h2 className="mt-3 text-4xl font-black tracking-tight md:text-5xl">What we stand for</h2>
<p className="mt-4 max-w-2xl text-muted-foreground">
The principles behind every machine we export, manufacture and supply.
</p>
<p className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4">03 — Values</p>
<h2 className="text-5xl font-display font-black tracking-tighter uppercase md:text-7xl">What we stand for.</h2>
</Reveal>
<div className="mt-10 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
<div className="mt-24 grid gap-16 md:grid-cols-2 lg:grid-cols-4">
{values.map((val, index) => (
<Reveal key={val.id} delay={index * 80}>
<div className="h-full border-t-2 border-brand bg-mist p-8">
<span className="text-4xl font-bold text-brand/30">{String(index + 1).padStart(2, "0")}</span>
<h3 className="mt-4 text-lg font-bold">{val.title}</h3>
<div className="mt-3 text-sm leading-relaxed text-muted-foreground prose prose-invert" dangerouslySetInnerHTML={{ __html: val.values }} />
<div className="border-t-2 border-foreground pt-8">
<span className="text-4xl font-display font-black text-muted-foreground">{String(index + 1).padStart(2, "0")}</span>
<h3 className="mt-6 text-xl font-display font-black uppercase tracking-tight">{val.title}</h3>
<div className="mt-4 text-sm font-medium leading-relaxed text-muted-foreground prose prose-invert" dangerouslySetInnerHTML={{ __html: val.values }} />
</div>
</Reveal>
))}
+11 -11
View File
@@ -32,22 +32,22 @@ function Career() {
description="We hire people who care about the details — precise hands, clear communication and a habit of finishing the job."
/>
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 pb-24">
<div className="divide-y divide-border overflow-hidden border-y border-border bg-background">
<section className="relative z-10 border-t border-border mt-16 pt-16">
<div className="mx-auto max-w-7xl px-6 pb-32">
<div className="flex flex-col gap-0 border-t-2 border-foreground">
{roles?.map((role, i) => (
<Reveal key={role.id} delay={i * 70}>
<div className="flex flex-wrap items-center justify-between gap-4 p-7">
<div>
<h2 className="text-xl font-bold">{role.name}</h2>
<p className="mt-1 text-xs font-semibold uppercase tracking-[0.15em] text-accent">
{role.job_time} · {role.location}
<div className="flex flex-wrap items-start md:items-center justify-between gap-8 py-10 border-b border-border hover:bg-muted/30 transition-colors">
<div className="flex-1">
<p className="mb-4 text-xs font-bold uppercase tracking-widest text-muted-foreground">
{role.job_time} <span className="mx-2">—</span> {role.location}
</p>
<p className="mt-2 max-w-lg text-sm text-muted-foreground">{role.short_info}</p>
<h2 className="text-3xl font-display font-black tracking-tighter uppercase">{role.name}</h2>
<p className="mt-4 max-w-lg text-sm font-medium leading-relaxed text-muted-foreground">{role.short_info}</p>
</div>
<Link
to={`/career/${role.id}`}
className="bg-ink px-6 py-3 text-sm font-semibold text-primary-foreground transition hover:bg-brand"
className="inline-flex items-center gap-2 text-xs font-bold uppercase tracking-widest text-background bg-foreground px-8 py-4 hover:bg-foreground/80 transition-colors shrink-0"
>
View role
</Link>
@@ -55,7 +55,7 @@ function Career() {
</Reveal>
))}
</div>
<p className="mt-8 text-sm text-muted-foreground">
<p className="mt-12 text-sm font-bold uppercase tracking-widest text-muted-foreground">
Don't see your role? Send your CV through the contact page and we'll keep it on file.
</p>
</div>
+62 -83
View File
@@ -70,27 +70,27 @@ export default function Contact() {
<Reveal className="order-2 lg:order-1 lg:col-span-7">
<form
onSubmit={handleSubmit}
className="flex flex-col gap-6 rounded-2xl border border-border bg-card p-8 shadow-lg md:p-12"
className="flex flex-col gap-8 border-t-2 border-foreground pt-12"
>
<div className="mb-2">
<h3 className="text-2xl font-bold text-foreground">Send an enquiry</h3>
<p className="mt-2 text-sm text-muted-foreground">We generally respond within 24 hours.</p>
<div className="mb-4">
<h3 className="text-4xl font-display font-black tracking-tighter uppercase text-foreground">Send an enquiry</h3>
<p className="mt-4 text-xs font-bold uppercase tracking-widest text-muted-foreground">We generally respond within 24 hours.</p>
</div>
<div className="grid gap-6 sm:grid-cols-2">
<div className="space-y-2">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
<div className="grid gap-8 sm:grid-cols-2">
<div className="space-y-4">
<label className="text-xs font-bold uppercase tracking-widest text-foreground">
Full Name
</label>
<input
required
name="name"
placeholder="John Doe"
className="w-full rounded-xl border border-border bg-background px-4 py-3.5 text-sm text-foreground outline-none transition placeholder:text-muted-foreground/50 focus:border-brand focus:bg-background focus:ring-1 focus:ring-brand"
className="w-full border-b border-border bg-transparent px-0 py-3 text-base text-foreground outline-none transition placeholder:text-muted-foreground/30 focus:border-foreground"
/>
</div>
<div className="space-y-2">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
<div className="space-y-4">
<label className="text-xs font-bold uppercase tracking-widest text-foreground">
Phone Number
</label>
<input
@@ -98,14 +98,14 @@ export default function Contact() {
name="phone_no"
type="tel"
placeholder="+977 98..."
className="w-full rounded-xl border border-border bg-background px-4 py-3.5 text-sm text-foreground outline-none transition placeholder:text-muted-foreground/50 focus:border-brand focus:bg-background focus:ring-1 focus:ring-brand"
className="w-full border-b border-border bg-transparent px-0 py-3 text-base text-foreground outline-none transition placeholder:text-muted-foreground/30 focus:border-foreground"
/>
</div>
</div>
<div className="grid gap-6 sm:grid-cols-2">
<div className="space-y-2">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
<div className="grid gap-8 sm:grid-cols-2">
<div className="space-y-4">
<label className="text-xs font-bold uppercase tracking-widest text-foreground">
Email Address
</label>
<input
@@ -113,53 +113,52 @@ export default function Contact() {
name="email"
type="email"
placeholder="john@example.com"
className="w-full rounded-xl border border-border bg-background px-4 py-3.5 text-sm text-foreground outline-none transition placeholder:text-muted-foreground/50 focus:border-brand focus:bg-background focus:ring-1 focus:ring-brand"
className="w-full border-b border-border bg-transparent px-0 py-3 text-base text-foreground outline-none transition placeholder:text-muted-foreground/30 focus:border-foreground"
/>
</div>
<div className="space-y-2">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
<div className="space-y-4">
<label className="text-xs font-bold uppercase tracking-widest text-foreground">
Subject
</label>
<input
required
name="subject"
placeholder="Machinery Quote"
className="w-full rounded-xl border border-border bg-background px-4 py-3.5 text-sm text-foreground outline-none transition placeholder:text-muted-foreground/50 focus:border-brand focus:bg-background focus:ring-1 focus:ring-brand"
className="w-full border-b border-border bg-transparent px-0 py-3 text-base text-foreground outline-none transition placeholder:text-muted-foreground/30 focus:border-foreground"
/>
</div>
</div>
<div className="space-y-2">
<label className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
<div className="space-y-4">
<label className="text-xs font-bold uppercase tracking-widest text-foreground">
What are you looking for?
</label>
<textarea
required
name="message"
rows={5}
rows={4}
placeholder="Tell us about your requirements..."
className="w-full resize-none rounded-xl border border-border bg-background px-4 py-3.5 text-sm text-foreground outline-none transition placeholder:text-muted-foreground/50 focus:border-brand focus:bg-background focus:ring-1 focus:ring-brand"
className="w-full resize-none border-b border-border bg-transparent px-0 py-3 text-base text-foreground outline-none transition placeholder:text-muted-foreground/30 focus:border-foreground"
/>
</div>
<Button
<button
type="submit"
size="lg"
className="mt-2 h-14 w-full rounded-xl bg-brand text-base font-bold shadow-lg shadow-brand/20 transition-all hover:scale-[1.02] hover:bg-brand/90"
className="mt-6 inline-flex self-start items-center gap-2 text-sm font-bold uppercase tracking-widest text-background bg-foreground px-8 py-4 hover:bg-foreground/80 transition-colors"
>
Send Enquiry
</Button>
</button>
{sent && (
<div className="mt-2 rounded-lg bg-green-50 p-4 text-center border border-green-200 dark:bg-green-500/10 dark:border-green-500/20">
<p className="text-sm font-semibold text-green-600 dark:text-green-400">
<div className="mt-4 border border-border p-6 text-center">
<p className="text-sm font-bold uppercase tracking-widest text-foreground">
Thanks — your enquiry has been sent successfully. We will get back to you shortly.
</p>
</div>
)}
{error && (
<div className="mt-2 rounded-lg bg-red-50 p-4 text-center border border-red-200 dark:bg-red-500/10 dark:border-red-500/20">
<p className="text-sm font-semibold text-red-600 dark:text-red-400">
<div className="mt-4 border border-border p-6 text-center">
<p className="text-sm font-bold uppercase tracking-widest text-red-600">
There was an error sending your message. Please try again later.
</p>
</div>
@@ -170,72 +169,52 @@ export default function Contact() {
{/* Contact Info Sidebar */}
{org && (
<Reveal delay={90} className="order-1 lg:order-2 lg:col-span-5">
<div className="flex h-full flex-col justify-center space-y-10 rounded-2xl border border-border bg-card p-8 shadow-lg md:p-12">
<div className="flex flex-col justify-start space-y-16 border-t-2 border-border pt-12">
<div>
<h2 className="text-3xl font-bold text-foreground">{org.name || "Udhamsil Nepal"}</h2>
<p className="mt-2 text-sm font-semibold uppercase tracking-[0.2em] text-accent">
<h2 className="text-3xl font-display font-black tracking-tight uppercase text-foreground">{org.name || "Udhamsil"}</h2>
<p className="mt-2 text-xs font-bold uppercase tracking-widest text-muted-foreground">
Global Trade Company
</p>
</div>
<div className="space-y-8">
<div className="flex items-start gap-4">
<div className="mt-1 flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-muted text-brand">
<MapPin className="h-5 w-5" />
</div>
<div>
<h3 className="text-sm font-semibold text-foreground">Headquarters</h3>
<p className="mt-1 text-sm leading-relaxed text-muted-foreground whitespace-pre-line">
{org.address || "Kohalpur-11, Banke\nLumbini Province, Nepal"}
</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-1 gap-12">
<div className="space-y-2">
<h3 className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4 border-b border-border pb-2">Headquarters</h3>
<p className="text-sm font-medium leading-relaxed text-foreground whitespace-pre-line">
{org.address || "Kohalpur-11, Banke\nLumbini Province, Nepal"}
</p>
</div>
<div className="flex items-start gap-4">
<div className="mt-1 flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-muted text-brand">
<Mail className="h-5 w-5" />
</div>
<div>
<h3 className="text-sm font-semibold text-foreground">Email Us</h3>
<a href={`mailto:${org.primary_email || "info@udhamsilnepal.com"}`} className="mt-1 block text-sm text-muted-foreground hover:text-foreground transition-colors">
{org.primary_email || "info@udhamsilnepal.com"}
</a>
</div>
<div className="space-y-2">
<h3 className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4 border-b border-border pb-2">Email Us</h3>
<a href={`mailto:${org.primary_email || "info@udhamsilnepal.com"}`} className="block text-sm font-medium text-foreground hover:text-brand transition-colors">
{org.primary_email || "info@udhamsilnepal.com"}
</a>
</div>
{(org.phone_number || org.whatsapp_no) && (
<div className="flex items-start gap-4">
<div className="mt-1 flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-muted text-brand">
<Phone className="h-5 w-5" />
</div>
<div>
<h3 className="text-sm font-semibold text-foreground">Call Us</h3>
<div className="mt-1 space-y-1">
{org.phone_number && (
<a href={`tel:${org.phone_number}`} className="block text-sm text-muted-foreground hover:text-foreground transition-colors">
{org.phone_number}
</a>
)}
{org.whatsapp_no && (
<a href={`https://wa.me/${org.whatsapp_no}`} target="_blank" rel="noreferrer" className="flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors">
<MessageSquare className="h-3.5 w-3.5" /> WhatsApp: {org.whatsapp_no}
</a>
)}
</div>
<div className="space-y-2">
<h3 className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4 border-b border-border pb-2">Call Us</h3>
<div className="space-y-2">
{org.phone_number && (
<a href={`tel:${org.phone_number}`} className="block text-sm font-medium text-foreground hover:text-brand transition-colors">
{org.phone_number}
</a>
)}
{org.whatsapp_no && (
<a href={`https://wa.me/${org.whatsapp_no}`} target="_blank" rel="noreferrer" className="block text-sm font-medium text-foreground hover:text-brand transition-colors">
WhatsApp: {org.whatsapp_no}
</a>
)}
</div>
</div>
)}
<div className="flex items-start gap-4">
<div className="mt-1 flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-muted text-brand">
<Clock className="h-5 w-5" />
</div>
<div>
<h3 className="text-sm font-semibold text-foreground">Business Hours</h3>
<p className="mt-1 text-sm text-muted-foreground">
{org.working_hour || "Sunday – Friday, 9:00 – 18:00"}
</p>
</div>
<div className="space-y-2">
<h3 className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4 border-b border-border pb-2">Business Hours</h3>
<p className="text-sm font-medium text-foreground">
{org.working_hour || "Sunday – Friday, 9:00 – 18:00"}
</p>
</div>
</div>
</div>
@@ -247,7 +226,7 @@ export default function Contact() {
{(org?.google_map_link || org?.address) && (
<Reveal delay={180}>
<div className="mx-auto max-w-7xl px-6 pb-24">
<div className="h-[400px] w-full overflow-hidden rounded-2xl border border-border shadow-lg">
<div className="h-[500px] w-full overflow-hidden bg-muted grayscale">
<iframe
title="Google Maps"
src={org?.google_map_link && org.google_map_link.includes("embed") ? org.google_map_link : `https://www.google.com/maps?q=${encodeURIComponent(org?.address || "")}&output=embed`}
+165 -174
View File
@@ -2,7 +2,6 @@ import { Link } from "react-router-dom";
import { Star, ArrowRight } from "lucide-react";
import { LightField, Parallax, Reveal } from "@/components/site/Parallax";
import { OrbitalVisualization } from "@/components/site/OrbitalVisualization";
import { Button } from "@/components/ui/button";
import { ClientsMarquee } from "@/components/site/ClientsMarquee";
import { TestimonialsMarquee } from "@/components/site/TestimonialsMarquee";
import { useApi } from "@/hooks/useApi";
@@ -33,150 +32,148 @@ function Index() {
<LightField />
{hero && (
<section className="relative z-10 overflow-hidden">
<div className="mx-auto grid min-h-[720px] max-w-7xl items-center gap-12 px-6 py-16 lg:grid-cols-12 lg:py-24">
<div className="lg:col-span-6">
<div className="rise inline-flex items-center gap-3 rounded-full bg-brand/10 px-4 py-1.5 text-xs font-bold uppercase tracking-wider text-brand">
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-brand opacity-75"></span>
<span className="relative inline-flex h-2 w-2 rounded-full bg-brand"></span>
</span>
{hero.eyebrow || "Est. 2020 · Kohalpur, Banke"}
<section className="relative z-10 overflow-hidden pt-32 pb-24">
<div className="mx-auto max-w-7xl px-6">
<div className="grid lg:grid-cols-12 gap-12 items-end mb-16">
<div className="lg:col-span-9 rise">
<h1 className="font-display text-[12vw] sm:text-[8vw] lg:text-[6rem] leading-[0.85] tracking-tighter uppercase">
{hero.title || "Machinery built for"} <br />
<span className="text-brand">{hero.highlight || "Nepal."}</span>
</h1>
</div>
<h1 className="rise-2 mt-8 text-5xl font-black leading-[1.05] tracking-tight md:text-7xl">
{hero.title || "Machinery built for"} <span className="text-gradient">{hero.highlight || "Nepal."}</span>
</h1>
<p className="rise-3 mt-7 max-w-xl text-lg md:text-xl leading-relaxed text-muted-foreground">
{hero.description || "Reliable, innovative machinery solutions — exporting, manufacturing, distributing and supplying small, medium and commercial scale equipment across the nation."}
</p>
<div className="rise-3 mt-10 flex flex-wrap gap-4">
<Button asChild size="lg" className="h-14 rounded-full bg-brand px-8 text-base shadow-lg shadow-brand/20 transition-all hover:scale-105 hover:bg-brand/90">
<Link to="/products">Explore Products</Link>
</Button>
<Button asChild size="lg" variant="outline" className="h-14 rounded-full bg-background px-8 text-base border-border/50 hover:bg-muted transition-all hover:scale-105">
<Link to="/projects-events">View Projects</Link>
</Button>
</div>
{stats.length > 0 && (
<div className="rise-3 mt-16 grid max-w-xl grid-cols-3 gap-6 border-t border-border/40 pt-8">
{stats.map((st) => (
<div key={st.id} className="group">
<p className="font-display text-3xl font-black tracking-tight text-foreground transition-colors group-hover:text-brand">{st.stats}{st.title.includes('delivery') ? '%' : '+'}</p>
<p className="mt-1 text-sm font-medium text-muted-foreground">{st.title}</p>
</div>
))}
<div className="lg:col-span-3 pb-4 rise-2">
<p className="text-xs font-bold uppercase tracking-widest text-muted-foreground border-b border-border pb-4 mb-4">
{hero.eyebrow || "Est. 2020 · Kohalpur, Banke"}
</p>
<p className="text-sm font-medium leading-relaxed text-foreground">
{hero.description || "Reliable, innovative machinery solutions — exporting, manufacturing, distributing and supplying small, medium and commercial scale equipment across the nation."}
</p>
<div className="mt-8 flex flex-col gap-3">
<Link to="/products" className="inline-flex items-center gap-2 text-xs font-bold uppercase tracking-widest text-foreground hover:text-brand transition-colors">
Explore Products <ArrowRight className="h-4 w-4" />
</Link>
<Link to="/contact" className="inline-flex items-center gap-2 text-xs font-bold uppercase tracking-widest text-muted-foreground hover:text-foreground transition-colors">
Get a Quote <ArrowRight className="h-4 w-4" />
</Link>
</div>
)}
</div>
</div>
<div className="relative min-h-[480px] lg:col-span-6">
<div className="absolute inset-0 right-0 md:left-10">
<Parallax speed={0.06}>
<div className="group relative overflow-hidden rounded-3xl border border-border/40 bg-card p-2 shadow-2xl transition-all hover:shadow-brand/10">
<img
src={hero.image}
width={1024}
height={1280}
alt="Featured equipment"
className="h-[440px] w-full rounded-2xl object-cover transition duration-700 group-hover:scale-105 md:h-[580px]"
/>
<div className="absolute inset-x-4 bottom-4 flex items-end justify-between rounded-xl bg-ink/90 p-6 text-primary-foreground backdrop-blur-md">
<div>
<p className="text-xs font-bold uppercase tracking-widest text-primary-foreground/60">Featured equipment</p>
<p className="mt-2 font-display text-xl font-bold">{hero.featured_text || "Commercial systems"}</p>
</div>
<span className="font-display text-4xl font-black text-accent opacity-50">01</span>
</div>
</div>
</Parallax>
<div className="relative w-full aspect-[4/3] md:aspect-[21/9] bg-muted overflow-hidden rise-3">
<Parallax speed={0.05}>
<img
src={hero.image}
alt="Featured equipment"
className="w-full h-full object-cover object-center scale-110"
/>
</Parallax>
<div className="absolute inset-x-6 bottom-6 flex items-end justify-between">
<div>
<p className="text-xs font-bold uppercase tracking-widest text-white mix-blend-difference">Featured equipment</p>
<p className="mt-1 font-display text-lg text-white mix-blend-difference">{hero.featured_text || "Commercial systems"}</p>
</div>
<span className="font-display text-2xl font-black text-white mix-blend-difference opacity-50">01</span>
</div>
</div>
{stats.length > 0 && (
<div className="mt-24 grid grid-cols-2 md:grid-cols-4 gap-8 border-t border-border pt-8 rise-3">
{stats.map((st) => (
<div key={st.id}>
<p className="font-display text-4xl md:text-5xl font-black tracking-tighter">{st.stats}{st.title.includes('delivery') ? '%' : '+'}</p>
<p className="mt-2 text-xs font-bold uppercase tracking-widest text-muted-foreground">{st.title}</p>
</div>
))}
</div>
)}
</div>
</section>
)}
{marquee.length > 0 && (
<div className="relative z-10 flex overflow-hidden border-y border-border bg-card py-6">
<div className="animate-marquee flex whitespace-nowrap">
{[0, 1, 2, 3].map((i) => (
<div
key={i}
className="flex items-center gap-12 pr-12 text-xl font-black uppercase tracking-[0.1em] text-foreground md:text-2xl"
>
{marquee.map((m) => (
<span key={m.id} className="flex items-center gap-12">
<span>{m.title}</span>
<Star className="h-6 w-6 fill-brand text-brand" />
</span>
))}
<section className="relative z-10 border-t border-border mt-16 pt-32 pb-16">
<div className="mx-auto max-w-7xl px-6">
<Reveal>
<div className="mb-16">
<p className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4">Capabilities</p>
<h2 className="text-4xl font-display font-black tracking-tighter uppercase md:text-6xl">What we do at scale.</h2>
</div>
))}
</div>
</div>
)}
{partners.length > 0 && (
<section className="relative z-10 overflow-hidden border-b border-border bg-mist/30">
<div className="mx-auto grid max-w-7xl items-center gap-14 px-6 py-24 lg:grid-cols-12">
<div className="lg:col-span-5">
<Reveal>
<div className="inline-flex items-center gap-2 rounded-full bg-accent/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-accent">
Our clients
</div>
<h2 className="mt-6 text-4xl font-black tracking-tight md:text-5xl">Built around the people who produce.</h2>
<p className="mt-6 max-w-lg text-lg leading-relaxed text-muted-foreground">
We work with ambitious enterprises across agriculture, food production, construction,
utilities and commercial manufacturing.
</p>
</Reveal>
</div>
<div className="lg:col-span-7">
<Parallax speed={0.04}>
<div>
<ClientsMarquee partners={partners} />
</div>
</Parallax>
</Reveal>
<div className="grid grid-cols-1 md:grid-cols-4 gap-4 auto-rows-[200px] md:auto-rows-[250px]">
{marquee.map((m, i) => {
const bentoClasses = [
"md:col-span-2 lg:col-span-2",
"md:col-span-2 lg:col-span-2",
"md:col-span-4 lg:col-span-2",
"md:col-span-2 lg:col-span-1",
"md:col-span-2 lg:col-span-1"
];
const spanClass = bentoClasses[i % bentoClasses.length];
return (
<Reveal key={m.id} delay={i * 50} className={`${spanClass} bg-muted p-8 flex flex-col justify-between group overflow-hidden relative border border-border/50`}>
<div className="absolute inset-0 bg-foreground translate-y-full group-hover:translate-y-0 transition-transform duration-700 ease-in-out" />
<span className="relative z-10 text-2xl font-display font-black text-muted-foreground/30 group-hover:text-background/30 transition-colors duration-700">0{i + 1}</span>
<h3 className="relative z-10 text-3xl md:text-4xl lg:text-5xl font-display font-black uppercase tracking-tight text-foreground group-hover:text-background transition-colors duration-700 break-words">{m.title}</h3>
</Reveal>
);
})}
</div>
</div>
</section>
)}
{whatWeDo.length > 0 && (
<section className="relative z-10">
<div className="mx-auto max-w-7xl px-6 py-32">
<div className="mb-16 flex flex-col items-start justify-between gap-6 md:flex-row md:items-end">
<div>
<div className="inline-flex items-center gap-2 rounded-full bg-accent/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-accent">
What we do
</div>
<h2 className="mt-6 text-4xl font-black tracking-tight md:text-5xl">Machinery, end to end</h2>
{partners.length > 0 && (
<section className="relative z-10 w-full pt-32 pb-16 overflow-hidden">
{/* Centered pill on horizontal line */}
<div className="relative flex items-center justify-center">
<div className="absolute w-full h-px bg-border"></div>
<div className="relative z-10 bg-background px-4">
<div className="rounded-full bg-muted/30 border border-border/50 px-6 py-2 text-sm font-semibold tracking-wide text-foreground">
Our partners
</div>
<Button asChild variant="ghost" className="rounded-full font-bold text-brand hover:bg-brand/10 hover:text-brand">
<Link to="/products" className="flex items-center gap-2">
See all products <ArrowRight className="h-4 w-4" />
</Link>
</Button>
</div>
<div className="grid gap-8 md:grid-cols-3">
</div>
{/* Marquee below */}
<div className="mx-auto w-full max-w-[1600px] mt-16 px-4">
<ClientsMarquee partners={partners} />
</div>
</section>
)}
{whatWeDo.length > 0 && (
<section className="relative z-10 border-t border-border mt-24">
<div className="mx-auto max-w-7xl px-6 py-32">
<div className="mb-24 flex flex-col items-start gap-6 md:flex-row md:items-end md:justify-between">
<div>
<h2 className="text-5xl font-display font-black tracking-tighter uppercase md:text-7xl">Machinery,<br />end to end.</h2>
</div>
<Link to="/products" className="inline-flex items-center gap-2 text-xs font-bold uppercase tracking-widest text-foreground hover:text-brand transition-colors">
See all products <ArrowRight className="h-4 w-4" />
</Link>
</div>
<div className="grid gap-24">
{whatWeDo.map((c, i) => (
<Reveal key={c.id} delay={i * 90}>
<div className="group flex h-full flex-col overflow-hidden rounded-3xl border border-border/50 bg-card shadow-lg transition-all hover:-translate-y-1 hover:shadow-xl hover:shadow-brand/5">
{c.cover_image && (
<div className="overflow-hidden">
<img
src={c.cover_image}
loading="lazy"
width={1024}
height={768}
alt={c.title}
className="aspect-[4/3] w-full object-cover transition-transform duration-700 group-hover:scale-105"
/>
</div>
)}
<div className="flex flex-1 flex-col p-8">
<h3 className="text-2xl font-bold tracking-tight text-foreground">{c.title}</h3>
<div className="mt-4 text-muted-foreground prose prose-invert line-clamp-4" dangerouslySetInnerHTML={{ __html: c.what_we_do }} />
<Reveal key={c.id} delay={i * 50}>
<div className={`grid gap-12 items-center lg:grid-cols-12 ${i % 2 !== 0 ? 'lg:rtl' : ''}`}>
<div className={`lg:col-span-7 ${i % 2 !== 0 ? 'lg:ltr' : ''}`}>
{c.cover_image && (
<div className="overflow-hidden aspect-[4/3] bg-muted">
<img
src={c.cover_image}
loading="lazy"
alt={c.title}
className="w-full h-full object-cover grayscale hover:grayscale-0 transition-all duration-700"
/>
</div>
)}
</div>
<div className={`lg:col-span-5 ${i % 2 !== 0 ? 'lg:ltr' : ''}`}>
<span className="font-display text-4xl font-black text-brand/20">{(i + 1).toString().padStart(2, "0")}</span>
<h3 className="mt-4 text-3xl font-display font-black uppercase tracking-tight">{c.title}</h3>
<div className="mt-6 text-base leading-relaxed text-muted-foreground prose prose-invert" dangerouslySetInnerHTML={{ __html: c.what_we_do }} />
</div>
</div>
</Reveal>
@@ -187,46 +184,48 @@ function Index() {
)}
{services.length > 0 && (
<section className="relative z-10 border-y border-border bg-mist/30">
<section className="relative z-10 border-t border-border">
<div className="mx-auto max-w-7xl px-6 py-32">
<Reveal>
<div className="grid gap-8 md:grid-cols-[1fr_1.5fr] md:items-end">
<div>
<div className="inline-flex items-center gap-2 rounded-full bg-accent/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-accent">
Why Udhamsil
</div>
<h2 className="mt-6 text-4xl font-black tracking-tight md:text-5xl">From requirement to reliable output.</h2>
<div className="grid gap-12 lg:grid-cols-12 lg:items-start">
<div className="lg:col-span-5">
<h2 className="text-4xl font-display font-black tracking-tighter uppercase md:text-5xl">From requirement<br />to reliable output.</h2>
<p className="mt-6 max-w-sm text-sm font-medium leading-relaxed text-muted-foreground uppercase tracking-widest">
One accountable team helps you choose, receive and keep the right machinery running.
</p>
</div>
<div className="lg:col-span-7">
<div className="flex flex-col gap-0 border-t border-border">
{services.map((step, index) => (
<Reveal key={step.id} delay={index * 50}>
<div className="group grid grid-cols-1 sm:grid-cols-[auto_1fr] gap-6 sm:gap-12 py-10 border-b border-border transition-colors hover:bg-muted/30">
<span className="font-display text-lg font-black text-muted-foreground">{(index + 1).toString().padStart(2, "0")} —</span>
<div>
<h3 className="text-2xl font-display font-black tracking-tight uppercase group-hover:text-brand transition-colors">{step.name}</h3>
<div className="mt-4 text-base leading-relaxed text-muted-foreground prose prose-invert max-w-xl" dangerouslySetInnerHTML={{ __html: step.description }} />
</div>
</div>
</Reveal>
))}
</div>
</div>
<p className="max-w-xl text-lg leading-relaxed text-muted-foreground md:justify-self-end">
One accountable team helps you choose, receive and keep the right machinery running.
</p>
</div>
</Reveal>
<div className="mt-16 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
{services.map((step, index) => (
<Reveal key={step.id} delay={index * 70}>
<div className="group relative flex h-full flex-col rounded-3xl border border-border/50 bg-card p-8 shadow-lg transition-all hover:border-brand/30 hover:bg-muted/50">
<span className="font-display text-5xl font-black text-brand/10 transition-colors group-hover:text-brand/20">{(index + 1).toString().padStart(2, "0")}</span>
<h3 className="mt-6 text-xl font-bold tracking-tight">{step.name}</h3>
<div className="mt-4 text-sm leading-relaxed text-muted-foreground prose prose-invert" dangerouslySetInnerHTML={{ __html: step.description }} />
</div>
</Reveal>
))}
</div>
</div>
</section>
)}
{sisterCompanies.length > 0 && (
<section className="relative z-10 overflow-hidden bg-background">
<div className="mx-auto max-w-7xl px-6 py-32">
<section className="relative z-10 overflow-hidden border-t border-border mt-16 pt-32 pb-16">
<div className="mx-auto max-w-7xl px-6">
<Reveal>
<div className="mx-auto max-w-2xl text-center">
<div className="inline-flex items-center gap-2 rounded-full bg-accent/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-accent">
<div className="mx-auto max-w-4xl text-center mb-16">
<p className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4">
Ecosystem
</div>
<h2 className="mt-6 text-4xl font-black tracking-tight md:text-5xl">One group, connected capability.</h2>
<p className="mt-6 text-lg text-muted-foreground">A growing network designed to support enterprise from machinery to long-term operations.</p>
</p>
<h2 className="text-4xl font-display font-black tracking-tighter uppercase md:text-6xl">One group, connected capability.</h2>
<p className="mt-8 text-sm font-medium uppercase tracking-widest text-muted-foreground">A growing network designed to support enterprise from machinery to long-term operations.</p>
</div>
</Reveal>
<div className="mt-16">
@@ -240,31 +239,23 @@ function Index() {
<TestimonialsMarquee testimonials={testimonials} />
)}
<section className="relative z-10 border-t border-border/50 bg-gradient-to-b from-transparent to-mist/50">
<div className="mx-auto max-w-7xl px-6 py-32 text-center lg:py-40">
<section className="relative z-10 bg-brand text-white overflow-hidden">
<div className="mx-auto max-w-7xl px-6 py-32 md:py-48 text-center">
<Reveal>
<div className="mx-auto max-w-4xl">
<div className="inline-flex items-center gap-2 rounded-full bg-brand/10 px-4 py-1.5 text-xs font-bold uppercase tracking-widest text-brand">
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-brand opacity-75"></span>
<span className="relative inline-flex h-2 w-2 rounded-full bg-brand"></span>
</span>
<p className="text-xs font-bold uppercase tracking-widest text-white/70 mb-8">
Ready to scale
</div>
<h2 className="mt-8 text-4xl font-black tracking-tight text-foreground md:text-6xl md:leading-[1.1]">
Need a machine spec'd for your output?
</h2>
<p className="mx-auto mt-6 max-w-2xl text-xl leading-relaxed text-muted-foreground">
Tell us your scale and target production — our Banke team responds with a tailored
recommendation and pricing.
</p>
<div className="mt-10 flex flex-col items-center justify-center gap-4 sm:flex-row">
<Button asChild size="lg" className="h-14 w-full sm:w-auto rounded-full bg-brand px-10 text-base font-bold shadow-xl shadow-brand/20 transition-all hover:scale-105 hover:bg-brand/90">
<Link to="/contact">Get a Quote</Link>
</Button>
<Button asChild size="lg" variant="ghost" className="h-14 w-full sm:w-auto rounded-full px-8 text-base font-bold transition-all hover:bg-muted">
<Link to="/products">Browse Catalogue</Link>
</Button>
<h2 className="text-5xl font-display font-black tracking-tighter uppercase md:text-7xl lg:text-[7rem] leading-[0.9]">
Need a machine<br />spec'd for your<br />output?
</h2>
<div className="mt-16 flex flex-col items-center justify-center gap-8 sm:flex-row">
<Link to="/contact" className="inline-flex items-center gap-2 text-sm font-bold uppercase tracking-widest text-brand bg-white px-8 py-4 hover:bg-white/90 transition-colors">
Get a Quote <ArrowRight className="h-4 w-4" />
</Link>
<Link to="/products" className="inline-flex items-center gap-2 text-sm font-bold uppercase tracking-widest text-white hover:text-white/70 transition-colors border-b border-white/30 pb-1 hover:border-white">
Browse Catalogue
</Link>
</div>
</div>
</Reveal>
+37 -40
View File
@@ -35,48 +35,45 @@ function Products() {
/>
<section className="relative z-10">
<div className="mx-auto max-w-7xl space-y-12 px-6 pb-24">
{products?.map((product, i) => (
<Reveal key={product.id} delay={i * 80}>
<div className="group grid items-center gap-8 overflow-hidden rounded-3xl border border-border/50 bg-card p-6 shadow-lg transition-all hover:shadow-xl hover:shadow-brand/5 md:grid-cols-2 md:gap-12 md:p-10">
{product.image && (
<div className="overflow-hidden rounded-2xl shadow-md">
<img
src={product.image}
loading="lazy"
width={1024}
height={768}
alt={`${product.name} machinery`}
className="aspect-[4/3] w-full object-cover transition-transform duration-700 group-hover:scale-105"
/>
</div>
)}
<div>
<h2 className="text-3xl font-black tracking-tight text-foreground md:text-4xl">{product.name}</h2>
{product.features && product.features.length > 0 && (
<ul className="mt-8 grid gap-4 text-base text-muted-foreground sm:grid-cols-2">
{product.features.map((feature) => (
<li key={feature.id} className="flex items-center gap-3">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-brand/10 text-brand">
<svg className="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={3}>
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
</svg>
</span>
<span className="font-medium">{feature.name}</span>
</li>
))}
</ul>
<div className="mx-auto max-w-7xl px-6 pb-32">
<div className="flex flex-col gap-0 border-t border-border">
{products?.map((product, i) => (
<Reveal key={product.id} delay={i * 80}>
<div className="group grid items-center gap-12 border-b border-border py-16 transition-colors hover:bg-muted/30 md:grid-cols-12">
{product.image && (
<div className="md:col-span-6 overflow-hidden bg-muted aspect-[4/3]">
<img
src={product.image}
loading="lazy"
alt={`${product.name} machinery`}
className="w-full h-full object-cover grayscale transition duration-1000 group-hover:grayscale-0 group-hover:scale-105"
/>
</div>
)}
<Link
to="/contact"
className="mt-7 inline-block bg-ink px-6 py-3 text-sm font-semibold text-primary-foreground transition hover:bg-brand"
>
Request pricing
</Link>
<div className="md:col-span-6 md:pl-8">
<span className="text-sm font-bold uppercase tracking-widest text-muted-foreground mb-4 block">0{i + 1}</span>
<h2 className="text-4xl font-display font-black tracking-tighter uppercase text-foreground md:text-5xl">{product.name}</h2>
{product.features && product.features.length > 0 && (
<ul className="mt-8 grid gap-4 text-sm font-medium uppercase tracking-widest text-muted-foreground sm:grid-cols-2">
{product.features.map((feature) => (
<li key={feature.id} className="flex items-start gap-4">
<span className="text-foreground">—</span>
<span>{feature.name}</span>
</li>
))}
</ul>
)}
<Link
to="/contact"
className="mt-12 inline-flex items-center gap-2 text-xs font-bold uppercase tracking-widest text-background bg-foreground px-8 py-4 hover:bg-foreground/80 transition-colors"
>
Request pricing
</Link>
</div>
</div>
</div>
</Reveal>
))}
</Reveal>
))}
</div>
</div>
</section>
</div>
+29 -25
View File
@@ -80,31 +80,35 @@ function ProjectsEvents() {
description="A look at recent work — machines delivered, lines commissioned and exhibitions attended."
/>
<section className="relative z-10">
<div className="mx-auto grid max-w-7xl gap-6 px-6 pb-24 md:grid-cols-3">
{entries.map((e, i) => (
<Reveal key={e.id} delay={i * 80}>
<article className="group flex h-full flex-col overflow-hidden rounded-3xl border border-border/50 bg-card shadow-lg transition-all hover:-translate-y-1 hover:shadow-xl hover:shadow-brand/5">
{e.image && (
<img
src={e.image}
loading="lazy"
width={1024}
height={768}
alt={e.title}
className="aspect-[4/3] w-full object-cover transition-transform duration-700 group-hover:scale-105"
/>
)}
<div className="p-6">
<p className="inline-flex items-center gap-2 rounded-full bg-accent/10 px-3 py-1 text-xs font-bold uppercase tracking-widest text-accent">
{e.year} · {e.tag}
</p>
<h2 className="mt-2 text-xl font-bold">{e.title}</h2>
<p className="mt-2 text-sm text-muted-foreground">{e.copy}</p>
</div>
</article>
</Reveal>
))}
<section className="relative z-10 border-t border-border mt-16">
<div className="mx-auto max-w-7xl px-6 py-32">
<div className="grid gap-16 md:grid-cols-2 lg:grid-cols-3">
{entries.map((e, i) => (
<Reveal key={e.id} delay={i * 80}>
<article className="group flex h-full flex-col">
{e.image && (
<div className="aspect-[4/3] w-full overflow-hidden bg-muted mb-8">
<img
src={e.image}
loading="lazy"
alt={e.title}
className="w-full h-full object-cover grayscale transition-transform duration-1000 group-hover:grayscale-0 group-hover:scale-105"
/>
</div>
)}
<div className="flex flex-col flex-1 border-t-2 border-foreground pt-6">
<div className="flex items-center gap-4 mb-4">
<p className="text-xs font-bold uppercase tracking-widest text-muted-foreground">{e.year}</p>
<span className="h-px flex-1 bg-border" />
<p className="text-xs font-bold uppercase tracking-widest text-muted-foreground">{e.tag}</p>
</div>
<h2 className="text-2xl font-display font-black tracking-tight uppercase text-foreground">{e.title}</h2>
<p className="mt-4 text-sm font-medium leading-relaxed text-muted-foreground">{e.copy}</p>
</div>
</article>
</Reveal>
))}
</div>
</div>
</section>
</div>
+44 -58
View File
@@ -34,68 +34,54 @@ function Team() {
description="A compact, hands-on team of engineers, machinists and trade specialists working from Kohalpur-11, Banke."
/>
<section className="relative z-10">
<div className="mx-auto grid max-w-7xl gap-4 px-6 pb-24 md:grid-cols-2 lg:grid-cols-3">
{people?.map((person, i) => (
<Reveal key={person.id} delay={i * 70}>
<div className="flex h-full flex-col justify-between rounded-xl border border-border bg-card p-6 shadow-sm transition-all hover:shadow-md">
{/* Top Section: Avatar, Name, Status */}
<div className="flex items-start justify-between">
<div className="flex items-center gap-3">
{person.image ? (
<img src={person.image} alt={person.name} className="h-11 w-11 rounded-full object-cover" />
) : (
<div className="grid h-11 w-11 place-items-center rounded-full bg-muted font-display text-lg font-bold text-foreground">
{String(person.name).charAt(0)}
</div>
)}
<section className="relative z-10 border-t border-border">
<div className="mx-auto max-w-7xl px-6 pb-32 pt-16">
<div className="grid gap-16 sm:grid-cols-2 lg:grid-cols-3">
{people?.map((person, i) => (
<Reveal key={person.id} delay={i * 70}>
<div className="group flex h-full flex-col">
{person.image ? (
<div className="aspect-[3/4] w-full overflow-hidden bg-muted mb-6">
<img src={person.image} alt={person.name} className="h-full w-full object-cover grayscale transition duration-700 group-hover:grayscale-0" />
</div>
) : (
<div className="aspect-[3/4] w-full bg-muted mb-6 grid place-items-center">
<span className="font-display text-6xl font-black text-muted-foreground/30">{String(person.name).charAt(0)}</span>
</div>
)}
<div className="flex-1 flex flex-col justify-between">
<div>
<h2 className="text-[15px] font-semibold text-foreground leading-tight">{person.name}</h2>
<h3 className="text-[13px] text-muted-foreground mt-0.5">{person.position}</h3>
<h2 className="text-2xl font-display font-black tracking-tight uppercase text-foreground">{person.name}</h2>
<h3 className="text-xs font-bold uppercase tracking-widest text-muted-foreground mt-2 mb-6 border-b border-border pb-4">{person.position}</h3>
<p className="text-sm font-medium leading-relaxed text-foreground line-clamp-4">
{person.short_intro || person.bio.replace(/<[^>]*>?/gm, '')}
</p>
</div>
<div className="mt-8 flex flex-col gap-2">
{person.email && (
<a
href={`mailto:${person.email}`}
className="text-xs font-bold uppercase tracking-widest text-foreground hover:text-brand transition-colors flex items-center gap-2"
>
<Mail className="h-3 w-3" /> {person.email}
</a>
)}
{person.phone_no && (
<a
href={`tel:${person.phone_no}`}
className="text-xs font-bold uppercase tracking-widest text-foreground hover:text-brand transition-colors flex items-center gap-2"
>
<Phone className="h-3 w-3" /> {person.phone_no}
</a>
)}
</div>
</div>
<span className="text-[12px] text-muted-foreground">
{person.email && "Open to chat"}
</span>
</div>
{/* Middle: Bio */}
<p className="mt-5 text-[14px] leading-relaxed text-muted-foreground line-clamp-3">
{person.short_intro || person.bio.replace(/<[^>]*>?/gm, '')}
</p>
{/* Bottom: Location & Icons */}
<div className="mt-6 flex items-center justify-between">
<span className="text-[13px] text-muted-foreground">
{person.phone_no ? person.phone_no : "Kohalpur, Nepal"}
</span>
<div className="flex items-center gap-2">
{person.email && (
<a
href={`mailto:${person.email}`}
className="flex h-8 w-8 items-center justify-center rounded-md border border-border text-muted-foreground transition hover:bg-muted hover:text-foreground"
aria-label="Email"
>
<Mail className="h-4 w-4" />
</a>
)}
{person.phone_no && (
<a
href={`tel:${person.phone_no}`}
className="flex h-8 w-8 items-center justify-center rounded-md border border-border text-muted-foreground transition hover:bg-muted hover:text-foreground"
aria-label="Phone"
>
<Phone className="h-4 w-4" />
</a>
)}
</div>
</div>
</div>
</Reveal>
))}
</Reveal>
))}
</div>
</div>
</section>
</div>
+2 -2
View File
@@ -35,8 +35,8 @@
--color-brand: var(--brand);
--color-ink: var(--ink);
--color-mist: var(--mist);
--font-display: "Archivo Black", sans-serif;
--font-sans: "Hind", sans-serif;
--font-display: "Helvetica Neue", Helvetica, Arial, sans-serif;
--font-sans: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
:root {