update image and about section

This commit is contained in:
2026-06-13 00:27:45 +05:30
parent 2bc01b5952
commit 205924e057
75 changed files with 418 additions and 308 deletions

View File

@@ -507,7 +507,7 @@ body:not(.rtl) .elementor-element.elementor-element-13a7637 {
}
.elementor-element.elementor-element-7da6646:not(.elementor-motion-effects-element-type-background) {
background-image: url("/images/home4-banner-4.jpg");
background-image: url("/images/bg-header-women.webp");
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
@@ -8650,7 +8650,7 @@ h1:where(.wp-block-heading).has-background,
}
.elementor .elementor-element.elementor-element-6c7cbcb .elementor-repeater-item-3264830 {
background-image: url("/images/home2-slide-1.jpg");
background-image: url("/images/home2-slide-1.webp");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
@@ -8710,7 +8710,7 @@ h1:where(.wp-block-heading).has-background,
}
.elementor .elementor-element.elementor-element-6c7cbcb .elementor-repeater-item-6867061 {
background-image: url("/images/home2-slide-2.jpg");
background-image: url("/images/home2-slide-2.webp");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
@@ -8833,7 +8833,7 @@ h1:where(.wp-block-heading).has-background,
}
.elementor .elementor-element.elementor-element-ca6bc63:not(.elementor-motion-effects-element-type-background) {
background-image: linear-gradient(to right, #00000080, #00000010), url("/images/home2-banner-1.jpg");
background-image: linear-gradient(to right, #00000080, #00000010), url("/images/home2-banner-1.webp");
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
@@ -8952,7 +8952,7 @@ h1:where(.wp-block-heading).has-background,
}
.elementor .elementor-element.elementor-element-f003242:not(.elementor-motion-effects-element-type-background) {
background-image: url("/images/home2-banner-3.jpg");
background-image: url("/images/home2-banner-3.webp");
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
@@ -10216,7 +10216,7 @@ h1:where(.wp-block-heading).has-background,
}
#side-panel-2f31137:before {
background-image: url("/images/bg-slide-sidebar.jpg");
background-image: url("/images/bg-slide-sidebar.webp");
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
@@ -11406,7 +11406,7 @@ h1:where(.wp-block-heading).has-background,
}
.elementor-61 .elementor-element.elementor-element-6c7cbcb .elementor-repeater-item-3264830 {
background-image: url("/images/home2-slide-1.jpg");
background-image: url("/images/home2-slide-1.webp");
background-position: bottom center;
background-repeat: no-repeat;
background-size: cover;
@@ -11458,7 +11458,7 @@ h1:where(.wp-block-heading).has-background,
}
.elementor-61 .elementor-element.elementor-element-6c7cbcb .elementor-repeater-item-6867061 {
background-image: url("/images/home2-slide-2.jpg");
background-image: url("/images/home2-slide-2.webp");
background-position: bottom center;
background-repeat: no-repeat;
background-size: cover;
@@ -11569,7 +11569,7 @@ h1:where(.wp-block-heading).has-background,
}
.elementor-61 .elementor-element.elementor-element-ca6bc63:not(.elementor-motion-effects-element-type-background) {
background-image: url("/images/home2-banner-1.jpg");
background-image: url("/images/home2-banner-1.webp");
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
@@ -11684,7 +11684,7 @@ h1:where(.wp-block-heading).has-background,
}
.elementor-61 .elementor-element.elementor-element-f003242:not(.elementor-motion-effects-element-type-background) {
background-image: url("/images/home2-banner-3.jpg");
background-image: url("/images/home2-banner-3.webp");
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
@@ -14856,7 +14856,7 @@ img:is([sizes=auto i]) {
}
.elementor-element.elementor-element-7da6646:not(.elementor-motion-effects-element-type-background) {
background-image: url("/images/bg-header-5.png");
background-image: url("/images/bg-header-5.webp");
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
@@ -18143,13 +18143,13 @@ img:is([sizes=auto i]){contain-intrinsic-size:3000px 1500px}
/* STYLE BLOCK 50 */
.howits-hero-custom-bg.elementor-repeater-item-3264830,
.howits-hero-custom-bg.elementor-repeater-item-6867061 {
background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1)), url('/images/home1-slide-1.png') !important;
background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1)), url('/images/home1-slide-1.webp') !important;
background-position: center !important;
background-repeat: no-repeat !important;
background-size: cover !important;
}
.howits-hero-custom-bg.elementor-repeater-item-6867061 {
background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1)), url('/images/home1-slide-2.png') !important;
background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1)), url('/images/home1-slide-2.webp') !important;
background-position: center !important;
background-repeat: no-repeat !important;
background-size: cover !important;

BIN
public/images/Aravinth.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
public/images/Fazul.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
public/images/Investor.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
public/images/Parthi.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
public/images/Suriya.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
public/images/about-bg.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

BIN
public/images/ev.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
public/images/mile-1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

View File

