442 lines
19 KiB
TypeScript
442 lines
19 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
|
|
interface CounterProps {
|
|
from: number;
|
|
to: number;
|
|
duration?: number;
|
|
decimals?: number;
|
|
suffix?: string;
|
|
}
|
|
|
|
function Counter({ from, to, duration = 2000, decimals = 0, suffix = "" }: CounterProps) {
|
|
const [value, setValue] = useState(from);
|
|
|
|
useEffect(() => {
|
|
let startTimestamp: number | null = null;
|
|
const step = (timestamp: number) => {
|
|
if (!startTimestamp) startTimestamp = timestamp;
|
|
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
|
|
const currentValue = progress * (to - from) + from;
|
|
setValue(currentValue);
|
|
if (progress < 1) {
|
|
window.requestAnimationFrame(step);
|
|
}
|
|
};
|
|
window.requestAnimationFrame(step);
|
|
}, [from, to, duration]);
|
|
|
|
return (
|
|
<>
|
|
{value.toFixed(decimals)}
|
|
{suffix}
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default function MileTruthHero() {
|
|
const [mounted, setMounted] = useState(false);
|
|
|
|
useEffect(() => {
|
|
requestAnimationFrame(() => setMounted(true));
|
|
}, []);
|
|
|
|
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 {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0;
|
|
margin: 0;
|
|
padding: 0 20px;
|
|
}
|
|
|
|
/* ── 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.webp') !important;
|
|
background-size: cover !important;
|
|
background-position: center !important;
|
|
background-repeat: no-repeat !important;
|
|
/* Match the home page hero card (800px) so MileTruth has the same visual
|
|
presence on large desktop, MacBook M1/Pro, and standard laptops. */
|
|
min-height: 800px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
border-radius: 25px 25px 0 0;
|
|
margin-top: 20px;
|
|
padding: 100px 40px;
|
|
}
|
|
.miletruth-hero-container::before {
|
|
display: none !important;
|
|
}
|
|
.miletruth-content {
|
|
position: relative;
|
|
z-index: 2;
|
|
width: 100%;
|
|
padding: 0 40px !important;
|
|
box-sizing: border-box;
|
|
}
|
|
.miletruth-hero .content-slider-item-heading,
|
|
.miletruth-hero .content-slider-item-heading .heading-content {
|
|
color: rgba(255, 255, 255, 0.96) !important;
|
|
font-family: var(--font-manrope), "Manrope", sans-serif !important;
|
|
font-size: clamp(34px, 5.5vw, 72px) !important;
|
|
font-weight: 850 !important;
|
|
line-height: 1.05 !important;
|
|
letter-spacing: -1.5px !important;
|
|
text-transform: uppercase !important;
|
|
text-align: center !important;
|
|
display: block;
|
|
}
|
|
.miletruth-hero .content-slider-item-text {
|
|
margin-top: 22px !important;
|
|
text-align: center !important;
|
|
}
|
|
.miletruth-hero .content-slider-item-text p {
|
|
color: rgba(255, 255, 255, 0.72) !important;
|
|
font-family: var(--font-manrope), "Manrope", sans-serif !important;
|
|
font-size: clamp(17px, 1.6vw, 23px) !important;
|
|
font-weight: 500 !important;
|
|
line-height: 1.65 !important;
|
|
margin: 0 auto !important;
|
|
max-width: 820px;
|
|
}
|
|
.miletruth-hero .slide-content {
|
|
display: flex !important;
|
|
flex-direction: column !important;
|
|
align-items: center !important;
|
|
justify-content: center !important;
|
|
text-align: center !important;
|
|
width: 100% !important;
|
|
height: 100% !important;
|
|
padding: 0 40px !important;
|
|
box-sizing: border-box !important;
|
|
}
|
|
.miletruth-hero .slide-content,
|
|
.miletruth-hero .slide-content-inner {
|
|
/* These carry inherited 20px padding from the slider theme with
|
|
content-box sizing, so width:100% + padding overflowed the viewport
|
|
by ~40px and pushed the hero off-center. Force border-box so the
|
|
padding is contained and the block stays centered. */
|
|
box-sizing: border-box !important;
|
|
}
|
|
.miletruth-hero .slide-content-inner {
|
|
display: flex !important;
|
|
flex-direction: column !important;
|
|
align-items: center !important;
|
|
justify-content: center !important;
|
|
text-align: center !important;
|
|
margin-left: auto !important;
|
|
margin-right: auto !important;
|
|
max-width: 1000px !important;
|
|
width: 100% !important;
|
|
}
|
|
.miletruth-hero .content-slider-item-heading,
|
|
.miletruth-hero .content-slider-item-heading .heading-content {
|
|
text-align: center !important;
|
|
display: block !important;
|
|
width: 100% !important;
|
|
margin-left: auto !important;
|
|
margin-right: auto !important;
|
|
}
|
|
.miletruth-hero .content-slider-item-text {
|
|
display: flex !important;
|
|
justify-content: center !important;
|
|
width: 100% !important;
|
|
margin-top: 23px !important;
|
|
text-align: center !important;
|
|
}
|
|
.miletruth-hero .text-content {
|
|
text-align: center !important;
|
|
max-width: 800px !important;
|
|
margin: 0 auto !important;
|
|
}
|
|
/* The "logico" slider reveal animation leaves these at opacity:0 until
|
|
its JS runs (absent in this rebuild), hiding the heading + subtitle.
|
|
Force them visible. */
|
|
.miletruth-hero .content-slider-item-heading,
|
|
.miletruth-hero .content-slider-item-text,
|
|
.miletruth-hero .logico-content-wrapper-1,
|
|
.miletruth-hero .logico-content-wrapper-2 {
|
|
opacity: 1 !important;
|
|
transform: none !important;
|
|
visibility: visible !important;
|
|
}
|
|
|
|
/* ══════════════════════════════════════════════════════════════════
|
|
Stats bar — dark rounded card overlapping the hero bottom
|
|
══════════════════════════════════════════════════════════════════ */
|
|
.miletruth-hero .elementor-element-8e5c81e {
|
|
display: flex !important;
|
|
flex-direction: column !important;
|
|
justify-content: center !important;
|
|
width: 100% !important;
|
|
margin: -25px 0 0 0 !important;
|
|
background-color: #1F1F1F !important;
|
|
border-radius: 25px !important;
|
|
padding: 40px 0 !important;
|
|
position: relative !important;
|
|
z-index: 1 !important;
|
|
}
|
|
.miletruth-hero .elementor-element-8e5c81e > .e-con-inner {
|
|
width: 100% !important;
|
|
max-width: 1440px !important;
|
|
height: auto !important;
|
|
margin: 0 auto !important;
|
|
padding: 0 40px !important;
|
|
flex-grow: 0 !important;
|
|
box-sizing: border-box !important;
|
|
}
|
|
|
|
/* 4-col grid for counter widgets — rows size to content (not 1fr of the
|
|
container) so the counters aren't parked at the top of a tall row. */
|
|
.miletruth-hero .elementor-element-628123a {
|
|
display: grid !important;
|
|
grid-template-columns: repeat(4, 1fr) !important;
|
|
grid-template-rows: auto !important;
|
|
height: auto !important;
|
|
gap: 40px !important;
|
|
width: 100% !important;
|
|
justify-items: start !important;
|
|
align-items: start !important;
|
|
align-content: start !important;
|
|
}
|
|
|
|
/* Counter: title on top, number below, left-aligned */
|
|
.miletruth-hero .elementor-counter {
|
|
display: flex !important;
|
|
flex-direction: column !important;
|
|
align-items: flex-start !important;
|
|
text-align: left !important;
|
|
}
|
|
|
|
/* Counter title — above the number */
|
|
.miletruth-hero .elementor-counter-title {
|
|
font-family: var(--font-manrope), "Manrope", sans-serif !important;
|
|
font-size: 20px !important;
|
|
font-weight: 600 !important;
|
|
line-height: 1.3em !important;
|
|
color: #FFFFFF !important;
|
|
margin-bottom: 12px !important;
|
|
text-transform: none !important;
|
|
}
|
|
|
|
/* Counter number wrapper — centered */
|
|
.miletruth-hero .elementor-counter-number-wrapper {
|
|
font-family: var(--font-space-grotesk), "Space Grotesk", var(--font-manrope), "Manrope", sans-serif !important;
|
|
font-size: clamp(48px, 6.5vw, 100px) !important;
|
|
font-weight: 700 !important;
|
|
line-height: 1em !important;
|
|
color: #C01227 !important;
|
|
letter-spacing: -0.03em !important;
|
|
display: flex !important;
|
|
align-items: baseline !important;
|
|
justify-content: flex-start !important;
|
|
}
|
|
.miletruth-hero .elementor-counter-number {
|
|
color: #C01227 !important;
|
|
font-size: inherit !important;
|
|
font-weight: inherit !important;
|
|
}
|
|
.miletruth-hero .elementor-counter-number-suffix {
|
|
color: #C01227 !important;
|
|
font-size: inherit !important;
|
|
font-weight: inherit !important;
|
|
letter-spacing: -0.03em !important;
|
|
}
|
|
|
|
/* ── Responsive ── */
|
|
@media (max-width: 1200px) {
|
|
.miletruth-hero .content-slider-item-heading,
|
|
.miletruth-hero .content-slider-item-heading .heading-content {
|
|
font-size: 60px !important;
|
|
}
|
|
}
|
|
@media (max-width: 1024px) {
|
|
.miletruth-hero-container {
|
|
min-height: 600px;
|
|
padding: 120px 0;
|
|
}
|
|
.miletruth-hero .elementor-element-8e5c81e {
|
|
padding: 40px 0 !important;
|
|
}
|
|
.miletruth-hero .elementor-element-628123a {
|
|
grid-template-columns: repeat(2, 1fr) !important;
|
|
gap: 50px 40px !important;
|
|
}
|
|
.miletruth-hero .content-slider-item-heading,
|
|
.miletruth-hero .content-slider-item-heading .heading-content {
|
|
font-size: 50px !important;
|
|
line-height: 1.1 !important;
|
|
}
|
|
}
|
|
@media (max-width: 768px) {
|
|
.miletruth-hero .content-slider-item-heading,
|
|
.miletruth-hero .content-slider-item-heading .heading-content {
|
|
font-size: 40px !important;
|
|
line-height: 1.12 !important;
|
|
}
|
|
.miletruth-hero .content-slider-item-text p {
|
|
font-size: 16px !important;
|
|
}
|
|
}
|
|
@media (max-width: 580px) {
|
|
.miletruth-hero-container {
|
|
min-height: 500px;
|
|
padding: 100px 0;
|
|
}
|
|
.miletruth-hero .elementor-element-86f3204 {
|
|
padding: 0 12px;
|
|
}
|
|
/* Collapse the nested horizontal padding (was 40px + 40px on top of the
|
|
12px wrapper) — at 320px that left only ~136px for text and the long
|
|
heading words overflowed, causing horizontal scroll + off-center look. */
|
|
.miletruth-content {
|
|
padding: 0 14px !important;
|
|
}
|
|
.miletruth-hero .slide-content {
|
|
padding: 0 !important;
|
|
}
|
|
.miletruth-hero .elementor-element-8e5c81e {
|
|
padding: 30px 0 !important;
|
|
border-radius: 20px !important;
|
|
}
|
|
.miletruth-hero .elementor-element-8e5c81e > .e-con-inner {
|
|
padding: 0 20px !important;
|
|
}
|
|
.miletruth-hero .elementor-element-628123a {
|
|
grid-template-columns: 1fr !important;
|
|
gap: 36px !important;
|
|
/* Single column on mobile → center each stat in the card */
|
|
justify-items: center !important;
|
|
}
|
|
.miletruth-hero .elementor-counter {
|
|
align-items: center !important;
|
|
text-align: center !important;
|
|
}
|
|
.miletruth-hero .elementor-counter-number-wrapper {
|
|
justify-content: center !important;
|
|
}
|
|
.miletruth-hero .content-slider-item-heading,
|
|
.miletruth-hero .content-slider-item-heading .heading-content {
|
|
font-size: clamp(26px, 8vw, 32px) !important;
|
|
letter-spacing: -0.5px !important;
|
|
/* never let a single long word push past the viewport */
|
|
overflow-wrap: break-word;
|
|
word-break: break-word;
|
|
}
|
|
}
|
|
`}} />
|
|
|
|
<div className="elementor-63 miletruth-hero">
|
|
{/* Parent wrapper matching reference elementor-element-86f3204 */}
|
|
<div className="elementor-element elementor-element-86f3204 e-con-full e-flex cut-corner-no sticky-container-off e-con e-parent" data-id="86f3204" data-element_type="container" data-e-type="container">
|
|
{/* Hero slider card — NOT using custom-standard-hero-container/card
|
|
because this hero has a unique structure: hero + stats bar in a
|
|
single column with -25px overlap and no overflow:hidden */}
|
|
<div className="miletruth-hero-container">
|
|
<div className="e-con-inner miletruth-content">
|
|
<div className="logico-content-slider-widget">
|
|
<div className="content-slider-wrapper">
|
|
<div className="content-slider-container">
|
|
<div className="content-slider owl-carousel owl-theme">
|
|
<div className="content-item slider-item elementor-repeater-item-6867061 slide-style-standard">
|
|
<div className="slide-content" style={{ paddingLeft: 0, paddingRight: 0 }}>
|
|
<div className="slide-content-inner">
|
|
<h1 className="content-slider-item-heading logico-content-wrapper-1">
|
|
<span className="heading-content">The Only AI Built<br />Exclusively for Logistics</span>
|
|
</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>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Metric Stats Bar */}
|
|
<div className="elementor-element elementor-element-8e5c81e e-flex e-con-boxed cut-corner-no sticky-container-off e-con e-child" data-id="8e5c81e" data-element_type="container" data-e-type="container" data-settings='{"background_background":"classic"}'>
|
|
<div className="e-con-inner">
|
|
<div className="elementor-element elementor-element-628123a e-con-full e-grid cut-corner-no sticky-container-off e-con e-child" data-id="628123a" data-element_type="container" data-e-type="container">
|
|
|
|
{/* SLA Compliance */}
|
|
<div className="elementor-element elementor-element-1da88b5 elementor-widget elementor-widget-counter" data-id="1da88b5" data-element_type="widget" data-e-type="widget" data-widget_type="counter.default">
|
|
<div className="elementor-widget-container">
|
|
<div className="elementor-counter">
|
|
<div className="elementor-counter-title">SLA Compliance</div>
|
|
<div className="elementor-counter-number-wrapper">
|
|
<span className="elementor-counter-number">
|
|
{mounted ? <Counter from={1} to={99.9} decimals={1} suffix="" /> : "1"}
|
|
</span>
|
|
<span className="elementor-counter-number-suffix"> %</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Distance Saved */}
|
|
<div className="elementor-element elementor-element-1da88b5 elementor-widget elementor-widget-counter" data-id="1da88b5-2" data-element_type="widget" data-e-type="widget" data-widget_type="counter.default">
|
|
<div className="elementor-widget-container">
|
|
<div className="elementor-counter">
|
|
<div className="elementor-counter-title">Distance Saved</div>
|
|
<div className="elementor-counter-number-wrapper">
|
|
<span className="elementor-counter-number">
|
|
{mounted ? <Counter from={1} to={42} decimals={0} suffix="" /> : "1"}
|
|
</span>
|
|
<span className="elementor-counter-number-suffix"> %</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Fewer Vehicles */}
|
|
<div className="elementor-element elementor-element-1da88b5 elementor-widget elementor-widget-counter" data-id="1da88b5-3" data-element_type="widget" data-e-type="widget" data-widget_type="counter.default">
|
|
<div className="elementor-widget-container">
|
|
<div className="elementor-counter">
|
|
<div className="elementor-counter-title">Fewer Vehicles</div>
|
|
<div className="elementor-counter-number-wrapper">
|
|
<span className="elementor-counter-number">
|
|
{mounted ? <Counter from={1} to={37} decimals={0} suffix="" /> : "1"}
|
|
</span>
|
|
<span className="elementor-counter-number-suffix"> %</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Dispatch Latency */}
|
|
<div className="elementor-element elementor-element-a1cf3d4 elementor-widget elementor-widget-counter" data-id="a1cf3d4" data-element_type="widget" data-e-type="widget" data-widget_type="counter.default">
|
|
<div className="elementor-widget-container">
|
|
<div className="elementor-counter">
|
|
<div className="elementor-counter-title">Dispatch Latency</div>
|
|
<div className="elementor-counter-number-wrapper">
|
|
<span className="elementor-counter-number">
|
|
{mounted ? <Counter from={1} to={45} decimals={0} suffix="" /> : "45"}
|
|
</span>
|
|
<span className="elementor-counter-number-suffix">ms</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|