update miletruth page and remove unwanted files
This commit is contained in:
@@ -74,8 +74,10 @@ export default function CompetitiveEdge() {
|
||||
<div className="container">
|
||||
{/* Section Header */}
|
||||
<div className="comparison-header" ref={headerRef}>
|
||||
<div className="advantage-badge">DoorMile Advantage</div>
|
||||
<h2 className="moat-heading">WHERE DOORMILE SITS AND WHY IT WINS</h2>
|
||||
<div className="advantage-eyebrow-container">
|
||||
<span className="advantage-eyebrow">/ DoorMile wins/</span>
|
||||
</div>
|
||||
<h2 className="moat-heading" data-text="WHERE DOORMILE SITS AND WHY IT WINS">WHERE DOORMILE SITS AND WHY IT WINS</h2>
|
||||
<p className="moat-desc">
|
||||
A side-by-side technical capabilities comparison showing how operational fleet ownership and dynamic AI planning disrupt basic aggregators.
|
||||
</p>
|
||||
@@ -253,59 +255,61 @@ export default function CompetitiveEdge() {
|
||||
|
||||
/* Section Header Layout */
|
||||
.comparison-header {
|
||||
text-align: center;
|
||||
text-align: left;
|
||||
margin-bottom: 60px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* DoorMile Advantage Badge */
|
||||
.advantage-badge {
|
||||
.advantage-eyebrow-container {
|
||||
width: 100%;
|
||||
border-bottom: 2px solid rgba(0, 0, 0, 0.16);
|
||||
padding-bottom: 16px;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
/* DoorMile Advantage Eyebrow */
|
||||
.advantage-eyebrow {
|
||||
font-family: 'Manrope', sans-serif;
|
||||
font-weight: 800;
|
||||
font-size: 0.75rem;
|
||||
letter-spacing: 0.12em;
|
||||
font-weight: 700;
|
||||
font-size: 0.85rem;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: #c8102e;
|
||||
background: rgba(200, 16, 46, 0.06);
|
||||
padding: 6px 14px;
|
||||
border-radius: 30px;
|
||||
margin: 0 auto 24px auto;
|
||||
border: 1.5px solid rgba(200, 16, 46, 0.15);
|
||||
color: #060606ff;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Centered heading with bottom accent underline */
|
||||
/* Outlined heading style with clean duplicate layering hack */
|
||||
.moat-heading {
|
||||
font-family: 'Manrope', sans-serif;
|
||||
font-size: clamp(2rem, 3.4vw, 3.2rem); /* Slightly enlarged for premium visual weight */
|
||||
font-weight: 800;
|
||||
line-height: 1.15;
|
||||
color: #111111;
|
||||
margin: 0 auto 20px auto;
|
||||
letter-spacing: -0.03em;
|
||||
position: relative;
|
||||
font-family: var(--font-syne), 'Syne', sans-serif !important;
|
||||
font-size: clamp(2.4rem, 6.8vw, 6.6rem) !important;
|
||||
font-weight: 800 !important;
|
||||
line-height: 1.1 !important;
|
||||
color: #fafafa !important; /* solid background color to cover inner overlapping outlines */
|
||||
margin: 0 0 24px 0;
|
||||
letter-spacing: -0.02em;
|
||||
text-transform: uppercase;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Centered horizontal red underline accent decoration */
|
||||
.moat-heading::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 72px;
|
||||
height: 4px;
|
||||
background: #c8102e;
|
||||
margin-top: 18px;
|
||||
border-radius: 2px;
|
||||
content: attr(data-text) !important;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
color: transparent !important;
|
||||
-webkit-text-stroke: 2.2px #c8102e;
|
||||
-webkit-text-fill-color: transparent !important;
|
||||
pointer-events: none;
|
||||
display: block !important; /* override any old display: none */
|
||||
}
|
||||
|
||||
.moat-desc {
|
||||
@@ -313,9 +317,9 @@ export default function CompetitiveEdge() {
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.65;
|
||||
color: #585c67;
|
||||
margin: 16px auto 0 auto !important;
|
||||
max-width: 760px !important;
|
||||
text-align: center !important;
|
||||
margin: 16px 0 0 0 !important;
|
||||
max-width: 820px !important;
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
/* Spacious table styling wrapper (100% width on Desktop) */
|
||||
|
||||
@@ -1,405 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { ScrollReveal } from "@/animations/Reveal";
|
||||
import emailjs from "@emailjs/browser";
|
||||
|
||||
// Type definitions for EmailJS template parameters
|
||||
interface EmailJSTemplateParams extends Record<string, unknown> {
|
||||
name: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
company: string;
|
||||
subject: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export default function ContactForm() {
|
||||
const socialIconSpacing = {
|
||||
"--grid-column-gap": "52px",
|
||||
"--grid-row-gap": "18px",
|
||||
columnGap: "52px",
|
||||
rowGap: "18px",
|
||||
} as React.CSSProperties;
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
fullName: "",
|
||||
email: "",
|
||||
subject: "",
|
||||
message: "",
|
||||
});
|
||||
const [formStatus, setFormStatus] = useState<"idle" | "submitting" | "success" | "error">("idle");
|
||||
const [errorMessage, setErrorMessage] = useState<string>("");
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData((prev) => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
// Pre-submission validation function
|
||||
const validateForm = (): string | null => {
|
||||
if (!formData.fullName.trim()) {
|
||||
return "Full name is required.";
|
||||
}
|
||||
if (formData.fullName.trim().length < 2) {
|
||||
return "Full name must be at least 2 characters.";
|
||||
}
|
||||
|
||||
if (!formData.email.trim()) {
|
||||
return "Email is required.";
|
||||
}
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(formData.email.trim())) {
|
||||
return "Please enter a valid email address.";
|
||||
}
|
||||
|
||||
if (!formData.subject.trim()) {
|
||||
return "Subject is required.";
|
||||
}
|
||||
|
||||
if (!formData.message.trim()) {
|
||||
return "Message is required.";
|
||||
}
|
||||
if (formData.message.trim().length < 10) {
|
||||
return "Message must be at least 10 characters.";
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setErrorMessage("");
|
||||
|
||||
// Validate inputs before submitting to EmailJS
|
||||
const validationError = validateForm();
|
||||
if (validationError) {
|
||||
setErrorMessage(validationError);
|
||||
setFormStatus("error");
|
||||
return;
|
||||
}
|
||||
|
||||
setFormStatus("submitting");
|
||||
|
||||
// Fetch credentials from Next.js environment variables
|
||||
const serviceId = process.env.NEXT_PUBLIC_EMAILJS_SERVICE_ID;
|
||||
const templateId = process.env.NEXT_PUBLIC_EMAILJS_TEMPLATE_ID;
|
||||
const publicKey = process.env.NEXT_PUBLIC_EMAILJS_PUBLIC_KEY;
|
||||
|
||||
if (!serviceId || !templateId || !publicKey) {
|
||||
console.error("EmailJS credentials are not configured in environment variables.");
|
||||
setErrorMessage("Email service configuration error. Please contact the administrator.");
|
||||
setFormStatus("error");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Map form fields to EmailJS template variables matching user's template config
|
||||
const templateParams: EmailJSTemplateParams = {
|
||||
name: formData.fullName.trim(),
|
||||
email: formData.email.trim(),
|
||||
phone: "", // phone is not available in the current contact form UI
|
||||
company: "", // company is not available in the current contact form UI
|
||||
subject: formData.subject.trim(),
|
||||
message: formData.message.trim(),
|
||||
};
|
||||
|
||||
// Send email via EmailJS API
|
||||
await emailjs.send(serviceId, templateId, templateParams, publicKey);
|
||||
|
||||
setFormStatus("success");
|
||||
// Reset form fields after successful submission
|
||||
setFormData({ fullName: "", email: "", subject: "", message: "" });
|
||||
} catch (error) {
|
||||
console.error("EmailJS Error:", error);
|
||||
setErrorMessage("Failed to send message. Please try again later.");
|
||||
setFormStatus("error");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="elementor elementor-6585">
|
||||
<style dangerouslySetInnerHTML={{ __html: `
|
||||
/* ---- Clean contact form (scoped to this section) ---- */
|
||||
.elementor-6585 .elementor-element.elementor-element-a5c503d {
|
||||
--padding-top: 60px;
|
||||
--padding-bottom: 60px;
|
||||
--padding-left: 60px;
|
||||
--padding-right: 60px;
|
||||
}
|
||||
.elementor-6585 .elementor-element.elementor-element-0e6fedf > .elementor-widget-container {
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
|
||||
/* drop the legacy notched / floating-label borders */
|
||||
.elementor-6585 .wpforms-form .logico-form-field:before,
|
||||
.elementor-6585 .wpforms-form .logico-form-field:after,
|
||||
.elementor-6585 .wpforms-form .logico-label-placeholder { display: none !important; }
|
||||
|
||||
/* even field rhythm */
|
||||
.elementor-6585 .wpforms-form .wpforms-field-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.elementor-6585 .wpforms-form .wpforms-field { padding: 0 !important; margin: 0 !important; }
|
||||
|
||||
/* labels stay for screen readers; placeholders carry the visible text */
|
||||
.elementor-6585 .wpforms-form .wpforms-field-label {
|
||||
position: absolute !important;
|
||||
width: 1px; height: 1px;
|
||||
padding: 0; margin: -1px;
|
||||
overflow: hidden; clip: rect(0 0 0 0);
|
||||
white-space: nowrap; border: 0;
|
||||
}
|
||||
|
||||
/* clean rounded inputs */
|
||||
.elementor-6585 .wpforms-form input[type="text"],
|
||||
.elementor-6585 .wpforms-form input[type="email"],
|
||||
.elementor-6585 .wpforms-form textarea {
|
||||
width: 100%;
|
||||
border: 1px solid #e3e3e3 !important;
|
||||
border-radius: 12px !important;
|
||||
padding: 16px 20px !important;
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
color: #111;
|
||||
background: #fff;
|
||||
box-shadow: none !important;
|
||||
transition: border-color .25s ease;
|
||||
}
|
||||
.elementor-6585 .wpforms-form textarea { min-height: 150px; resize: vertical; }
|
||||
.elementor-6585 .wpforms-form input::placeholder,
|
||||
.elementor-6585 .wpforms-form textarea::placeholder { color: #9a9a9a; opacity: 1; }
|
||||
.elementor-6585 .wpforms-form input:focus,
|
||||
.elementor-6585 .wpforms-form textarea:focus { border-color: #c01227 !important; outline: none; }
|
||||
|
||||
.elementor-6585 .wpforms-form .wpforms-submit-container { padding-top: 26px !important; }
|
||||
|
||||
@media (max-width: 1020px) {
|
||||
.elementor-6585 .elementor-element.elementor-element-a5c503d {
|
||||
--padding-top: 40px;
|
||||
--padding-bottom: 40px;
|
||||
--padding-left: 32px;
|
||||
--padding-right: 32px;
|
||||
}
|
||||
}
|
||||
` }} />
|
||||
<div className="elementor-element elementor-element-3cd920c e-con-full e-flex cut-corner-no sticky-container-off e-con e-parent" data-id="3cd920c" data-element_type="container" data-e-type="container">
|
||||
<div className="elementor-element elementor-element-b29b8fc e-flex e-con-boxed cut-corner-no sticky-container-off e-con e-child" data-id="b29b8fc" data-element_type="container" data-e-type="container" data-settings="{"background_background":"classic"}">
|
||||
<div className="e-con-inner">
|
||||
<div className="elementor-element elementor-element-ef6fa6d e-con-full e-flex cut-corner-no sticky-container-off e-con e-child" data-id="ef6fa6d" data-element_type="container" data-e-type="container">
|
||||
{/* Left Dark Panel */}
|
||||
<div className="elementor-element elementor-element-9990148 e-con-full e-flex cut-corner-no sticky-container-off e-con e-child" data-id="9990148" data-element_type="container" data-e-type="container">
|
||||
<div className="elementor-element elementor-element-8899bdf elementor-absolute elementor-widget elementor-widget-image" data-id="8899bdf" data-element_type="widget" data-e-type="widget" data-settings="{"_position":"absolute"}" data-widget_type="image.default">
|
||||
<div className="elementor-widget-container">
|
||||
<Image width={965} height={474} src="/images/bg-map.png" className="attachment-full size-full wp-image-1148" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="elementor-element elementor-element-a0e7516 elementor-widget elementor-widget-logico_heading" data-id="a0e7516" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
|
||||
<div className="elementor-widget-container">
|
||||
<div className="logico-title">/ get in touch /</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="elementor-element elementor-element-51cdf4f elementor-widget elementor-widget-logico_heading" data-id="51cdf4f" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
|
||||
<div className="elementor-widget-container">
|
||||
<ScrollReveal delay={0.1} duration={0.8} yOffset={25}>
|
||||
<h3 className="logico-title">
|
||||
We are always ready to help you and answer your questions
|
||||
</h3>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</div>
|
||||
<div className="elementor-element elementor-element-670d1b2 elementor-widget elementor-widget-text-editor" data-id="670d1b2" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
|
||||
<div className="elementor-widget-container">
|
||||
<p>Connecting businesses with fast, secure, smart deliveries.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="elementor-element elementor-element-2631b42 e-flex e-con-boxed cut-corner-no sticky-container-off e-con e-child" data-id="2631b42" data-element_type="container" data-e-type="container">
|
||||
<div className="e-con-inner">
|
||||
<div className="elementor-element elementor-element-df89993 e-con-full e-flex cut-corner-no sticky-container-off e-con e-child" data-id="df89993" data-element_type="container" data-e-type="container">
|
||||
<div className="elementor-element elementor-element-69b6892 elementor-widget elementor-widget-logico_heading" data-id="69b6892" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
|
||||
<div className="elementor-widget-container">
|
||||
<div className="logico-title">Call Center</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="elementor-element elementor-element-87be926 elementor-widget elementor-widget-text-editor" data-id="87be926" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
|
||||
<div className="elementor-widget-container">
|
||||
<p>Tel : +91 86886 97941</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="elementor-element elementor-element-f5d8e63 e-con-full e-flex cut-corner-no sticky-container-off e-con e-child" data-id="f5d8e63" data-element_type="container" data-e-type="container">
|
||||
<div className="elementor-element elementor-element-774e540 elementor-widget elementor-widget-logico_heading" data-id="774e540" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
|
||||
<div className="elementor-widget-container">
|
||||
<div className="logico-title">Our Location</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="elementor-element elementor-element-9c1cf03 elementor-widget elementor-widget-text-editor" data-id="9c1cf03" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
|
||||
<div className="elementor-widget-container">
|
||||
<p>5th Floor, Vision Ultima, Street No.3, Jayabheri Enclave, Gachibowli, Hyderabad, Telangana 500032.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="elementor-element elementor-element-645be8d e-flex e-con-boxed cut-corner-no sticky-container-off e-con e-child" data-id="645be8d" data-element_type="container" data-e-type="container">
|
||||
<div className="e-con-inner">
|
||||
<div className="elementor-element elementor-element-a96d151 e-con-full e-flex cut-corner-no sticky-container-off e-con e-child" data-id="a96d151" data-element_type="container" data-e-type="container">
|
||||
<div className="elementor-element elementor-element-37e647f elementor-widget elementor-widget-logico_heading" data-id="37e647f" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
|
||||
<div className="elementor-widget-container">
|
||||
<div className="logico-title">Email</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="elementor-element elementor-element-ba67644 elementor-widget elementor-widget-text-editor" data-id="ba67644" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
|
||||
<div className="elementor-widget-container">
|
||||
<p>
|
||||
<a href="mailto:care@doormile.com">care@doormile.com</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="elementor-element elementor-element-9ba4b82 e-con-full e-flex cut-corner-no sticky-container-off e-con e-child" data-id="9ba4b82" data-element_type="container" data-e-type="container">
|
||||
<div className="elementor-element elementor-element-e9a5d79 elementor-widget elementor-widget-logico_heading" data-id="e9a5d79" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
|
||||
<div className="elementor-widget-container">
|
||||
<div className="logico-title">Social network</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="elementor-element elementor-element-a6bccba elementor-shape-square elementor-grid-0 elementor-widget elementor-widget-social-icons" data-id="a6bccba" data-element_type="widget" data-e-type="widget" data-widget_type="social-icons.default">
|
||||
<div className="elementor-widget-container">
|
||||
<div className="elementor-social-icons-wrapper elementor-grid" role="list" style={socialIconSpacing}>
|
||||
<span className="elementor-grid-item" role="listitem" style={{padding:"0 15px"}}>
|
||||
<a className="elementor-icon elementor-social-icon elementor-social-icon-facebook-f elementor-repeater-item-3fbe893" href="https://www.facebook.com" target="_blank" rel="noopener noreferrer">
|
||||
<span className="elementor-screen-only">Facebook</span>
|
||||
<svg aria-hidden="true" className="e-font-icon-svg e-fab-facebook-f" viewBox="0 0 320 512" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M279.14 288l14.22-92.66h-88.91v-60.13c0-25.35 12.42-50.06 52.24-50.06h40.42V6.26S260.43 0 225.36 0c-73.22 0-121.08 44.38-121.08 124.72v70.62H22.89V288h81.39v224h100.17V288z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</span>
|
||||
<span className="elementor-grid-item" role="listitem" style={{padding:"0 15px"}}>
|
||||
<a className="elementor-icon elementor-social-icon elementor-social-icon-x-twitter elementor-repeater-item-64ac94e" href="https://x.com" target="_blank" rel="noopener noreferrer">
|
||||
<span className="elementor-screen-only">X</span>
|
||||
<svg aria-hidden="true" className="e-font-icon-svg e-fab-x-twitter" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</span>
|
||||
<span className="elementor-grid-item" role="listitem" style={{padding:"0 15px"}}>
|
||||
<a className="elementor-icon elementor-social-icon elementor-social-icon-linkedin-in elementor-repeater-item-38e1bcc" href="https://www.linkedin.com" target="_blank" rel="noopener noreferrer">
|
||||
<span className="elementor-screen-only">LinkedIn</span>
|
||||
<svg aria-hidden="true" className="e-font-icon-svg e-fab-linkedin-in" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M100.28 448H7.4V148.9h92.88zM53.79 108.1C24.09 108.1 0 83.5 0 53.8a53.79 53.79 0 0 1 107.58 0c0 29.7-24.1 54.3-53.79 54.3zM447.9 448h-92.68V302.4c0-34.7-.7-79.2-48.29-79.2-48.29 0-55.69 37.7-55.69 76.7V448h-92.78V148.9h89.08v40.8h1.3c12.4-23.5 42.69-48.3 87.88-48.3 94 0 111.28 61.9 111.28 142.3V448z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</span>
|
||||
<span className="elementor-grid-item" role="listitem" style={{padding:"0 15px"}}>
|
||||
<a className="elementor-icon elementor-social-icon elementor-social-icon-youtube elementor-repeater-item-b0d5e1f" href="https://www.youtube.com" target="_blank" rel="noopener noreferrer">
|
||||
<span className="elementor-screen-only">YouTube</span>
|
||||
<svg aria-hidden="true" className="e-font-icon-svg e-fab-youtube" viewBox="0 0 576 512" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right White Form Card */}
|
||||
<div className="elementor-element elementor-element-a5c503d e-con-full e-flex cut-corner-no sticky-container-off e-con e-child" data-id="a5c503d" data-element_type="container" data-e-type="container" data-settings="{"background_background":"classic"}">
|
||||
<div className="elementor-element elementor-element-535776a elementor-widget elementor-widget-logico_heading" data-id="535776a" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
|
||||
<div className="elementor-widget-container">
|
||||
<div className="logico-title">Get in Touch</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="elementor-element elementor-element-0e6fedf elementor-widget elementor-widget-logico_wpforms" data-id="0e6fedf" data-element_type="widget" data-e-type="widget" data-widget_type="logico_wpforms.default">
|
||||
<div className="elementor-widget-container">
|
||||
<div className="logico-wpforms-widget">
|
||||
<div className="wpforms-container wpforms-render-modern" id="wpforms-369-contact">
|
||||
<form id="wpforms-form-369-contact" className="wpforms-validate wpforms-form" onSubmit={handleSubmit} noValidate>
|
||||
<div className="wpforms-field-container">
|
||||
<div className="wpforms-field logico-form-field">
|
||||
<label className="wpforms-field-label" htmlFor="contact-field-name">Full name</label>
|
||||
<input
|
||||
type="text"
|
||||
id="contact-field-name"
|
||||
name="fullName"
|
||||
placeholder="Full name"
|
||||
value={formData.fullName}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="wpforms-field logico-form-field">
|
||||
<label className="wpforms-field-label" htmlFor="contact-field-email">Email</label>
|
||||
<input
|
||||
type="email"
|
||||
id="contact-field-email"
|
||||
name="email"
|
||||
placeholder="Email"
|
||||
value={formData.email}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="wpforms-field logico-form-field">
|
||||
<label className="wpforms-field-label" htmlFor="contact-field-subject">Subject</label>
|
||||
<input
|
||||
type="text"
|
||||
id="contact-field-subject"
|
||||
name="subject"
|
||||
placeholder="Subject"
|
||||
value={formData.subject}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="wpforms-field logico-form-field">
|
||||
<label className="wpforms-field-label" htmlFor="contact-field-message">Message</label>
|
||||
<textarea
|
||||
id="contact-field-message"
|
||||
name="message"
|
||||
placeholder="Message"
|
||||
value={formData.message}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div className="wpforms-submit-container">
|
||||
<button
|
||||
type="submit"
|
||||
id="wpforms-submit-369-contact"
|
||||
className="logico-alter-button wpforms-submit"
|
||||
disabled={formStatus === "submitting"}
|
||||
>
|
||||
{formStatus === "submitting" ? "Sending..." : "Send a message"}
|
||||
</button>
|
||||
{formStatus === "success" && (
|
||||
<div style={{ color: "#4caf50", marginTop: "10px", fontSize: "14px" }}>
|
||||
Message sent successfully!
|
||||
</div>
|
||||
)}
|
||||
{formStatus === "error" && (
|
||||
<div style={{ color: "#f44336", marginTop: "10px", fontSize: "14px" }}>
|
||||
{errorMessage || "Something went wrong. Please try again."}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useRef } from "react";
|
||||
|
||||
/**
|
||||
* EV-Native Design background — drifting SQUARE particles with 3D depth.
|
||||
* Each square has a depth (0.3–1): nearer squares are larger, brighter, and
|
||||
* parallax further on mouse-move + a slow auto-sway, creating a layered 3D
|
||||
* field. Mix of brand-red (#dc2626) and soft gray/white squares. Full section,
|
||||
* pointer-events:none, behind content.
|
||||
*/
|
||||
export default function EVParticles() {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const canvas = canvasRef.current;
|
||||
const parent = canvas?.parentElement;
|
||||
if (!canvas || !parent) return;
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (!ctx) return;
|
||||
|
||||
const reduced = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
||||
const COUNT = 120;
|
||||
type P = { x: number; y: number; vx: number; vy: number; s: number; red: boolean; a: number; d: number };
|
||||
let particles: P[] = [];
|
||||
let w = 0, h = 0, raf = 0, startTs = 0;
|
||||
|
||||
// mouse parallax (canvas is pointer-events:none, so track on window)
|
||||
const mouse = { x: 0, y: 0 };
|
||||
const cur = { x: 0, y: 0 };
|
||||
const onMove = (e: MouseEvent) => {
|
||||
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
|
||||
mouse.y = (e.clientY / window.innerHeight) * 2 - 1;
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
particles = [];
|
||||
for (let i = 0; i < COUNT; i++) {
|
||||
const t = Math.random();
|
||||
const s = t > 0.92 ? 12 + Math.random() * 6 : t > 0.68 ? 7 + Math.random() * 5 : 3 + Math.random() * 4;
|
||||
const red = Math.random() < 0.3;
|
||||
particles.push({
|
||||
x: Math.random() * w,
|
||||
y: Math.random() * h,
|
||||
vx: (Math.random() - 0.5) * 0.22,
|
||||
vy: (Math.random() - 0.5) * 0.22,
|
||||
s,
|
||||
red,
|
||||
a: red ? Math.random() * 0.4 + 0.35 : Math.random() * 0.28 + 0.12,
|
||||
d: Math.random() * 0.7 + 0.3, // depth 0.3 (far) .. 1 (near)
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const resize = () => {
|
||||
const rect = parent.getBoundingClientRect();
|
||||
w = Math.max(1, rect.width);
|
||||
h = Math.max(1, rect.height);
|
||||
const dpr = Math.min(window.devicePixelRatio || 1, 2);
|
||||
canvas.width = Math.round(w * dpr);
|
||||
canvas.height = Math.round(h * dpr);
|
||||
canvas.style.width = w + "px";
|
||||
canvas.style.height = h + "px";
|
||||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||||
if (!particles.length) init();
|
||||
};
|
||||
|
||||
const render = (time: number, move: boolean) => {
|
||||
ctx.clearRect(0, 0, w, h);
|
||||
|
||||
// ease the parallax origin toward the pointer
|
||||
cur.x += (mouse.x - cur.x) * 0.04;
|
||||
cur.y += (mouse.y - cur.y) * 0.04;
|
||||
// slow auto-sway so the 3D depth animates even without mouse input
|
||||
const swayX = Math.sin(time * 0.00026) * 0.6;
|
||||
const swayY = Math.cos(time * 0.0002) * 0.45;
|
||||
const ox = (cur.x + swayX) * 34;
|
||||
const oy = (cur.y + swayY) * 26;
|
||||
|
||||
for (const p of particles) {
|
||||
if (move) {
|
||||
p.x += p.vx * p.d;
|
||||
p.y += p.vy * p.d;
|
||||
const m = p.s + 6;
|
||||
if (p.x < -m) p.x = w + m;
|
||||
else if (p.x > w + m) p.x = -m;
|
||||
if (p.y < -m) p.y = h + m;
|
||||
else if (p.y > h + m) p.y = -m;
|
||||
}
|
||||
// depth-scaled size + parallax offset (near squares move/scale more)
|
||||
const size = p.s * (0.55 + p.d * 0.75);
|
||||
const dx = p.x + ox * p.d;
|
||||
const dy = p.y + oy * p.d;
|
||||
const alpha = p.a * (0.55 + p.d * 0.45);
|
||||
|
||||
if (p.red) {
|
||||
ctx.shadowColor = "rgba(220,38,38,0.55)";
|
||||
ctx.shadowBlur = 8 * p.d;
|
||||
ctx.fillStyle = `rgba(220,38,38,${alpha})`;
|
||||
} else {
|
||||
ctx.shadowBlur = 0;
|
||||
ctx.fillStyle = `rgba(200,202,210,${alpha})`;
|
||||
}
|
||||
ctx.fillRect(dx - size / 2, dy - size / 2, size, size);
|
||||
}
|
||||
ctx.shadowBlur = 0;
|
||||
};
|
||||
|
||||
const loop = (ts: number) => {
|
||||
if (!startTs) startTs = ts;
|
||||
render(ts - startTs, true);
|
||||
raf = requestAnimationFrame(loop);
|
||||
};
|
||||
|
||||
resize();
|
||||
init();
|
||||
if (reduced) {
|
||||
render(0, false);
|
||||
} else {
|
||||
window.addEventListener("mousemove", onMove, { passive: true });
|
||||
raf = requestAnimationFrame(loop);
|
||||
}
|
||||
|
||||
const ro = new ResizeObserver(() => {
|
||||
resize();
|
||||
if (reduced) render(0, false);
|
||||
});
|
||||
ro.observe(parent);
|
||||
|
||||
return () => {
|
||||
cancelAnimationFrame(raf);
|
||||
ro.disconnect();
|
||||
window.removeEventListener("mousemove", onMove);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return <canvas ref={canvasRef} className="evnd__canvas" aria-hidden="true" />;
|
||||
}
|
||||
@@ -8,46 +8,50 @@ if (typeof window !== "undefined") {
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
}
|
||||
|
||||
const PILLS: { value: string; label: string }[] = [
|
||||
{ value: "100%", label: "Electric Fleet" },
|
||||
{ value: "Live", label: "Route Sync" },
|
||||
{ value: "Real-time", label: "Battery Monitoring" },
|
||||
];
|
||||
|
||||
const MINI_STATS: { value: number; decimals?: number; suffix: string; label: string }[] = [
|
||||
{ value: 94, suffix: "K+", label: "Routes Optimised" },
|
||||
{ value: 23, suffix: "%", label: "Avg Battery Saved" },
|
||||
{ value: 1.4, decimals: 1, suffix: "x", label: "Charging Stops Saved" },
|
||||
];
|
||||
|
||||
const FEATURES: { icon: string; title: string; desc: string }[] = [
|
||||
const FEATURES: { icon: React.ReactNode; title: string; desc: string }[] = [
|
||||
{
|
||||
icon: "⚡",
|
||||
icon: (
|
||||
<svg className="evnd-icon" viewBox="0 0 24 24" fill="none" stroke="#f59e0b" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
|
||||
</svg>
|
||||
),
|
||||
title: "Battery-Aware Routing",
|
||||
desc: "Battery level, health, and degradation are first-class inputs to route optimization — not afterthoughts.",
|
||||
},
|
||||
{
|
||||
icon: "🔌",
|
||||
icon: (
|
||||
<svg className="evnd-icon" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M18 10h-1.28A6 6 0 0 0 12 5V3M12 5V3M6 10h1.28A6 6 0 0 0 12 5M12 18v2M12 18v2M8 10v6a4 4 0 0 0 8 0v-6" />
|
||||
</svg>
|
||||
),
|
||||
title: "Charging Integration",
|
||||
desc: "Seamlessly integrate charging stops without compromising delivery windows or SLA commitments.",
|
||||
},
|
||||
{
|
||||
icon: "⛰",
|
||||
icon: (
|
||||
<svg className="evnd-icon" viewBox="0 0 24 24" fill="none" stroke="#ef4444" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="m8 3 4 8 5-5 5 15H2L8 3z" />
|
||||
</svg>
|
||||
),
|
||||
title: "Energy-Optimized Paths",
|
||||
desc: "Factor in elevation, speed limits, payload weight, and live weather for maximum range efficiency.",
|
||||
},
|
||||
{
|
||||
icon: "🛡",
|
||||
icon: (
|
||||
<svg className="evnd-icon" viewBox="0 0 24 24" fill="none" stroke="#ef4444" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
||||
</svg>
|
||||
),
|
||||
title: "Predictable Operations",
|
||||
desc: "EVs become predictable assets, not operational risks. Full visibility from depot to doorstep.",
|
||||
},
|
||||
];
|
||||
|
||||
const BOTTOM_STATS: { value: number; decimals?: number; suffix: string; label: string }[] = [
|
||||
{ value: 120, suffix: "K+", label: "Deliveries Completed" },
|
||||
{ value: 98, suffix: "%", label: "On-Time Rate" },
|
||||
{ value: 31, suffix: "%", label: "Range Efficiency Gain" },
|
||||
{ value: 340, suffix: "ms", label: "Avg Route Calc Time" },
|
||||
{ value: 99.9, decimals: 1, suffix: "%", label: "SLA Compliance" },
|
||||
{ value: 42, suffix: "%", label: "Distance Saved" },
|
||||
{ value: 37, suffix: "%", label: "Fewer Vehicles" },
|
||||
{ value: 45, suffix: "ms", label: "Dispatch Latency" },
|
||||
];
|
||||
|
||||
/** Count-up that fires once when scrolled ~20% into view (ease-out cubic). */
|
||||
@@ -143,7 +147,7 @@ export default function EVSection() {
|
||||
<style dangerouslySetInnerHTML={{ __html: `
|
||||
/* ============================================================
|
||||
EV-Native Design — redesigned section
|
||||
bg #0d0d0d · red #dc2626 / #ef4444 · Syne + DM Sans
|
||||
bg #080808 · red #ef4444 · Manrope
|
||||
============================================================ */
|
||||
|
||||
#evnd, #evnd * { font-family: "Manrope", Sans-serif !important; }
|
||||
@@ -152,12 +156,12 @@ export default function EVSection() {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
overflow: hidden;
|
||||
background: #0d0d0d;
|
||||
background: #080808;
|
||||
/* flat top so it connects seamlessly to the banner above; rounded
|
||||
bottom only, and no top margin so there is no white gap */
|
||||
border-radius: 0 0 clamp(16px, 2vw, 28px) clamp(16px, 2vw, 28px);
|
||||
margin: 0 0 clamp(28px, 5vw, 64px);
|
||||
padding: 56px 48px 64px;
|
||||
padding: 64px 48px clamp(48px, 6vw, 80px);
|
||||
}
|
||||
/* subtle diagonal light band for depth (matches reference) */
|
||||
.evnd::before {
|
||||
@@ -166,181 +170,206 @@ export default function EVSection() {
|
||||
inset: 0;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
background: linear-gradient(120deg, transparent 28%, rgba(255,255,255,0.025) 50%, transparent 72%);
|
||||
}
|
||||
.evnd__canvas {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
background: linear-gradient(120deg, transparent 28%, rgba(255,255,255,0.015) 50%, transparent 72%);
|
||||
}
|
||||
.evnd__inner { position: relative; z-index: 1; max-width: 1280px; margin: 0 auto; }
|
||||
|
||||
/* ---- TOP ROW ---- */
|
||||
.evnd__top {
|
||||
/* ---- MAIN GRID ---- */
|
||||
.evnd__grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1.5fr 1fr;
|
||||
gap: 44px;
|
||||
grid-template-columns: 1.15fr 1fr;
|
||||
gap: clamp(32px, 4vw, 56px);
|
||||
align-items: center;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.evnd__left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.evnd__right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.evnd__eyebrow {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
color: #dc2626 !important;
|
||||
font-weight: 700;
|
||||
color: #ef4444 !important;
|
||||
font-weight: 800;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.16em;
|
||||
font-size: 13px;
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.evnd__eyebrow::before { content: ''; width: 24px; height: 2px; background: #dc2626; }
|
||||
.evnd__eyebrow::before {
|
||||
content: '';
|
||||
width: 16px;
|
||||
height: 2px;
|
||||
background: #ef4444;
|
||||
}
|
||||
|
||||
.evnd__title {
|
||||
color: #fff !important;
|
||||
font-weight: 800 !important;
|
||||
font-size: clamp(30px, 4.4vw, 56px) !important;
|
||||
line-height: 1.04 !important;
|
||||
font-size: clamp(32px, 3.8vw, 48px) !important;
|
||||
line-height: 1.15 !important;
|
||||
letter-spacing: -0.01em;
|
||||
margin: 0;
|
||||
margin: 0 0 36px 0;
|
||||
}
|
||||
.evnd__title .accent { color: #ef4444 !important; }
|
||||
|
||||
.evnd__pills { display: flex; flex-direction: column; gap: 12px; }
|
||||
.evnd__pill {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 13px 20px;
|
||||
background: rgba(255,255,255,0.04);
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
border-radius: 100px;
|
||||
@media (min-width: 768px) {
|
||||
.evnd__title {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
.evnd__pill .dot {
|
||||
flex: 0 0 auto;
|
||||
width: 8px; height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #22c55e;
|
||||
box-shadow: 0 0 8px #22c55e;
|
||||
animation: evndBlink 1.4s ease-in-out infinite;
|
||||
.evnd__title .accent {
|
||||
color: #ef4444 !important;
|
||||
}
|
||||
.evnd__pill b { color: #ef4444 !important; font-weight: 800; font-size: 15px; }
|
||||
.evnd__pill span { color: rgba(255,255,255,0.62) !important; font-size: 13px; }
|
||||
|
||||
/* ---- MAIN GRID ---- */
|
||||
.evnd__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: start; }
|
||||
|
||||
.evnd__media { position: relative; }
|
||||
.evnd__media {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
.evnd__glow {
|
||||
position: absolute;
|
||||
left: 50%; bottom: -4%;
|
||||
width: 72%; height: 64px;
|
||||
width: 80%; height: 80px;
|
||||
transform: translateX(-50%);
|
||||
background: radial-gradient(50% 50% at 50% 50%, rgba(220,38,38,0.5), transparent 72%);
|
||||
filter: blur(30px);
|
||||
background: radial-gradient(50% 50% at 50% 50%, rgba(239,68,68,0.3), transparent 72%);
|
||||
filter: blur(35px);
|
||||
z-index: 0;
|
||||
animation: evndGlow 4s ease-in-out infinite;
|
||||
}
|
||||
.evnd__imgwrap { position: relative; z-index: 1; animation: evndFloat 7s ease-in-out infinite; will-change: transform; }
|
||||
.evnd__imgwrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(255,255,255,0.06);
|
||||
box-shadow: 0 30px 60px -25px rgba(0,0,0,0.85);
|
||||
}
|
||||
.evnd__img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 30px 60px -25px rgba(0,0,0,0.7);
|
||||
object-fit: cover;
|
||||
transition: transform 0.8s cubic-bezier(0.25, 1, 0.5, 1);
|
||||
}
|
||||
.evnd__imgwrap:hover .evnd__img {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
/* Badge overlay styling */
|
||||
.evnd__badge {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
padding: 10px 14px;
|
||||
background: rgba(10,10,10,0.88);
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
padding: 12px 16px;
|
||||
background: rgba(13,13,13,0.72);
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
border-radius: 8px;
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
}
|
||||
.evnd__badge b { color: #ef4444 !important; font-weight: 800; font-size: 24px; line-height: 1; }
|
||||
.evnd__badge span { color: rgba(255,255,255,0.55) !important; font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; }
|
||||
.evnd__badge--tl { top: 14px; left: 14px; }
|
||||
.evnd__badge--br { bottom: 14px; right: 14px; }
|
||||
|
||||
.evnd__ministats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-top: 20px; }
|
||||
.evnd__mini {
|
||||
position: relative;
|
||||
background: rgba(255,255,255,0.03);
|
||||
border: 1px solid rgba(255,255,255,0.06);
|
||||
border-radius: 10px;
|
||||
padding: 18px 14px 14px;
|
||||
overflow: hidden;
|
||||
.evnd__badge b {
|
||||
color: #ef4444 !important;
|
||||
font-weight: 800;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
}
|
||||
.evnd__mini::before {
|
||||
content: '';
|
||||
position: absolute; top: 0; left: 0; right: 0;
|
||||
height: 2px;
|
||||
background: linear-gradient(90deg, #dc2626, transparent);
|
||||
.evnd__badge span {
|
||||
color: rgba(255,255,255,0.7) !important;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.evnd__mini b { display: block; color: #fff !important; font-weight: 800; font-size: clamp(20px, 2.3vw, 28px); line-height: 1; margin-bottom: 6px; }
|
||||
.evnd__mini span { color: rgba(255,255,255,0.5) !important; font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; line-height: 1.3; display: block; }
|
||||
.evnd__badge--tl { top: 20px; left: 20px; }
|
||||
.evnd__badge--br { bottom: 20px; right: 20px; }
|
||||
|
||||
/* ---- Feature cards ---- */
|
||||
.evnd__features { display: flex; flex-direction: column; gap: 10px; }
|
||||
.evnd__features {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
height: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.evnd-feature {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: 40px 1fr auto;
|
||||
gap: 16px;
|
||||
grid-template-columns: 48px 1fr auto;
|
||||
gap: 20px;
|
||||
align-items: start;
|
||||
background: rgba(255,255,255,0.028);
|
||||
border: 1px solid rgba(255,255,255,0.07);
|
||||
border-radius: 12px;
|
||||
padding: 18px 20px;
|
||||
background: rgba(255,255,255,0.02);
|
||||
border: 1px solid rgba(255,255,255,0.05);
|
||||
border-radius: 16px;
|
||||
padding: 24px;
|
||||
overflow: hidden;
|
||||
transition: background-color 0.35s ease, border-color 0.35s ease, transform 0.35s cubic-bezier(.25,1,.5,1);
|
||||
transition: background-color 0.4s ease, border-color 0.4s ease, transform 0.4s cubic-bezier(.25,1,.5,1);
|
||||
}
|
||||
.evnd-feature::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0; top: 0; bottom: 0;
|
||||
width: 3px;
|
||||
background: #dc2626;
|
||||
background: #ef4444;
|
||||
transform: scaleY(0);
|
||||
transform-origin: bottom;
|
||||
transition: transform 0.35s ease;
|
||||
transition: transform 0.4s ease;
|
||||
}
|
||||
.evnd-feature:hover {
|
||||
background: rgba(239,68,68,0.03);
|
||||
border-color: rgba(239,68,68,0.2);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.evnd-feature:hover { background: rgba(220,38,38,0.06); border-color: rgba(220,38,38,0.25); transform: translateX(4px); }
|
||||
.evnd-feature:hover::before { transform: scaleY(1); }
|
||||
.evnd-feature__icon {
|
||||
width: 40px; height: 40px;
|
||||
|
||||
.evnd-feature__icon-container {
|
||||
width: 48px; height: 48px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
background: rgba(220,38,38,0.1);
|
||||
border: 1px solid rgba(220,38,38,0.2);
|
||||
border-radius: 10px;
|
||||
font-size: 18px;
|
||||
background: rgba(255,255,255,0.03);
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
border-radius: 12px;
|
||||
transition: background-color 0.3s ease, border-color 0.3s ease;
|
||||
}
|
||||
.evnd-feature:hover .evnd-feature__icon-container {
|
||||
background: rgba(239,68,68,0.08);
|
||||
border-color: rgba(239,68,68,0.25);
|
||||
}
|
||||
|
||||
.evnd-icon {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.evnd-feature__title {
|
||||
color: #fff !important;
|
||||
font-weight: 700;
|
||||
font-size: 15px !important;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
margin: 3px 0 7px;
|
||||
letter-spacing: 0.05em;
|
||||
margin: 4px 0 8px;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
.evnd-feature:hover .evnd-feature__title { color: #ef4444 !important; }
|
||||
.evnd-feature__desc {
|
||||
color: rgba(255,255,255,0.75) !important;
|
||||
color: rgba(255,255,255,0.65) !important;
|
||||
font-weight: 400 !important;
|
||||
font-size: 14.5px !important;
|
||||
line-height: 1.65 !important;
|
||||
font-size: 14px !important;
|
||||
line-height: 1.6 !important;
|
||||
margin: 0;
|
||||
}
|
||||
.evnd-feature__arrow {
|
||||
color: rgba(255,255,255,0.2);
|
||||
font-size: 14px;
|
||||
color: rgba(255,255,255,0.25);
|
||||
font-size: 16px;
|
||||
align-self: flex-start;
|
||||
margin-top: 4px;
|
||||
transition: color 0.3s ease, transform 0.3s ease;
|
||||
}
|
||||
.evnd-feature:hover .evnd-feature__arrow { color: #ef4444; transform: translate(3px, -3px); }
|
||||
@@ -349,47 +378,69 @@ export default function EVSection() {
|
||||
.evnd__bar {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 1px;
|
||||
background: rgba(255,255,255,0.06);
|
||||
border-radius: 12px;
|
||||
background: rgba(255,255,255,0.02);
|
||||
border: 1px solid rgba(255,255,255,0.06);
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
margin-top: 40px;
|
||||
margin-top: 60px;
|
||||
padding: 38px 0;
|
||||
}
|
||||
.evnd__bar-item {
|
||||
background: #0d0d0d;
|
||||
padding: 24px 22px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
padding: 12px 24px;
|
||||
}
|
||||
.evnd__bar-item .dot {
|
||||
width: 7px; height: 7px;
|
||||
border-radius: 50%;
|
||||
background: #dc2626;
|
||||
box-shadow: 0 0 8px rgba(220,38,38,0.85);
|
||||
animation: evndBlink 1.4s ease-in-out infinite;
|
||||
.evnd__bar-item:not(:last-child)::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 15%;
|
||||
height: 70%;
|
||||
width: 1px;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.evnd__bar-val {
|
||||
color: #ef4444 !important;
|
||||
font-weight: 800;
|
||||
font-size: clamp(32px, 4vw, 56px);
|
||||
line-height: 1;
|
||||
}
|
||||
.evnd__bar-label {
|
||||
color: #fff !important;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.02em;
|
||||
text-transform: none;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.evnd__bar-item b { color: #fff !important; font-weight: 800; font-size: clamp(22px, 2.6vw, 30px); line-height: 1; }
|
||||
.evnd__bar-item span { color: rgba(255,255,255,0.45) !important; font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; }
|
||||
|
||||
@keyframes evndFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
|
||||
@keyframes evndGlow { 0%,100% { opacity: 0.6; } 50% { opacity: 1; } }
|
||||
@keyframes evndBlink { 0%,100% { opacity: 1; } 50% { opacity: 0.3; } }
|
||||
@keyframes evndGlow { 0%,100% { opacity: 0.75; } 50% { opacity: 1; } }
|
||||
|
||||
/* ---- Responsive ---- */
|
||||
@media (max-width: 900px) {
|
||||
.evnd { padding: 48px 28px 52px; }
|
||||
.evnd__top { grid-template-columns: 1fr; gap: 28px; margin-bottom: 36px; }
|
||||
.evnd__grid { grid-template-columns: 1fr; gap: 36px; }
|
||||
@media (max-width: 991px) {
|
||||
.evnd { padding: 48px 32px 56px; }
|
||||
.evnd__grid { grid-template-columns: 1fr; gap: 40px; }
|
||||
.evnd__title { margin-bottom: 28px; }
|
||||
.evnd__features { gap: 14px; }
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.evnd { padding: 40px 18px 44px; }
|
||||
.evnd__bar { grid-template-columns: repeat(2, 1fr); }
|
||||
.evnd__pill { padding: 11px 16px; }
|
||||
@media (max-width: 767px) {
|
||||
.evnd__bar { grid-template-columns: repeat(2, 1fr); gap: 24px 0; padding: 24px 0; }
|
||||
.evnd__bar-item:nth-child(even)::after { display: none; }
|
||||
.evnd__bar-item:nth-child(2)::after { display: none; }
|
||||
.evnd__bar-item { padding: 12px 16px; }
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.evnd__imgwrap, .evnd__glow, .evnd__pill .dot, .evnd__bar-item .dot { animation: none !important; }
|
||||
@media (max-width: 480px) {
|
||||
.evnd { padding: 40px 16px 48px; }
|
||||
.evnd__bar { grid-template-columns: 1fr; gap: 28px 0; }
|
||||
.evnd__bar-item::after { display: none !important; }
|
||||
.evnd__badge { padding: 8px 12px; }
|
||||
.evnd__badge b { font-size: 20px; }
|
||||
}
|
||||
`}} />
|
||||
|
||||
@@ -441,24 +492,10 @@ export default function EVSection() {
|
||||
{/* ===== EV-Native Design (redesigned) ===== */}
|
||||
<section className="evnd" id="evnd" aria-label="EV-Native Design">
|
||||
<div className="evnd__inner">
|
||||
{/* TOP ROW */}
|
||||
<div className="evnd__top">
|
||||
<div className="evnd__head">
|
||||
<span className="evnd__eyebrow">/ EV-Native Design /</span>
|
||||
<div className="evnd__title">
|
||||
BUILT FOR ELECTRIC. <span className="accent">NOT ADAPTED.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="evnd__pills">
|
||||
{PILLS.map((p) => (
|
||||
<div className="evnd__pill" key={p.label}>
|
||||
<span className="dot" />
|
||||
<b>{p.value}</b>
|
||||
<span>{p.label}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<span className="evnd__eyebrow">/ EV-Native Design /</span>
|
||||
<h2 className="evnd__title">
|
||||
BUILT FOR ELECTRIC. <span className="accent">NOT ADAPTED.</span>
|
||||
</h2>
|
||||
|
||||
{/* MAIN GRID */}
|
||||
<div className="evnd__grid">
|
||||
@@ -471,37 +508,32 @@ export default function EVSection() {
|
||||
<img className="evnd__img" src="/images/premium-ev-van.png" alt="DoorMile electric delivery van" decoding="async" />
|
||||
<div className="evnd__badge evnd__badge--tl">
|
||||
<b>100%</b>
|
||||
<span>Electric Fleet</span>
|
||||
<span>ELECTRIC FLEET</span>
|
||||
</div>
|
||||
<div className="evnd__badge evnd__badge--br">
|
||||
<b>−40%</b>
|
||||
<span>Cost / Mile</span>
|
||||
<b>-40%</b>
|
||||
<span>COST / MILE</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="evnd__ministats">
|
||||
{MINI_STATS.map((s) => (
|
||||
<div className="evnd__mini" key={s.label}>
|
||||
<CountUp value={s.value} decimals={s.decimals} suffix={s.suffix} />
|
||||
<span>{s.label}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right column */}
|
||||
<div className="evnd__features">
|
||||
{FEATURES.map((f) => (
|
||||
<div className="evnd-feature" key={f.title}>
|
||||
<span className="evnd-feature__icon" aria-hidden="true">{f.icon}</span>
|
||||
<div className="evnd-feature__body">
|
||||
<div className="evnd-feature__title">{f.title}</div>
|
||||
<p className="evnd-feature__desc">{f.desc}</p>
|
||||
<div className="evnd__right">
|
||||
<div className="evnd__features">
|
||||
{FEATURES.map((f) => (
|
||||
<div className="evnd-feature" key={f.title}>
|
||||
<div className="evnd-feature__icon-container" aria-hidden="true">
|
||||
{f.icon}
|
||||
</div>
|
||||
<div className="evnd-feature__body">
|
||||
<div className="evnd-feature__title">{f.title}</div>
|
||||
<p className="evnd-feature__desc">{f.desc}</p>
|
||||
</div>
|
||||
<span className="evnd-feature__arrow" aria-hidden="true">↗</span>
|
||||
</div>
|
||||
<span className="evnd-feature__arrow" aria-hidden="true">↗</span>
|
||||
</div>
|
||||
))}
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -509,9 +541,8 @@ export default function EVSection() {
|
||||
<div className="evnd__bar">
|
||||
{BOTTOM_STATS.map((s) => (
|
||||
<div className="evnd__bar-item" key={s.label}>
|
||||
<span className="dot" />
|
||||
<CountUp value={s.value} decimals={s.decimals} suffix={s.suffix} />
|
||||
<span>{s.label}</span>
|
||||
<span className="evnd__bar-label">{s.label}</span>
|
||||
<CountUp value={s.value} decimals={s.decimals} suffix={s.suffix} className="evnd__bar-val" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -25,15 +25,16 @@ export default function IndustrySolutions() {
|
||||
style={{marginLeft: "50px"}}
|
||||
>
|
||||
<div className="elementor-widget-container" style={{ margin: "30px 0 0 0"}}>
|
||||
<h3 className="logico-title" style={{ fontSize: "clamp(36px, 5.5vw, 62px)", lineHeight: "1.1", fontWeight: 800, textTransform: "uppercase", paddingRight: "clamp(20px, 8vw, 120px)" }}>
|
||||
<style dangerouslySetInnerHTML={{ __html: `
|
||||
@media (min-width: 1024px) {
|
||||
.industry-title-single-line {
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
}
|
||||
`}} />
|
||||
<h3 className="logico-title industry-title-single-line" style={{ fontSize: "clamp(28px, 3.5vw, 48px)", lineHeight: "1.1", fontWeight: 800, textTransform: "uppercase" }}>
|
||||
<ScrollReveal delay={0.05} duration={0.8} yOffset={25}>
|
||||
<span className="block">Smart solutions built</span>
|
||||
</ScrollReveal>
|
||||
<ScrollReveal delay={0.15} duration={0.8} yOffset={25}>
|
||||
<span className="block">exclusively for your</span>
|
||||
</ScrollReveal>
|
||||
<ScrollReveal delay={0.25} duration={0.8} yOffset={25}>
|
||||
<span className="block" style={{ color: "#c01227" }}>industry</span>
|
||||
Smart solutions built exclusively for your <span style={{ color: "#c01227" }}>industry</span>
|
||||
</ScrollReveal>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
@@ -1,498 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import IndustryWorldMap from "./IndustryWorldMap";
|
||||
|
||||
type Tab = "challenges" | "solutions";
|
||||
|
||||
interface Industry {
|
||||
id: string;
|
||||
tab: string;
|
||||
eyebrow: string;
|
||||
title: string;
|
||||
image: string;
|
||||
alt: string;
|
||||
desc: string;
|
||||
chips: [string, string];
|
||||
challenges: string[];
|
||||
solutions: string[];
|
||||
}
|
||||
|
||||
const INDUSTRIES: Industry[] = [
|
||||
{
|
||||
id: "fmcg",
|
||||
tab: "FMCG",
|
||||
eyebrow: "Fast-Moving Consumer Goods",
|
||||
title: "FMCG",
|
||||
image: "/images/tab-pic-1-solution.jpeg",
|
||||
alt: "FMCG logistics",
|
||||
desc:
|
||||
"FMCG logistics demands speed, precision, and continuous fulfillment across high-volume delivery networks — balancing tight timelines, inventory movement, and efficiency without compromising availability.",
|
||||
chips: ["99.2% On-Time", "Live Route Sync"],
|
||||
challenges: [
|
||||
"Unpredictable demand spikes create delivery pressure during peak periods.",
|
||||
"Fresh-product expiry constraints require faster, precisely timed deliveries.",
|
||||
"Multi-stop route complexity increases travel time and coordination cost.",
|
||||
"Inventory stockout risks rise when delays disrupt fast-moving distribution.",
|
||||
],
|
||||
solutions: [
|
||||
"AI demand forecasting adapts delivery plans instantly to real-time order demand.",
|
||||
"Expiry-aware routing prioritises perishable goods for on-time freshness.",
|
||||
"Smart multi-stop optimisation groups orders to cut cost and travel time.",
|
||||
"Real-time inventory sync prevents stockouts and improves fulfilment accuracy.",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "pharma",
|
||||
tab: "Pharma",
|
||||
eyebrow: "Pharmaceutical Logistics",
|
||||
title: "Pharma",
|
||||
image: "/images/tab-pic-2-solution.jpeg",
|
||||
alt: "Pharma logistics",
|
||||
desc:
|
||||
"Pharma logistics requires precision, compliance, and real-time monitoring so every shipment arrives safely and on time — from temperature-sensitive medicines to urgent emergency deliveries.",
|
||||
chips: ["Cold Chain Active", "Zero Delay SLA"],
|
||||
challenges: [
|
||||
"Cold chain integrity demands precise temperature control throughout transit.",
|
||||
"Regulatory compliance must be tracked and documented on every delivery.",
|
||||
"Critical delivery time windows require highly accurate scheduling.",
|
||||
"Emergency shipments need instant dispatch and zero-delay execution.",
|
||||
],
|
||||
solutions: [
|
||||
"Cold chain monitoring with automatic re-routing keeps shipments in-spec.",
|
||||
"Compliance engine with audit trails ensures full chain-of-custody visibility.",
|
||||
"Precision scheduling locks in critical delivery windows reliably.",
|
||||
"Priority dispatch queue fast-tracks urgent, life-critical shipments.",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "b2b",
|
||||
tab: "Enterprise & B2B",
|
||||
eyebrow: "Enterprise & B2B",
|
||||
title: "Enterprise & B2B",
|
||||
image: "/images/tab-pic-3-solution.jpeg",
|
||||
alt: "Enterprise and B2B logistics",
|
||||
desc:
|
||||
"Enterprise and B2B logistics require coordination and reliability to manage high-value shipments at scale — with appointment scheduling, white-glove standards, and strict SLA commitments.",
|
||||
chips: ["SLA Guaranteed", "White-Glove Ready"],
|
||||
challenges: [
|
||||
"Appointment scheduling requires precise timing across many locations.",
|
||||
"White-glove delivery standards demand premium handling and accuracy.",
|
||||
"Multi-location routing complexity grows with large-scale operations.",
|
||||
"Strict SLA commitments pressure teams to stay timely and error-free.",
|
||||
],
|
||||
solutions: [
|
||||
"Intelligent appointment engine streamlines and automates delivery slots.",
|
||||
"White-glove workflow module enforces premium handling end to end.",
|
||||
"Enterprise route planner coordinates efficient multi-location delivery.",
|
||||
"SLA monitoring dashboard tracks commitments and flags risk in real time.",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default function SolutionCard1() {
|
||||
const [active, setActive] = useState(0);
|
||||
const [tab, setTab] = useState<Tab>("challenges");
|
||||
|
||||
const ind = INDUSTRIES[active];
|
||||
|
||||
const selectIndustry = (i: number) => {
|
||||
setActive(i);
|
||||
setTab("challenges"); // reset to Challenges on industry switch
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<style dangerouslySetInnerHTML={{ __html: `
|
||||
/* ============================================================
|
||||
Solutions — Industry section (FMCG / Pharma / Enterprise & B2B)
|
||||
Brand red #dc2626 / #ef4444 · bg #0d0d0d · Syne + DM Sans
|
||||
============================================================ */
|
||||
|
||||
/* The theme forces Manrope on every element via a high-specificity
|
||||
universal :not() !important rule; re-assert Syne / DM Sans from the
|
||||
ID selector (which outranks it) directly on each text node. */
|
||||
#ind-solutions .ind__eyebrow,
|
||||
#ind-solutions .ind__title,
|
||||
#ind-solutions .ind__tab,
|
||||
#ind-solutions .ind__toggle-btn {
|
||||
font-family: var(--font-syne), 'Syne', sans-serif !important;
|
||||
}
|
||||
#ind-solutions .ind__desc,
|
||||
#ind-solutions .ind__chip,
|
||||
#ind-solutions .ind__list li {
|
||||
font-family: var(--font-dm-sans), 'DM Sans', sans-serif !important;
|
||||
}
|
||||
/* kit-5 also forces heading color/size on the title (an <h3>). */
|
||||
#ind-solutions .ind__title {
|
||||
color: #fff !important;
|
||||
font-size: clamp(34px, 5.5vw, 68px) !important;
|
||||
font-weight: 800 !important;
|
||||
line-height: 1.02 !important;
|
||||
margin: 0 0 16px !important;
|
||||
letter-spacing: -0.01em !important;
|
||||
}
|
||||
#ind-solutions .ind__list li { color: #c9c9c9 !important; }
|
||||
|
||||
.ind {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
overflow: hidden;
|
||||
background: #0d0d0d;
|
||||
border-radius: clamp(16px, 2vw, 26px);
|
||||
max-width: 1400px;
|
||||
margin: clamp(24px, 4vw, 56px) auto;
|
||||
padding: clamp(34px, 5vw, 76px) clamp(18px, 4vw, 64px);
|
||||
}
|
||||
.ind__map {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.55;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.ind__inner {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 1240px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* ---- Top tab bar ---- */
|
||||
.ind__tabs {
|
||||
display: flex;
|
||||
gap: clamp(10px, 3vw, 36px);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.1);
|
||||
margin-bottom: clamp(28px, 4vw, 52px);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.ind__tab {
|
||||
appearance: none;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 10px 2px 16px;
|
||||
font-weight: 700;
|
||||
font-size: clamp(14px, 1.4vw, 18px);
|
||||
color: #888;
|
||||
position: relative;
|
||||
letter-spacing: 0.01em;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
.ind__tab::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0; right: 0; bottom: -1px;
|
||||
height: 2px;
|
||||
background: #dc2626;
|
||||
transform: scaleX(0);
|
||||
transform-origin: left;
|
||||
transition: transform 0.35s cubic-bezier(.25,1,.5,1);
|
||||
}
|
||||
.ind__tab:hover { color: #ccc; }
|
||||
.ind__tab.active { color: #fff; }
|
||||
.ind__tab.active::after { transform: scaleX(1); }
|
||||
|
||||
/* ---- Grid ---- */
|
||||
.ind__grid {
|
||||
display: grid;
|
||||
grid-template-columns: 0.9fr 1.1fr;
|
||||
gap: clamp(28px, 4vw, 64px);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* ---- Left media ---- */
|
||||
.ind__media {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 300px;
|
||||
}
|
||||
.ind__glow {
|
||||
position: absolute;
|
||||
left: 50%; bottom: 4%;
|
||||
width: 74%; height: 70px;
|
||||
transform: translateX(-50%);
|
||||
background: radial-gradient(50% 50% at 50% 50%, rgba(220,38,38,0.5), transparent 72%);
|
||||
filter: blur(32px);
|
||||
z-index: 0;
|
||||
animation: indGlow 4s ease-in-out infinite;
|
||||
}
|
||||
.ind__img-wrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
max-width: 460px;
|
||||
animation: indFloat 6s ease-in-out infinite;
|
||||
will-change: transform;
|
||||
}
|
||||
.ind__img-wrap::before,
|
||||
.ind__img-wrap::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 44px; height: 44px;
|
||||
border: 2px solid #dc2626;
|
||||
z-index: 3;
|
||||
}
|
||||
.ind__img-wrap::before {
|
||||
top: -10px; left: -10px;
|
||||
border-right: none; border-bottom: none;
|
||||
border-radius: 10px 0 0 0;
|
||||
}
|
||||
.ind__img-wrap::after {
|
||||
bottom: -10px; right: -10px;
|
||||
border-left: none; border-top: none;
|
||||
border-radius: 0 0 10px 0;
|
||||
}
|
||||
.ind__img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 12px;
|
||||
object-fit: cover;
|
||||
box-shadow: 0 30px 60px -25px rgba(0,0,0,0.7);
|
||||
animation: indImgFade 0.55s ease both;
|
||||
}
|
||||
.ind__chip {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 9px 16px;
|
||||
border-radius: 999px;
|
||||
background: rgba(16,16,16,0.82);
|
||||
border: 1px solid rgba(239,68,68,0.4);
|
||||
backdrop-filter: blur(8px);
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
white-space: nowrap;
|
||||
box-shadow: 0 12px 28px -12px rgba(0,0,0,0.7);
|
||||
animation: indFloat 6s ease-in-out infinite;
|
||||
}
|
||||
.ind__chip .dot {
|
||||
width: 7px; height: 7px;
|
||||
border-radius: 50%;
|
||||
background: #ef4444;
|
||||
box-shadow: 0 0 8px #ef4444;
|
||||
animation: indDot 1.6s ease-in-out infinite;
|
||||
}
|
||||
.ind__chip--1 { top: 7%; left: -5%; animation-delay: 0.4s; }
|
||||
.ind__chip--2 { bottom: 12%; right: -5%; animation-delay: 1.3s; }
|
||||
|
||||
/* ---- Right text ---- */
|
||||
.ind__text { min-width: 0; }
|
||||
.ind__eyebrow {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
color: #ef4444;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.16em;
|
||||
font-size: clamp(11px, 1vw, 13px);
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.ind__eyebrow::before {
|
||||
content: '';
|
||||
width: 30px; height: 2px;
|
||||
background: #ef4444;
|
||||
}
|
||||
.ind__desc {
|
||||
color: #b4b4b4;
|
||||
font-size: clamp(15px, 1.2vw, 18px);
|
||||
line-height: 1.7;
|
||||
font-weight: 400;
|
||||
margin: 0 0 24px;
|
||||
max-width: 580px;
|
||||
}
|
||||
|
||||
/* ---- Challenges / Solutions toggle ---- */
|
||||
.ind__toggle {
|
||||
display: inline-flex;
|
||||
gap: 4px;
|
||||
padding: 5px;
|
||||
border-radius: 999px;
|
||||
background: rgba(255,255,255,0.05);
|
||||
border: 1px solid rgba(255,255,255,0.09);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.ind__toggle-btn {
|
||||
appearance: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 9px 28px;
|
||||
border-radius: 999px;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
color: #9a9a9a;
|
||||
background: transparent;
|
||||
transition: color 0.3s ease, background-color 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
.ind__toggle-btn:hover { color: #ddd; }
|
||||
.ind__toggle-btn.active {
|
||||
background: #dc2626;
|
||||
color: #fff;
|
||||
box-shadow: 0 8px 20px -8px rgba(220,38,38,0.6);
|
||||
}
|
||||
|
||||
/* ---- Sliding panels ---- */
|
||||
.ind__slider { overflow: hidden; }
|
||||
.ind__track {
|
||||
display: flex;
|
||||
width: 200%;
|
||||
transition: transform 0.4s cubic-bezier(.4,0,.2,1);
|
||||
}
|
||||
.ind__panel { width: 50%; flex: 0 0 50%; }
|
||||
.ind__list { list-style: none; margin: 0; padding: 0; }
|
||||
.ind__list li {
|
||||
position: relative;
|
||||
padding-left: 30px;
|
||||
margin-bottom: 16px;
|
||||
font-size: clamp(14px, 1.1vw, 16px);
|
||||
line-height: 1.6;
|
||||
opacity: 0;
|
||||
transform: translateX(-16px);
|
||||
}
|
||||
.ind__list li:last-child { margin-bottom: 0; }
|
||||
.ind__list li::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 4px; top: 8px;
|
||||
width: 8px; height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #dc2626;
|
||||
box-shadow: 0 0 8px rgba(220,38,38,0.7);
|
||||
}
|
||||
.ind__panel.is-active .ind__list li {
|
||||
animation: indBullet 0.5s cubic-bezier(.25,1,.5,1) forwards;
|
||||
}
|
||||
.ind__panel.is-active .ind__list li:nth-child(1) { animation-delay: 0.05s; }
|
||||
.ind__panel.is-active .ind__list li:nth-child(2) { animation-delay: 0.13s; }
|
||||
.ind__panel.is-active .ind__list li:nth-child(3) { animation-delay: 0.21s; }
|
||||
.ind__panel.is-active .ind__list li:nth-child(4) { animation-delay: 0.29s; }
|
||||
.ind__panel.is-active .ind__list li:nth-child(5) { animation-delay: 0.37s; }
|
||||
|
||||
@keyframes indFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-14px); } }
|
||||
@keyframes indGlow { 0%,100% { opacity: 0.6; } 50% { opacity: 1; } }
|
||||
@keyframes indDot { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }
|
||||
@keyframes indBullet { to { opacity: 1; transform: translateX(0); } }
|
||||
@keyframes indImgFade { from { opacity: 0; transform: scale(0.97); } to { opacity: 1; transform: scale(1); } }
|
||||
|
||||
/* ---- Responsive ---- */
|
||||
@media (max-width: 900px) {
|
||||
.ind__grid { grid-template-columns: 1fr; gap: clamp(40px, 8vw, 56px); }
|
||||
.ind__media { order: -1; }
|
||||
.ind__img-wrap { max-width: 380px; }
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.ind__chip { font-size: 12px; padding: 7px 12px; }
|
||||
.ind__chip--1 { left: 0; }
|
||||
.ind__chip--2 { right: 0; }
|
||||
.ind__toggle-btn { padding: 9px 20px; }
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.ind__img-wrap, .ind__glow, .ind__chip, .ind__chip .dot { animation: none !important; }
|
||||
.ind__track { transition: none !important; }
|
||||
.ind__panel.is-active .ind__list li { animation: none !important; opacity: 1; transform: none; }
|
||||
}
|
||||
`}} />
|
||||
|
||||
<section id="ind-solutions" className="ind" aria-label="Industry solutions">
|
||||
<IndustryWorldMap />
|
||||
|
||||
<div className="ind__inner">
|
||||
{/* Top tab bar */}
|
||||
<div className="ind__tabs" role="tablist" aria-label="Industries">
|
||||
{INDUSTRIES.map((it, i) => (
|
||||
<button
|
||||
key={it.id}
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={i === active}
|
||||
className={`ind__tab ${i === active ? "active" : ""}`}
|
||||
onClick={() => selectIndustry(i)}
|
||||
>
|
||||
{it.tab}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="ind__grid">
|
||||
{/* Left media */}
|
||||
<div className="ind__media">
|
||||
<div className="ind__glow" />
|
||||
<div className="ind__img-wrap">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img key={active} className="ind__img" src={ind.image} alt={ind.alt} decoding="async" />
|
||||
</div>
|
||||
<div className="ind__chip ind__chip--1">
|
||||
<span className="dot" />
|
||||
{ind.chips[0]}
|
||||
</div>
|
||||
<div className="ind__chip ind__chip--2">
|
||||
<span className="dot" />
|
||||
{ind.chips[1]}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right text */}
|
||||
<div className="ind__text">
|
||||
<span className="ind__eyebrow">{ind.eyebrow}</span>
|
||||
<h3 className="ind__title">{ind.title}</h3>
|
||||
<p className="ind__desc">{ind.desc}</p>
|
||||
|
||||
<div className="ind__toggle" role="tablist" aria-label="Challenges or Solutions">
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={tab === "challenges"}
|
||||
className={`ind__toggle-btn ${tab === "challenges" ? "active" : ""}`}
|
||||
onClick={() => setTab("challenges")}
|
||||
>
|
||||
Challenges
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={tab === "solutions"}
|
||||
className={`ind__toggle-btn ${tab === "solutions" ? "active" : ""}`}
|
||||
onClick={() => setTab("solutions")}
|
||||
>
|
||||
Solutions
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="ind__slider">
|
||||
<div
|
||||
className="ind__track"
|
||||
key={active}
|
||||
style={{ transform: tab === "challenges" ? "translateX(0)" : "translateX(-50%)" }}
|
||||
>
|
||||
<div className={`ind__panel ${tab === "challenges" ? "is-active" : ""}`}>
|
||||
<ul className="ind__list">
|
||||
{ind.challenges.map((c, idx) => (
|
||||
<li key={idx}>{c}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className={`ind__panel ${tab === "solutions" ? "is-active" : ""}`}>
|
||||
<ul className="ind__list">
|
||||
{ind.solutions.map((s, idx) => (
|
||||
<li key={idx}>{s}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import LogisticsBrainSection from "../logisticsbrain/LogisticsBrainSection";
|
||||
|
||||
export default function Workflow2() {
|
||||
const [activeSlide, setActiveSlide] = useState(0);
|
||||
@@ -22,83 +23,67 @@ export default function Workflow2() {
|
||||
];
|
||||
|
||||
return (
|
||||
<section className="dm-workflow" aria-label="Workflow 2 — Competitive Edge & Innovation">
|
||||
<div className="dm-workflow__container">
|
||||
<section className="dm-wf2" aria-label="Workflow 2 — How Our Logistics Brain Works & Innovation">
|
||||
|
||||
{/* ── Top sub-section: Competitive Edge banner ── */}
|
||||
<div className="dm-workflow-banner">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
className="dm-workflow-banner__img"
|
||||
src="/images/miletruth-2.png"
|
||||
alt="Our Competitive Edge"
|
||||
width={1733}
|
||||
height={773}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
<div className="dm-workflow-banner__caption">
|
||||
<span className="dm-workflow-banner__title-text">Our Competitive Edge</span>
|
||||
</div>
|
||||
{/* ── Top sub-section: the complete "How Our Logistics Brain Works" experience ── */}
|
||||
<LogisticsBrainSection connected />
|
||||
|
||||
{/* ── Bottom sub-section: Innovation content, flush + colour-matched to the
|
||||
logistics-brain card above so the whole workflow reads as one container ── */}
|
||||
<div className="dm-wf2-card">
|
||||
{/* Left Column: Overlapping Chevron Graphic */}
|
||||
<div className="dm-workflow-left">
|
||||
<svg viewBox="0 0 320 280" fill="none" xmlns="http://www.w3.org/2000/svg" className="dm-workflow-svg">
|
||||
<path
|
||||
d="M 30,20 C 22,20 16,26 16,34 L 78,85 C 81,88 81,92 78,95 L 16,146 C 16,154 22,160 30,160 L 130,160 C 138,160 145,154 148,146 L 204,95 C 207,92 207,88 204,85 L 148,34 C 145,26 138,20 130,20 Z"
|
||||
stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.25"
|
||||
/>
|
||||
<path
|
||||
d="M 110,100 C 102,100 96,106 96,114 L 158,165 C 161,168 161,172 158,175 L 96,226 C 96,234 102,240 110,240 L 210,240 C 218,240 225,234 228,226 L 284,175 C 287,172 287,168 284,165 L 228,114 C 225,106 218,100 210,100 Z"
|
||||
stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.85"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* ── Bottom sub-section: Innovation content ── */}
|
||||
<div className="dm-workflow-card">
|
||||
{/* Left Column: Overlapping Chevron Graphic */}
|
||||
<div className="dm-workflow-left">
|
||||
<svg viewBox="0 0 320 280" fill="none" xmlns="http://www.w3.org/2000/svg" className="dm-workflow-svg">
|
||||
<path
|
||||
d="M 30,20 C 22,20 16,26 16,34 L 78,85 C 81,88 81,92 78,95 L 16,146 C 16,154 22,160 30,160 L 130,160 C 138,160 145,154 148,146 L 204,95 C 207,92 207,88 204,85 L 148,34 C 145,26 138,20 130,20 Z"
|
||||
stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.25"
|
||||
/>
|
||||
<path
|
||||
d="M 110,100 C 102,100 96,106 96,114 L 158,165 C 161,168 161,172 158,175 L 96,226 C 96,234 102,240 110,240 L 210,240 C 218,240 225,234 228,226 L 284,175 C 287,172 287,168 284,165 L 228,114 C 225,106 218,100 210,100 Z"
|
||||
stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.85"
|
||||
/>
|
||||
</svg>
|
||||
{/* Right Column: Quotes & Text Content */}
|
||||
<div className="dm-workflow-right">
|
||||
<svg width="32" height="24" viewBox="0 0 32 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="dm-workflow-quote">
|
||||
<rect x="2" y="2" width="9" height="20" rx="1.5" transform="skewX(-12)" fill="#C01227" />
|
||||
<rect x="16" y="2" width="9" height="20" rx="1.5" transform="skewX(-12)" fill="#C01227" />
|
||||
</svg>
|
||||
|
||||
<h3 className="dm-workflow-title">{slides[activeSlide].title}</h3>
|
||||
|
||||
<div className="dm-workflow-text-container">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.p
|
||||
key={activeSlide}
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -12 }}
|
||||
transition={{ duration: 0.28, ease: "easeInOut" }}
|
||||
className="dm-workflow-text"
|
||||
>
|
||||
{slides[activeSlide].text}
|
||||
</motion.p>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{/* Right Column: Quotes & Text Content */}
|
||||
<div className="dm-workflow-right">
|
||||
<svg width="32" height="24" viewBox="0 0 32 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="dm-workflow-quote">
|
||||
<rect x="2" y="2" width="9" height="20" rx="1.5" transform="skewX(-12)" fill="#C01227" />
|
||||
<rect x="16" y="2" width="9" height="20" rx="1.5" transform="skewX(-12)" fill="#C01227" />
|
||||
</svg>
|
||||
|
||||
<h3 className="dm-workflow-title">{slides[activeSlide].title}</h3>
|
||||
|
||||
<div className="dm-workflow-text-container">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.p
|
||||
key={activeSlide}
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -12 }}
|
||||
transition={{ duration: 0.28, ease: "easeInOut" }}
|
||||
className="dm-workflow-text"
|
||||
>
|
||||
{slides[activeSlide].text}
|
||||
</motion.p>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
<div className="dm-workflow-nav">
|
||||
<span className="dm-workflow-counter">0{activeSlide + 1}/03</span>
|
||||
<div className="dm-workflow-bars">
|
||||
{slides.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
type="button"
|
||||
aria-label={`Go to slide ${index + 1}`}
|
||||
className={`dm-workflow-bar ${index === activeSlide ? "is-active" : ""}`}
|
||||
onClick={() => setActiveSlide(index)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="dm-workflow-nav">
|
||||
<span className="dm-workflow-counter">0{activeSlide + 1}/03</span>
|
||||
<div className="dm-workflow-bars">
|
||||
{slides.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
type="button"
|
||||
aria-label={`Go to slide ${index + 1}`}
|
||||
className={`dm-workflow-bar ${index === activeSlide ? "is-active" : ""}`}
|
||||
onClick={() => setActiveSlide(index)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<style dangerouslySetInnerHTML={{ __html: styles }} />
|
||||
@@ -108,73 +93,37 @@ export default function Workflow2() {
|
||||
|
||||
const styles = `
|
||||
/* ============================================================
|
||||
Workflow = ONE container: image-title banner (top) flush with
|
||||
the dark content card (bottom). Single overflow:hidden wrapper
|
||||
rounds the whole stack — no gap, no separate backgrounds.
|
||||
Workflow 2 = ONE container:
|
||||
├─ How Our Logistics Brain Works (full LogisticsBrainSection)
|
||||
└─ Innovation (content card, flush + colour-matched)
|
||||
The Innovation card is pulled up to butt against the logistics-brain
|
||||
card's flat bottom and shares its dark red/black surface, so the two
|
||||
read as a single continuous container with no gap / no break — the
|
||||
same connected storytelling structure used in Workflow 1
|
||||
(Impact of Optimisation → Performance).
|
||||
============================================================ */
|
||||
.dm-workflow {
|
||||
max-width: 100%;
|
||||
margin: 24px auto;
|
||||
padding: 0 40px;
|
||||
box-sizing: border-box;
|
||||
.dm-wf2 {
|
||||
position: relative;
|
||||
margin: 0 auto 24px;
|
||||
}
|
||||
|
||||
.dm-workflow__container {
|
||||
/* Innovation card — aligned to the logistics-brain card (16px side insets),
|
||||
red/black-matched, flat top, rounded bottom, pulled up to close the seam. */
|
||||
.dm-wf2-card {
|
||||
position: relative;
|
||||
border-radius: 40px;
|
||||
overflow: hidden;
|
||||
background: #181818;
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
box-shadow: 0 14px 50px -16px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
/* ── Banner (top) ── */
|
||||
.dm-workflow-banner {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
}
|
||||
.dm-workflow-banner__img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 380px;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
.dm-workflow-banner__caption {
|
||||
position: absolute;
|
||||
left: 40px;
|
||||
bottom: 32px;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
padding: 16px 26px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 10px 28px -10px rgba(0, 0, 0, 0.45);
|
||||
line-height: normal;
|
||||
}
|
||||
.dm-workflow-banner__title-text {
|
||||
display: block;
|
||||
color: #C01227 !important;
|
||||
font-family: var(--font-space-grotesk), var(--font-manrope), system-ui, sans-serif !important;
|
||||
font-size: clamp(20px, 2.4vw, 34px) !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1.1 !important;
|
||||
letter-spacing: -0.01em;
|
||||
text-transform: none !important;
|
||||
}
|
||||
|
||||
/* ── Content card (bottom), flush under the banner ── */
|
||||
.dm-workflow-card {
|
||||
position: relative;
|
||||
background: #181818;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
||||
z-index: 2;
|
||||
margin: 0 16px 0;
|
||||
background: radial-gradient(120% 100% at 50% 0%, #12090c 0%, #0a070a 55%, #060507 100%);
|
||||
border: 1px solid rgba(192, 18, 39, 0.16);
|
||||
border-top: none;
|
||||
border-radius: 0 0 28px 28px;
|
||||
box-shadow: 0 10px 40px -10px rgba(0, 0, 0, 0.5);
|
||||
padding: 48px 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 40px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -251,24 +200,21 @@ const styles = `
|
||||
.dm-workflow-bar:hover { background: rgba(255, 255, 255, 0.35); }
|
||||
.dm-workflow-bar.is-active:hover { background: #C01227; }
|
||||
|
||||
/* ── Responsive ── */
|
||||
/* ── Responsive — keep insets/radius aligned to the logistics-brain card ── */
|
||||
@media (max-width: 1024px) {
|
||||
.dm-workflow__container { border-radius: 32px; }
|
||||
.dm-workflow-banner__img { max-height: 300px; }
|
||||
.dm-workflow-banner__caption { left: 28px; bottom: 24px; padding: 13px 20px; }
|
||||
.dm-workflow-card { padding: 44px 44px; gap: 44px; }
|
||||
.dm-wf2-card {
|
||||
padding: 44px 44px;
|
||||
gap: 44px;
|
||||
}
|
||||
.dm-workflow-title { font-size: 32px; }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.dm-workflow { padding: 0 16px; }
|
||||
.dm-workflow__container { border-radius: 24px; }
|
||||
.dm-workflow-banner__img { max-height: 220px; }
|
||||
.dm-workflow-banner__caption { left: 16px; bottom: 16px; padding: 11px 16px; }
|
||||
.dm-workflow-card {
|
||||
flex-direction: column;
|
||||
@media (max-width: 767px) {
|
||||
.dm-wf2-card {
|
||||
margin: 0 10px 0;
|
||||
border-radius: 0 0 20px 20px;
|
||||
padding: 36px 28px;
|
||||
gap: 36px;
|
||||
flex-direction: column;
|
||||
}
|
||||
.dm-workflow-left { max-width: 280px; }
|
||||
.dm-workflow-right { width: 100%; }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import StrategySection from "../strategy/StrategySection";
|
||||
|
||||
export default function Workflow3() {
|
||||
const [activeSlide, setActiveSlide] = useState(0);
|
||||
@@ -22,83 +23,69 @@ export default function Workflow3() {
|
||||
];
|
||||
|
||||
return (
|
||||
<section className="dm-workflow" aria-label="Workflow 3 — Happier Riders & Strategy">
|
||||
<div className="dm-workflow__container">
|
||||
<section className="dm-wf3" aria-label="Workflow 3 — Happier Riders. Higher Fulfillment. & Strategy">
|
||||
|
||||
{/* ── Top sub-section: Happier Riders banner ── */}
|
||||
<div className="dm-workflow-banner">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
className="dm-workflow-banner__img"
|
||||
src="/images/miletruth-3.png"
|
||||
alt="Happier Riders. Higher Fulfillment"
|
||||
width={1733}
|
||||
height={773}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
<div className="dm-workflow-banner__caption">
|
||||
<span className="dm-workflow-banner__title-text">Happier Riders. Higher Fulfillment</span>
|
||||
</div>
|
||||
{/* ── Top sub-section: the full "Happier Riders. Higher Fulfillment."
|
||||
3D scroll-storytelling experience ── */}
|
||||
<StrategySection connected />
|
||||
|
||||
{/* ── Bottom sub-section: Strategy content, flush + pulled up to butt against
|
||||
the 3D card's flat bottom so the whole workflow reads as one container —
|
||||
the same connected structure used in Workflow 1 & 2 ── */}
|
||||
<div className="dm-wf3-card">
|
||||
{/* Left Column: Overlapping Chevron Graphic */}
|
||||
<div className="dm-workflow-left">
|
||||
<svg viewBox="0 0 320 280" fill="none" xmlns="http://www.w3.org/2000/svg" className="dm-workflow-svg">
|
||||
<path
|
||||
d="M 30,20 C 22,20 16,26 16,34 L 78,85 C 81,88 81,92 78,95 L 16,146 C 16,154 22,160 30,160 L 130,160 C 138,160 145,154 148,146 L 204,95 C 207,92 207,88 204,85 L 148,34 C 145,26 138,20 130,20 Z"
|
||||
stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.25"
|
||||
/>
|
||||
<path
|
||||
d="M 110,100 C 102,100 96,106 96,114 L 158,165 C 161,168 161,172 158,175 L 96,226 C 96,234 102,240 110,240 L 210,240 C 218,240 225,234 228,226 L 284,175 C 287,172 287,168 284,165 L 228,114 C 225,106 218,100 210,100 Z"
|
||||
stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.85"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* ── Bottom sub-section: Strategy content ── */}
|
||||
<div className="dm-workflow-card">
|
||||
{/* Left Column: Overlapping Chevron Graphic */}
|
||||
<div className="dm-workflow-left">
|
||||
<svg viewBox="0 0 320 280" fill="none" xmlns="http://www.w3.org/2000/svg" className="dm-workflow-svg">
|
||||
<path
|
||||
d="M 30,20 C 22,20 16,26 16,34 L 78,85 C 81,88 81,92 78,95 L 16,146 C 16,154 22,160 30,160 L 130,160 C 138,160 145,154 148,146 L 204,95 C 207,92 207,88 204,85 L 148,34 C 145,26 138,20 130,20 Z"
|
||||
stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.25"
|
||||
/>
|
||||
<path
|
||||
d="M 110,100 C 102,100 96,106 96,114 L 158,165 C 161,168 161,172 158,175 L 96,226 C 96,234 102,240 110,240 L 210,240 C 218,240 225,234 228,226 L 284,175 C 287,172 287,168 284,165 L 228,114 C 225,106 218,100 210,100 Z"
|
||||
stroke="white" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.85"
|
||||
/>
|
||||
</svg>
|
||||
{/* Right Column: Quotes & Text Content */}
|
||||
<div className="dm-workflow-right">
|
||||
<svg width="32" height="24" viewBox="0 0 32 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="dm-workflow-quote">
|
||||
<rect x="2" y="2" width="9" height="20" rx="1.5" transform="skewX(-12)" fill="#C01227" />
|
||||
<rect x="16" y="2" width="9" height="20" rx="1.5" transform="skewX(-12)" fill="#C01227" />
|
||||
</svg>
|
||||
|
||||
<h3 className="dm-workflow-title">{slides[activeSlide].title}</h3>
|
||||
|
||||
<div className="dm-workflow-text-container">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.p
|
||||
key={activeSlide}
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -12 }}
|
||||
transition={{ duration: 0.28, ease: "easeInOut" }}
|
||||
className="dm-workflow-text"
|
||||
>
|
||||
{slides[activeSlide].text}
|
||||
</motion.p>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{/* Right Column: Quotes & Text Content */}
|
||||
<div className="dm-workflow-right">
|
||||
<svg width="32" height="24" viewBox="0 0 32 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="dm-workflow-quote">
|
||||
<rect x="2" y="2" width="9" height="20" rx="1.5" transform="skewX(-12)" fill="#C01227" />
|
||||
<rect x="16" y="2" width="9" height="20" rx="1.5" transform="skewX(-12)" fill="#C01227" />
|
||||
</svg>
|
||||
|
||||
<h3 className="dm-workflow-title">{slides[activeSlide].title}</h3>
|
||||
|
||||
<div className="dm-workflow-text-container">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.p
|
||||
key={activeSlide}
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -12 }}
|
||||
transition={{ duration: 0.28, ease: "easeInOut" }}
|
||||
className="dm-workflow-text"
|
||||
>
|
||||
{slides[activeSlide].text}
|
||||
</motion.p>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
<div className="dm-workflow-nav">
|
||||
<span className="dm-workflow-counter">0{activeSlide + 1}/03</span>
|
||||
<div className="dm-workflow-bars">
|
||||
{slides.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
type="button"
|
||||
aria-label={`Go to slide ${index + 1}`}
|
||||
className={`dm-workflow-bar ${index === activeSlide ? "is-active" : ""}`}
|
||||
onClick={() => setActiveSlide(index)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="dm-workflow-nav">
|
||||
<span className="dm-workflow-counter">0{activeSlide + 1}/03</span>
|
||||
<div className="dm-workflow-bars">
|
||||
{slides.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
type="button"
|
||||
aria-label={`Go to slide ${index + 1}`}
|
||||
className={`dm-workflow-bar ${index === activeSlide ? "is-active" : ""}`}
|
||||
onClick={() => setActiveSlide(index)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<style dangerouslySetInnerHTML={{ __html: styles }} />
|
||||
@@ -108,73 +95,33 @@ export default function Workflow3() {
|
||||
|
||||
const styles = `
|
||||
/* ============================================================
|
||||
Workflow = ONE container: image-title banner (top) flush with
|
||||
the dark content card (bottom). Single overflow:hidden wrapper
|
||||
rounds the whole stack — no gap, no separate backgrounds.
|
||||
Workflow 3 = ONE container:
|
||||
├─ Happier Riders. Higher Fulfillment. (full StrategySection — 3D)
|
||||
└─ Strategy (content card, flush, pulled up)
|
||||
The Strategy card aligns to the 3D card's 16px side insets, butts against
|
||||
its flat bottom and rounds the bottom corners, so the two read as a single
|
||||
continuous container — same technique as Workflow 1 & 2.
|
||||
============================================================ */
|
||||
.dm-workflow {
|
||||
max-width: 100%;
|
||||
margin: 24px auto;
|
||||
padding: 0 40px;
|
||||
box-sizing: border-box;
|
||||
.dm-wf3 {
|
||||
position: relative;
|
||||
margin: 0 auto 24px;
|
||||
}
|
||||
|
||||
.dm-workflow__container {
|
||||
.dm-wf3-card {
|
||||
position: relative;
|
||||
border-radius: 40px;
|
||||
overflow: hidden;
|
||||
z-index: 2;
|
||||
margin: 0 16px 0;
|
||||
background: #181818;
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
box-shadow: 0 14px 50px -16px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
/* ── Banner (top) ── */
|
||||
.dm-workflow-banner {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
}
|
||||
.dm-workflow-banner__img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 380px;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
.dm-workflow-banner__caption {
|
||||
position: absolute;
|
||||
left: 40px;
|
||||
bottom: 32px;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
padding: 16px 26px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 10px 28px -10px rgba(0, 0, 0, 0.45);
|
||||
line-height: normal;
|
||||
}
|
||||
.dm-workflow-banner__title-text {
|
||||
display: block;
|
||||
color: #C01227 !important;
|
||||
font-family: var(--font-space-grotesk), var(--font-manrope), system-ui, sans-serif !important;
|
||||
font-size: clamp(20px, 2.4vw, 34px) !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1.1 !important;
|
||||
letter-spacing: -0.01em;
|
||||
text-transform: none !important;
|
||||
}
|
||||
|
||||
/* ── Content card (bottom), flush under the banner ── */
|
||||
.dm-workflow-card {
|
||||
position: relative;
|
||||
background: #181818;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
||||
border-top: none;
|
||||
border-radius: 0 0 28px 28px;
|
||||
box-shadow: 0 10px 40px -10px rgba(0, 0, 0, 0.5);
|
||||
padding: 48px 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 40px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -251,24 +198,18 @@ const styles = `
|
||||
.dm-workflow-bar:hover { background: rgba(255, 255, 255, 0.35); }
|
||||
.dm-workflow-bar.is-active:hover { background: #C01227; }
|
||||
|
||||
/* ── Responsive ── */
|
||||
/* ── Responsive — keep insets/radius aligned to the 3D card ── */
|
||||
@media (max-width: 1024px) {
|
||||
.dm-workflow__container { border-radius: 32px; }
|
||||
.dm-workflow-banner__img { max-height: 300px; }
|
||||
.dm-workflow-banner__caption { left: 28px; bottom: 24px; padding: 13px 20px; }
|
||||
.dm-workflow-card { padding: 44px 44px; gap: 44px; }
|
||||
.dm-wf3-card { padding: 44px 44px; gap: 44px; }
|
||||
.dm-workflow-title { font-size: 32px; }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.dm-workflow { padding: 0 16px; }
|
||||
.dm-workflow__container { border-radius: 24px; }
|
||||
.dm-workflow-banner__img { max-height: 220px; }
|
||||
.dm-workflow-banner__caption { left: 16px; bottom: 16px; padding: 11px 16px; }
|
||||
.dm-workflow-card {
|
||||
flex-direction: column;
|
||||
@media (max-width: 767px) {
|
||||
.dm-wf3-card {
|
||||
margin: 0 10px 0;
|
||||
border-radius: 0 0 20px 20px;
|
||||
padding: 36px 28px;
|
||||
gap: 36px;
|
||||
flex-direction: column;
|
||||
}
|
||||
.dm-workflow-left { max-width: 280px; }
|
||||
.dm-workflow-right { width: 100%; }
|
||||
|
||||
Reference in New Issue
Block a user