Update AboutUsPage, server routes, packages, and assets

This commit is contained in:
Vishva
2026-07-29 16:53:09 +05:30
parent ff9795e4c9
commit 3ee3d8c652
67 changed files with 7641 additions and 175 deletions
+169 -144
View File
@@ -8,6 +8,7 @@ import ServiceDial from './components/ServiceDial';
import FeaturedGallery from './components/FeaturedGallery';
import ProductCard from './components/ProductCard';
import ContactSection from './components/ContactSection';
import AboutUsPage from './components/AboutUsPage';
// Reusable Scroll Reveal Wrapper with Reduced Motion Support
function Reveal({ children, delay = 0, style }) {
@@ -377,7 +378,9 @@ export default function App({ previewMode = false }) {
const [activeSection, setActiveSection] = useState('home');
const [currentPage, setCurrentPage] = useState(() => {
const hash = typeof window !== 'undefined' ? window.location.hash : '';
return hash === '#contact' || hash === '#contactus' ? 'contact' : 'home';
if (hash === '#contact' || hash === '#contactus') return 'contact';
if (hash === '#about' || hash === '#aboutus') return 'about';
return 'home';
});
useEffect(() => {
@@ -387,6 +390,10 @@ export default function App({ previewMode = false }) {
setCurrentPage('contact');
setActiveSection('contactus');
window.scrollTo({ top: 0, behavior: 'smooth' });
} else if (hash === '#about' || hash === '#aboutus') {
setCurrentPage('about');
setActiveSection('aboutus');
window.scrollTo({ top: 0, behavior: 'smooth' });
} else if (hash === '#home' || hash === '') {
setCurrentPage('home');
}
@@ -481,6 +488,7 @@ export default function App({ previewMode = false }) {
const getActiveNavItem = () => {
if (currentPage === 'contact') return 'Contact Us';
if (currentPage === 'about') return 'About Us';
switch (activeSection) {
case 'home':
return 'Home';
@@ -560,6 +568,14 @@ export default function App({ previewMode = false }) {
return;
}
if (item === 'About Us') {
setCurrentPage('about');
setActiveSection('aboutus');
window.location.hash = 'aboutus';
window.scrollTo({ top: 0, behavior: 'smooth' });
return;
}
const sectionMap = {
Home: 'home',
'About Us': 'aboutus',
@@ -820,6 +836,8 @@ export default function App({ previewMode = false }) {
)}
{currentPage === 'contact' ? (
<ContactSection isMobile={isMobile} onOpenStrategy={() => setIsStrategyOpen(true)} />
) : currentPage === 'about' ? (
<AboutUsPage isMobile={isMobile} onOpenStrategy={() => setIsStrategyOpen(true)} onNavigate={handleNavClick} />
) : (
<>
{/* Main Homepage Content */}
@@ -1788,32 +1806,36 @@ export default function App({ previewMode = false }) {
{/* Products Suite */}
<section id="products" style={{
padding: isMobile ? '4rem 1.25rem' : '6rem 4rem',
backgroundImage: `url(${assetUrl('/assets/products_bg.svg')})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
background: 'linear-gradient(180deg, #2791a5 0%, #0f4652 35%, #020710 100%)',
position: 'relative',
overflow: 'hidden'
}}>
{/* Soft gradient from bottom to top: light bottom fading to 0 opacity at top */}
<div style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: 'linear-gradient(0deg, #ffffff 0%, rgba(255, 255, 255, 0.85) 45%, rgba(255, 255, 255, 0.25) 75%, rgba(255, 255, 255, 0) 100%)',
pointerEvents: 'none',
zIndex: 1
}} />
{/* Wave Pattern Overlay */}
<img
src={assetUrl('/assets/Wave Pattern 2.svg')}
alt=""
aria-hidden="true"
style={{
position: 'absolute',
top: '-50%',
left: 0,
width: '100%',
height: '180%',
objectFit: 'cover',
objectPosition: 'center top',
opacity: 0.42,
pointerEvents: 'none',
zIndex: 1
}}
/>
<div style={{ maxWidth: '1440px', margin: '0 auto', width: '100%', position: 'relative', zIndex: 10 }}>
{/* Header - Left Aligned matching screenshot */}
<Reveal>
<div style={{ textAlign: 'left', marginBottom: '3.5rem', position: 'relative', zIndex: 10 }}>
<h2 style={{ fontSize: 'clamp(2.2rem, 3.2vw, 2.8rem)', fontWeight: 800, color: '#0f172a', margin: '0 0 0.4rem 0', letterSpacing: '-0.02em' }}>
<h2 style={{ fontSize: 'clamp(2.2rem, 3.2vw, 2.8rem)', fontWeight: 500, color: '#ffffff', margin: '0 0 0.4rem 0', letterSpacing: '-0.02em' }}>
{products.title || 'Our Products Suite'}
</h2>
<span style={{ color: '#64748b', fontSize: '0.78rem', fontWeight: 500, textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block' }}>
<span style={{ color: '#8c9ba5', fontSize: '0.78rem', fontWeight: 500, textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block' }}>
{products.eyebrow || 'ONE ECOSYSTEM. EXPONENTIAL IMPACT.'}
</span>
</div>
@@ -1827,7 +1849,7 @@ export default function App({ previewMode = false }) {
alignItems: 'stretch',
position: 'relative',
zIndex: 10,
marginBottom: '4rem'
marginBottom: '2.5rem'
}}>
{products.items.map((item, index) => (
<ProductCard
@@ -1839,6 +1861,56 @@ export default function App({ previewMode = false }) {
/>
))}
</div>
{/* Sub-text below product cards */}
<p style={{
color: '#8c9ba5',
fontSize: '0.88rem',
textAlign: 'center',
maxWidth: '850px',
margin: '0 auto 1.8rem auto',
lineHeight: '1.5',
fontWeight: 400
}}>
Plus many more specialized solutions: LiveWire, Nucleus, Digital Meeting Agenda, SEC, XR Workbench, TMS, and others - purpose-built for manufacturing and enterprise excellence.
</p>
{/* Bottom CTA Button */}
<div style={{ display: 'flex', justifyContent: 'center' }}>
<button
type="button"
onClick={() => scrollToSection('contactus')}
style={{
display: 'inline-flex',
alignItems: 'center',
gap: '0.6rem',
background: 'rgba(255, 255, 255, 0.05)',
border: '1.5px solid rgba(255, 255, 255, 0.35)',
boxShadow: '0 8px 25px rgba(0, 0, 0, 0.3)',
borderRadius: '50px',
color: '#ffffff',
padding: '0.75rem 2rem',
fontSize: '0.92rem',
fontWeight: 600,
cursor: 'pointer',
transition: 'all 0.25s ease',
backdropFilter: 'blur(10px)'
}}
onMouseEnter={(e) => {
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.12)';
e.currentTarget.style.borderColor = 'rgba(255, 255, 255, 0.6)';
e.currentTarget.style.transform = 'translateY(-2px)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.05)';
e.currentTarget.style.borderColor = 'rgba(255, 255, 255, 0.35)';
e.currentTarget.style.transform = 'translateY(0)';
}}
>
<span>Explore Our Full Product Suite</span>
<ArrowRight size={16} />
</button>
</div>
</div>
</section>
@@ -2069,20 +2141,21 @@ export default function App({ previewMode = false }) {
<div style={{
background: 'linear-gradient(135deg, #092244 0%, #05162d 100%)',
borderRadius: '20px',
padding: '2.5rem 1.8rem',
padding: '2.2rem 1.6rem',
display: 'flex',
flexDirection: 'column',
gap: '2rem',
marginBottom: '3rem',
gap: '1.2rem',
marginBottom: '2.5rem',
position: 'relative',
overflow: 'hidden',
boxShadow: '0 20px 40px rgba(0,0,0,0.2)'
boxShadow: '0 20px 40px rgba(0,0,0,0.25)',
border: '1px solid rgba(255, 255, 255, 0.08)'
}}>
<div>
<h2 style={{ fontSize: '1.8rem', fontWeight: 500, color: '#ffffff', lineHeight: 1.2, marginBottom: '1rem', letterSpacing: '-0.02em' }}>
<h2 style={{ fontSize: '1.65rem', fontWeight: 600, color: '#ffffff', lineHeight: 1.25, marginBottom: '0.8rem', letterSpacing: '-0.02em' }}>
Let's Build What's Next -<br/>Together.
</h2>
<p style={{ fontSize: '0.88rem', fontWeight: 500, lineHeight: 1.55, color: '#cbd5e1', marginBottom: '2rem', textTransform: 'uppercase', letterSpacing: '0.06em' }}>
<p style={{ fontSize: '0.82rem', fontWeight: 500, lineHeight: 1.55, color: '#cbd5e1', marginBottom: '1.8rem', textTransform: 'uppercase', letterSpacing: '0.06em' }}>
{footer.cta.body}
</p>
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.9rem' }}>
@@ -2098,45 +2171,14 @@ export default function App({ previewMode = false }) {
fontSize: '0.88rem',
fontWeight: 600,
cursor: 'pointer',
width: '100%',
textAlign: 'center'
}}
>
{footer.cta.primaryButton}
</button>
{/* Secondary button commented out per user request
<button
onClick={() => setIsStrategyOpen(true)}
style={{
background: '#e8f1f8',
border: 'none',
color: '#2a4a6c',
padding: '0.85rem 1.6rem',
borderRadius: '50px',
fontSize: '0.88rem',
fontWeight: 600,
cursor: 'pointer',
}}
>
{footer.cta.secondaryButton}
</button>
*/}
</div>
</div>
{/* Phone mockup container on mobile */}
<div style={{ width: '100%', height: '180px', position: 'relative', overflow: 'hidden', borderRadius: '12px' }}>
<img
src={assetUrl(footer.cta.image)}
alt="Phone preview"
style={{
position: 'absolute',
right: '-20px',
top: '-90px',
width: '280px',
height: 'auto',
maxWidth: 'none',
}}
/>
</div>
</div>
</Reveal>
) : (
@@ -2209,34 +2251,6 @@ export default function App({ previewMode = false }) {
>
{footer.cta.primaryButton}
</button>
{/* Secondary button commented out per user request
<button
onClick={() => setIsStrategyOpen(true)}
style={{
background: '#e8f1f8',
border: 'none',
color: '#2a4a6c',
padding: '0.85rem 1.8rem',
borderRadius: '50px',
fontSize: 'clamp(0.75rem, 0.95vw, 0.88rem)',
fontWeight: 600,
cursor: 'pointer',
transition: 'all 0.25s ease',
}}
onMouseEnter={e => {
e.currentTarget.style.transform = 'translateY(-2px)';
e.currentTarget.style.background = '#ffffff';
e.currentTarget.style.boxShadow = '0 8px 20px rgba(0, 0, 0, 0.1)';
}}
onMouseLeave={e => {
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.background = '#e8f1f8';
e.currentTarget.style.boxShadow = 'none';
}}
>
{footer.cta.secondaryButton}
</button>
*/}
</div>
</div>
</div>
@@ -2247,20 +2261,20 @@ export default function App({ previewMode = false }) {
<div style={{
display: 'grid',
gridTemplateColumns: isMobile ? '1fr 1fr' : '180px 180px 1fr',
gap: isMobile ? '1.5rem' : '1.25rem',
paddingBottom: '2.5rem',
gap: isMobile ? '2rem 1.5rem' : '1.25rem',
paddingBottom: isMobile ? '2rem' : '2.5rem',
borderBottom: '1px solid rgba(30,41,59,0.12)',
marginBottom: '1.5rem',
}}>
{/* Quick Links */}
<div>
<h5 style={{ fontSize: '0.7rem', fontWeight: 800, letterSpacing: '0.12em', textTransform: 'uppercase', color: '#1e293b', marginBottom: '1rem' }}>Quick Links</h5>
<ul style={{ listStyle: 'none', display: 'flex', flexDirection: 'column', gap: '0.35rem', padding: 0, margin: 0 }}>
<h5 style={{ fontSize: '0.75rem', fontWeight: 800, letterSpacing: '0.12em', textTransform: 'uppercase', color: '#1e293b', marginBottom: '1rem' }}>Quick Links</h5>
<ul style={{ listStyle: 'none', display: 'flex', flexDirection: 'column', gap: '0.45rem', padding: 0, margin: 0 }}>
<li>
<a href="#home" onClick={e => {
e.preventDefault();
scrollToSection('home');
}} style={{ color: '#475569', textDecoration: 'none', fontSize: '0.84rem', transition: 'color 0.2s' }}
}} style={{ color: '#475569', textDecoration: 'none', fontSize: '0.85rem', transition: 'color 0.2s' }}
onMouseEnter={e => e.currentTarget.style.color = '#1e40af'}
onMouseLeave={e => e.currentTarget.style.color = '#475569'}>Home</a>
</li>
@@ -2268,7 +2282,7 @@ export default function App({ previewMode = false }) {
<a href="#certifications" onClick={e => {
e.preventDefault();
scrollToSection('certifications');
}} style={{ color: '#475569', textDecoration: 'none', fontSize: '0.84rem', transition: 'color 0.2s' }}
}} style={{ color: '#475569', textDecoration: 'none', fontSize: '0.85rem', transition: 'color 0.2s' }}
onMouseEnter={e => e.currentTarget.style.color = '#1e40af'}
onMouseLeave={e => e.currentTarget.style.color = '#475569'}>About Us</a>
</li>
@@ -2276,7 +2290,7 @@ export default function App({ previewMode = false }) {
<a href="#services" onClick={e => {
e.preventDefault();
scrollToSection('services');
}} style={{ color: '#475569', textDecoration: 'none', fontSize: '0.84rem', transition: 'color 0.2s' }}
}} style={{ color: '#475569', textDecoration: 'none', fontSize: '0.85rem', transition: 'color 0.2s' }}
onMouseEnter={e => e.currentTarget.style.color = '#1e40af'}
onMouseLeave={e => e.currentTarget.style.color = '#475569'}>Our Services</a>
</li>
@@ -2285,72 +2299,83 @@ export default function App({ previewMode = false }) {
{/* Products */}
<div>
<h5 style={{ fontSize: '0.7rem', fontWeight: 800, letterSpacing: '0.12em', textTransform: 'uppercase', color: '#1e293b', marginBottom: '1rem' }}>Products</h5>
<ul style={{ listStyle: 'none', display: 'flex', flexDirection: 'column', gap: '0.35rem', padding: 0, margin: 0 }}>
{['PRODMAX', 'Budgie HRMS', 'EVIDO'].map(l => (
<h5 style={{ fontSize: '0.75rem', fontWeight: 800, letterSpacing: '0.12em', textTransform: 'uppercase', color: '#1e293b', marginBottom: '1rem' }}>Products</h5>
<ul style={{ listStyle: 'none', display: 'flex', flexDirection: 'column', gap: '0.45rem', padding: 0, margin: 0 }}>
{(footer.productLinks && footer.productLinks.length ? footer.productLinks.map(p => p.label) : ['Nebula AI platform', 'Prodmax', 'Budgie']).map(l => (
<li key={l}><a href="#products" onClick={e => {
e.preventDefault();
scrollToSection('products');
}} style={{ color: '#475569', textDecoration: 'none', fontSize: '0.84rem', transition: 'color 0.2s' }}
}} style={{ color: '#475569', textDecoration: 'none', fontSize: '0.85rem', transition: 'color 0.2s' }}
onMouseEnter={e => e.currentTarget.style.color = '#1e40af'}
onMouseLeave={e => e.currentTarget.style.color = '#475569'}>{l}</a></li>
))}
</ul>
</div>
{/* Social Links Column */}
<div style={{ gridColumn: isMobile ? 'span 2' : 'auto' }}>
<h5 style={{ fontSize: '0.7rem', fontWeight: 800, letterSpacing: '0.12em', textTransform: 'uppercase', color: '#1e40af', marginBottom: '1rem' }}>Social Links</h5>
<h5 style={{ fontSize: '0.75rem', fontWeight: 800, letterSpacing: '0.12em', textTransform: 'uppercase', color: '#1e40af', marginBottom: '1rem' }}>Social Links</h5>
<div style={{ display: 'flex', gap: '0.75rem', alignItems: 'center', flexWrap: 'wrap' }}>
{[
{ label: 'Facebook', d: 'M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z' },
{ label: 'Instagram', d: 'M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.051.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 1 0 0 12.324 6.162 6.162 0 0 0 0-12.324zM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm6.406-11.845a1.44 1.44 0 1 0 0 2.881 1.44 1.44 0 0 0 0-2.881z' },
{ label: 'LinkedIn', d: 'M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z' },
{ label: 'Telegram', d: 'M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.562 8.161c-.18.717-.962 4.084-1.362 5.462-.168.58-.506.772-.712.791-.45.041-.79-.297-1.225-.583-.681-.447-1.066-.723-1.727-1.158-.764-.502-.269-.778.167-1.23.114-.118 2.096-1.922 2.134-2.083.005-.02.009-.095-.036-.135-.045-.04-.112-.026-.16-.015-.069.016-1.171.745-3.305 2.186-.313.215-.596.321-.85.315-.281-.006-.822-.153-1.225-.284-.494-.16-.887-.246-.853-.518.178-.142.716-.291 1.6-.447 5.485-2.385 9.143-3.957 10.973-4.717.868-.362 1.8-.425 2.39-.425.13 0 .42.03.606.18.156.126.2.296.21.425.013.167.013.435-.008.685z' },
{ label: 'WhatsApp', d: 'M12.008 22c-1.948 0-3.855-.522-5.504-1.508l-.395-.235-4.093 1.073 1.092-3.993-.257-.408C1.815 15.222 1.25 13.064 12.008 12c5.514 0 10.008 4.486 10.008 10S17.522 22 12.008 22zm8.487-18.49C18.232 1.257 15.258 0 12.008 0 5.394 0 .02 5.373.017 11.99c0 2.115.553 4.18 1.603 5.996L0 24l6.155-1.615c1.768.964 3.753 1.472 5.845 1.474v-.002c6.611 0 11.986-5.375 11.99-11.994.002-3.206-1.242-6.22-3.497-8.48zM17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.063 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.715 2.006-1.404.248-.69.248-1.278.173-1.402-.074-.125-.272-.199-.57-.348z' },
{ label: 'X', d: 'M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z' },
{ label: 'YouTube', d: 'M23.498 6.163a3.003 3.003 0 0 0-2.11-2.11C19.53 3.545 12 3.545 12 3.545s-7.53 0-9.388.508a3.003 3.003 0 0 0-2.11 2.11C0 8.017 0 12 0 12s0 3.983.502 5.837a3.003 3.003 0 0 0 2.11 2.11c1.858.508 9.388.508 9.388.508s7.53 0 9.388-.508a3.003 3.003 0 0 0 2.11-2.11C24 15.983 24 12 24 12s0-3.983-.502-5.837zM9.545 15.568V8.432L15.818 12l-6.273 3.568z' },
].map(({ label, d }) => (
<a key={label} href="#" aria-label={label}
style={{
width: '34px', height: '34px', borderRadius: '50%',
background: 'rgba(30,41,59,0.08)', border: '1px solid rgba(30,41,59,0.12)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
transition: 'all 0.2s ease', color: '#475569',
}}
onMouseEnter={e => { e.currentTarget.style.background = '#1e40af'; e.currentTarget.style.color = '#fff'; e.currentTarget.style.borderColor = '#1e40af'; }}
onMouseLeave={e => { e.currentTarget.style.background = 'rgba(30,41,59,0.08)'; e.currentTarget.style.color = '#475569'; e.currentTarget.style.borderColor = 'rgba(30,41,59,0.12)'; }}
>
<svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor" stroke="none">
<path d={d} />
</svg>
</a>
))}
</div>
<div style={{
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
gap: '1rem',
marginTop: '1.5rem',
fontSize: '0.82rem',
color: '#475569',
}}>
<a href="#" style={{ color: '#475569', textDecoration: 'none', fontWeight: 500, transition: 'color 0.2s' }}
onMouseEnter={e => e.currentTarget.style.color = '#1e40af'}
onMouseLeave={e => e.currentTarget.style.color = '#475569'}>Privacy Policy</a>
<span style={{ color: '#cbd5e1' }}>&bull;</span>
<a href="#" style={{ color: '#475569', textDecoration: 'none', fontWeight: 500, transition: 'color 0.2s' }}
onMouseEnter={e => e.currentTarget.style.color = '#1e40af'}
onMouseLeave={e => e.currentTarget.style.color = '#475569'}>Terms & Conditions</a>
<span style={{ color: '#cbd5e1' }}>&bull;</span>
<span style={{ fontSize: '0.78rem', color: '#334155' }}>
Copyrights reserved to CAVIN INFOTECH
</span>
{(footer.social && footer.social.length ? footer.social : [
{ platform: 'Facebook', url: 'https://www.facebook.com/cavininfotech1' },
{ platform: 'X', url: 'https://x.com/cavin_infotech' },
{ platform: 'Instagram', url: 'https://www.instagram.com/cavin_infotech' },
{ platform: 'LinkedIn', url: 'https://www.linkedin.com/company/cavin-infotech/' },
{ platform: 'YouTube', url: 'https://youtube.com/@cavin_infotech' }
]).map(({ platform, url }) => {
const paths = {
Facebook: 'M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z',
Instagram: 'M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.051.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 1 0 0 12.324 6.162 6.162 0 0 0 0-12.324zM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm6.406-11.845a1.44 1.44 0 1 0 0 2.881 1.44 1.44 0 0 0 0-2.881z',
LinkedIn: 'M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z',
X: 'M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z',
YouTube: 'M23.498 6.163a3.003 3.003 0 0 0-2.11-2.11C19.53 3.545 12 3.545 12 3.545s-7.53 0-9.388.508a3.003 3.003 0 0 0-2.11 2.11C0 8.017 0 12 0 12s0 3.983.502 5.837a3.003 3.003 0 0 0 2.11 2.11c1.858.508 9.388.508 9.388.508s7.53 0 9.388-.508a3.003 3.003 0 0 0 2.11-2.11C24 15.983 24 12 24 12s0-3.983-.502-5.837zM9.545 15.568V8.432L15.818 12l-6.273 3.568z'
};
const d = paths[platform] || paths.Facebook;
return (
<a key={platform} href={url || '#'} target="_blank" rel="noopener noreferrer" aria-label={platform}
style={{
width: '36px', height: '36px', borderRadius: '50%',
background: 'rgba(30,41,59,0.08)', border: '1px solid rgba(30,41,59,0.12)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
transition: 'all 0.2s ease', color: '#475569',
}}
onMouseEnter={e => { e.currentTarget.style.background = '#1e40af'; e.currentTarget.style.color = '#fff'; e.currentTarget.style.borderColor = '#1e40af'; }}
onMouseLeave={e => { e.currentTarget.style.background = 'rgba(30,41,59,0.08)'; e.currentTarget.style.color = '#475569'; e.currentTarget.style.borderColor = 'rgba(30,41,59,0.12)'; }}
>
<svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor" stroke="none">
<path d={d} />
</svg>
</a>
);
})}
</div>
</div>
</div>
{/* Legal / Copyright Bottom Bar */}
<div style={{
display: 'flex',
flexDirection: isMobile ? 'column' : 'row',
alignItems: isMobile ? 'flex-start' : 'center',
justifyContent: 'space-between',
gap: isMobile ? '0.75rem' : '1.5rem',
fontSize: '0.82rem',
color: '#475569',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem', flexWrap: 'wrap' }}>
<a href="#" style={{ color: '#475569', textDecoration: 'none', fontWeight: 500, transition: 'color 0.2s' }}
onMouseEnter={e => e.currentTarget.style.color = '#1e40af'}
onMouseLeave={e => e.currentTarget.style.color = '#475569'}>Privacy Policy</a>
<span style={{ color: '#cbd5e1' }}>&bull;</span>
<a href="#" style={{ color: '#475569', textDecoration: 'none', fontWeight: 500, transition: 'color 0.2s' }}
onMouseEnter={e => e.currentTarget.style.color = '#1e40af'}
onMouseLeave={e => e.currentTarget.style.color = '#475569'}>Terms & Conditions</a>
</div>
<span style={{ fontSize: '0.78rem', color: '#64748b' }}>
Copyrights reserved to CAVIN INFOTECH
</span>
</div>
</div>
</footer>
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 169 KiB

+9
View File
@@ -0,0 +1,9 @@
<svg width="1728" height="1016" viewBox="0 0 1728 1016" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="1728" height="1016" fill="url(#paint0_linear_291_10455)"/>
<defs>
<linearGradient id="paint0_linear_291_10455" x1="864" y1="0" x2="864" y2="1016" gradientUnits="userSpaceOnUse">
<stop stop-color="#2FA0B6"/>
<stop offset="1" stop-color="#01040B"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 397 B

+9
View File
@@ -0,0 +1,9 @@
<svg width="1728" height="1107" viewBox="0 0 1728 1107" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="1728" height="1107" fill="url(#paint0_linear_291_8788)"/>
<defs>
<linearGradient id="paint0_linear_291_8788" x1="864" y1="0" x2="864" y2="1107" gradientUnits="userSpaceOnUse">
<stop offset="0.591346" stop-color="#01040B"/>
<stop offset="1" stop-color="#2FA0B6"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 413 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="29" height="29" viewBox="0 0 29 29" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="14.1884" cy="14.1884" r="14.1884" fill="#F67057"/>
<circle cx="14.1883" cy="14.1864" r="8.73132" fill="#F4F8FB"/>
</svg>

After

Width:  |  Height:  |  Size: 229 B

+12
View File
@@ -0,0 +1,12 @@
<svg width="902" height="552" viewBox="0 0 902 552" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_f_291_11190)">
<circle cx="774.8" cy="774.8" r="537" fill="#2FA0B6" fill-opacity="0.3"/>
</g>
<defs>
<filter id="filter0_f_291_11190" x="-1.52588e-05" y="-0.000198364" width="1549.6" height="1549.6" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="118.9" result="effect1_foregroundBlur_291_11190"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 635 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 85 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 79 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 77 KiB

+36
View File
@@ -0,0 +1,36 @@
<svg width="1692" height="800" viewBox="0 0 1692 800" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_ddddd_8_95442)">
<path d="M28.0001 422.23C125.66 501.049 344.154 624.207 436.852 486.29C552.725 313.894 712.875 317.661 907.88 346.866C1096 375.039 1100.5 -16.459 1325.5 29.8044" stroke="#DA290C" stroke-width="4" stroke-linecap="round"/>
</g>
<defs>
<filter id="filter0_ddddd_8_95442" x="0" y="0" width="1714.5" height="1000.52" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="11" dy="13"/>
<feGaussianBlur stdDeviation="18.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.713726 0 0 0 0 0.333333 0 0 0 0 0.262745 0 0 0 0.98 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_8_95442"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="43" dy="53"/>
<feGaussianBlur stdDeviation="34"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.713726 0 0 0 0 0.333333 0 0 0 0 0.262745 0 0 0 0.85 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_8_95442" result="effect2_dropShadow_8_95442"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="97" dy="119"/>
<feGaussianBlur stdDeviation="46"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.713726 0 0 0 0 0.333333 0 0 0 0 0.262745 0 0 0 0.5 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_8_95442" result="effect3_dropShadow_8_95442"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="172" dy="212"/>
<feGaussianBlur stdDeviation="54.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.713726 0 0 0 0 0.333333 0 0 0 0 0.262745 0 0 0 0.15 0"/>
<feBlend mode="normal" in2="effect3_dropShadow_8_95442" result="effect4_dropShadow_8_95442"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="268" dy="331"/>
<feGaussianBlur stdDeviation="59.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.713726 0 0 0 0 0.333333 0 0 0 0 0.262745 0 0 0 0.02 0"/>
<feBlend mode="normal" in2="effect4_dropShadow_8_95442" result="effect5_dropShadow_8_95442"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect5_dropShadow_8_95442" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 78 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 76 KiB

+15
View File
@@ -0,0 +1,15 @@
<svg width="1434" height="1200" viewBox="0 0 1434 1200" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_f_291_11185)">
<path d="M537.476 100H411.257L1288.66 1027.7H1334L537.476 100Z" fill="white" fill-opacity="0.1"/>
<path d="M126.959 101.225H294.842L1092.59 1027.7H1053.38L126.959 101.225Z" fill="white" fill-opacity="0.1"/>
<path d="M100 362.255V200.49L885.496 1088.97H847.507L100 362.255Z" fill="white" fill-opacity="0.1"/>
<path d="M103.676 477.451V620.833L646.538 1100H701.682L103.676 477.451Z" fill="white" fill-opacity="0.1"/>
</g>
<defs>
<filter id="filter0_f_291_11185" x="0" y="0" width="1434" height="1200" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="50" result="effect1_foregroundBlur_291_11185"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 951 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

@@ -0,0 +1,12 @@
<svg width="647" height="504" viewBox="0 0 647 504" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_f_291_11290)">
<ellipse cx="323.5" cy="252" rx="163.5" ry="92" fill="#B3776D"/>
</g>
<defs>
<filter id="filter0_f_291_11290" x="0" y="0" width="647" height="504" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="80" result="effect1_foregroundBlur_291_11290"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 595 B

@@ -0,0 +1,12 @@
<svg width="647" height="504" viewBox="0 0 647 504" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_f_291_11291)">
<ellipse cx="323.5" cy="252" rx="163.5" ry="92" fill="#4D5154"/>
</g>
<defs>
<filter id="filter0_f_291_11291" x="0" y="0" width="647" height="504" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="80" result="effect1_foregroundBlur_291_11291"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 595 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 MiB

File diff suppressed because it is too large Load Diff
+23 -9
View File
@@ -31,8 +31,7 @@ export default function ContactSection({ isMobile, onOpenStrategy }) {
setErrorMsg('');
try {
// Try sending via API endpoint
const response = await fetch('/api/send', {
let response = await fetch('/api/contact', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
@@ -40,21 +39,36 @@ export default function ContactSection({ isMobile, onOpenStrategy }) {
name: formData.name,
email: formData.email,
phone: formData.phone,
interests: formData.subject,
subject: formData.subject,
message: formData.message
})
});
if (response.ok) {
if (!response.ok) {
response = await fetch('/api/send', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: 'contact',
name: formData.name,
email: formData.email,
phone: formData.phone,
subject: formData.subject,
message: formData.message
})
});
}
const resData = await response.json().catch(() => ({}));
if (response.ok && resData.success) {
setSubmitted(true);
setFormData({ name: '', email: '', phone: '', subject: '', message: '' });
} else {
// Fallback smooth demo success if backend API is not configured with live EmailJS keys
setSubmitted(true);
setFormData({ name: '', email: '', phone: '', subject: '', message: '' });
setErrorMsg(resData.error || resData.smtpError || 'Failed to send message. Please check SMTP configuration.');
}
} catch {
// Graceful fallback for local development without server
} catch (err) {
console.error('Contact submit error:', err);
setSubmitted(true);
setFormData({ name: '', email: '', phone: '', subject: '', message: '' });
} finally {
+56 -9
View File
@@ -27,17 +27,22 @@ export default function FeaturedGallery({ gallery }) {
}, [activeGalleryIndex, galleryData.length]);
return (
<section id="featured-gallery" style={{ padding: isMobile ? '4rem 1.25rem' : '6rem 4rem', background: '#020710', position: 'relative' }}>
<section id="featured-gallery" style={{
padding: isMobile ? '4rem 1.25rem' : '6rem 4rem 4rem 4rem',
background: 'linear-gradient(180deg, #020710 0%, #0f4652 65%, #2791a5 100%)',
position: 'relative',
overflow: 'hidden'
}}>
<div style={{ maxWidth: '1440px', margin: '0 auto', width: '100%', position: 'relative', zIndex: 10 }}>
<div style={{ marginBottom: '3.5rem' }}>
<span style={{ color: '#ffaa00', fontSize: '0.9rem', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.1em' }}>
{header.eyebrow}
</span>
<h2 style={{ fontSize: 'clamp(2rem, 3vw, 2.5rem)', fontWeight: 800, marginTop: '0.5rem', color: '#ffffff' }}>
{header.title}
<div style={{ marginBottom: '3rem' }}>
<h2 style={{ fontSize: 'clamp(2.2rem, 3.2vw, 2.8rem)', fontWeight: 500, color: '#ffffff', margin: '0 0 0.4rem 0', letterSpacing: '-0.02em' }}>
Case Studies
</h2>
<p style={{ color: '#94a3b8', fontSize: '1rem', marginTop: '0.75rem', maxWidth: '600px', lineHeight: '1.5' }}>
{header.subtitle}
<span style={{ color: '#8c9ba5', fontSize: '0.78rem', fontWeight: 500, textTransform: 'uppercase', letterSpacing: '0.08em', display: 'block', marginBottom: '0.6rem' }}>
BEFORE VS. AFTER: THE NUMBERS DON'T LIE.
</span>
<p style={{ color: '#94a3b8', fontSize: '0.95rem', marginTop: '0.5rem', maxWidth: '720px', lineHeight: '1.5', fontWeight: 400 }}>
Discover how leading manufacturers are using AI, SAP, and smart factory technologies to boost productivity, reduce costs, and gain competitive advantage.
</p>
</div>
@@ -46,6 +51,48 @@ export default function FeaturedGallery({ gallery }) {
activeIdx={activeGalleryIndex}
setActiveIdx={setActiveGalleryIndex}
/>
{/* Bottom CTA Button matching design screenshot */}
<div style={{ display: 'flex', justifyContent: 'center', marginTop: '3rem' }}>
<button
type="button"
onClick={() => {
const footer = document.getElementById('contactus');
if (footer) {
footer.scrollIntoView({ behavior: 'smooth' });
}
}}
style={{
display: 'inline-flex',
alignItems: 'center',
gap: '0.6rem',
background: 'rgba(255, 255, 255, 0.05)',
border: '1.5px solid rgba(255, 255, 255, 0.35)',
boxShadow: '0 8px 25px rgba(0, 0, 0, 0.3)',
borderRadius: '50px',
color: '#ffffff',
padding: '0.75rem 2rem',
fontSize: '0.92rem',
fontWeight: 600,
cursor: 'pointer',
transition: 'all 0.25s ease',
backdropFilter: 'blur(10px)'
}}
onMouseEnter={(e) => {
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.12)';
e.currentTarget.style.borderColor = 'rgba(255, 255, 255, 0.6)';
e.currentTarget.style.transform = 'translateY(-2px)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.05)';
e.currentTarget.style.borderColor = 'rgba(255, 255, 255, 0.35)';
e.currentTarget.style.transform = 'translateY(0)';
}}
>
<span>Explore Success Stories</span>
<ArrowRight size={16} />
</button>
</div>
</div>
</section>
);
+3 -3
View File
@@ -2,9 +2,9 @@ import { motion, useReducedMotion } from 'framer-motion';
import { assetUrl } from '../lib/assetUrl';
const ACCENT_GRADIENTS = [
'linear-gradient(0deg, #ffffff 0%, rgba(255, 255, 255, 0.95) 50%, rgba(235, 252, 240, 0.5) 100%)',
'linear-gradient(0deg, #ffffff 0%, rgba(255, 255, 255, 0.95) 50%, rgba(250, 243, 255, 0.5) 100%)',
'linear-gradient(0deg, #ffffff 0%, rgba(255, 255, 255, 0.95) 50%, rgba(254, 252, 232, 0.5) 100%)',
'linear-gradient(0deg, #ffffff 0%, #ffffff 50%, #e6f7ef 100%)',
'linear-gradient(0deg, #ffffff 0%, #ffffff 50%, #f7effe 100%)',
'linear-gradient(0deg, #ffffff 0%, #ffffff 50%, #fefce8 100%)',
];
export default function ProductCard({ product, isMobile, delay = 0, index = 0 }) {