update solution page

This commit is contained in:
2026-07-20 13:33:30 +05:30
parent c29dc64c38
commit ca83f34b11
46 changed files with 4058 additions and 146 deletions

1
doorven.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 105 KiB

View File

@@ -16678,6 +16678,20 @@ body:not(.rtl) .elementor-6585 .elementor-element.elementor-element-8899bdf {
}
}
/* Footer's own breakpoint above switches horizontal padding at 1020px, but
every other section's shared container (.sw-in, and the Hero's matching
padding) switches at 1024px — leaving a 1021-1024px viewport gap where
the footer sits 10px further in than everything above it (e.g. iPad
portrait, 1024px wide). This closes that gap without touching the
1020px block above, which also carries unrelated vertical-rhythm rules
for other footer elements. */
@media (max-width: 1024px) and (min-width: 1021px) {
.elementor-6585 .elementor-element.elementor-element-3cd920c {
--padding-left: 10px;
--padding-right: 10px;
}
}
@media(max-width: 840px) {
.elementor-6585 .elementor-element.elementor-element-2631b42 {
--flex-direction:row;

1
public/doorven.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

1
public/live-track.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -4,7 +4,7 @@ import BlogGrid from "@/components/sections/BlogGrid";
export const metadata = {
title: "Blog Doormile",
description: "Practical notes on delivery planning, EV fleet operations, route optimisation, charging, and last-mile performance from the Doormile team.",
description: "Practical notes on logistics planning, EV fleet operations, route intelligence, charging, and last-mile performance from the Doormile team.",
};
export default function BlogPage() {

View File

@@ -11,13 +11,13 @@ import WingsRoadmap from "@/components/sections/WingsRoadmap";
export const metadata = {
title: "Doormile Wings Redefining Domestic Air Logistics Through AI",
description: "Doormile Wings links India's major regional capitals with AI-powered, same-day air logistics and zero-emission EV last-mile delivery — where quick commerce meets quick logistics.",
description: "Doormile Wings links India's major regional capitals with AI-powered, same-day air logistics and zero-emission EV last-mile transport — where quick commerce meets quick logistics.",
alternates: {
canonical: "https://doormile.com/doormile-wings",
},
openGraph: {
title: "Doormile Wings Redefining Domestic Air Logistics Through AI",
description: "Same-day air logistics linking India's major regional capitals, powered by MileTruth™ AI and zero-emission EV last-mile delivery.",
description: "Same-day air logistics linking India's major regional capitals, powered by MileTruth™ AI and zero-emission EV last-mile transport.",
url: "https://doormile.com/doormile-wings",
siteName: "Doormile",
type: "website",
@@ -33,7 +33,7 @@ export const metadata = {
twitter: {
card: "summary_large_image",
title: "Doormile Wings Redefining Domestic Air Logistics Through AI",
description: "Same-day air logistics linking India's major regional capitals, powered by MileTruth™ AI and zero-emission EV last-mile delivery.",
description: "Same-day air logistics linking India's major regional capitals, powered by MileTruth™ AI and zero-emission EV last-mile transport.",
images: ["https://doormile.com/images/wings-logo.png"],
},
};

View File

@@ -4,7 +4,7 @@ import Experience3DLoader from "@/modules/how-it-works-3d/Experience3DLoader";
export const metadata = {
title: "How It Works Doormile",
description: "See how Doormile connects first, mid, and last mile into a seamless delivery experience powered by MileTruth™ AI.",
description: "See how Doormile connects first, mid, and last mile into a seamless end-to-end logistics experience powered by MileTruth™ AI.",
};
export default function HowItWorksPage() {

View File

@@ -1,5 +1,6 @@
import React from "react";
import MileTruthHero from "../../components/sections/MileTruthHero";
import MileTruthIntro from "../../components/sections/MileTruthIntro";
import Workflow1 from "../../components/sections/Workflow1";
import Workflow2 from "../../components/sections/Workflow2";
import Workflow4 from "../../components/sections/Workflow4";
@@ -7,7 +8,7 @@ import Workflow3Lazy from "../../components/sections/Workflow3Lazy";
export const metadata = {
title: "MileTruth Doormile",
description: "Optimizes every stage of the delivery journey for maximum efficiency. Explore the only AI built exclusively for logistics.",
description: "Optimizes every stage of the logistics journey for maximum efficiency. Explore the only AI built exclusively for logistics.",
};
export default function MileTruthPage() {
@@ -17,6 +18,7 @@ export default function MileTruthPage() {
<div className="content-inner">
<div data-elementor-type="wp-page" data-elementor-id="59" className="elementor elementor-59">
<MileTruthHero />
<MileTruthIntro />
<Workflow1 />
<Workflow2 />
<Workflow4 />

View File

@@ -1,10 +1,10 @@
import React from "react";
import SolutionsHero from "@/components/sections/SolutionsHero";
import IndustryStack from "@/components/sections/IndustryStack";
import SolutionsWorkflow from "@/components/sections/SolutionsWorkflow";
export const metadata = {
title: "Solutions Doormile",
description: "Discover how Doormile's connected logistics platform serves diverse industries (FMCG, Pharma, and Enterprise) with tailored solutions.",
description: "See how Doormile's AI-powered Logistics Intelligence Platform works end-to-end — from pickup and AI vehicle selection to Quantum routing, live shipment tracking, door-to-door movement, MileTruth AI and real-time operations monitoring.",
};
export default function SolutionsPage() {
@@ -55,7 +55,7 @@ export default function SolutionsPage() {
<div className="content-inner">
<div data-elementor-type="wp-page" data-elementor-id="59" className="elementor elementor-59">
<SolutionsHero />
<IndustryStack />
<SolutionsWorkflow />
</div>
</div>
</div>

View File

@@ -72,7 +72,7 @@ export default function BlogSidebar({ current }: { current?: BlogPost }) {
{/* CTA Card */}
<section className="dm-blog-widget dm-blog-cta-card">
<h2 className="dm-blog-cta-title">Planning delivery routes?</h2>
<h2 className="dm-blog-cta-title">Planning logistics routes?</h2>
<p className="dm-blog-cta-text">
Talk to us about reducing wasted distance, missed windows, and avoidable
vehicle time.

View File

@@ -126,7 +126,7 @@ export default function Footer() {
</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>
<p>Connecting businesses with fast, secure, intelligent logistics.</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">
@@ -360,7 +360,7 @@ export default function Footer() {
<div className="elementor-widget-container">
<ScrollReveal delay={0.1} duration={0.8} yOffset={25}>
<h2 className="logico-title">
Delivered <span style={{ color: "#c01227" }}>on time</span> with no hassle.
Shipped <span style={{ color: "#c01227" }}>on time</span> with no hassle.
</h2>
</ScrollReveal>
</div>

View File

@@ -243,18 +243,18 @@ export default function LogisticsBrainSection({ connected = false }: { connected
</motion.div>
<motion.div className="dm-lb-scrollhint" style={{ opacity: introOpacity }}>
<span>Scroll to see how every delivery is planned</span>
<span>Scroll to see how every shipment is planned</span>
<span className="dm-lb-arrow"></span>
</motion.div>
{/* STEP 01 — Generate Routes (card anchored LEFT) */}
<StoryCard step={step} index={0} pos="left" opacity={p1o} y={p1y} x={p1x} scale={p1s} num="01" kicker="Generate Routes" title="We create many delivery plans at once">
<StoryCard step={step} index={0} pos="left" opacity={p1o} y={p1y} x={p1x} scale={p1s} num="01" kicker="Generate Routes" title="We create many route plans at once">
<div className="dm-lb-chips">
{STRATEGIES.map((s, i) => (
<span key={s} className={`dm-lb-chip${i === WINNER_INDEX ? " dm-lb-chip--active" : ""}`}>{s}</span>
))}
</div>
<p className="dm-lb-pillar__foot">6 different ways to deliver all 59 orders generated in milliseconds.</p>
<p className="dm-lb-pillar__foot">6 different ways to move all 59 orders generated in milliseconds.</p>
</StoryCard>
{/* STEP 02 — Check Constraints (card anchored CENTER) */}
@@ -268,11 +268,11 @@ export default function LogisticsBrainSection({ connected = false }: { connected
</li>
))}
</ul>
<p className="dm-lb-pillar__stat"><strong>59/59</strong> delivered <em>vs 34/59 when battery limits are ignored</em></p>
<p className="dm-lb-pillar__stat"><strong>59/59</strong> fulfilled <em>vs 34/59 when battery limits are ignored</em></p>
</StoryCard>
{/* STEP 03 — Score & Compare (card anchored RIGHT) */}
<StoryCard step={step} index={2} pos="right" opacity={p3o} y={p3y} x={p3x} scale={p3s} num="03" kicker="Score &amp; Compare" title="Each plan is scored by total delivery cost">
<StoryCard step={step} index={2} pos="right" opacity={p3o} y={p3y} x={p3x} scale={p3s} num="03" kicker="Score &amp; Compare" title="Each plan is scored by total logistics cost">
<ul className="dm-lb-board">
{STRATEGY_SCORES.map((s) => (
<li key={s.name} className={s.win ? "is-win" : ""}>
@@ -290,7 +290,7 @@ export default function LogisticsBrainSection({ connected = false }: { connected
<span className="dm-lb-sla__badge"> On-time only</span>
<span className="dm-lb-sla__x"> Late plan dropped</span>
</div>
<p className="dm-lb-pillar__foot">We only keep plans that hit every promised delivery window.</p>
<p className="dm-lb-pillar__foot">We only keep plans that hit every promised arrival window.</p>
</StoryCard>
{/* STEP 05 — Pick & Dispatch (card anchored CENTER, hero) */}
@@ -308,7 +308,7 @@ export default function LogisticsBrainSection({ connected = false }: { connected
<motion.div className="dm-lb-kpis" style={{ y: finaleY }}>
<div className="dm-lb-kpi">
<span className="dm-lb-kpi__num"><Counter mv={orders} />/59</span>
<span className="dm-lb-kpi__label">Orders Delivered</span>
<span className="dm-lb-kpi__label">Orders Fulfilled</span>
</div>
<div className="dm-lb-kpi dm-lb-kpi--green">
<span className="dm-lb-kpi__num">0</span>

View File

@@ -74,7 +74,7 @@ export const CONSTRAINT_LIST = [
{ icon: "🔋", label: "Battery", note: "EV range & recharge stops" },
{ icon: "📍", label: "Distance", note: "Total km per route" },
{ icon: "📦", label: "Capacity", note: "Orders each vehicle can carry" },
{ icon: "⏱️", label: "Time / SLA", note: "Promised delivery windows" },
{ icon: "⏱️", label: "Time / SLA", note: "Promised arrival windows" },
] as const;
/**
@@ -119,7 +119,7 @@ export type PhaseKey = keyof typeof P;
* scroll-progress threshold where each step becomes the active one.
*/
export const ENGINE_STEPS = [
{ n: "01", at: P.routes, title: "Generate Routes", caption: "Many delivery plans created at once" },
{ n: "01", at: P.routes, title: "Generate Routes", caption: "Many route plans created at once" },
{ n: "02", at: P.ev, title: "Check Constraints", caption: "Battery, distance, capacity & time" },
{ n: "03", at: P.network, title: "Score & Compare", caption: "Every plan ranked by total cost" },
{ n: "04", at: P.sla, title: "Guarantee On-Time", caption: "Late plans rejected automatically" },
@@ -129,9 +129,9 @@ export const ENGINE_STEPS = [
export const PHASE_CAPTIONS: Record<PhaseKey, string> = {
birth: "Initializing the logistics brain",
routes: "Simulating delivery strategies",
routes: "Simulating routing strategies",
ev: "Recalculating around EV constraints",
network: "Mapping the live delivery network",
network: "Mapping the live logistics network",
sla: "Enforcing on-time SLA reliability",
ecosystem: "Autonomous fleet in motion",
finale: "",

View File

@@ -122,7 +122,7 @@ function WithoutPanelBody() {
<li><span className="dm-opt-marker dm-opt-marker--x"></span> Chaotic overlapping routes</li>
<li><span className="dm-opt-marker dm-opt-marker--x"></span> Duplicate &amp; idle trips</li>
<li><span className="dm-opt-marker dm-opt-marker--x"></span> 8 vehicles required</li>
<li><span className="dm-opt-marker dm-opt-marker--x"></span> 23 delivery delays</li>
<li><span className="dm-opt-marker dm-opt-marker--x"></span> 23 shipment delays</li>
<li><span className="dm-opt-marker dm-opt-marker--x"></span> +18% cost overrun</li>
</ul>
</>
@@ -141,7 +141,7 @@ function WithPanelBody() {
<li><span className="dm-opt-marker dm-opt-marker--ok"></span> Optimized route clusters</li>
<li><span className="dm-opt-marker dm-opt-marker--ok"></span> Intelligent vehicle assignment</li>
<li><span className="dm-opt-marker dm-opt-marker--ok"></span> Multi-trip &amp; EV planning</li>
<li><span className="dm-opt-marker dm-opt-marker--ok"></span> Zero delivery delays</li>
<li><span className="dm-opt-marker dm-opt-marker--ok"></span> Zero shipment delays</li>
<li><span className="dm-opt-marker dm-opt-marker--ok"></span> 18% cost saved</li>
<li><span className="dm-opt-marker dm-opt-marker--ok"></span> Carbon footprint reduced</li>
</ul>
@@ -318,7 +318,7 @@ export default function OptimizationSection() {
</div>
<h2>AI Logistics Optimization Engine</h2>
<p>
Watch Doormile&apos;s AI engine transform chaotic logistics into precision-optimized delivery networks reducing distance, fleet size, delays, and cost.
Watch Doormile&apos;s AI engine transform chaotic operations into precision-optimized logistics networks reducing distance, fleet size, delays, and cost.
</p>
</header>
@@ -461,7 +461,7 @@ export default function OptimizationSection() {
viewport={{ once: true }}
transition={{ duration: 0.7, delay: 0.12 }}
>
Watch Doormile&apos;s AI engine transform chaotic logistics into precision-optimized delivery networks reducing distance, fleet size, delays, and cost in real time.
Watch Doormile&apos;s AI engine transform chaotic operations into precision-optimized logistics networks reducing distance, fleet size, delays, and cost in real time.
</motion.p>
{/* Workflow step indicators */}

View File

@@ -259,7 +259,7 @@ export default function ConnectedLogistics() {
</div>
<div className="elementor-element elementor-element-165dfa5 elementor-widget__width-initial elementor-widget elementor-widget-text-editor" data-id="165dfa5" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
<div className="elementor-widget-container">
<p>Learn from every delivery. Get smarter with every mile traveled.</p>
<p>Learn from every shipment. Get smarter with every mile traveled.</p>
</div>
</div>
</ScrollReveal>

View File

@@ -13,7 +13,7 @@ const CARDS_DATA = [
{
index: 1,
title: "Operational Visibility",
desc: "Real-time tracking and centralized control provide complete visibility across every shipment, vehicle, and delivery milestone.",
desc: "Real-time tracking and centralized control provide complete visibility across every shipment, vehicle, and logistics milestone.",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<rect x="2" y="7" width="16" height="10" rx="2" ry="2" />
@@ -26,7 +26,7 @@ const CARDS_DATA = [
{
index: 2,
title: "Intelligent Routing",
desc: "AI-powered route optimization reduces travel time, improves delivery accuracy, and maximizes fleet utilization.",
desc: "AI-powered route optimization reduces travel time, improves routing accuracy, and maximizes fleet utilization.",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
@@ -49,7 +49,7 @@ const CARDS_DATA = [
{
index: 4,
title: "Scalable Network",
desc: "Flexible logistics infrastructure supports growth across cities, regions, and high-volume delivery operations without disruption.",
desc: "Flexible logistics infrastructure supports growth across cities, regions, and high-volume logistics operations without disruption.",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 3.5 2 5.5a7 7 0 0 1-7 7h-3" />

View File

@@ -135,7 +135,7 @@ const DEFAULT_FEATURES: EVFeature[] = [
</svg>
),
title: "Charging Integration",
desc: "Seamlessly integrate charging stops without compromising delivery windows or SLA commitments.",
desc: "Seamlessly integrate charging stops without compromising arrival windows or SLA commitments.",
},
{
icon: (
@@ -352,7 +352,7 @@ export default function EVSection({
titleAccent = "NOT ADAPTED.",
features = DEFAULT_FEATURES,
image = "/images/premium-ev-van.webp",
imageAlt = "DoorMile electric delivery van",
imageAlt = "DoorMile electric fleet van",
badges = DEFAULT_BADGES,
stats = DEFAULT_STATS,
gapTop = false,

View File

@@ -301,8 +301,8 @@ export default function HowItWorksHero() {
<div className="text-content">
<p>
See how Doormile connects first, mid, and
last mile into a seamless delivery
experience powered by MileTruth AI.
last mile into a seamless end-to-end
logistics experience powered by MileTruth AI.
</p>
</div>
</div>
@@ -341,8 +341,8 @@ export default function HowItWorksHero() {
<div className="text-content">
<p>
See how Doormile connects first, mid, and
last mile into a seamless delivery
experience powered by MileTruth AI.
last mile into a seamless end-to-end
logistics experience powered by MileTruth AI.
</p>
</div>
</div>

View File

@@ -197,7 +197,7 @@ export default function IndexHero() {
</h1>
<div className="content-slider-item-text logico-content-wrapper-2" style={{ display: "flex", justifyContent: "center", width: "100%", marginTop: "23px" }}>
<div className="text-content" style={{ textAlign: "center", maxWidth: "680px", margin: "0 auto" }}>
<p>Stop managing three separate logistics services. Doormile unifies first, mid and last mile into a single intelligent delivery system powered by MileTruth AI.</p>
<p>Stop managing three separate logistics services. Doormile unifies first, mid and last mile into a single intelligent logistics system powered by MileTruth AI.</p>
</div>
</div>
</div>

View File

@@ -189,7 +189,7 @@ export default function IndustrySolutions() {
<h5 className="industry-card-section-title">Doormile Solutions</h5>
<ul className="industry-card-list">
<li className="industry-card-list-item bullet-4">AI-driven demand-responsive routing</li>
<li className="industry-card-list-item bullet-5">Freshness-aware delivery prioritization</li>
<li className="industry-card-list-item bullet-5">Freshness-aware shipment prioritization</li>
<li className="industry-card-list-item bullet-6">Dynamic batch optimization</li>
</ul>
</div>
@@ -246,7 +246,7 @@ export default function IndustrySolutions() {
<ul className="industry-card-list">
<li className="industry-card-list-item bullet-1">Cold chain integrity requirements</li>
<li className="industry-card-list-item bullet-2">Regulatory compliance tracking</li>
<li className="industry-card-list-item bullet-3">Critical delivery time windows</li>
<li className="industry-card-list-item bullet-3">Critical shipment time windows</li>
</ul>
</div>
<div>
@@ -303,13 +303,13 @@ export default function IndustrySolutions() {
<div className="industry-card-hover-content">
<div className="industry-card-hover-top">
<p className="industry-card-description">
High-value shipments with complex delivery requirements.
High-value shipments with complex logistics requirements.
</p>
<div>
<h5 className="industry-card-section-title">Challenges</h5>
<ul className="industry-card-list">
<li className="industry-card-list-item bullet-1">Appointment scheduling coordination</li>
<li className="industry-card-list-item bullet-2">White-glove delivery standards</li>
<li className="industry-card-list-item bullet-2">White-glove logistics standards</li>
<li className="industry-card-list-item bullet-3">Multi-location routing complexity</li>
</ul>
</div>

View File

@@ -22,15 +22,15 @@ const SECTIONS: Section[] = [
image: "/images/tab-pic-1-solution.webp",
alt: "FMCG logistics",
desc:
"FMCG logistics demands speed, precision, and continuous fulfillment across high-volume delivery networks. Businesses must balance tight delivery timelines, inventory movement, and operational efficiency without compromising product availability.",
"FMCG logistics demands speed, precision, and continuous fulfillment across high-volume logistics networks. Businesses must balance tight shipment timelines, inventory movement, and operational efficiency without compromising product availability.",
ch: [
"Unpredictable demand spikes create delivery pressure and reduce operational efficiency during peak periods.",
"Fresh product expiry constraints require faster, precisely timed deliveries to maintain product quality.",
"Multi-stop route complexity increases travel time, operational costs, and delivery coordination challenges.",
"Inventory stockout risks increase when delivery delays disrupt fast-moving product distribution.",
"Unpredictable demand spikes create logistics pressure and reduce operational efficiency during peak periods.",
"Fresh product expiry constraints require faster, precisely timed shipments to maintain product quality.",
"Multi-stop route complexity increases travel time, operational costs, and logistics coordination challenges.",
"Inventory stockout risks increase when shipment delays disrupt fast-moving product distribution.",
],
so: [
"AI demand forecasting adapts delivery plans instantly to real-time order demand.",
"AI demand forecasting adapts logistics 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.",
@@ -42,17 +42,17 @@ const SECTIONS: Section[] = [
image: "/images/tab-pic-2-solution.webp",
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.",
"Pharma logistics requires precision, compliance, and real-time monitoring so every shipment arrives safely and on time — from temperature-sensitive medicines to urgent emergency shipments.",
ch: [
"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.",
"Regulatory compliance must be tracked and documented on every shipment.",
"Critical arrival windows require highly accurate scheduling.",
"Emergency shipments need instant dispatch and zero-delay execution.",
],
so: [
"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.",
"Precision scheduling locks in critical arrival windows reliably.",
"Priority dispatch queue fast-tracks urgent, life-critical shipments.",
],
},
@@ -65,14 +65,14 @@ const SECTIONS: Section[] = [
"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.",
ch: [
"Appointment scheduling requires precise timing across many locations.",
"White-glove delivery standards demand premium handling and accuracy.",
"White-glove logistics 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.",
],
so: [
"Intelligent appointment engine streamlines and automates delivery slots.",
"Intelligent appointment engine streamlines and automates arrival slots.",
"White-glove workflow module enforces premium handling end to end.",
"Enterprise route planner coordinates efficient multi-location delivery.",
"Enterprise route planner coordinates efficient multi-location logistics.",
"SLA monitoring dashboard tracks commitments and flags risk in real time.",
],
},

View File

@@ -0,0 +1,164 @@
"use client";
import React, { useMemo, useRef } from "react";
import { Canvas, useFrame } from "@react-three/fiber";
import { Sparkles } from "@react-three/drei";
import { EffectComposer, Bloom } from "@react-three/postprocessing";
import { KernelSize } from "postprocessing";
import * as THREE from "three";
/* ============================================================
MileTruthCanvas — small, self-contained R3F scene for the
"MileTruth AI" section: a 4-node data → AI → recommendations →
improvement network with glowing cores and travelling light
packets along each connector. Deliberately lightweight (a
handful of meshes + a low-count sparkle field) — this and the
Quantum section are the ONLY two places on the Solutions page
that touch Three.js.
============================================================ */
const RED = "#C01227";
const RED_BRIGHT = "#E2354A";
const STEEL = "#8b8b96";
const WHITE = "#f4f4f6";
type Node = { pos: [number, number, number]; color: string; label: string; scale: number };
const NODES: Node[] = [
{ pos: [-4.6, 0.3, 0], color: STEEL, label: "data", scale: 0.34 },
{ pos: [-1.6, 0.75, 0.4], color: RED, label: "ai", scale: 0.46 },
{ pos: [1.5, 0.25, -0.35], color: RED_BRIGHT, label: "recs", scale: 0.38 },
{ pos: [4.5, -0.15, 0.15], color: WHITE, label: "improve", scale: 0.34 },
];
const LINKS: [number, number][] = [
[0, 1],
[1, 2],
[2, 3],
];
function NodeMesh({ node, reduced, seed }: { node: Node; reduced: boolean; seed: number }) {
const meshRef = useRef<THREE.Mesh>(null);
const haloRef = useRef<THREE.Mesh>(null);
useFrame((state) => {
const t = state.clock.elapsedTime;
const pulse = reduced ? 1 : 1 + Math.sin(t * 1.6 + seed) * 0.08;
if (meshRef.current) meshRef.current.scale.setScalar(node.scale * pulse);
if (haloRef.current) {
const haloPulse = reduced ? 1.4 : 1.4 + Math.sin(t * 1.6 + seed) * 0.18;
haloRef.current.scale.setScalar(node.scale * haloPulse);
const mat = haloRef.current.material as THREE.MeshBasicMaterial;
mat.opacity = reduced ? 0.16 : 0.14 + Math.sin(t * 1.6 + seed) * 0.06;
}
});
return (
<group position={node.pos}>
<mesh ref={haloRef}>
<sphereGeometry args={[1, 20, 20]} />
<meshBasicMaterial color={node.color} transparent opacity={0.16} depthWrite={false} />
</mesh>
<mesh ref={meshRef}>
<sphereGeometry args={[1, 28, 28]} />
<meshStandardMaterial
color={node.color}
emissive={node.color}
emissiveIntensity={1.4}
roughness={0.35}
metalness={0.1}
/>
</mesh>
</group>
);
}
function Connector({ a, b, reduced, index }: { a: Node; b: Node; reduced: boolean; index: number }) {
const packetRef = useRef<THREE.Mesh>(null);
const lineMatRef = useRef<THREE.LineBasicMaterial>(null);
const start = useMemo(() => new THREE.Vector3(...a.pos), [a]);
const end = useMemo(() => new THREE.Vector3(...b.pos), [b]);
const geo = useMemo(() => {
const g = new THREE.BufferGeometry();
g.setAttribute("position", new THREE.BufferAttribute(new Float32Array([...a.pos, ...b.pos]), 3));
return g;
}, [a, b]);
useFrame((state) => {
const t = state.clock.elapsedTime;
if (lineMatRef.current) {
lineMatRef.current.opacity = reduced ? 0.3 : 0.2 + Math.sin(t * 1.2 + index) * 0.12;
}
if (packetRef.current) {
if (reduced) {
packetRef.current.visible = false;
return;
}
packetRef.current.visible = true;
const speed = 0.28;
const u = (t * speed + index * 0.33) % 1;
packetRef.current.position.lerpVectors(start, end, u);
const mat = packetRef.current.material as THREE.MeshBasicMaterial;
mat.opacity = Math.sin(u * Math.PI);
}
});
return (
<group>
<lineSegments geometry={geo}>
<lineBasicMaterial ref={lineMatRef} color={RED_BRIGHT} transparent opacity={0.25} depthWrite={false} />
</lineSegments>
<mesh ref={packetRef}>
<sphereGeometry args={[0.09, 12, 12]} />
<meshBasicMaterial color="#ffffff" transparent opacity={0.9} depthWrite={false} />
</mesh>
</group>
);
}
function SlowSpin({ reduced, children }: { reduced: boolean; children: React.ReactNode }) {
const group = useRef<THREE.Group>(null);
useFrame((_state, dt) => {
if (reduced || !group.current) return;
group.current.rotation.y += dt * 0.035;
});
return <group ref={group}>{children}</group>;
}
export default function MileTruthCanvas({
reduced = false,
isMobile = false,
active = true,
}: {
reduced?: boolean;
isMobile?: boolean;
active?: boolean;
}) {
return (
<Canvas
flat
frameloop={active ? "always" : "never"}
dpr={[1, isMobile || reduced ? 1.2 : 1.6]}
camera={{ position: [0, 1.4, 9.2], fov: 42, near: 0.1, far: 60 }}
gl={{ antialias: !isMobile, powerPreference: "high-performance", alpha: false }}
>
<color attach="background" args={["#0c0c10"]} />
<ambientLight intensity={0.35} />
<SlowSpin reduced={reduced}>
{LINKS.map(([a, b], i) => (
<Connector key={i} a={NODES[a]} b={NODES[b]} reduced={reduced} index={i} />
))}
{NODES.map((n, i) => (
<NodeMesh key={n.label} node={n} reduced={reduced} seed={i * 1.75} />
))}
</SlowSpin>
{!isMobile && (
<Sparkles count={70} scale={[11, 4.5, 6]} size={1.6} speed={reduced ? 0 : 0.15} color={RED_BRIGHT} opacity={0.3} />
)}
<EffectComposer enabled={!isMobile} multisampling={isMobile ? 0 : 2}>
<Bloom kernelSize={KernelSize.SMALL} luminanceThreshold={0.2} intensity={0.55} mipmapBlur />
</EffectComposer>
</Canvas>
);
}

View File

@@ -260,9 +260,6 @@ export default function MileTruthHero() {
}
}
@media (max-width: 1024px) {
.miletruth-hero .elementor-element-86f3204 {
padding: 0 10px !important;
}
.miletruth-hero-container {
min-height: 600px;
padding: 80px 0 !important;
@@ -290,6 +287,15 @@ export default function MileTruthHero() {
font-size: 16px !important;
}
}
/* Horizontal inset switches to 10px here (not at 1024px) to match the
breakpoint every other MileTruth section (Intro, Workflow1/2/4) uses
for the same 20px -> 10px step, so the Hero's left/right edges stay
aligned with the rest of the page through the whole 768-1024px range. */
@media (max-width: 767px) {
.miletruth-hero .elementor-element-86f3204 {
padding: 0 10px !important;
}
}
@media (max-width: 580px) {
.miletruth-hero-container {
min-height: 500px;
@@ -358,7 +364,7 @@ export default function MileTruthHero() {
</h1>
<div className="content-slider-item-text logico-content-wrapper-2">
<div className="text-content">
<p>Optimizes every stage of the delivery journey for maximum efficiency.</p>
<p>Optimizes every stage of the logistics journey for maximum efficiency.</p>
</div>
</div>
</div>

View File

@@ -0,0 +1,413 @@
"use client";
import { useEffect, useRef } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
if (typeof window !== "undefined") {
gsap.registerPlugin(ScrollTrigger);
}
/* A small route graph: three loose columns of candidate nodes converging on
* one destination. Coordinates are hand-placed (not a strict grid) so the
* mesh reads as organic route options rather than a wiring diagram. */
const NODES = [
{ x: 40, y: 50 },
{ x: 40, y: 130 },
{ x: 40, y: 210 },
{ x: 150, y: 30 },
{ x: 150, y: 95 },
{ x: 150, y: 160 },
{ x: 150, y: 225 },
{ x: 270, y: 55 },
{ x: 270, y: 130 },
{ x: 270, y: 200 },
{ x: 400, y: 130 },
] as const;
const FINAL_NODE = 10;
const DIM_NODES = [0, 2, 3, 5, 6, 7, 9];
const ALL_EDGES: [number, number][] = [
[0, 3], [0, 4], [1, 4], [1, 5], [2, 5], [2, 6],
[3, 7], [4, 7], [4, 8], [5, 8], [5, 9], [6, 9],
[7, 10], [8, 10], [9, 10],
];
const SURVIVOR_EDGES: [number, number][] = [
[1, 4],
[4, 8],
[8, 10],
];
const edgeLength = (a: number, b: number) =>
Math.hypot(NODES[b].x - NODES[a].x, NODES[b].y - NODES[a].y);
/** Conceptual preview of Workflow1's route optimization: many candidate
* routes converge into the single plan MileTruth keeps. Plays once on
* scroll-in — grey mesh appears, a soft sweep suggests evaluation, unused
* routes fade, the surviving path draws in red, the destination pulses
* once — then stops. No loop, no labels, respects prefers-reduced-motion. */
function RouteConverge() {
const wrapRef = useRef<HTMLDivElement>(null);
const sweepRef = useRef<HTMLDivElement>(null);
const edgeRefs = useRef<(SVGLineElement | null)[]>([]);
const survivorEdgeRefs = useRef<(SVGLineElement | null)[]>([]);
const nodeRefs = useRef<(SVGCircleElement | null)[]>([]);
const haloRef = useRef<SVGCircleElement>(null);
const pulseRef = useRef<SVGCircleElement>(null);
useEffect(() => {
const wrap = wrapRef.current;
const sweep = sweepRef.current;
const halo = haloRef.current;
const pulse = pulseRef.current;
const edges = edgeRefs.current.filter(Boolean) as SVGLineElement[];
const survivorEdges = survivorEdgeRefs.current.filter(Boolean) as SVGLineElement[];
const nodes = nodeRefs.current.filter(Boolean) as SVGCircleElement[];
if (!wrap || !sweep || !halo || !pulse || edges.length === 0 || nodes.length === 0) return;
const dimNodes = DIM_NODES.map((i) => nodeRefs.current[i]).filter(Boolean) as SVGCircleElement[];
const survivorNodes = [1, 4, 8].map((i) => nodeRefs.current[i]).filter(Boolean) as SVGCircleElement[];
const finalNode = nodeRefs.current[FINAL_NODE] as SVGCircleElement;
gsap.set(edges, { opacity: 0 });
gsap.set(nodes, { opacity: 0, attr: { fill: "#fdfdfd", stroke: "rgba(17, 17, 17, 0.3)" } });
survivorEdges.forEach((el, i) => {
const [a, b] = SURVIVOR_EDGES[i];
const len = edgeLength(a, b);
gsap.set(el, { attr: { "stroke-dasharray": len, "stroke-dashoffset": len } });
});
gsap.set(halo, { opacity: 0 });
gsap.set(pulse, { opacity: 0, attr: { r: 5 } });
gsap.set(sweep, { opacity: 0, left: "-30%" });
const showFinalState = () => {
gsap.set(edges, { opacity: 0.08 });
gsap.set(dimNodes, { opacity: 0.3 });
gsap.set(nodes, { opacity: 1 });
gsap.set([...survivorNodes, finalNode], { attr: { fill: "#C01227", stroke: "#C01227" } });
survivorEdges.forEach((el) => gsap.set(el, { attr: { "stroke-dashoffset": 0 } }));
gsap.set(halo, { opacity: 0.22 });
};
if (typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) {
showFinalState();
return;
}
let tl: gsap.core.Timeline | undefined;
const play = () => {
tl = gsap.timeline();
tl.to(edges, { opacity: 1, duration: 0.5, ease: "power1.out" }, 0)
.to(nodes, { opacity: 1, duration: 0.5, ease: "power1.out" }, 0.05)
.set(sweep, { opacity: 0.9 }, 0.55)
.to(sweep, { left: "104%", duration: 1, ease: "power1.inOut" }, 0.55)
.to(sweep, { opacity: 0, duration: 0.3 }, 1.35)
.to(dimNodes, { opacity: 0.28, duration: 0.6, ease: "power1.out" }, 1.3)
.to(edges, { opacity: 0.08, duration: 0.6, ease: "power1.out" }, 1.3)
.to(survivorNodes, { attr: { fill: "#C01227", stroke: "#C01227" }, duration: 0.35, ease: "power1.out" }, 1.5)
.to(survivorEdges[0], { attr: { "stroke-dashoffset": 0 }, duration: 0.4, ease: "power2.inOut" }, 1.55)
.to(survivorEdges[1], { attr: { "stroke-dashoffset": 0 }, duration: 0.4, ease: "power2.inOut" }, 1.85)
.to(survivorEdges[2], { attr: { "stroke-dashoffset": 0 }, duration: 0.4, ease: "power2.inOut" }, 2.15)
.to(finalNode, { attr: { fill: "#C01227", stroke: "#C01227" }, duration: 0.3, ease: "power1.out" }, 2.5)
.to(halo, { opacity: 0.22, duration: 0.4, ease: "power1.out" }, 2.55)
.fromTo(
pulse,
{ opacity: 0.7, attr: { r: 5 } },
{ opacity: 0, attr: { r: 22 }, duration: 0.7, ease: "power2.out" },
2.55,
);
};
const st = ScrollTrigger.create({
trigger: wrap,
start: "top 82%",
once: true,
onEnter: play,
});
const raf = requestAnimationFrame(() => {
const r = wrap.getBoundingClientRect();
const vh = window.innerHeight || document.documentElement.clientHeight;
if (r.top < vh && r.bottom > 0) {
play();
st.kill();
}
});
return () => {
cancelAnimationFrame(raf);
st.kill();
tl?.kill();
};
}, []);
return (
<div className="mti__viz" ref={wrapRef} aria-hidden="true">
<div className="mti__viz-frame">
<div className="mti__viz-sweep" ref={sweepRef} />
<svg className="mti__viz-svg" viewBox="0 0 440 260" preserveAspectRatio="xMidYMid meet">
<g>
{ALL_EDGES.map(([a, b], i) => (
<line
key={i}
ref={(el) => {
edgeRefs.current[i] = el;
}}
x1={NODES[a].x}
y1={NODES[a].y}
x2={NODES[b].x}
y2={NODES[b].y}
className="mti__viz-edge"
/>
))}
</g>
<g>
{SURVIVOR_EDGES.map(([a, b], i) => (
<line
key={i}
ref={(el) => {
survivorEdgeRefs.current[i] = el;
}}
x1={NODES[a].x}
y1={NODES[a].y}
x2={NODES[b].x}
y2={NODES[b].y}
className="mti__viz-edge-active"
/>
))}
</g>
<circle ref={haloRef} cx={NODES[FINAL_NODE].x} cy={NODES[FINAL_NODE].y} r={11} className="mti__viz-halo" />
<g>
{NODES.map((n, i) => (
<circle
key={i}
ref={(el) => {
nodeRefs.current[i] = el;
}}
cx={n.x}
cy={n.y}
r={i === FINAL_NODE ? 4.5 : 3.2}
className={i === FINAL_NODE ? "mti__viz-node mti__viz-node--final" : "mti__viz-node"}
/>
))}
</g>
<circle ref={pulseRef} cx={NODES[FINAL_NODE].x} cy={NODES[FINAL_NODE].y} r={5} className="mti__viz-pulse" />
</svg>
</div>
</div>
);
}
/** Short editorial bridge between the MileTruth hero/metrics and Workflow1 —
* a quick read, not a second hero. No motion, no media, no CTA.
*
* Spacing mirrors the workflow shells (EVSection): a 20px outer inset
* (width calc(100% - 40px) / margin 0 20px) and a 1280px inner with 48px
* horizontal padding, so the heading/body left-align with the workflow
* cards above and below instead of using an unrelated flat gutter. The
* shell also carries the same external top margin as EVSection's
* `.evnd-gap-top` (40 / 32 / 24 desktop-tablet-mobile) so the gap above
* this section matches the gap above every workflow section below it —
* otherwise the Hero sits flush against this section while every other
* section boundary on the page carries that gap.
*
* The right side carries a minimal "many routes -> one route" visualization
* (see RouteConverge above) instead of sitting empty — it never touches the
* heading/copy, spacing, or section height on the left. */
export default function MileTruthIntro() {
return (
<>
<style
dangerouslySetInnerHTML={{
__html: `
.mti-shell {
width: calc(100% - 40px);
margin: 40px 20px 0;
}
.mti {
background: #fafafa;
padding: clamp(28px, 3.5vw, 40px) 0;
}
.mti__inner {
max-width: 1280px;
margin: 0 auto;
padding: 0 48px;
}
.mti__row {
display: flex;
align-items: center;
gap: clamp(32px, 5vw, 64px);
}
.mti__left {
flex: 1;
min-width: 0;
}
.mti__eyebrow {
display: inline-flex;
align-items: center;
gap: 12px;
color: #C01227 !important;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 0.16em;
font-size: 13px;
margin-bottom: clamp(14px, 1.8vw, 18px);
}
.mti__eyebrow::before {
content: '';
width: 16px;
height: 2px;
background: #C01227;
}
.mti__divider {
border: 0;
height: 1px;
background: rgba(17, 17, 17, 0.12);
margin: 0 0 clamp(20px, 2.4vw, 28px);
}
.mti__heading {
margin: 0 0 clamp(18px, 2vw, 24px);
color: #111111 !important;
font-weight: 800 !important;
font-size: clamp(28px, 3.4vw, 46px) !important;
line-height: 1.15 !important;
letter-spacing: -0.02em;
text-transform: uppercase;
}
.mti__accent {
color: #C01227 !important;
}
.mti__copy {
max-width: 680px;
}
.mti__copy p {
margin: 0 0 14px;
color: rgba(17, 17, 17, 0.68) !important;
font-size: clamp(15px, 1.05vw, 17px) !important;
font-weight: 500 !important;
line-height: 1.6 !important;
}
.mti__copy p:last-child {
margin-bottom: 0;
}
.mti__lede {
margin-left: clamp(16px, 2vw, 24px);
}
.mti__viz {
flex: 0 1 38%;
min-width: 240px;
max-width: 460px;
display: flex;
align-items: center;
justify-content: center;
}
.mti__viz-frame {
position: relative;
width: 100%;
}
.mti__viz-svg {
display: block;
width: 100%;
height: auto;
overflow: visible;
}
.mti__viz-edge {
stroke: rgba(17, 17, 17, 0.16);
stroke-width: 1;
}
.mti__viz-edge-active {
fill: none;
stroke: #C01227;
stroke-width: 1.4;
}
.mti__viz-node {
fill: #fdfdfd;
stroke: rgba(17, 17, 17, 0.3);
stroke-width: 1.1;
}
.mti__viz-node--final {
stroke-width: 1.3;
}
.mti__viz-halo {
fill: #C01227;
opacity: 0;
filter: blur(6px);
}
.mti__viz-pulse {
fill: none;
stroke: #C01227;
stroke-width: 1.4;
opacity: 0;
}
.mti__viz-sweep {
position: absolute;
top: 0;
bottom: 0;
width: 24%;
background: linear-gradient(90deg, transparent, rgba(192, 18, 39, 0.14), transparent);
opacity: 0;
pointer-events: none;
}
@media (max-width: 1024px) {
.mti-shell { margin-top: 32px; }
.mti__inner { padding: 0 32px; }
}
@media (max-width: 900px) {
.mti__row {
flex-direction: column;
align-items: center;
gap: clamp(28px, 5vw, 40px);
}
.mti__left {
width: 100%;
}
.mti__viz {
flex: none;
width: 100%;
max-width: 360px;
}
}
@media (max-width: 767px) {
.mti-shell {
width: calc(100% - 20px);
margin: 24px 10px 0;
}
.mti__inner { padding: 0 20px; }
}
`,
}}
/>
<div className="mti-shell">
<section className="mti" aria-label="MileTruth AI introduction">
<div className="mti__inner">
<div className="mti__row">
<div className="mti__left">
<span className="mti__eyebrow">/ MILETRUTH AI /</span>
<hr className="mti__divider" />
<h2 className="mti__heading">
ROUTING IS A <span className="mti__accent">DECISION PROBLEM.</span>
</h2>
<div className="mti__copy">
<p className="mti__lede">Routing is not one path between two points.</p>
<p>
Orders change. Vehicles have different limits. Capacity, range
and time change what is possible.
</p>
<p>
MileTruth evaluates the options, checks what can actually work,
and moves the strongest plan forward.
</p>
</div>
</div>
<RouteConverge />
</div>
</div>
</section>
</div>
</>
);
}

View File

@@ -0,0 +1,69 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
import dynamic from "next/dynamic";
/* ============================================================
MileTruthNetwork — gated mount for MileTruthCanvas (the lightweight
R3F data -> AI -> recommendations -> improvement scene). Mirrors
WorkflowScene.tsx: code-split, mounts a little before it scrolls
into view, pauses the render loop off-screen, and respects
prefers-reduced-motion.
============================================================ */
const MileTruthCanvas = dynamic(() => import("./MileTruthCanvas"), { ssr: false });
export default function MileTruthNetwork({ ariaLabel }: { ariaLabel?: string }) {
const wrapRef = useRef<HTMLDivElement>(null);
const [mountScene, setMountScene] = useState(false);
const [active, setActive] = useState(false);
const [isMobile, setIsMobile] = useState(false);
const [reduced, setReduced] = useState(false);
useEffect(() => {
const mqMobile = window.matchMedia("(max-width: 767px)");
const mqReduce = window.matchMedia("(prefers-reduced-motion: reduce)");
const sync = () => {
setIsMobile(mqMobile.matches);
setReduced(mqReduce.matches);
};
sync();
mqMobile.addEventListener("change", sync);
mqReduce.addEventListener("change", sync);
return () => {
mqMobile.removeEventListener("change", sync);
mqReduce.removeEventListener("change", sync);
};
}, []);
// Single observer: mount the scene a little before it scrolls into view and
// keep it active from then on (this scene is small/light enough that a
// second "pause when off-screen" observer isn't worth the added race risk
// between two independent IntersectionObservers on the same element).
useEffect(() => {
const el = wrapRef.current;
if (!el) return;
const mountIo = new IntersectionObserver(
(entries) => {
if (entries.some((e) => e.isIntersecting)) {
setMountScene(true);
setActive(true);
mountIo.disconnect();
}
},
{ rootMargin: "50% 0px" },
);
mountIo.observe(el);
return () => mountIo.disconnect();
}, []);
return (
<div ref={wrapRef} className="mtn-scene" role="img" aria-label={ariaLabel ?? "MileTruth AI network"}>
<style dangerouslySetInnerHTML={{ __html: `
.mtn-scene { position: relative; width: 100%; height: 100%; min-height: 320px; }
.mtn-scene canvas { display: block; width: 100% !important; height: 100% !important; }
`}} />
{mountScene && <MileTruthCanvas reduced={reduced} isMobile={isMobile} active={active} />}
</div>
);
}

View File

@@ -195,7 +195,7 @@ export default function Miles3() {
</div>
<div className="elementor-element elementor-element-63a9de5 elementor-widget elementor-widget-logico_heading" data-id="63a9de5" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
<div className="elementor-widget-container">
<h3 className="logico-title">Doormile connects first, mid, and last mile into a seamless delivery experience</h3>
<h3 className="logico-title">Doormile connects first, mid, and last mile into a seamless end-to-end logistics experience</h3>
</div>
</div>
</div>
@@ -243,7 +243,7 @@ export default function Miles3() {
</div>
<div className="elementor-element elementor-element-3ae1ce0 elementor-widget elementor-widget-text-editor" data-id="3ae1ce0" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
<div className="elementor-widget-container">
<p>Smooth inter-city delivery through strategically located hubs with live tracking.</p>
<p>Smooth inter-city logistics through strategically located hubs with live tracking.</p>
</div>
</div>
</div>
@@ -266,7 +266,7 @@ export default function Miles3() {
</div>
<div className="elementor-element elementor-element-1057c22 elementor-widget elementor-widget-text-editor" data-id="1057c22" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
<div className="elementor-widget-container">
<p>Packages are delivered to customers with real-time updates and proof of delivery.</p>
<p>Packages reach customers with real-time updates and proof of delivery.</p>
</div>
</div>
</div>

View File

@@ -0,0 +1,164 @@
"use client";
import React, { useEffect, useRef } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import WorkflowScene from "./WorkflowScene";
if (typeof window !== "undefined") {
gsap.registerPlugin(ScrollTrigger);
}
/* ============================================================
QuantumStage — the page's ONE true 3D moment. Wraps the existing
production "Logistics Brain" scene (glowing core, orbiting particle
shells, six parallel route strategies racing, live network) —
already built and already on-brand red — inside a near-full-viewport
frame, with a floating Traditional-vs-Quantum comparison overlaid.
GSAP drives only the entrance (fade/rise); the 3D scene animates
itself.
============================================================ */
export default function QuantumStage() {
const rootRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const root = rootRef.current;
if (!root) return;
const frame = root.querySelector(".qs-frame");
const tradCol = root.querySelector(".qs-col--trad");
const qSteps = Array.from(root.querySelectorAll(".qs-qstep"));
const qDot = root.querySelector(".qs-qdot");
if (!frame || !tradCol || qSteps.length === 0) return;
if (window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) {
gsap.set([frame, tradCol, ...qSteps], { opacity: 1, y: 0, scale: 1 });
return;
}
gsap.set(frame, { opacity: 0, y: 26 });
gsap.set(tradCol, { opacity: 0, y: 26 });
gsap.set(qSteps, { opacity: 0.25, y: 10 });
gsap.set(qDot, { scale: 0.6, opacity: 0 });
const play = () => {
const tl = gsap.timeline();
// Frame + traditional baseline settle in first (the "boring" case).
tl.to(frame, { opacity: 1, y: 0, duration: 0.9, ease: "power3.out" }, 0)
.to(tradCol, { opacity: 1, y: 0, duration: 0.7, ease: "power3.out" }, 0.15);
// Quantum steps light up one at a time — a process unfolding, not a fade group.
qSteps.forEach((el, i) => {
tl.to(el, { opacity: 1, y: 0, scale: 1.04, duration: 0.32, ease: "power2.out" }, 0.7 + i * 0.42)
.to(el, { scale: 1, duration: 0.22, ease: "power1.out" }, 0.7 + i * 0.42 + 0.32);
});
// Dispatch pulses brighter — the decisive moment.
const last = qSteps[qSteps.length - 1];
tl.to(qDot, { opacity: 1, scale: 1, duration: 0.4, ease: "back.out(2)" }, 0.7 + qSteps.length * 0.42)
.to(last, { color: "#ff5a6e", duration: 0.3 }, "<");
};
const st = ScrollTrigger.create({ trigger: root, start: "top 78%", once: true, onEnter: play });
return () => st.kill();
}, []);
return (
<div ref={rootRef} className="qs">
<style dangerouslySetInnerHTML={{ __html: CSS }} />
<div className="qs-frame">
<WorkflowScene variant="logistics" ariaLabel="Quantum decision engine — parallel route simulation" />
</div>
<div className="qs-compare">
<div className="qs-col qs-col--trad">
<span className="qs-col-tag">Traditional</span>
<div className="qs-col-steps">
<span>One Route</span>
<span className="qs-col-arrow"></span>
<span>Dispatch</span>
</div>
</div>
<div className="qs-col qs-col--q">
<span className="qs-col-tag qs-col-tag--accent">Quantum</span>
<div className="qs-col-steps qs-col-steps--accent">
<span className="qs-qstep">100+ Route Simulations</span>
<span className="qs-col-arrow"></span>
<span className="qs-qstep">AI Comparison</span>
<span className="qs-col-arrow"></span>
<span className="qs-qstep">Best Route</span>
<span className="qs-col-arrow"></span>
<span className="qs-qstep qs-col-final">
Dispatch<span className="qs-qdot" aria-hidden="true" />
</span>
</div>
</div>
</div>
</div>
);
}
const CSS = `
.qs { position: relative; }
/* --------------------------------------------------------------
Section 05 runs light — every other section on this page keeps
the shared dark "ground texture" system, but this one uses the
shared white .sw-bg--white variant (set via the Section's bg
prop in SolutionsWorkflow.tsx) so the workflow reads as a
dashboard panel, not a visualization sitting in a black canvas —
while still going through the exact same inset/rounded .sw-bg
card surface as every other section. Only the text colors need
a local override here, for readability on that white surface.
-------------------------------------------------------------- */
#quantum .sw-h { color: #14151a !important; }
#quantum .sw-lede { color: #5a5b64 !important; }
.qs-frame {
position: relative;
width: 100%;
aspect-ratio: auto;
min-height: min(84vh, 900px);
border-radius: 28px;
overflow: hidden;
background: #f6f6f7;
border: 1px solid rgba(20,21,26,0.08);
box-shadow: 0 30px 70px -45px rgba(20,21,26,0.25);
}
.qs-frame .wf-scene {
position: absolute;
inset: clamp(16px, 3vw, 32px);
width: auto;
height: auto;
aspect-ratio: auto;
border-radius: 16px;
}
.qs-compare {
position: relative;
margin-top: clamp(28px, 4vw, 48px);
display: grid;
grid-template-columns: 1fr 1.4fr;
gap: clamp(20px, 3vw, 40px);
}
.qs-col {
padding: clamp(20px, 2.4vw, 30px) clamp(22px, 2.6vw, 34px);
border-radius: 22px;
background: #f6f6f7;
border: 1px solid rgba(20,21,26,0.08);
box-shadow: 0 20px 44px -34px rgba(20,21,26,0.2);
display: flex; flex-direction: column; align-items: center; gap: 18px; text-align: center;
}
.qs-col--q { background: linear-gradient(180deg, rgba(192,18,39,0.06), rgba(246,246,247,0.4)); border-color: rgba(192,18,39,0.22); }
.qs-col-tag { font-size: 12px; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; color: #8a8b93; }
.qs-col-tag--accent { color: #C01227; }
.qs-col-steps { display: flex; flex-direction: column; align-items: center; gap: 8px; color: #4a4b53; font-weight: 700; font-size: 14px; }
.qs-col-steps--accent { color: #14151a; font-size: 15px; flex-direction: row; flex-wrap: wrap; justify-content: center; }
.qs-qstep { display: inline-flex; align-items: center; position: relative; }
.qs-col-arrow { color: rgba(20,21,26,0.28); font-size: 13px; }
.qs-col-final { color: #C01227; display: inline-flex; align-items: center; gap: 8px; }
.qs-qdot { width: 8px; height: 8px; border-radius: 50%; background: #E2354A; box-shadow: 0 0 12px 3px rgba(226,53,74,0.55); }
@media (max-width: 860px) {
.qs-compare { grid-template-columns: 1fr; }
.qs-col-steps--accent { flex-direction: column; }
}
@media (max-width: 767px) {
.qs-frame { min-height: 62vh; border-radius: 20px; }
.qs-frame .wf-scene { border-radius: 14px; }
}
`;

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,7 @@ export default function StatsBar() {
<div className="elementor-widget-container">
<div className="logico-title">
<CountUp end={99.2} decimals={1} suffix="%" duration={2.2} /> <br />
<span style={{ fontSize: "20px" }}>On-Time Delivery</span>
<span style={{ fontSize: "20px" }}>On-Time Performance</span>
</div>
</div>
</div>

View File

@@ -59,10 +59,10 @@ export default function TheDoormileWay() {
<p>
<strong>
We connect first mile and last mile into one seamless system, reducing delays and improving efficiency. With real-time tracking and digital workflows,
<br /> every delivery is faster, reliable, and fully transparent.
<br /> every shipment is faster, reliable, and fully transparent.
</strong>
</p>
<p>Seamless logistics powered by real-time tracking, digital processes, and reliable delivery execution.</p>
<p>Seamless logistics powered by real-time tracking, digital processes, and reliable logistics execution.</p>
</div>
</div>
</div>
@@ -118,7 +118,7 @@ export default function TheDoormileWay() {
</div>
<div className="elementor-element elementor-element-74d14e3 elementor-widget elementor-widget-text-editor" data-id="74d14e3" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
<div className="elementor-widget-container">
<p>Real-time monitoring helps prevent delays before they impact deliveries.</p>
<p>Real-time monitoring helps prevent delays before they impact operations.</p>
</div>
</div>
</div>
@@ -141,7 +141,7 @@ export default function TheDoormileWay() {
</div>
<div className="elementor-element elementor-element-74cfdf7 elementor-widget elementor-widget-text-editor" data-id="74cfdf7" data-element_type="widget" data-e-type="widget" data-widget_type="text-editor.default">
<div className="elementor-widget-container">
<p>One unified system manages the entire delivery process seamlessly.</p>
<p>One unified system manages the entire logistics process seamlessly.</p>
</div>
</div>
</div>

View File

@@ -45,12 +45,12 @@ const STAGES: Stage[] = [
{
img: "/images/last-mile-approach.webp",
label: "Stage 03",
title: "Last Mile Delivery",
title: "Last Mile Logistics",
subtitle: "Hub to Doorstep",
desc: "The final handoff. Our routing engine optimizes multi-stop itineraries to deliver parcels directly to customers' doorsteps in record time.",
points: ["Multi-stop route optimisation", "Precise delivery windows", "Digital proof of delivery"],
desc: "The final handoff. Our routing engine optimizes multi-stop itineraries to move parcels directly to customers' doorsteps in record time.",
points: ["Multi-stop route optimisation", "Precise arrival windows", "Digital proof of delivery"],
stats: [
{ value: "450K+", label: "Happy Deliveries" },
{ value: "450K+", label: "Shipments Delivered" },
{ value: "2.8 Hours", label: "Average Turnaround" }
]
},

View File

@@ -465,7 +465,7 @@ export default function WingsHero() {
<p>
Linking India&apos;s major regional capitals with
AI-powered air movement and zero-emission EV
last-mile delivery.
last-mile transport.
</p>
</div>
</div>

View File

@@ -48,7 +48,7 @@ const STEPS = [
},
{
label: "EV Last-Mile",
desc: "Zero-emission electric vehicles complete the final delivery.",
desc: "Zero-emission electric vehicles complete the final mile.",
icon: (
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.25" strokeLinecap="round" strokeLinejoin="round">
<path d="M3 13h13l3 4h2v3H3z" />
@@ -72,7 +72,7 @@ export default function WingsHowItWorks() {
<h2 className={styles.title}>
Pickup to
<br />
delivery, one
arrival, one
<br />
connected flow
</h2>

View File

@@ -3,7 +3,7 @@ import { ScrollReveal } from "@/animations/Reveal";
const INDUSTRIES = [
{
title: "Quick Commerce",
challenge: "Sub-3-hour delivery windows for dark stores and micro-warehouses.",
challenge: "Sub-3-hour arrival windows for dark stores and micro-warehouses.",
solution: "Dedicated same-day air capacity linking metros to fulfillment hubs.",
image: "/images/card 1.png",
},
@@ -34,7 +34,7 @@ const INDUSTRIES = [
{
title: "E-Commerce Logistics",
challenge: "Next-day and same-day fulfillment expectations across tier-1 and tier-2 cities.",
solution: "Direct sorting-hub-to-airport clearance network for faster regional delivery.",
solution: "Direct sorting-hub-to-airport clearance network for faster regional logistics.",
image: "/images/card6.png",
},
];

View File

@@ -475,7 +475,7 @@ export default function WingsMileTruth() {
<div className="wmt-inner dm-section-container">
<ScrollReveal delay={0.05} duration={0.75} yOffset={25} className="wmt-header">
<div className="wmt-eyebrow">/ MileTruth&trade; AI /</div>
<h2 className="wmt-title">The intelligence layer behind every delivery</h2>
<h2 className="wmt-title">The intelligence layer behind every shipment</h2>
</ScrollReveal>
<StaggerChildren stagger={0.08} duration={0.65} yOffset={25} className="wmt-grid">

View File

@@ -204,7 +204,7 @@ export default function WingsSpeedAdvantage() {
Max <CountUp end={3} duration={1.4} triggerOnce />
</div>
<div className="wsa-unit">Hours, Door-to-Door</div>
<p className="wsa-panel-sub">Same-day delivery between major regional capitals.</p>
<p className="wsa-panel-sub">Same-day logistics between major regional capitals.</p>
</div>
</div>
</div>

View File

@@ -37,7 +37,7 @@ const MAX_WAVE_AMP_FACTOR = 1 + 0.28 + 0.15;
const FEATURES = [
{
title: "Same-Day Air Logistics",
desc: "Max 3-hour door-to-door delivery between India's major regional capitals.",
desc: "Max 3-hour door-to-door transit between India's major regional capitals.",
icon: (
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.25" strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="12" r="10" />
@@ -70,7 +70,7 @@ const FEATURES = [
},
{
title: "EV Last Mile",
desc: "Zero-emission electric vehicles complete every first- and final-mile delivery.",
desc: "Zero-emission electric vehicles complete every first- and final-mile leg.",
icon: (
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.25" strokeLinecap="round" strokeLinejoin="round">
<path d="M3 13h13l3 4h2v3H3z" />

View File

@@ -6,7 +6,7 @@ import IndustryWorldMap from "./IndustryWorldMap";
const WS_STATS = [
{ value: "500", plus: "+", label: "Women Partners" },
{ value: "35", plus: "+", label: "Cities" },
{ value: "10K", plus: "+", label: "Deliveries" },
{ value: "10K", plus: "+", label: "Shipments" },
];
const WS_CARDS = [

View File

@@ -54,7 +54,7 @@ const FEATURES: EVFeature[] = [
</>,
),
title: "Distance Reduction",
desc: "Same volume delivered with a leaner, better-used fleet.",
desc: "Same volume moved with a leaner, better-used fleet.",
},
{
icon: ico(
@@ -74,7 +74,7 @@ const FEATURES: EVFeature[] = [
</>,
),
title: "SLA Performance",
desc: "Real-time correction keeps deliveries on time.",
desc: "Real-time correction keeps shipments on time.",
},
];

View File

@@ -91,12 +91,12 @@ export default function Workflow2() {
gapBottom
bannerImage="/images/mid-mile-approach.webp"
cardTitle="CHOOSE THE BEST PLAN"
cardSubtitle="Analyze thousands of route possibilities and automatically select the most efficient delivery strategy."
cardSubtitle="Analyze thousands of route possibilities and automatically select the most efficient routing strategy."
eyebrow="/ Innovation /"
titleLead="MANY STRATEGIES. "
titleAccent="ONE BEST PLAN."
image="/videos/workflow-2-routing.mp4"
imageAlt="AI route-planning engine selecting the best delivery plan"
imageAlt="AI route-planning engine selecting the best route plan"
metrics={METRICS}
features={FEATURES}
cardsHeading="AI Decision Engine"

View File

@@ -18,7 +18,7 @@ export default function Workflow3() {
return (
<section
className="dm-wf3"
aria-label="Workflow 3 — Happier Riders. Higher Fulfillment."
aria-label="Workflow 3 — Happier Fleet Drivers. Higher Fulfillment."
>
<StrategySection />

View File

@@ -32,7 +32,7 @@ const METRICS: EVStat[] = [
/* Distinct copy for the bottom capability bar (not a repeat of the KPI row —
* Workflow 4's brief specifies separate content for each). */
const BAR_STATS: EVStat[] = [
{ text: "Multi-Rider", value: 0, suffix: "", label: "Dynamic Routing" },
{ text: "Multi-Driver", value: 0, suffix: "", label: "Dynamic Routing" },
{ text: "Optimized", value: 0, suffix: "", label: "Time Windows" },
{ text: "Real-Time", value: 0, suffix: "", label: "Fleet Balancing" },
{ text: "Cost + Distance + SLA", value: 0, suffix: "", label: "Objectives" },
@@ -62,7 +62,7 @@ const FEATURES: EVFeature[] = [
</>,
),
title: "Encode the Problem",
desc: "Rider assignments, delivery sequences, capacity, traffic, service time, and SLA constraints become part of one mathematical optimization model.",
desc: "Fleet driver assignments, stop sequences, capacity, traffic, service time, and SLA constraints become part of one mathematical optimization model.",
},
{
icon: ico(<path d="m8 3 4 8 5-5 5 15H2L8 3z" />),
@@ -105,7 +105,7 @@ export default function Workflow4() {
gapBottom
bannerImage="/images/workflow4.png"
image="/videos/Doormile-quantum-video3.mp4"
cardTitle="BUILDING QUANTUM INTELLIGENCE"
cardTitle="QUANTUM INTELLIGENCE"
cardSubtitle="Exploring a hybrid optimization layer that treats routing as an energy landscape, not a search problem."
eyebrow="/ Quantum Intelligence /"
titleLead="FROM ROUTE SEARCH. "

View File

@@ -341,7 +341,7 @@ function RiderAvatar({ rider, register, awake, focused }: { rider: typeof RIDERS
<Html center distanceFactor={9} position={[0, 1.5, 0]} zIndexRange={[20, 0]} pointerEvents="none">
<div className="dm-st3d-chip" ref={register}>
<span className="dm-st3d-chip__ico">{rider.icon}</span>
<span className="dm-st3d-chip__txt"><b>Rider {rider.id}</b>{rider.veh}</span>
<span className="dm-st3d-chip__txt"><b>Driver {rider.id}</b>{rider.veh}</span>
</div>
</Html>
)}
@@ -497,7 +497,7 @@ const VALIDATIONS = [
];
// Node labels along the delivery route (Dispatch Hub → Route Nodes → Delivery).
const DEST_LABELS: (string | null)[] = ["Route Node A", null, "Route Node B", null, "Route Node C", "📦 Delivery"];
const DEST_LABELS: (string | null)[] = ["Route Node A", null, "Route Node B", null, "Route Node C", "📦 Destination"];
/** Expanding ring at the delivery node — fires only once the truck arrives (local t > 0.85). */
function DeliveryPulse({ pos, i, progress }: { pos: [number, number, number]; i: number; progress: React.RefObject<number> }) {

View File

@@ -183,7 +183,7 @@ export default function StrategySection({ connected = false }: { connected?: boo
<section
ref={containerRef}
className={`dm-st is-${pinState}${connected ? " is-connected" : ""}`}
aria-label="Strategy — Happier Riders. Higher Fulfillment."
aria-label="Strategy — Happier Fleet Drivers. Higher Fulfillment."
>
<div className="dm-st-sticky">
<div className="dm-st-card">
@@ -235,11 +235,11 @@ export default function StrategySection({ connected = false }: { connected?: boo
{/* STAGE 01 — INPUT (green) */}
<StageCard i={0} scroll={scroll} side="left" active={active}>
<h3 className="dm-st-pillar__title">Orders &amp; riders enter the system</h3>
<h3 className="dm-st-pillar__title">Orders &amp; fleet drivers enter the system</h3>
<p className="dm-st-anchor__lead">Orders are uploaded and matched against the available fleet, ready for assignment.</p>
<div className="dm-st-anchor__chips">
<span className="dm-st-anchor__chip">59 Orders</span>
<span className="dm-st-anchor__chip">4 Riders</span>
<span className="dm-st-anchor__chip">4 Drivers</span>
<span className="dm-st-anchor__chip">Fleet ready</span>
</div>
</StageCard>
@@ -258,7 +258,7 @@ export default function StrategySection({ connected = false }: { connected?: boo
{/* STAGE 03 — SMART OPTIMIZATION (blue) */}
<StageCard i={2} scroll={scroll} side="left" active={active}>
<h3 className="dm-st-pillar__title">Routes optimized &amp; validated</h3>
<p className="dm-st-anchor__lead">Every route is solved for distance, then checked against battery range and delivery SLAs.</p>
<p className="dm-st-anchor__lead">Every route is solved for distance, then checked against battery range and service SLAs.</p>
<div className="dm-st-anchor__chips">
<span className="dm-st-anchor__chip">Optimize</span>
<span className="dm-st-anchor__chip">Battery</span>
@@ -279,8 +279,8 @@ export default function StrategySection({ connected = false }: { connected?: boo
{/* STAGE 05 — STRATEGY COMPARISON (red, hero) */}
<StageCard i={4} scroll={scroll} side="right" active={active}>
<h3 className="dm-st-pillar__title">Happier riders. Higher fulfillment.</h3>
<p className="dm-st-anchor__lead">EV Aware wins the best fulfillment with feasible, battery-safe routes for every rider.</p>
<h3 className="dm-st-pillar__title">Happier fleet drivers. Higher fulfillment.</h3>
<p className="dm-st-anchor__lead">EV Aware wins the best fulfillment with feasible, battery-safe routes for every fleet driver.</p>
<div className="dm-st-anchor__chips">
<span className="dm-st-anchor__chip dm-st-anchor__chip--win">🏆 EV Aware</span>
<span className="dm-st-anchor__chip">88% Score</span>

View File

@@ -43,7 +43,7 @@ function templateContent(post: {
return [
{
type: "paragraph",
text: `In last-mile logistics, a missed SLA is rarely caused by one big failure. It usually comes from small delays adding up across a route. ${post.title} looks at how delivery teams can spot those delays early and plan around them before vehicles leave the hub.`,
text: `In last-mile logistics, a missed SLA is rarely caused by one big failure. It usually comes from small delays adding up across a route. ${post.title} looks at how logistics teams can spot those delays early and plan around them before vehicles leave the hub.`,
},
{
type: "heading",
@@ -52,14 +52,14 @@ function templateContent(post: {
},
{
type: "paragraph",
text: "Every extra kilometre costs money. It uses fuel or charge, adds rider time, wears down vehicles, and increases the chance of a late delivery. When routes are built from fixed zones or old habits, those costs repeat every day.",
text: "Every extra kilometre costs money. It uses fuel or charge, adds driver time, wears down vehicles, and increases the chance of a late shipment. When routes are built from fixed zones or old habits, those costs repeat every day.",
},
{
type: "list",
items: [
"Fewer vehicles needed for the same number of drops",
"Lower cost per drop through better stop sequencing",
"ETAs that match traffic, distance, and delivery windows",
"ETAs that match traffic, distance, and arrival windows",
"Less fuel or charge used per completed order",
],
},
@@ -70,7 +70,7 @@ function templateContent(post: {
},
{
type: "paragraph",
text: `A good dispatch plan starts with the basics: order locations, promised delivery windows, rider capacity, vehicle range, and known traffic trouble spots. MileTruth™ checks those inputs before dispatch so the team is not fixing avoidable mistakes on the road.`,
text: `A good dispatch plan starts with the basics: order locations, promised arrival windows, driver capacity, vehicle range, and known traffic trouble spots. MileTruth™ checks those inputs before dispatch so the team is not fixing avoidable mistakes on the road.`,
},
{
type: "image",
@@ -80,7 +80,7 @@ function templateContent(post: {
},
{
type: "quote",
text: "A route should be checked before the rider leaves, not explained after the customer calls.",
text: "A route should be checked before the driver leaves, not explained after the customer calls.",
cite: "Doormile Operations",
},
{
@@ -90,21 +90,21 @@ function templateContent(post: {
},
{
type: "paragraph",
text: "The best improvements usually start with simple measurements. Track distance per route, failed delivery windows, rider idle time, and orders moved between vehicles after dispatch. Those numbers show where the operation is leaking time.",
text: "The best improvements usually start with simple measurements. Track distance per route, failed arrival windows, driver idle time, and orders moved between vehicles after dispatch. Those numbers show where the operation is leaking time.",
},
{
type: "list",
ordered: true,
items: [
"Benchmark today's distance, fleet size, and on-time rate.",
"Include vehicle capacity, delivery windows, rider shifts, and battery charge.",
"Include vehicle capacity, arrival windows, driver shifts, and battery charge.",
"Check routes against traffic and customer commitments before dispatch.",
"Compare the next dispatch cycle against the old plan.",
],
},
{
type: "paragraph",
text: "Better routing is not about pushing riders harder. It is about giving them a plan that already accounts for the real day ahead.",
text: "Better routing is not about pushing drivers harder. It is about giving them a plan that already accounts for the real day ahead.",
},
];
}
@@ -124,14 +124,14 @@ const seeds: SeedPost[] = [
// ── Flagship 1 ───────────────────────────────────────────────────────────
{
slug: "how-ai-is-transforming-last-mile-ev-delivery",
title: "How Better Planning Improves Last-Mile EV Delivery",
title: "How Better Planning Improves Last-Mile EV Logistics",
excerpt:
"A practical look at how EV fleets can plan routes, manage charging, and keep delivery promises without adding unnecessary vehicles.",
"A practical look at how EV fleets can plan routes, manage charging, and keep service promises without adding unnecessary vehicles.",
category: "Technology",
image: "/images/blog-post-pic-17.webp",
date: "2025-10-02",
intro:
"The last mile is already difficult to plan. With electric vehicles, the team also has to think about battery range, charging time, rider load, traffic, and delivery windows. Good planning turns those moving parts into a workable dispatch plan.",
"The last mile is already difficult to plan. With electric vehicles, the team also has to think about battery range, charging time, driver load, traffic, and arrival windows. Good planning turns those moving parts into a workable dispatch plan.",
content: [
{
type: "paragraph",
@@ -144,15 +144,15 @@ const seeds: SeedPost[] = [
},
{
type: "paragraph",
text: "A fixed-zone plan may look clean in the morning, but the road rarely follows the plan. A rider may get delayed near Hitec City, a gated community may hold a vehicle for ten extra minutes, or a battery may drain faster because the load is heavier than usual.",
text: "A fixed-zone plan may look clean in the morning, but the road rarely follows the plan. A driver may get delayed near Hitec City, a gated community may hold a vehicle for ten extra minutes, or a battery may drain faster because the load is heavier than usual.",
},
{
type: "list",
items: [
"Order volumes by area, time slot, and customer type",
"Travel times based on the city's actual traffic patterns",
"Battery use by vehicle type, rider load, and route length",
"Feedback from completed deliveries, failed attempts, and late arrivals",
"Battery use by vehicle type, driver load, and route length",
"Feedback from completed shipments, failed attempts, and late arrivals",
],
},
{ type: "heading", level: 3, text: "Adjusting during the day" },
@@ -162,14 +162,14 @@ const seeds: SeedPost[] = [
},
{
type: "paragraph",
text: "During peak traffic hours in Hyderabad, some vehicles were arriving 20 to 30 minutes later than planned. By adjusting routes based on live traffic and battery levels, the hub reduced missed delivery windows and improved on-time performance.",
text: "During peak traffic hours in Hyderabad, some vehicles were arriving 20 to 30 minutes later than planned. By adjusting routes based on live traffic and battery levels, the hub reduced missed arrival windows and improved on-time performance.",
},
{
type: "image",
src: "/images/ev-paradox.webp",
alt: "Electric delivery vehicle routing visualisation",
alt: "Electric fleet vehicle routing visualisation",
caption:
"EV route plans need to account for range, load, traffic, and charging time before riders leave the hub.",
"EV route plans need to account for range, load, traffic, and charging time before drivers leave the hub.",
},
{
type: "quote",
@@ -183,21 +183,21 @@ const seeds: SeedPost[] = [
},
{
type: "paragraph",
text: "For a fleet manager, this is not about fancy software. It is about fewer emergency calls, fewer mid-route swaps, and fewer customers asking why their delivery missed the promised window.",
text: "For a fleet manager, this is not about fancy software. It is about fewer emergency calls, fewer mid-route swaps, and fewer customers asking why their shipment missed the promised window.",
},
{
type: "list",
ordered: true,
items: [
"Record delivery times, failed attempts, traffic delays, and charging cycles.",
"Build travel-time estimates from the areas your riders actually serve.",
"Record arrival times, failed attempts, traffic delays, and charging cycles.",
"Build travel-time estimates from the areas your drivers actually serve.",
"Check every route against battery capacity before dispatch.",
"Replan when traffic, orders, or vehicle availability changes.",
],
},
{
type: "paragraph",
text: "The fleets that improve fastest are usually not the ones adding vehicles first. They are the ones removing wasted distance, planning charging properly, and giving riders routes they can complete on time.",
text: "The fleets that improve fastest are usually not the ones adding vehicles first. They are the ones removing wasted distance, planning charging properly, and giving drivers routes they can complete on time.",
},
],
},
@@ -207,7 +207,7 @@ const seeds: SeedPost[] = [
slug: "42-less-distance-insights-from-our-hyderabad-hub",
title: "42% Less Distance: Insights from Our Hyderabad Hub",
excerpt:
"A practical look at how one Hyderabad hub reduced distance, used fewer vehicles, and protected delivery windows with better route planning.",
"A practical look at how one Hyderabad hub reduced distance, used fewer vehicles, and protected arrival windows with better route planning.",
category: "Case Study",
image: "/images/blog-post-pic-15.webp",
date: "2025-09-18",
@@ -216,7 +216,7 @@ const seeds: SeedPost[] = [
content: [
{
type: "paragraph",
text: "Hyderabad is not an easy city for delivery planning. Dense commercial areas, fast-growing suburbs, flyover work, narrow service lanes, apartment security checks, and sudden traffic build-up can all change the day.",
text: "Hyderabad is not an easy city for logistics planning. Dense commercial areas, fast-growing suburbs, flyover work, narrow service lanes, apartment security checks, and sudden traffic build-up can all change the day.",
},
{
type: "heading",
@@ -225,11 +225,11 @@ const seeds: SeedPost[] = [
},
{
type: "paragraph",
text: "Before MileTruth, the hub planned routes in the usual way. Zones were drawn from experience, dispatchers sequenced stops manually, and riders adjusted on the road when something changed.",
text: "Before MileTruth, the hub planned routes in the usual way. Zones were drawn from experience, dispatchers sequenced stops manually, and drivers adjusted on the road when something changed.",
},
{
type: "paragraph",
text: "That process worked, but it carried hidden costs. Two riders might cross the same area in the same hour. A vehicle might take a longer loop to avoid one late stop. A dispatcher might hold back an order because the best vehicle was not obvious in the moment.",
text: "That process worked, but it carried hidden costs. Two drivers might cross the same area in the same hour. A vehicle might take a longer loop to avoid one late stop. A dispatcher might hold back an order because the best vehicle was not obvious in the moment.",
},
{
type: "list",
@@ -237,7 +237,7 @@ const seeds: SeedPost[] = [
"Zone-based allocation that missed nearby cross-zone drops",
"Manual stop sequencing during busy dispatch windows",
"ETAs checked after routing instead of before dispatch",
"Traffic and delay handling that depended on phone calls from riders",
"Traffic and delay handling that depended on phone calls from drivers",
],
},
{
@@ -247,18 +247,18 @@ const seeds: SeedPost[] = [
},
{
type: "paragraph",
text: "The main change was treating the day's orders as one connected plan instead of separate zone lists. The route plan considered distance, rider capacity, delivery windows, traffic, and vehicle availability together.",
text: "The main change was treating the day's orders as one connected plan instead of separate zone lists. The route plan considered distance, driver capacity, arrival windows, traffic, and vehicle availability together.",
},
{
type: "paragraph",
text: "During peak traffic hours in Hyderabad, some vehicles were arriving 20 to 30 minutes later than planned. By adjusting routes based on live traffic and battery levels, we reduced missed delivery windows and improved on-time performance.",
text: "During peak traffic hours in Hyderabad, some vehicles were arriving 20 to 30 minutes later than planned. By adjusting routes based on live traffic and battery levels, we reduced missed arrival windows and improved on-time performance.",
},
{
type: "image",
src: "/images/last-mile-approach.webp",
alt: "Hyderabad delivery hub routing analysis",
alt: "Hyderabad logistics hub routing analysis",
caption:
"Planning the day's deliveries together removed repeated cross-town travel.",
"Planning the day's shipments together removed repeated cross-town travel.",
},
{
type: "heading",
@@ -269,14 +269,14 @@ const seeds: SeedPost[] = [
type: "list",
items: [
"42% reduction in total distance travelled across the hub",
"37% fewer vehicles required for the same delivery volume",
"37% fewer vehicles required for the same shipment volume",
"No SLA misses during the measured deployment window",
"Lower fuel use and fewer unnecessary kilometres per parcel",
],
},
{
type: "quote",
text: "The improvement did not come from asking riders to work harder. It came from giving the team a better route plan before the vehicles left.",
text: "The improvement did not come from asking drivers to work harder. It came from giving the team a better route plan before the vehicles left.",
cite: "Hyderabad Hub Operations",
},
{
@@ -300,16 +300,16 @@ const seeds: SeedPost[] = [
slug: "miletruth-ai-10-stages-to-smarter-dispatch",
title: "MileTruth™: 10 Stages to Smarter Dispatch",
excerpt:
"From order intake to final route output, here is how a dispatch plan is checked before riders leave the hub.",
"From order intake to final route output, here is how a dispatch plan is checked before drivers leave the hub.",
category: "MileTruth",
image: "/images/blog-post-pic-31.webp",
date: "2025-09-05",
intro:
"Behind every Doormile dispatch is a step-by-step route planning process. Each stage removes a common source of error before the plan reaches the rider.",
"Behind every Doormile dispatch is a step-by-step route planning process. Each stage removes a common source of error before the plan reaches the driver.",
content: [
{
type: "paragraph",
text: "A dispatch plan has to be fast, but it also has to be usable. A quick route that ignores a bad address, low battery, or tight delivery window creates problems later in the day.",
text: "A dispatch plan has to be fast, but it also has to be usable. A quick route that ignores a bad address, low battery, or tight arrival window creates problems later in the day.",
},
{
type: "heading",
@@ -320,15 +320,15 @@ const seeds: SeedPost[] = [
type: "list",
ordered: true,
items: [
"Order intake: new orders, rider availability, and vehicle status are collected.",
"Address check: delivery points, time windows, and service notes are verified.",
"Stop planning: each stop gets an expected service time and delivery priority.",
"Order intake: new orders, driver availability, and vehicle status are collected.",
"Address check: drop points, time windows, and service notes are verified.",
"Stop planning: each stop gets an expected service time and stop priority.",
"Travel-time check: routes are compared against time-of-day traffic.",
"Constraint check: capacity, shift time, customer windows, and range are applied.",
"Route options: several possible plans are built for the same order set.",
"Plan selection: the lowest-cost workable route plan is selected.",
"Battery check: EV routes are checked against real charge capacity.",
"ETA check: promised delivery times are verified before dispatch.",
"ETA check: promised arrival times are verified before dispatch.",
"Dispatch output: the final route is sent to the operations team.",
],
},
@@ -339,14 +339,14 @@ const seeds: SeedPost[] = [
},
{
type: "paragraph",
text: "When everything is checked in one step, small errors slip through. A wrong pin, a missing apartment note, or a low battery warning can reach the rider and become a customer issue.",
text: "When everything is checked in one step, small errors slip through. A wrong pin, a missing apartment note, or a low battery warning can reach the driver and become a customer issue.",
},
{
type: "image",
src: "/images/blog-post-pic-31.webp",
alt: "MileTruth routing pipeline diagram",
caption:
"A staged dispatch process catches address, range, and ETA issues before riders leave.",
"A staged dispatch process catches address, range, and ETA issues before drivers leave.",
},
{
type: "quote",
@@ -360,14 +360,14 @@ const seeds: SeedPost[] = [
},
{
type: "paragraph",
text: "The useful part is not only building one route. It is comparing a few workable route options before choosing the plan. One option may save distance, another may protect a tight delivery window, and another may keep an EV closer to a charger.",
text: "The useful part is not only building one route. It is comparing a few workable route options before choosing the plan. One option may save distance, another may protect a tight arrival window, and another may keep an EV closer to a charger.",
},
{
type: "list",
items: [
"Several route plans checked before dispatch",
"Distance, time windows, capacity, and range considered together",
"Range and ETA checked before the route reaches the rider",
"Range and ETA checked before the route reaches the driver",
"Fast output that still leaves room for dispatcher review",
],
},
@@ -403,7 +403,7 @@ const seeds: SeedPost[] = [
},
{
slug: "fleet-reduction-without-compromising-delivery-volume",
title: "Fleet Reduction Without Compromising Delivery Volume",
title: "Fleet Reduction Without Compromising Shipment Volume",
excerpt:
"Handling the same order volume with fewer vehicles starts by removing avoidable kilometres and overlapping routes.",
category: "Fleet Management",
@@ -416,12 +416,12 @@ const seeds: SeedPost[] = [
slug: "building-a-greener-city-the-future-of-urban-logistics",
title: "Building a Greener City: The Future of Urban Logistics",
excerpt:
"Cities are asking for cleaner delivery. The practical challenge is planning EV routes that can meet customer windows without wasting charge.",
"Cities are asking for cleaner logistics. The practical challenge is planning EV routes that can meet customer windows without wasting charge.",
category: "Sustainability",
image: "/images/blog-post-pic-6.webp",
date: "2025-07-10",
intro:
"Cleaner delivery is becoming an operating requirement, not just a brand message. It depends on EV adoption and route plans that make those vehicles practical every day.",
"Cleaner logistics is becoming an operating requirement, not just a brand message. It depends on EV adoption and route plans that make those vehicles practical every day.",
},
{
slug: "how-doormile-maintains-99-9-sla-compliance-at-scale",
@@ -432,18 +432,18 @@ const seeds: SeedPost[] = [
image: "/images/last-mile-approach.webp",
date: "2025-06-26",
intro:
"Strong SLA performance is not luck. It comes from planning the day so late deliveries are the exception, not the expected risk.",
"Strong SLA performance is not luck. It comes from planning the day so late shipments are the exception, not the expected risk.",
},
{
slug: "battery-simulation-the-secret-to-ev-route-pre-validation",
title: "Battery Simulation: The Secret to EV Route Pre-Validation",
excerpt:
"Before a rider leaves the hub, every EV route should be checked against real charge capacity and the expected return plan.",
"Before a driver leaves the hub, every EV route should be checked against real charge capacity and the expected return plan.",
category: "EV Fleet",
image: "/images/blog-post-pic-3.webp",
date: "2025-06-12",
intro:
"A stranded EV is not just a late delivery. It means a vehicle is out of service, a customer is waiting, and the hub has to arrange recovery. Range checks need to happen before dispatch.",
"A stranded EV is not just a late shipment. It means a vehicle is out of service, a customer is waiting, and the hub has to arrange recovery. Range checks need to happen before dispatch.",
},
];