@@ -15,7 +15,7 @@ export const metadata = {
export default function AboutUsPage() {
return (
<div className="content-wrapper content-wrapper-may-contain-elementor-code content-wrapper-sidebar-position-none">
<div id="about" className="content-wrapper content-wrapper-may-contain-elementor-code content-wrapper-sidebar-position-none">
<div className="content">
<div className="content-inner">
<div data-elementor-type="wp-page" data-elementor-id="86" className="elementor elementor-86 elementor-59">

View File

@@ -9,7 +9,7 @@ export const metadata = {
export default function BlogPage() {
return (
<div className="content-wrapper content-wrapper-may-contain-elementor-code content-wrapper-sidebar-position-none">
<div id="blogs" className="content-wrapper content-wrapper-may-contain-elementor-code content-wrapper-sidebar-position-none">
<div className="content">
<div className="content-inner">
<div data-elementor-type="wp-page" data-elementor-id="104" className="elementor elementor-104">

View File

@@ -9,7 +9,7 @@ export const metadata = {
export default function HowItWorksPage() {
return (
<div className="content-wrapper content-wrapper-may-contain-elementor-code content-wrapper-sidebar-position-none">
<div id="how-it-works" className="content-wrapper content-wrapper-may-contain-elementor-code content-wrapper-sidebar-position-none">
<div className="content">
<div className="content-inner">
<div data-elementor-type="wp-page" data-elementor-id="59" className="elementor elementor-59">

View File

@@ -78,12 +78,6 @@ export default function RootLayout({
purgecss.config.cjs. ~2.86 MB of vendor CSS -> ~560 KB, one request.
*/}
<link rel="stylesheet" href="/css/site.css" />
<link rel="preload" as="image" href="/images/home-bg-1.png" />
<link rel="preload" as="image" href="/images/about-bg.png" />
<link rel="preload" as="image" href="/images/home2-banner-3.jpg" />
<link rel="preload" as="image" href="/images/home1-slide-1.png" />
<link rel="preload" as="image" href="/images/home2-banner-1.jpg" />
<link rel="preload" as="image" href="/images/miletruth-bg.png" />
</head>
{/*
Production DOM (index.php + header.php):

View File

@@ -11,7 +11,7 @@ export const metadata = {
export default function MileTruthPage() {
return (
<div className="content-wrapper content-wrapper-may-contain-elementor-code content-wrapper-sidebar-position-none">
<div id="miletruth" className="content-wrapper content-wrapper-may-contain-elementor-code content-wrapper-sidebar-position-none">
<div className="content">
<div className="content-inner">
<div data-elementor-type="wp-page" data-elementor-id="59" className="elementor elementor-59">

View File

@@ -17,7 +17,7 @@ export const metadata: Metadata = {
export default function Home() {
return (
<div className="content-wrapper content-wrapper-may-contain-elementor-code content-wrapper-sidebar-position-none">
<div id="home" className="content-wrapper content-wrapper-may-contain-elementor-code content-wrapper-sidebar-position-none">
<div className="content">
<div className="content-inner">
<div data-elementor-type="wp-page" data-elementor-id="61" className="elementor elementor-61">

View File

@@ -50,7 +50,7 @@ export default function SolutionsPage() {
}
`}} />
<div className="content-wrapper content-wrapper-may-contain-elementor-code content-wrapper-sidebar-position-none">
<div id="solutions" className="content-wrapper content-wrapper-may-contain-elementor-code content-wrapper-sidebar-position-none">
<div className="content">
<div className="content-inner">
<div data-elementor-type="wp-page" data-elementor-id="59" className="elementor elementor-59">

View File

@@ -7,7 +7,7 @@
* Menu open/close + sidebar state is read from HeaderUIProvider so BodyOverlay (sibling at body level) can react.
*/
import { useEffect, useState } from "react";
import { MouseEvent, useEffect, useState } from "react";
import Link from "next/link";
import Image from "next/image";
import { usePathname } from "next/navigation";
@@ -44,6 +44,34 @@ export default function Header() {
const dmHeaderActive = (key: string) =>
(CURRENT_PAGE_ALIASES[key] ?? []).includes(currentPage) ? " active" : "";
const scrollToNavTarget = (targetId: string) => {
const target = document.getElementById(targetId);
if (target) {
target.scrollIntoView({ behavior: "smooth", block: "start" });
return;
}
window.scrollTo({ top: 0, behavior: "smooth" });
};
const handleNavClick = (
event: MouseEvent<HTMLAnchorElement>,
targetPath: string,
targetId: string,
shouldCloseMenu = false,
) => {
if (shouldCloseMenu) closeAll();
if (pathname !== targetPath) return;
event.preventDefault();
const targetUrl = `${targetPath}#${targetId}`;
if (`${window.location.pathname}${window.location.hash}` !== targetUrl) {
window.history.pushState(null, "", targetUrl);
}
requestAnimationFrame(() => scrollToNavTarget(targetId));
};
// Mirror of header.php <script> block (lines 628-660):
// - on doc.ready: $('.header-hide-until-scroll').addClass('header-visible-scrolled')
// - on scroll: toggleClass('dm-header-scrolled', scrollTop > 50)
@@ -406,22 +434,22 @@ export default function Header() {
<nav>
<ul id="menu-main-menu" className="main-menu">
<li id="menu-item-10508" className={`menu-item menu-item-type-custom menu-item-object-custom menu-item-10508${dmHeaderActive("home")}`}>
<Link href="/">Home</Link>
<Link href="/#home" onClick={(event) => handleNavClick(event, "/", "home")}>Home</Link>
</li>
<li id="menu-item-10509" className={`menu-item menu-item-type-custom menu-item-object-custom menu-item-10509${dmHeaderActive("how-it-works")}`}>
<Link href="/how-it-works">How It Works</Link>
<Link href="/how-it-works#how-it-works" onClick={(event) => handleNavClick(event, "/how-it-works", "how-it-works")}>How It Works</Link>
</li>
<li id="menu-item-10510" className={`menu-item menu-item-type-custom menu-item-object-custom menu-item-10510${dmHeaderActive("miletruth")}`}>
<Link href="/miletruth">MileTruth&trade; AI</Link>
<Link href="/miletruth#miletruth" onClick={(event) => handleNavClick(event, "/miletruth", "miletruth")}>MileTruth&trade; AI</Link>
</li>
<li id="menu-item-10511" className={`menu-item menu-item-type-custom menu-item-10511${dmHeaderActive("solutions")}`}>
<Link href="/solutions">Solutions</Link>
<Link href="/solutions#solutions" onClick={(event) => handleNavClick(event, "/solutions", "solutions")}>Solutions</Link>
</li>
<li id="menu-item-10512" className={`menu-item menu-item-type-custom menu-item-object-custom menu-item-10512${dmHeaderActive("about")}`}>
<Link href="/about-us">About</Link>
<Link href="/about-us#about" onClick={(event) => handleNavClick(event, "/about-us", "about")}>About</Link>
</li>
<li id="menu-item-10535" className={`menu-item menu-item-type-post_type menu-item-object-page menu-item-10535${dmHeaderActive("blogs")}`}>
<Link href="/blog">Blogs</Link>
<Link href="/blog#blogs" onClick={(event) => handleNavClick(event, "/blog", "blogs")}>Blogs</Link>
</li>
</ul>
</nav>
@@ -454,22 +482,22 @@ export default function Header() {
<nav>
<ul id="menu-main-menu-1" className="main-menu">
<li className={`menu-item menu-item-type-custom menu-item-object-custom menu-item-10508${dmHeaderActive("home")}`}>
<Link href="/" onClick={closeAll}>Home</Link>
<Link href="/#home" onClick={(event) => handleNavClick(event, "/", "home", true)}>Home</Link>
</li>
<li className={`menu-item menu-item-type-custom menu-item-object-custom menu-item-10509${dmHeaderActive("how-it-works")}`}>
<Link href="/how-it-works" onClick={closeAll}>How It Works</Link>
<Link href="/how-it-works#how-it-works" onClick={(event) => handleNavClick(event, "/how-it-works", "how-it-works", true)}>How It Works</Link>
</li>
<li className={`menu-item menu-item-type-custom menu-item-object-custom menu-item-10510${dmHeaderActive("miletruth")}`}>
<Link href="/miletruth" onClick={closeAll}>MileTruth&trade; AI</Link>
<Link href="/miletruth#miletruth" onClick={(event) => handleNavClick(event, "/miletruth", "miletruth", true)}>MileTruth&trade; AI</Link>
</li>
<li className={`menu-item menu-item-type-custom menu-item-10511${dmHeaderActive("solutions")}`}>
<Link href="/solutions" onClick={closeAll}>Solutions</Link>
<Link href="/solutions#solutions" onClick={(event) => handleNavClick(event, "/solutions", "solutions", true)}>Solutions</Link>
</li>
<li className={`menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-10512${dmHeaderActive("about")}`}>
<Link href="/about-us" onClick={closeAll}>About</Link>
<Link href="/about-us#about" onClick={(event) => handleNavClick(event, "/about-us", "about", true)}>About</Link>
</li>
<li className={`menu-item menu-item-type-post_type menu-item-object-page menu-item-10535${dmHeaderActive("blogs")}`}>
<Link href="/blog" onClick={closeAll}>Blogs</Link>
<Link href="/blog#blogs" onClick={(event) => handleNavClick(event, "/blog", "blogs", true)}>Blogs</Link>
</li>
</ul>
</nav>

View File

@@ -1,56 +1,161 @@
"use client";
import { useEffect, useRef, useState } from "react";
import { useEffect, useRef, useState, type MutableRefObject } from "react";
import Image from "next/image";
import { usePathname } from "next/navigation";
/**
* LoadingScreen
* ---------------------------------------------------------------------------
* Native reimplementation of the legacy WordPress page-loader: a black
* full-screen overlay with a centered, pulsing Doormile logo that fades out.
* Route-transition loader only: a black full-screen overlay with a centered,
* pulsing Doormile logo. It intentionally does not run on initial page render,
* image loading, lazy component loading, API requests, or scroll.
*
* Shows only on initial application boot (until the window finishes loading,
* min ~450ms to avoid a flash, capped at 2.5s so it never blocks). It must not
* reappear during client-side route transitions: Next keeps the current page
* visible while the next route payload is prepared, and a global overlay here
* would create an artificial black flash between otherwise-ready pages.
* The App Router does not expose the old `next/router` routeChangeStart /
* routeChangeComplete event API. This component provides the same behavior by
* detecting internal route-link starts and completing when `usePathname()`
* reports the committed route.
*/
type Phase = "visible" | "hiding" | "gone";
type Phase = "hidden" | "visible" | "hiding";
const MIN_SHOW_MS = 450;
const MAX_SHOW_MS = 2500;
const MIN_VISIBLE_MS = 420;
const MAX_VISIBLE_MS = 800;
function getRoutePath(url: URL) {
return `${url.pathname}${url.search}`;
}
export default function LoadingScreen() {
const [phase, setPhase] = useState<Phase>("visible");
const bootComplete = useRef(false);
const pathname = usePathname();
const [phase, setPhase] = useState<Phase>("hidden");
const phaseRef = useRef<Phase>("hidden");
const visibleSince = useRef(0);
const pendingPath = useRef<string | null>(null);
const currentRoutePath = useRef<string | null>(null);
const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
const safetyTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
// Initial load: hide once the page is ready.
useEffect(() => {
const start = performance.now();
let began = false;
let fadeTimer: ReturnType<typeof setTimeout>;
const begin = () => {
if (began || bootComplete.current) return;
began = true;
const wait = Math.max(0, MIN_SHOW_MS - (performance.now() - start));
fadeTimer = setTimeout(() => setPhase("hiding"), wait);
const setLoaderPhase = (nextPhase: Phase) => {
phaseRef.current = nextPhase;
setPhase(nextPhase);
};
const cap = setTimeout(begin, MAX_SHOW_MS);
const onReady = () => begin();
const clearTimer = (timer: MutableRefObject<ReturnType<typeof setTimeout> | null>) => {
if (!timer.current) return;
clearTimeout(timer.current);
timer.current = null;
};
if (document.readyState === "complete") begin();
else window.addEventListener("load", onReady, { once: true });
const completeTransition = () => {
pendingPath.current = null;
clearTimer(safetyTimer);
if (phaseRef.current === "hidden" || phaseRef.current === "hiding") return;
const elapsed = performance.now() - visibleSince.current;
const wait = Math.max(0, MIN_VISIBLE_MS - elapsed);
clearTimer(hideTimer);
hideTimer.current = setTimeout(() => {
setLoaderPhase("hiding");
hideTimer.current = setTimeout(() => setLoaderPhase("hidden"), 360);
}, wait);
};
useEffect(() => {
currentRoutePath.current = `${pathname}${window.location.search}`;
completeTransition();
// `phase` intentionally stays out of this dependency list. The route commit
// is the completion signal; phase changes should not repeatedly restart hide.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [pathname]);
useEffect(() => {
const startTransition = (targetPath: string, force = false) => {
if (!force && targetPath === getRoutePath(new URL(window.location.href))) return;
if (pendingPath.current === targetPath && phaseRef.current === "visible") return;
pendingPath.current = targetPath;
clearTimer(hideTimer);
clearTimer(safetyTimer);
visibleSince.current = performance.now();
setLoaderPhase("visible");
safetyTimer.current = setTimeout(() => {
completeTransition();
}, MAX_VISIBLE_MS);
};
const getInternalRouteTarget = (anchor: HTMLAnchorElement) => {
const rawHref = anchor.getAttribute("href");
if (!rawHref || rawHref.startsWith("#")) return null;
if (anchor.target && anchor.target !== "_self") return null;
if (anchor.hasAttribute("download")) return null;
if (/^(mailto:|tel:|sms:|javascript:)/i.test(rawHref)) return null;
const url = new URL(rawHref, window.location.href);
if (url.origin !== window.location.origin) return null;
const current = new URL(window.location.href);
const sameRoute = url.pathname === current.pathname && url.search === current.search;
if (sameRoute) return null;
return getRoutePath(url);
};
const handleDocumentClick = (event: MouseEvent) => {
if (event.defaultPrevented) return;
if (event.button !== 0) return;
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
const anchor = (event.target as Element | null)?.closest("a[href]");
if (!anchor || !(anchor instanceof HTMLAnchorElement)) return;
const targetPath = getInternalRouteTarget(anchor);
if (targetPath) startTransition(targetPath);
};
const originalPushState = window.history.pushState;
const originalReplaceState = window.history.replaceState;
window.history.pushState = function patchedPushState(...args) {
const urlArg = args[2];
if (typeof urlArg === "string" || urlArg instanceof URL) {
const url = new URL(urlArg, window.location.href);
if (url.origin === window.location.origin) startTransition(getRoutePath(url));
}
return originalPushState.apply(this, args);
};
window.history.replaceState = function patchedReplaceState(...args) {
const urlArg = args[2];
if (typeof urlArg === "string" || urlArg instanceof URL) {
const url = new URL(urlArg, window.location.href);
if (url.origin === window.location.origin) startTransition(getRoutePath(url));
}
return originalReplaceState.apply(this, args);
};
const handlePopState = () => {
const targetPath = getRoutePath(new URL(window.location.href));
if (targetPath !== currentRoutePath.current) startTransition(targetPath, true);
};
document.addEventListener("click", handleDocumentClick, true);
window.addEventListener("popstate", handlePopState);
return () => {
clearTimeout(cap);
clearTimeout(fadeTimer);
window.removeEventListener("load", onReady);
document.removeEventListener("click", handleDocumentClick, true);
window.removeEventListener("popstate", handlePopState);
window.history.pushState = originalPushState;
window.history.replaceState = originalReplaceState;
clearTimer(hideTimer);
clearTimer(safetyTimer);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
if (phase === "gone") return null;
if (phase === "hidden") return null;
return (
<div
@@ -60,8 +165,8 @@ export default function LoadingScreen() {
aria-label="Loading"
onTransitionEnd={(e) => {
if (e.propertyName === "opacity" && phase === "hiding") {
bootComplete.current = true;
setPhase("gone");
setPhase("hidden");
phaseRef.current = "hidden";
}
}}
>

View File

@@ -4,9 +4,9 @@
* ContactMapEmbed
* ---------------------------------------------------------------------------
* Client boundary that lazy-loads the Leaflet map. `ssr: false` keeps Leaflet
* out of the server bundle and off the critical render path; the skeleton fills
* the host container's fixed height so there is zero layout shift (CLS) while
* the map chunk loads.
* out of the server bundle and off the critical render path. The host container
* already owns the fixed height, so the loading state stays invisible before
* the interactive map is ready.
*/
import dynamic from "next/dynamic";
@@ -14,7 +14,7 @@ import styles from "./OfficeMap.module.css";
const OfficeMap = dynamic(() => import("./OfficeMap"), {
ssr: false,
loading: () => <div className={styles.skeleton} role="presentation" aria-hidden="true" />,
loading: () => <div className={styles.mapMountReserve} role="presentation" aria-hidden="true" />,
});
export default function ContactMapEmbed() {

View File

@@ -315,30 +315,14 @@
}
}
/* ---- Loading skeleton ---- */
.skeleton {
/* ---- Invisible lazy mount reserve ---- */
.mapMountReserve {
width: 100%;
height: 100%;
border-radius: inherit;
background:
linear-gradient(
100deg,
rgba(255, 255, 255, 0) 30%,
rgba(255, 255, 255, 0.05) 50%,
rgba(255, 255, 255, 0) 70%
),
#101012;
background-size: 200% 100%;
animation: shimmer 1.4s ease-in-out infinite;
}
@keyframes shimmer {
from { background-position: 200% 0; }
to { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
.skeleton { animation: none; }
.markerIcon,
.markerIconHq { transition: none; }
.pinPulse { animation: none; opacity: 0.45; }

View File

@@ -3,6 +3,7 @@ import React from "react";
export default function AboutHero() {
return (
<>
<link rel="preload" as="image" href="/images/about-bg.webp" />
<style dangerouslySetInnerHTML={{ __html: `
.about-us-hero-content {
width: 100% !important;
@@ -33,7 +34,7 @@ export default function AboutHero() {
<div className="custom-standard-hero-container">
<div
style={{
backgroundImage: "url('/images/about-bg.png')",
backgroundImage: "url('/images/about-bg.webp')",
"--hero-overlay": "linear-gradient(to bottom, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.92) 60%, rgba(0, 0, 0, 0.98) 100%)"
} as React.CSSProperties}
className="custom-standard-hero-card"
@@ -48,4 +49,3 @@ export default function AboutHero() {
</>
);
}

View File

@@ -1,9 +1,9 @@
import React from "react";
import Link from "next/link";
export default function BlogsHero() {
return (
<>
<link rel="preload" as="image" href="/images/home2-banner-1.webp" />
<style dangerouslySetInnerHTML={{ __html: `
.blogs-hero-title {
color: #ffffff !important;
@@ -19,7 +19,7 @@ export default function BlogsHero() {
<div className="custom-standard-hero-container">
<div
style={{
backgroundImage: "url(/images/home2-banner-1.jpg)",
backgroundImage: "url(/images/home2-banner-1.webp)",
backgroundPosition: "center center",
backgroundRepeat: "no-repeat",
backgroundSize: "cover"
@@ -43,4 +43,3 @@ export default function BlogsHero() {
</>
);
}

View File

@@ -135,7 +135,7 @@ export default function ConnectedLogistics() {
priority
width={578}
height={790}
src="/images/home2-pic-3.png"
src="/images/home2-pic-3.webp"
className="attachment-full size-full wp-image-4481"
alt="Connected Logistics"
style={{

View File

@@ -41,7 +41,7 @@ export default function ContactMap() {
(bottom was square before, leaving a hard edge above the footer gap). */
border-radius: 25px;
overflow: hidden;
background: #0b0b0b;
background: transparent;
line-height: 0;
}
@media (max-width: 840px) {

View File

@@ -3,10 +3,11 @@ import React from "react";
export default function ContactsHero() {
return (
<>
<link rel="preload" as="image" href="/images/home2-banner-3.webp" />
<style dangerouslySetInnerHTML={{ __html: `
.contacts-hero-custom {
background-color: #0b0b0b !important;
background-image: url('/images/home2-banner-3.jpg') !important;
background-image: url('/images/home2-banner-3.webp') !important;
background-size: cover !important;
background-position: center !important;
}
@@ -221,4 +222,3 @@ export default function ContactsHero() {
);
}

View File

@@ -12,8 +12,8 @@ if (typeof window !== "undefined") {
const CARDS_DATA = [
{
index: 1,
title: "Battery-First Planning",
desc: "Routes are optimized around battery levels and charging windows, not retrofitted as an afterthought.",
title: "Operational Visibility",
desc: "Real-time tracking and centralized control provide complete visibility across every shipment, vehicle, and delivery 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" />
@@ -25,8 +25,8 @@ const CARDS_DATA = [
},
{
index: 2,
title: "Energy-Aware Routing",
desc: "Our algorithms factor in terrain, traffic, and payload weight to maximize range efficiency.",
title: "Intelligent Routing",
desc: "AI-powered route optimization reduces travel time, improves delivery 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" />
@@ -35,8 +35,8 @@ const CARDS_DATA = [
},
{
index: 3,
title: "Smart Charging Integration",
desc: "Seamless coordination with charging infrastructure to eliminate range anxiety for drivers.",
title: "EV-First Logistics",
desc: "Purpose-built workflows for electric fleets improve battery efficiency, charging management, and sustainable operations.",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M12 2v10" />
@@ -48,8 +48,8 @@ const CARDS_DATA = [
},
{
index: 4,
title: "Carbon Footprint Tracking",
desc: "Real-time emissions monitoring and sustainability reports for every delivery.",
title: "Scalable Network",
desc: "Flexible logistics infrastructure supports growth across cities, regions, and high-volume delivery 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" />
@@ -89,18 +89,16 @@ export default function EVLogisticSection() {
});
entryTl
.to(container.querySelector(".ev-logistic-kicker"), {
.to(container.querySelector(".ev-logistic-kicker-widget"), {
opacity: 1,
y: 0,
letterSpacing: "3px", // Kinetic letter-spacing track expand effect!
duration: 0.8,
ease: "power3.out",
})
.to(container.querySelectorAll(".ev-char"), {
y: "0%",
.to(container.querySelector(".ev-logistic-title-widget"), {
y: 0,
opacity: 1,
duration: 0.95,
stagger: 0.02, // Rapid letter-by-letter wave reveal!
duration: 0.85,
ease: "power4.out",
}, "-=0.45")
.to(container.querySelectorAll(".ev-feature-card"), {
@@ -125,20 +123,11 @@ export default function EVLogisticSection() {
};
}, []);
const headingText = "LOGISTICS BUILT FOR ELECTRIC VEHICLES";
const headingWords = headingText.split(" ");
return (
<>
<style dangerouslySetInnerHTML={{ __html: `
/* Custom CSS Scoped to EV Logistics Section */
.ev-logistic-section {
display: flex !important;
flex-direction: column !important;
width: 100% !important;
max-width: 1480px !important;
margin: 10px auto 120px auto !important;
padding: 80px 40px !important;
box-sizing: border-box !important;
background: #ffffff !important;
font-family: 'Manrope', sans-serif !important;
@@ -149,8 +138,6 @@ export default function EVLogisticSection() {
width: 100% !important;
max-width: 100% !important;
align-self: stretch !important;
border-bottom: 2px solid rgba(17, 17, 17, 0.09) !important;
padding-bottom: 24px !important;
margin-bottom: 48px !important;
display: block !important;
text-align: left !important;
@@ -223,57 +210,30 @@ export default function EVLogisticSection() {
margin: 0 !important;
}
.ev-logistic-kicker {
font-size: 14px !important;
font-weight: 400 !important;
line-height: 2.1429em !important;
letter-spacing: 0px !important;
text-transform: lowercase !important;
color: #111111 !important;
margin: 0 0 16px 0 !important;
.ev-logistic-kicker-widget {
opacity: 0;
transform: translateY(-12px);
will-change: transform, opacity, letter-spacing;
text-align: left !important;
display: inline-block !important;
will-change: transform, opacity;
}
.ev-logistic-title-wrapper {
margin: 0 !important;
}
/* Expanded clean headings look from the screenshot */
.ev-logistic-title {
font-size: clamp(40px, 5.5vw, 80px) !important;
font-weight: 500 !important;
line-height: 0.95 !important;
text-transform: uppercase !important;
color: #111111 !important;
margin: 0 10px 0 0 !important;
letter-spacing: -1.8px !important;
}
/* CSS for robust letter-by-letter animation wrapping */
.ev-word-inline {
display: inline-block !important;
white-space: nowrap !important;
}
.ev-char-wrapper {
display: inline-block !important;
overflow: hidden !important;
vertical-align: top !important;
}
.ev-char {
display: inline-block !important;
transform: translateY(110%);
.ev-logistic-title-widget {
opacity: 0;
transform: translateY(24px);
will-change: transform, opacity;
}
.ev-char-space {
display: inline-block !important;
.ev-logistic-title-widget > .elementor-widget-container {
margin: 0 !important;
padding: 0 !important;
}
.ev-logistic-title-widget .logico-title {
margin: 0 !important;
text-align: left !important;
}
/* Card Grid Layout */
@@ -360,11 +320,6 @@ export default function EVLogisticSection() {
/* Responsiveness constraints */
@media (max-width: 1024px) {
.ev-logistic-section {
padding: 60px 24px !important;
margin-bottom: 60px !important;
}
.ev-logistic-body-grid {
flex-direction: column !important;
gap: 50px !important;
@@ -389,20 +344,9 @@ export default function EVLogisticSection() {
max-width: 100% !important;
}
.ev-logistic-title {
font-size: clamp(32px, 5vw, 60px) !important;
}
}
@media (max-width: 768px) {
.ev-logistic-section {
padding: 40px 16px !important;
}
.ev-logistic-title {
font-size: 32px !important;
}
.ev-feature-grid {
grid-template-columns: 1fr !important;
gap: 20px !important;
@@ -410,26 +354,38 @@ export default function EVLogisticSection() {
}
`}} />
<div className="elementor-61">
<div
ref={containerRef}
className="ev-logistic-section"
className="elementor-element elementor-element-88745f4 e-flex e-con-boxed cut-corner-no sticky-container-off e-con e-parent ev-logistic-section"
data-id="88745f4"
data-element_type="container"
data-e-type="container"
>
{/* Top Header Row with / features / kicker and Full-Width Title */}
<div className="e-con-inner">
<div className="elementor-element elementor-element-343b363 e-con-full e-flex cut-corner-no sticky-container-off e-con e-child" data-id="343b363" data-element_type="container" data-e-type="container">
{/* Same header hierarchy and container structure as "The Doormile Way". */}
<div className="ev-logistic-header">
<div className="ev-logistic-kicker">/ Build Electric Vehicles /</div>
<div className="elementor-element elementor-element-7afb238 elementor-widget elementor-widget-logico_heading ev-logistic-kicker-widget" data-id="7afb238" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
<div className="elementor-widget-container">
<div className="logico-title ev-logistic-kicker">/ Build Electric Vehicles /</div>
</div>
</div>
<div className="ev-logistic-title-wrapper">
<h3 className="ev-logistic-title">
{headingWords.map((word, wordIndex) => (
<span key={wordIndex} className="ev-word-inline">
{word.split("").map((letter, letterIndex) => (
<span key={letterIndex} className="ev-char-wrapper">
<span className="ev-char">{letter}</span>
</span>
))}
<span className="ev-char-space">&nbsp;</span>
</span>
))}
</h3>
<div className="elementor-element elementor-element-1cc335a elementor-widget elementor-widget-logico_heading ev-logistic-title-widget" data-id="1cc335a" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
<div className="elementor-widget-container">
<div
className="logico-title"
style={{
WebkitTextStroke: "4px #c01227",
color: "#fff",
fontWeight: 800,
}}
>
LOGISTICS BUILT FOR ELECTRIC VEHICLES
</div>
</div>
</div>
</div>
</div>
@@ -441,7 +397,7 @@ export default function EVLogisticSection() {
<div ref={imageWrapperRef} className="ev-logistic-image-wrapper">
<Image
ref={imageRef}
src="/images/ev.jpeg"
src="/images/ev.webp"
alt="EV Logistics"
width={1050}
height={854}
@@ -469,6 +425,9 @@ export default function EVLogisticSection() {
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
}

View File

@@ -325,7 +325,7 @@ function DashboardPanel({
}
export default function EVSection({
bannerImage = "/images/bg-header-5.png",
bannerImage = "/images/bg-header-5.webp",
cardNumber = "",
cardTitle = "EV Logistics",
cardSubtitle = "Cleaner miles, lower costs",
@@ -333,7 +333,7 @@ export default function EVSection({
titleLead = "BUILT FOR ELECTRIC. ",
titleAccent = "NOT ADAPTED.",
features = DEFAULT_FEATURES,
image = "/images/premium-ev-van.png",
image = "/images/premium-ev-van.webp",
imageAlt = "DoorMile electric delivery van",
badges = DEFAULT_BADGES,
stats = DEFAULT_STATS,
@@ -539,12 +539,12 @@ export default function EVSection({
(fit-content), so it stays centred with no side bands. The cap is
kept below the dashboard height so the image never inflates the row.
Scoped to the non-scene wrapper; desktop only, mobile untouched. */
.evnd__grid--cards .evnd__imgwrap:not(.evnd__imgwrap--media) {
.evnd__grid--cards .evnd__imgwrap:not(.evnd__imgwrap--media):not(.evnd__imgwrap--video) {
width: fit-content;
max-width: 100%;
margin-inline: auto;
}
.evnd__grid--cards .evnd__imgwrap:not(.evnd__imgwrap--media) .evnd__img {
.evnd__grid--cards .evnd__imgwrap:not(.evnd__imgwrap--media):not(.evnd__imgwrap--video) .evnd__img {
width: auto;
height: auto;
max-height: clamp(520px, 46vw, 670px);
@@ -552,6 +552,19 @@ export default function EVSection({
}
}
@media (min-width: 1200px) {
.evnd__grid--cards .evnd__imgwrap--video {
width: 100%;
height: 100%;
min-height: 100%;
}
.evnd__grid--cards .evnd__imgwrap--video .evnd__video {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.evnd__left {
display: flex;
flex-direction: column;
@@ -627,6 +640,12 @@ export default function EVSection({
object-fit: cover;
transition: transform 0.8s cubic-bezier(0.25, 1, 0.5, 1);
}
.evnd__video {
display: block;
width: 100%;
height: 100%;
object-fit: contain;
}
.evnd__imgwrap:hover .evnd__img {
transform: scale(1.03);
}
@@ -1239,10 +1258,21 @@ export default function EVSection({
<div className="evnd__media">
<div className="evnd__glow" />
<div
className={`evnd__imgwrap${mediaSlot ? " evnd__imgwrap--media" : ""}`}
className={`evnd__imgwrap${mediaSlot ? " evnd__imgwrap--media" : ""}${image.endsWith(".mp4") ? " evnd__imgwrap--video" : ""}`}
>
{mediaSlot ? (
mediaSlot
) : image.endsWith(".mp4") ? (
<video
className="evnd__video"
autoPlay
muted
loop
playsInline
aria-label={imageAlt}
>
<source src={image} type="video/mp4" />
</video>
) : (
/* eslint-disable-next-line @next/next/no-img-element */
<img

View File

@@ -19,19 +19,20 @@ export default function HowItWorksHero() {
return (
<>
<link rel="preload" as="image" href="/images/home2-banner-1.webp" />
<style
dangerouslySetInnerHTML={{
__html: `
.howits-hero-custom-bg.elementor-repeater-item-3264830,
.howits-hero-custom-bg.elementor-repeater-item-6867061 {
background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1)), url('/images/home2-banner-1.jpg') !important;
background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1)), url('/images/home2-banner-1.webp') !important;
background-position: center !important;
background-repeat: no-repeat !important;
background-size: cover !important;
}
.howits-hero-custom-bg.elementor-repeater-item-6867061 {
background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1)), url('/images/home1-slide-2.png') !important;
background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1)), url('/images/home1-slide-2.webp') !important;
background-position: center !important;
background-repeat: no-repeat !important;
background-size: cover !important;

View File

@@ -52,6 +52,7 @@ export default function IndexHero() {
return (
<div className="elementor-element elementor-element-741f56c e-con-full e-flex cut-corner-no sticky-container-off e-con e-parent" data-id="741f56c" data-element_type="container" data-e-type="container">
<link rel="preload" as="image" href="/images/home-bg-1.webp" />
<style dangerouslySetInnerHTML={{ __html: `
/* Fluid responsive font size override for hero headings */
.logico-content-slider-widget .content-slider-item-heading {
@@ -177,7 +178,7 @@ export default function IndexHero() {
<div
className="content-item slider-item elementor-repeater-item-3264830 slide-style-standard"
style={{
backgroundImage: "url('/images/home-bg-1.png')",
backgroundImage: "url('/images/home-bg-1.webp')",
backgroundPosition: "center center",
backgroundRepeat: "no-repeat",
backgroundSize: "cover"
@@ -218,7 +219,7 @@ export default function IndexHero() {
<div
className="content-item slider-item elementor-repeater-item-6867061 slide-style-standard"
style={{
backgroundImage: "url('/images/home-bg-1.png')",
backgroundImage: "url('/images/home-bg-1.webp')",
backgroundPosition: "center center",
backgroundRepeat: "no-repeat",
backgroundSize: "cover"

View File

@@ -85,7 +85,7 @@ export default function IndustrySolutions() {
<Link href="/solutions" className="industry-card-link">
<div className="industry-card-bg">
<Image
src="/images/tab-pic-1.jpeg"
src="/images/tab-pic-1.webp"
alt="FMCG Logistics"
fill
style={{ objectFit: "cover" }}
@@ -149,7 +149,7 @@ export default function IndustrySolutions() {
<Link href="/solutions" className="industry-card-link">
<div className="industry-card-bg">
<Image
src="/images/tab-pic-2.jpeg"
src="/images/tab-pic-2.webp"
alt="Pharma Logistics"
fill
style={{ objectFit: "cover" }}
@@ -213,7 +213,7 @@ export default function IndustrySolutions() {
<Link href="/solutions" className="industry-card-link">
<div className="industry-card-bg">
<Image
src="/images/tab-pic-3.jpeg"
src="/images/tab-pic-3.webp"
alt="Enterprise Logistics"
fill
style={{ objectFit: "cover" }}

View File

@@ -19,7 +19,7 @@ const SECTIONS: Section[] = [
{
id: 1,
title: "FMCG",
image: "/images/tab-pic-1-solution.jpeg",
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.",
@@ -39,7 +39,7 @@ const SECTIONS: Section[] = [
{
id: 2,
title: "Pharma",
image: "/images/tab-pic-2-solution.jpeg",
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.",
@@ -59,7 +59,7 @@ const SECTIONS: Section[] = [
{
id: 3,
title: "Enterprise & B2B",
image: "/images/tab-pic-3-solution.jpeg",
image: "/images/tab-pic-3-solution.webp",
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.",

View File

@@ -44,6 +44,7 @@ export default function MileTruthHero() {
return (
<>
<link rel="preload" as="image" href="/images/miletruth-bg.webp" />
<style dangerouslySetInnerHTML={{ __html: `
/* ── Hero wrapper: column layout, zero gap between hero + stats ── */
.miletruth-hero .elementor-element-86f3204 {
@@ -56,7 +57,7 @@ export default function MileTruthHero() {
/* ── Hero slider card ── */
.miletruth-hero-container {
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.05) 0%, rgba(0, 0, 0, 0.15) 55%, rgba(0, 0, 0, 0.3) 100%), url('/images/miletruth-bg.png') !important;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.05) 0%, rgba(0, 0, 0, 0.15) 55%, rgba(0, 0, 0, 0.3) 100%), url('/images/miletruth-bg.webp') !important;
background-size: cover !important;
background-position: center !important;
background-repeat: no-repeat !important;

View File

@@ -6,28 +6,28 @@ export default function OurTeam() {
{
name: "Ratan Kumar",
position: "COO & Operational Specialist",
image: "/images/Investor.png",
image: "/images/Investor.webp",
},
{
name: "Parthiban",
position: "CGO & Growth Specialist",
image: "/images/Parthi.png",
image: "/images/Parthi.webp",
},
{
name: "Aravinth",
position: "CFO & Finance Specialist",
image: "/images/Aravinth.png",
image: "/images/Aravinth.webp",
},
{
name: "Fazul Ilahi",
position: "CTO & Technology Specialist",
image: "/images/Fazul.png",
image: "/images/Fazul.webp",
},
{
name: "Suriya Kumar",
position: "Engineering Head & AI Specialist",
image: "/images/Suriya.png",
image: "/images/Suriya.webp",
},
];
@@ -122,6 +122,10 @@ export default function OurTeam() {
width: 100%;
margin: 0;
}
.team-listing-wrapper.team-grid-listing .team-item .post-title .team-member-name {
color: inherit;
text-decoration: none;
}
`}} />
<div className="elementor-element elementor-element-c2c601a e-flex e-con-boxed cut-corner-no sticky-container-off e-con e-parent" data-id="c2c601a" data-element_type="container" data-e-type="container">
<div className="e-con-inner">
@@ -149,7 +153,6 @@ export default function OurTeam() {
<div className="team-item">
<div className="team-item-media">
<div className="post-media">
<a href="#">
<Image
src={member.image}
alt={member.name}
@@ -157,11 +160,10 @@ export default function OurTeam() {
height={360}
style={{ objectFit: "cover", width: "100%", height: "100%" }}
/>
</a>
</div>
</div>
<div className="team-item-content">
<div className="post-title"><a href="#">{member.name}</a></div>
<div className="post-title"><span className="team-member-name">{member.name}</span></div>
<div className="team-item-position" dangerouslySetInnerHTML={{ __html: member.position }}></div>
<div className="team-item-socials">
<ul className="team-socials wrapper-socials">

View File

@@ -74,6 +74,7 @@ export default function SingleBlog({ post }: { post: BlogPost }) {
return (
<article className="dm-single-blog">
<link rel="preload" as="image" href={post.image} />
<style dangerouslySetInnerHTML={{ __html: STYLES }} />
{/* ── Full-width page banner (image + badge + title only) ──────── */}

View File

@@ -19,17 +19,18 @@ export default function SolutionsHero() {
return (
<>
<link rel="preload" as="image" href="/images/home1-slide-1.webp" />
<style dangerouslySetInnerHTML={{ __html: `
.howits-hero-custom-bg.elementor-repeater-item-3264830,
.howits-hero-custom-bg.elementor-repeater-item-6867061 {
background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1)), url('/images/home1-slide-1.png') !important;
background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1)), url('/images/home1-slide-1.webp') !important;
background-position: center !important;
background-repeat: no-repeat !important;
background-size: cover !important;
}
.howits-hero-custom-bg.elementor-repeater-item-6867061 {
background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1)), url('/images/home1-slide-2.png') !important;
background-image: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1)), url('/images/home1-slide-2.webp') !important;
background-position: center !important;
background-repeat: no-repeat !important;
background-size: cover !important;

View File

@@ -19,7 +19,7 @@ type Stage = {
const STAGES: Stage[] = [
{
img: "/images/first-mile-approach.jpg",
img: "/images/first-mile-approach.webp",
label: "Stage 01",
title: "First Mile Warehouse",
subtitle: "Consolidation & Prep",
@@ -31,7 +31,7 @@ const STAGES: Stage[] = [
]
},
{
img: "/images/mid-mile-approach.jpg",
img: "/images/mid-mile-approach.webp",
label: "Stage 02",
title: "Mid Mile Transit",
subtitle: "Hub-to-Hub Transport",
@@ -43,7 +43,7 @@ const STAGES: Stage[] = [
]
},
{
img: "/images/last-mile-approach.jpg",
img: "/images/last-mile-approach.webp",
label: "Stage 03",
title: "Last Mile Delivery",
subtitle: "Hub to Doorstep",

View File

@@ -12,7 +12,7 @@ const WS_STATS = [
const WS_CARDS = [
{
title: "Women Leadership",
desc: "Women driving decisions across operations, routing, and last-mile delivery every day.",
desc: "Women shaping strategy and driving excellence across logistics operations.",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="9" r="5" />
@@ -22,7 +22,7 @@ const WS_CARDS = [
},
{
title: "Entrepreneurship",
desc: "Enabling women to build, own, and scale their own delivery businesses.",
desc: "Women building sustainable businesses within the logistics ecosystem.",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
<rect x="3" y="7" width="18" height="13" rx="2" />
@@ -32,7 +32,7 @@ const WS_CARDS = [
},
{
title: "Innovation",
desc: "Fresh thinking that reshapes how first and last-mile logistics actually work.",
desc: "Women advancing logistics through practical ideas and operational insight.",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
<path d="M9 18h6M10 21h4" />
@@ -42,7 +42,7 @@ const WS_CARDS = [
},
{
title: "Community Growth",
desc: "Local hiring and training that lifts entire neighbourhoods, not just routes.",
desc: "Creating local opportunities through training, employment, and empowerment.",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
<circle cx="9" cy="8" r="3" />
@@ -117,14 +117,18 @@ export default function WomenSection() {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
align-items: stretch;
}
#ws-stories .ws__card {
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
min-height: 168px;
background: rgba(255,255,255,0.035);
border: 1px solid rgba(255,255,255,0.08);
border-radius: 16px;
padding: 22px 20px;
border-radius: 14px;
padding: 20px;
transition: transform 0.35s cubic-bezier(.25,1,.5,1), border-color 0.35s ease, background-color 0.35s ease, box-shadow 0.35s ease;
}
#ws-stories .ws__card::after {
@@ -148,31 +152,31 @@ export default function WomenSection() {
display: inline-flex;
align-items: center;
justify-content: center;
width: 44px; height: 44px;
border-radius: 12px;
width: 40px; height: 40px;
border-radius: 11px;
background: rgba(220,38,38,0.12);
border: 1px solid rgba(220,38,38,0.25);
color: #ef4444;
margin-bottom: 14px;
margin-bottom: 16px;
transition: background-color 0.3s ease, color 0.3s ease;
}
#ws-stories .ws__card:hover .ws__card-icon { background: #dc2626; color: #fff; }
#ws-stories .ws__card-icon svg { width: 22px; height: 22px; }
#ws-stories .ws__card-icon svg { width: 21px; height: 21px; }
#ws-stories .ws__card-title {
color: #fff !important;
font-weight: 900;
font-size: 17px;
letter-spacing: -0.01em;
margin-bottom: 8px;
font-weight: 800;
font-size: 19px;
line-height: 1.2;
letter-spacing: 0;
margin-bottom: 9px;
}
#ws-stories .ws__card-desc {
color: rgba(255,255,255,0.6) !important;
font-size: 13.5px;
line-height: 1.6;
max-width: 28ch;
color: rgba(255,255,255,0.66) !important;
font-size: 15px;
line-height: 1.52;
margin: 0;
font-weight: 900;
font-size: 16px;
font-weight: 500;
}
.elementor-element-778840d .logico-title {
@@ -262,7 +266,7 @@ export default function WomenSection() {
</div>
<div
style={{ backgroundImage: "url(/images/bg-header-women.png)" }}
style={{ backgroundImage: "url(/images/bg-header-women.webp)" }}
className="elementor-element elementor-element-7da6646 e-con-full e-flex cut-corner-no sticky-container-off e-con e-child"
data-id="7da6646"
data-element_type="container"
@@ -331,7 +335,7 @@ export default function WomenSection() {
<div className="elementor-element elementor-element-bbfb67f elementor-widget elementor-widget-image" data-id="bbfb67f" data-element_type="widget" data-e-type="widget" data-widget_type="image.default">
<div className="elementor-widget-container">
<Image
src="/images/bg-map-women.png"
src="/images/bg-map-women.webp"
alt="Women Map"
width={626}
height={692}

View File

@@ -89,7 +89,7 @@ export default function Workflow1() {
ariaLabel="Workflow 1 — Performance"
gapTop
gapBottom
bannerImage="/images/mile-1.png"
bannerImage="/images/mile-1.webp"
cardTitle="OPTIMIZE EVERY MILE"
cardSubtitle="Cut travel distance, reduce operating cost, and improve fleet productivity across every route."
eyebrow="/ Performance /"

View File

@@ -89,13 +89,13 @@ export default function Workflow2() {
<EVSection
ariaLabel="Workflow 2 — Innovation"
gapBottom
bannerImage="/images/mid-mile-approach.jpg"
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."
eyebrow="/ Innovation /"
titleLead="MANY STRATEGIES. "
titleAccent="ONE BEST PLAN."
image="/images/b5b560fe-aab0-4fe6-9f8c-4b187c2f0e99.png"
image="/videos/workflow-2-routing.mp4"
imageAlt="AI route-planning engine selecting the best delivery plan"
metrics={METRICS}
features={FEATURES}

View File

@@ -128,7 +128,7 @@ const seeds: SeedPost[] = [
excerpt:
"A practical look at how EV fleets can plan routes, manage charging, and keep delivery promises without adding unnecessary vehicles.",
category: "Technology",
image: "/images/blog-post-pic-17.png",
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.",
@@ -166,7 +166,7 @@ const seeds: SeedPost[] = [
},
{
type: "image",
src: "/images/ev-paradox.png",
src: "/images/ev-paradox.webp",
alt: "Electric delivery vehicle routing visualisation",
caption:
"EV route plans need to account for range, load, traffic, and charging time before riders leave the hub.",
@@ -209,7 +209,7 @@ const seeds: SeedPost[] = [
excerpt:
"A practical look at how one Hyderabad hub reduced distance, used fewer vehicles, and protected delivery windows with better route planning.",
category: "Case Study",
image: "/images/blog-post-pic-15.png",
image: "/images/blog-post-pic-15.webp",
date: "2025-09-18",
intro:
"Numbers settle arguments. At our Hyderabad hub, the goal was simple: reduce avoidable distance without missing customer commitments. The result was a 42% reduction in total distance travelled.",
@@ -255,7 +255,7 @@ const seeds: SeedPost[] = [
},
{
type: "image",
src: "/images/last-mile-approach.jpg",
src: "/images/last-mile-approach.webp",
alt: "Hyderabad delivery hub routing analysis",
caption:
"Planning the day's deliveries together removed repeated cross-town travel.",
@@ -302,7 +302,7 @@ const seeds: SeedPost[] = [
excerpt:
"From order intake to final route output, here is how a dispatch plan is checked before riders leave the hub.",
category: "MileTruth",
image: "/images/blog-post-pic-31.png",
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.",
@@ -343,7 +343,7 @@ const seeds: SeedPost[] = [
},
{
type: "image",
src: "/images/blog-post-pic-31.png",
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.",
@@ -385,7 +385,7 @@ const seeds: SeedPost[] = [
excerpt:
"Electric vehicles lower running costs, but battery range changes how routes must be planned before dispatch.",
category: "EV Fleet",
image: "/images/ev-paradox.png",
image: "/images/ev-paradox.webp",
date: "2025-08-21",
intro:
"Electric fleets can lower running costs, but range becomes a daily planning constraint. The route has to match the battery, the load, the traffic, and the return plan.",
@@ -396,7 +396,7 @@ const seeds: SeedPost[] = [
excerpt:
"Fixed routing rules are easy to start with, but they often miss better stop sequences as order volume grows.",
category: "Technology",
image: "/images/blog-post-pic-14.jpeg",
image: "/images/blog-post-pic-14.webp",
date: "2025-08-07",
intro:
"Simple routing rules are fast to set up, but they can quietly add distance every day. Better planning compares more route options before dispatch.",
@@ -407,7 +407,7 @@ const seeds: SeedPost[] = [
excerpt:
"Handling the same order volume with fewer vehicles starts by removing avoidable kilometres and overlapping routes.",
category: "Fleet Management",
image: "/images/blog-post-pic-8.jpeg",
image: "/images/blog-post-pic-8.webp",
date: "2025-07-24",
intro:
"Cutting vehicles usually means cutting capacity unless the removed kilometres were never needed. Better route planning turns wasted distance into operating headroom.",
@@ -418,7 +418,7 @@ const seeds: SeedPost[] = [
excerpt:
"Cities are asking for cleaner delivery. The practical challenge is planning EV routes that can meet customer windows without wasting charge.",
category: "Sustainability",
image: "/images/blog-post-pic-6.jpeg",
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.",
@@ -429,7 +429,7 @@ const seeds: SeedPost[] = [
excerpt:
"High SLA performance comes from checking ETAs before dispatch, reacting early to delays, and keeping customer commitments visible throughout the day.",
category: "Operations",
image: "/images/last-mile-approach.jpg",
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.",
@@ -440,7 +440,7 @@ const seeds: SeedPost[] = [
excerpt:
"Before a rider 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.jpeg",
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.",

View File

@@ -118,7 +118,7 @@ function StaticFallback() {
>
{/* Optional poster image; if it 404s we keep the gradient + caption. */}
<img
src="/images/hiw-3d-fallback.jpg"
src="/images/home2-banner-1.webp"
alt="Doormile delivery journey — first mile to last mile"
loading="lazy"
decoding="async"

Binary file not shown.