fix padding gap
This commit is contained in:
@@ -5,7 +5,7 @@ import { useHeaderUI } from "./HeaderUIProvider";
|
||||
/**
|
||||
* Production: `<div class="body-overlay"></div>` is a direct child of body
|
||||
* (rendered by both index.php line 6 and header.php line 5 — production has two; we render one).
|
||||
* CSS (in vendor-theme-core.css and elementor-frontend-inline-css.css) styles it as fixed-position fullscreen overlay.
|
||||
* CSS (consolidated into /public/css/site.css) styles it as fixed-position fullscreen overlay.
|
||||
*/
|
||||
export default function BodyOverlay() {
|
||||
const { isMenuOpen, isSidebarOpen, closeAll } = useHeaderUI();
|
||||
|
||||
@@ -527,6 +527,16 @@ export default function Header() {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
#masthead .header-menu-container .main-menu > li.active > a {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
#masthead .header-menu-container .main-menu > li > a:focus,
|
||||
#masthead .header-menu-container .main-menu > li > a:focus-visible {
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* Responsive logo adjustment on mobile/tablet */
|
||||
@media (max-width: 1024px) {
|
||||
#masthead .elementor-element.elementor-element-846e53d .hfe-site-logo .hfe-site-logo-container img {
|
||||
|
||||
@@ -5,7 +5,7 @@ import dynamic from "next/dynamic";
|
||||
import { motion, useMotionValue, useTransform, type MotionValue } from "framer-motion";
|
||||
import gsap from "gsap";
|
||||
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||
import { P, STRATEGIES, ENGINE_STEPS, CONSTRAINT_LIST, STRATEGY_SCORES } from "./theme";
|
||||
import { P, STRATEGIES, WINNER_INDEX, ENGINE_STEPS, CONSTRAINT_LIST, STRATEGY_SCORES } from "./theme";
|
||||
|
||||
const LogisticsBrainCanvas = dynamic(() => import("./LogisticsBrainCanvas"), { ssr: false });
|
||||
|
||||
@@ -53,12 +53,21 @@ function StepRail({ active }: { active: number }) {
|
||||
);
|
||||
}
|
||||
|
||||
/** One cross-fading workflow card pinned to the lower-left. */
|
||||
/**
|
||||
* One workflow card that travels through the story. The outer anchor pins it to
|
||||
* its stage position (Left / Center / Right / Center-Hero); the inner motion card
|
||||
* slides + scales into that anchor in lockstep with scroll, so as the camera moves
|
||||
* through the stages the card visibly moves with the narrative instead of sitting
|
||||
* fixed in one corner.
|
||||
*/
|
||||
function StoryCard({
|
||||
step,
|
||||
index,
|
||||
pos,
|
||||
opacity,
|
||||
y,
|
||||
x,
|
||||
scale,
|
||||
num,
|
||||
kicker,
|
||||
title,
|
||||
@@ -66,8 +75,11 @@ function StoryCard({
|
||||
}: {
|
||||
step: number;
|
||||
index: number;
|
||||
pos: "left" | "center" | "right" | "hero";
|
||||
opacity: MotionValue<number>;
|
||||
y: MotionValue<number>;
|
||||
x: MotionValue<number>;
|
||||
scale: MotionValue<number>;
|
||||
num: string;
|
||||
kicker: string;
|
||||
title: string;
|
||||
@@ -76,14 +88,16 @@ function StoryCard({
|
||||
// Don't mount this beat's card until its step is active.
|
||||
if (step !== index) return null;
|
||||
return (
|
||||
<motion.div className="dm-lb-card-story" style={{ opacity, y }}>
|
||||
<div className="dm-lb-card-story__head">
|
||||
<span className="dm-lb-pillar__num">{num}</span>
|
||||
<span className="dm-lb-pillar__kicker">{kicker}</span>
|
||||
</div>
|
||||
<h3 className="dm-lb-pillar__title">{title}</h3>
|
||||
{children}
|
||||
</motion.div>
|
||||
<div className={`dm-lb-card-anchor is-${pos}`}>
|
||||
<motion.div className="dm-lb-card-story" style={{ opacity, y, x, scale }}>
|
||||
<div className="dm-lb-card-story__head">
|
||||
<span className="dm-lb-pillar__num">{num}</span>
|
||||
<span className="dm-lb-pillar__kicker">{kicker}</span>
|
||||
</div>
|
||||
<h3 className="dm-lb-pillar__title">{title}</h3>
|
||||
{children}
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -182,6 +196,22 @@ export default function LogisticsBrainSection({ connected = false }: { connected
|
||||
const p5o = useTransform(scroll, [0.75, 0.78, 0.855, 0.875], [0, 1, 1, 0]);
|
||||
const p5y = useTransform(scroll, [0.75, 0.79], [26, 0]);
|
||||
|
||||
// Horizontal slide + scale per beat — same windows as the opacity above, so the
|
||||
// card glides between its stage anchors (Left → Center → Right → Left → Center-Hero)
|
||||
// in lockstep with the camera. Each card enters from the direction of the previous
|
||||
// stage and drifts toward the next as it leaves, reading as one continuous travel.
|
||||
const p1x = useTransform(scroll, [0.135, 0.165, 0.255, 0.275], [-52, 0, 0, 52]);
|
||||
const p1s = useTransform(scroll, [0.135, 0.165, 0.255, 0.275], [0.965, 1, 1, 0.965]);
|
||||
const p2x = useTransform(scroll, [0.29, 0.32, 0.415, 0.435], [-52, 0, 0, 52]);
|
||||
const p2s = useTransform(scroll, [0.29, 0.32, 0.415, 0.435], [0.965, 1, 1, 0.965]);
|
||||
const p3x = useTransform(scroll, [0.45, 0.48, 0.575, 0.595], [-52, 0, 0, -52]);
|
||||
const p3s = useTransform(scroll, [0.45, 0.48, 0.575, 0.595], [0.965, 1, 1, 0.965]);
|
||||
const p4x = useTransform(scroll, [0.61, 0.64, 0.715, 0.735], [52, 0, 0, 52]);
|
||||
const p4s = useTransform(scroll, [0.61, 0.64, 0.715, 0.735], [0.965, 1, 1, 0.965]);
|
||||
// Hero (final selection): scales up a touch and holds center as it settles.
|
||||
const p5x = useTransform(scroll, [0.75, 0.78, 0.855, 0.875], [-52, 0, 0, 0]);
|
||||
const p5s = useTransform(scroll, [0.75, 0.78, 0.855, 0.875], [0.97, 1.05, 1.05, 1.0]);
|
||||
|
||||
const finaleOpacity = useTransform(scroll, [P.finale - 0.02, P.finale + 0.04], [0, 1]);
|
||||
const finaleY = useTransform(scroll, [P.finale - 0.02, P.finale + 0.06], [40, 0]);
|
||||
const taglineOpacity = useTransform(scroll, [P.finale + 0.04, P.finale + 0.1], [0, 1]);
|
||||
@@ -217,18 +247,18 @@ export default function LogisticsBrainSection({ connected = false }: { connected
|
||||
<span className="dm-lb-arrow">↓</span>
|
||||
</motion.div>
|
||||
|
||||
{/* STEP 01 — Generate Routes */}
|
||||
<StoryCard step={step} index={0} opacity={p1o} y={p1y} num="01" kicker="Generate Routes" title="We create many delivery plans at once">
|
||||
{/* 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">
|
||||
<div className="dm-lb-chips">
|
||||
{STRATEGIES.map((s) => (
|
||||
<span key={s} className="dm-lb-chip">{s}</span>
|
||||
{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>
|
||||
</StoryCard>
|
||||
|
||||
{/* STEP 02 — Check Constraints (the EV paradox) */}
|
||||
<StoryCard step={step} index={1} opacity={p2o} y={p2y} num="02" kicker="Check Constraints" title="Every plan must respect real-world limits">
|
||||
{/* STEP 02 — Check Constraints (card anchored CENTER) */}
|
||||
<StoryCard step={step} index={1} pos="center" opacity={p2o} y={p2y} x={p2x} scale={p2s} num="02" kicker="Check Constraints" title="Every plan must respect real-world limits">
|
||||
<ul className="dm-lb-constraints">
|
||||
{CONSTRAINT_LIST.map((c) => (
|
||||
<li key={c.label}>
|
||||
@@ -241,8 +271,8 @@ export default function LogisticsBrainSection({ connected = false }: { connected
|
||||
<p className="dm-lb-pillar__stat"><strong>59/59</strong> delivered <em>vs 34/59 when battery limits are ignored</em></p>
|
||||
</StoryCard>
|
||||
|
||||
{/* STEP 03 — Score & Compare (the leaderboard) */}
|
||||
<StoryCard step={step} index={2} opacity={p3o} y={p3y} num="03" kicker="Score & Compare" title="Each plan is scored by total delivery cost">
|
||||
{/* 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 & Compare" title="Each plan is scored by total delivery cost">
|
||||
<ul className="dm-lb-board">
|
||||
{STRATEGY_SCORES.map((s) => (
|
||||
<li key={s.name} className={s.win ? "is-win" : ""}>
|
||||
@@ -254,8 +284,8 @@ export default function LogisticsBrainSection({ connected = false }: { connected
|
||||
</ul>
|
||||
</StoryCard>
|
||||
|
||||
{/* STEP 04 — Guarantee On-Time */}
|
||||
<StoryCard step={step} index={3} opacity={p4o} y={p4y} num="04" kicker="Guarantee On-Time" title="Any plan even 1 minute late is rejected">
|
||||
{/* STEP 04 — Guarantee On-Time (card anchored LEFT) */}
|
||||
<StoryCard step={step} index={3} pos="left" opacity={p4o} y={p4y} x={p4x} scale={p4s} num="04" kicker="Guarantee On-Time" title="Any plan even 1 minute late is rejected">
|
||||
<div className="dm-lb-sla">
|
||||
<span className="dm-lb-sla__badge">⏱️ On-time only</span>
|
||||
<span className="dm-lb-sla__x">✕ Late plan → dropped</span>
|
||||
@@ -263,8 +293,8 @@ export default function LogisticsBrainSection({ connected = false }: { connected
|
||||
<p className="dm-lb-pillar__foot">We only keep plans that hit every promised delivery window.</p>
|
||||
</StoryCard>
|
||||
|
||||
{/* STEP 05 — Pick & Dispatch */}
|
||||
<StoryCard step={step} index={4} opacity={p5o} y={p5y} num="05" kicker="Pick & Dispatch" title="The winning plan is sent to the fleet">
|
||||
{/* STEP 05 — Pick & Dispatch (card anchored CENTER, hero) */}
|
||||
<StoryCard step={step} index={4} pos="hero" opacity={p5o} y={p5y} x={p5x} scale={p5s} num="05" kicker="Pick & Dispatch" title="The winning plan is sent to the fleet">
|
||||
<div className="dm-lb-winner">✓ Multi-Trip selected — lowest cost, zero delays</div>
|
||||
<div className="dm-lb-chips">
|
||||
<span className="dm-lb-chip">EV Bikes</span>
|
||||
@@ -381,62 +411,76 @@ const styles = `
|
||||
.dm-lb-arrow { font-size: 18px; animation: dmLbBob 1.8s ease-in-out infinite; }
|
||||
@keyframes dmLbBob { 0%,100% { transform: translateY(0); opacity: 0.5; } 50% { transform: translateY(6px); opacity: 1; } }
|
||||
|
||||
/* ---- Lower-left workflow card (glass panel, cross-fades per step) ---- */
|
||||
.dm-lb-card-story { position: absolute; left: clamp(18px, 4vw, 56px); bottom: clamp(26px, 7vh, 64px);
|
||||
width: min(440px, 84vw); pointer-events: auto; will-change: opacity, transform;
|
||||
/* ---- Story card: a premium light-glass panel that TRAVELS between stage
|
||||
anchors. The anchor pins the stage position; the inner card slides/scales into
|
||||
it (Left → Center → Right → Left → Center-Hero) in lockstep with scroll. ---- */
|
||||
.dm-lb-card-anchor { position: absolute; bottom: clamp(26px, 7vh, 64px); z-index: 6; pointer-events: none; }
|
||||
.dm-lb-card-anchor.is-left { left: clamp(18px, 4vw, 56px); }
|
||||
.dm-lb-card-anchor.is-right { right: clamp(18px, 4vw, 56px); }
|
||||
.dm-lb-card-anchor.is-center,
|
||||
.dm-lb-card-anchor.is-hero { left: 50%; transform: translateX(-50%); }
|
||||
/* Hero (final selection) sits a little higher + centred so it reads as the payoff. */
|
||||
.dm-lb-card-anchor.is-hero { bottom: clamp(40px, 9vh, 92px); }
|
||||
|
||||
.dm-lb-card-story { position: relative; width: min(440px, 84vw); pointer-events: auto;
|
||||
will-change: opacity, transform; transform-origin: bottom center;
|
||||
padding: 18px 20px; border-radius: 18px;
|
||||
background: rgba(14,8,10,0.9); border: 1px solid rgba(226,53,66,0.22);
|
||||
/* backdrop blur removed — this card cross-fades/translates on scroll, so the blur
|
||||
was recomputed every frame; a near-opaque fill keeps the look at no per-frame cost. */
|
||||
box-shadow: 0 24px 64px -30px rgba(0,0,0,0.92); }
|
||||
/* Premium light glass — clean SaaS surface, brand red used only as a top accent. */
|
||||
background: rgba(255,255,255,0.94);
|
||||
border: 1px solid rgba(15,23,42,0.08); border-top: 3px solid #C01227;
|
||||
box-shadow: 0 28px 70px -34px rgba(15,23,42,0.45); }
|
||||
.dm-lb-card-anchor.is-hero .dm-lb-card-story { width: min(480px, 88vw);
|
||||
box-shadow: 0 38px 92px -34px rgba(192,18,39,0.4); }
|
||||
.dm-lb-card-story__head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
|
||||
.dm-lb-pillar__num { font-size: 12px; font-weight: 700; letter-spacing: 0.1em; color: #ffffff;
|
||||
background: linear-gradient(135deg, #E2354A, #C01227); border-radius: 7px; padding: 3px 8px; }
|
||||
.dm-lb-pillar__kicker { font-size: clamp(11px, 1.1vw, 13px); font-weight: 700; letter-spacing: 0.18em;
|
||||
text-transform: uppercase; color: #F2667A; }
|
||||
.dm-lb .dm-lb-pillar__title { margin: 0 0 12px !important; padding: 0 !important; color: #fbf5f6 !important;
|
||||
text-transform: uppercase; color: #C01227; }
|
||||
.dm-lb .dm-lb-pillar__title { margin: 0 0 12px !important; padding: 0 !important; color: #0f172a !important;
|
||||
font-weight: 700 !important; text-transform: none !important; letter-spacing: -0.015em !important;
|
||||
font-size: clamp(17px, 1.9vw, 24px) !important; line-height: 1.18 !important;
|
||||
text-shadow: 0 0 30px rgba(192,18,39,0.3) !important; }
|
||||
.dm-lb-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
|
||||
.dm-lb-chip { font-size: 11.5px; font-weight: 600; letter-spacing: 0.02em; color: #f1dadd;
|
||||
padding: 4px 11px; border-radius: 999px; background: rgba(192,18,39,0.12);
|
||||
border: 1px solid rgba(226,53,66,0.30); white-space: nowrap; }
|
||||
.dm-lb-pillar__foot { margin: 0; font-size: clamp(12px, 1.1vw, 13.5px); line-height: 1.45; color: rgba(236,224,226,0.72); }
|
||||
.dm-lb-pillar__stat { margin: 6px 0 0; font-size: clamp(12.5px, 1.2vw, 15px); color: rgba(236,224,226,0.78); }
|
||||
.dm-lb-pillar__stat strong { color: #4ade80; font-weight: 800; font-size: 1.25em; text-shadow: 0 0 20px rgba(34,197,94,0.5); }
|
||||
.dm-lb-pillar__stat em { font-style: normal; color: rgba(230,218,220,0.55); }
|
||||
font-size: clamp(17px, 1.9vw, 24px) !important; line-height: 1.18 !important; }
|
||||
.dm-lb-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 10px; }
|
||||
/* Strategy pills — white pills, soft border + light shadow, brand-red active state. */
|
||||
.dm-lb-chip { font-size: 11.5px; font-weight: 600; letter-spacing: 0.02em; color: #334155;
|
||||
padding: 5px 12px; border-radius: 999px; background: #ffffff;
|
||||
border: 1px solid rgba(15,23,42,0.1); box-shadow: 0 1px 2px rgba(15,23,42,0.06); white-space: nowrap; }
|
||||
.dm-lb-chip--active { color: #ffffff; background: linear-gradient(135deg, #E2354A, #C01227);
|
||||
border-color: transparent; box-shadow: 0 6px 16px -6px rgba(192,18,39,0.5); }
|
||||
.dm-lb-pillar__foot { margin: 0; font-size: clamp(12px, 1.1vw, 13.5px); line-height: 1.45; color: #475569; }
|
||||
.dm-lb-pillar__stat { margin: 6px 0 0; font-size: clamp(12.5px, 1.2vw, 15px); color: #475569; }
|
||||
.dm-lb-pillar__stat strong { color: #16a34a; font-weight: 800; font-size: 1.25em; }
|
||||
.dm-lb-pillar__stat em { font-style: normal; color: #94a3b8; }
|
||||
|
||||
/* Constraints checklist (step 02) */
|
||||
.dm-lb-constraints { list-style: none; margin: 0 0 10px; padding: 0; display: grid; gap: 7px; }
|
||||
.dm-lb-constraints li { display: flex; align-items: center; gap: 9px; }
|
||||
.dm-lb-constraints__icon { font-size: 14px; width: 20px; text-align: center; }
|
||||
.dm-lb-constraints__label { font-size: 13px; font-weight: 700; color: #fbeff0; min-width: 84px; }
|
||||
.dm-lb-constraints__note { font-size: 12px; color: rgba(232,222,224,0.6); }
|
||||
.dm-lb-constraints__label { font-size: 13px; font-weight: 700; color: #0f172a; min-width: 84px; }
|
||||
.dm-lb-constraints__note { font-size: 12px; color: #64748b; }
|
||||
|
||||
/* Scored leaderboard (step 03) */
|
||||
.dm-lb-board { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
|
||||
.dm-lb-board li { display: grid; grid-template-columns: 104px 1fr 26px; align-items: center; gap: 9px; }
|
||||
.dm-lb-board__name { font-size: 11.5px; font-weight: 600; color: rgba(234,226,228,0.68); display: flex; align-items: center; gap: 6px; white-space: nowrap; }
|
||||
.dm-lb-board li.is-win .dm-lb-board__name { color: #fff; font-weight: 800; }
|
||||
.dm-lb-board__name { font-size: 11.5px; font-weight: 600; color: #64748b; display: flex; align-items: center; gap: 6px; white-space: nowrap; }
|
||||
.dm-lb-board li.is-win .dm-lb-board__name { color: #0f172a; font-weight: 800; }
|
||||
.dm-lb-board__tag { font-size: 8px; font-weight: 800; letter-spacing: 0.08em; color: #fff;
|
||||
background: linear-gradient(135deg,#E2354A,#C01227); padding: 2px 5px; border-radius: 5px; }
|
||||
.dm-lb-board__track { height: 7px; border-radius: 999px; background: rgba(255,255,255,0.08); overflow: hidden; }
|
||||
.dm-lb-board__fill { display: block; height: 100%; border-radius: 999px; background: rgba(150,150,165,0.5); }
|
||||
.dm-lb-board li.is-win .dm-lb-board__fill { background: linear-gradient(90deg,#E2354A,#C01227); box-shadow: 0 0 12px rgba(226,53,66,0.6); }
|
||||
.dm-lb-board__score { font-size: 12px; font-weight: 700; color: rgba(234,226,228,0.68); text-align: right; }
|
||||
.dm-lb-board li.is-win .dm-lb-board__score { color: #fff; }
|
||||
.dm-lb-board__track { height: 7px; border-radius: 999px; background: rgba(15,23,42,0.08); overflow: hidden; }
|
||||
.dm-lb-board__fill { display: block; height: 100%; border-radius: 999px; background: rgba(100,116,139,0.45); }
|
||||
.dm-lb-board li.is-win .dm-lb-board__fill { background: linear-gradient(90deg,#E2354A,#C01227); box-shadow: 0 0 12px rgba(226,53,66,0.4); }
|
||||
.dm-lb-board__score { font-size: 12px; font-weight: 700; color: #64748b; text-align: right; }
|
||||
.dm-lb-board li.is-win .dm-lb-board__score { color: #0f172a; }
|
||||
|
||||
/* SLA badges (step 04) */
|
||||
.dm-lb-sla { display: flex; gap: 8px; margin-bottom: 10px; flex-wrap: wrap; }
|
||||
.dm-lb-sla__badge { font-size: 12px; font-weight: 700; color: #86efac; background: rgba(34,197,94,0.1);
|
||||
border: 1px solid rgba(34,197,94,0.32); padding: 6px 12px; border-radius: 999px; }
|
||||
.dm-lb-sla__x { font-size: 12px; font-weight: 700; color: #fca5a5; background: rgba(239,68,68,0.1);
|
||||
border: 1px solid rgba(239,68,68,0.32); padding: 6px 12px; border-radius: 999px; }
|
||||
.dm-lb-sla__badge { font-size: 12px; font-weight: 700; color: #15803d; background: rgba(34,197,94,0.1);
|
||||
border: 1px solid rgba(34,197,94,0.3); padding: 6px 12px; border-radius: 999px; }
|
||||
.dm-lb-sla__x { font-size: 12px; font-weight: 700; color: #b91c1c; background: rgba(239,68,68,0.08);
|
||||
border: 1px solid rgba(239,68,68,0.28); padding: 6px 12px; border-radius: 999px; }
|
||||
|
||||
/* Winner banner (step 05) */
|
||||
.dm-lb-winner { font-size: 13.5px; font-weight: 700; color: #fff; margin-bottom: 10px; padding: 9px 13px; border-radius: 12px;
|
||||
background: linear-gradient(135deg, rgba(192,18,39,0.24), rgba(34,197,94,0.16)); border: 1px solid rgba(226,53,66,0.4); }
|
||||
.dm-lb-winner { font-size: 13.5px; font-weight: 700; color: #0f172a; margin-bottom: 10px; padding: 9px 13px; border-radius: 12px;
|
||||
background: linear-gradient(135deg, rgba(192,18,39,0.08), rgba(34,197,94,0.08)); border: 1px solid rgba(226,53,66,0.32); }
|
||||
|
||||
/* ---- Finale: KPI cards ---- */
|
||||
.dm-lb-finale { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 0 20px; }
|
||||
@@ -466,7 +510,15 @@ const styles = `
|
||||
.dm-lb { height: 400vh; }
|
||||
.dm-lb-kpis { gap: 12px; }
|
||||
.dm-lb-kpi { min-width: 96px; padding: 14px 14px; }
|
||||
.dm-lb-card-story { left: 0; right: 0; margin: 0 auto; width: calc(100% - 28px); bottom: clamp(20px, 5vh, 44px); padding: 14px 16px; }
|
||||
/* On phones every stage collapses to one centred, full-width position — the
|
||||
horizontal travel only reads on wider screens. */
|
||||
.dm-lb-card-anchor,
|
||||
.dm-lb-card-anchor.is-left,
|
||||
.dm-lb-card-anchor.is-right,
|
||||
.dm-lb-card-anchor.is-center,
|
||||
.dm-lb-card-anchor.is-hero { left: 50%; right: auto; transform: translateX(-50%); bottom: clamp(20px, 5vh, 44px); }
|
||||
.dm-lb-card-story,
|
||||
.dm-lb-card-anchor.is-hero .dm-lb-card-story { width: calc(100vw - 28px); padding: 14px 16px; }
|
||||
.dm-lb-board li { grid-template-columns: 88px 1fr 24px; }
|
||||
.dm-lb-constraints__note { display: none; }
|
||||
}
|
||||
|
||||
@@ -5,63 +5,54 @@ import { ScrollReveal } from "@/animations/Reveal";
|
||||
export default function BlogGrid() {
|
||||
const blogs = [
|
||||
{
|
||||
date: "Apl.06/2025",
|
||||
title: "How AI Is Transforming Last-Mile EV Delivery",
|
||||
excerpt: "Machine learning and real-time data are reshaping how fleets plan, dispatch, and adapt — making every kilometre smarter than the last.",
|
||||
category: "Technology",
|
||||
image: "/images/blog-post-pic-17.png",
|
||||
},
|
||||
{
|
||||
date: "Apl.06/2025",
|
||||
title: "The EV Paradox: Solving Range Anxiety for Urban Fleets",
|
||||
excerpt: "Electric vehicles promise sustainability, but battery constraints introduce a new routing challenge. Here's how MileTruth™ AI solves it before dispatch.",
|
||||
category: "EV Fleet",
|
||||
image: "/images/blog-post-pic-18-840x840.jpg",
|
||||
image: "/images/ev-paradox.png",
|
||||
},
|
||||
{
|
||||
date: "Apl.06/2025",
|
||||
title: "42% Less Distance: Insights from Our Hyderabad Hub",
|
||||
excerpt: "A detailed look at how Doormile's MileTruth routing engine delivered measurable efficiency gains — fewer vehicles, less fuel, and zero SLA misses.",
|
||||
category: "Case Study",
|
||||
image: "/images/blog-post-pic-15.png",
|
||||
},
|
||||
{
|
||||
date: "Apl.06/2025",
|
||||
title: "MileTruth™ AI — 10 Stages to Smarter Dispatch",
|
||||
excerpt: "From order ingestion to final route output in under 45ms — a technical walkthrough of the ten-stage pipeline at the heart of our routing engine.",
|
||||
category: "MileTruth",
|
||||
image: "/images/blog-post-pic-31.png",
|
||||
},
|
||||
{
|
||||
date: "Apl.06/2025",
|
||||
title: "Why Mathematical Precision Beats Heuristics in Routing",
|
||||
excerpt: "Most routing tools guess. We calculate. Powered by Google OR-Tools, MileTruth evaluates six parallel strategy universes to select the optimal route every time.",
|
||||
category: "Technology",
|
||||
image: "/images/blog-post-pic-14.jpeg",
|
||||
},
|
||||
{
|
||||
date: "Apl.06/2025",
|
||||
title: "Fleet Reduction Without Compromising Delivery Volume",
|
||||
excerpt: "Deploying 37% fewer vehicles while handling the same order volumes isn't a trade-off — it's the result of smarter routing intelligence applied at every dispatch.",
|
||||
category: "Fleet Management",
|
||||
image: "/images/blog-post-pic-8.jpeg",
|
||||
},
|
||||
{
|
||||
date: "Apl.06/2025",
|
||||
title: "Building a Greener City: The Future of Urban Logistics",
|
||||
excerpt: "Cities are demanding cleaner delivery. We explore how AI-powered EV fleets and optimised routing create a path to zero-emission last-mile logistics at city scale.",
|
||||
category: "Sustainability",
|
||||
image: "/images/blog-post-pic-6.jpeg",
|
||||
},
|
||||
{
|
||||
date: "Apl.06/2025",
|
||||
title: "How Doormile Maintains 99.9% SLA Compliance at Scale",
|
||||
excerpt: "Hitting SLA targets 99.9% of the time isn't luck — it's the product of ETA pre-validation, real-time rebalancing, and a routing engine built with delivery reliability as its first constraint.",
|
||||
category: "Operations",
|
||||
image: "/images/blog-post-pic-4.jpeg",
|
||||
image: "/images/last-mile-approach.jpg",
|
||||
},
|
||||
{
|
||||
date: "Apl.06/2025",
|
||||
title: "Battery Simulation: The Secret to EV Route Pre-Validation",
|
||||
excerpt: "Before a single rider leaves the hub, MileTruth™ simulates every route against real charge capacity — eliminating mid-route failures and protecting your fulfillment rate.",
|
||||
category: "EV Fleet",
|
||||
@@ -114,24 +105,6 @@ export default function BlogGrid() {
|
||||
border-color: rgba(192, 18, 39, 0.2) !important;
|
||||
}
|
||||
|
||||
.custom-blog-date {
|
||||
font-size: 12px !important;
|
||||
font-weight: 700 !important;
|
||||
color: #94a3b8 !important;
|
||||
text-transform: uppercase !important;
|
||||
letter-spacing: 1px !important;
|
||||
margin-bottom: 8px !important;
|
||||
display: block !important;
|
||||
font-family: var(--font-manrope), sans-serif !important;
|
||||
}
|
||||
|
||||
.custom-blog-divider {
|
||||
width: 100% !important;
|
||||
height: 1px !important;
|
||||
background: rgba(0, 0, 0, 0.08) !important;
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
|
||||
.custom-blog-title {
|
||||
font-size: 20px !important;
|
||||
font-weight: 800 !important;
|
||||
@@ -157,11 +130,32 @@ export default function BlogGrid() {
|
||||
font-weight: 500 !important;
|
||||
color: #64748b !important;
|
||||
line-height: 1.6 !important;
|
||||
margin: 0 0 24px 0 !important;
|
||||
margin: 0 0 18px 0 !important;
|
||||
text-transform: none !important;
|
||||
font-family: var(--font-manrope), sans-serif !important;
|
||||
}
|
||||
|
||||
.custom-blog-readmore {
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
gap: 6px !important;
|
||||
font-size: 13px !important;
|
||||
font-weight: 800 !important;
|
||||
color: #c01227 !important;
|
||||
text-transform: uppercase !important;
|
||||
letter-spacing: 0.5px !important;
|
||||
margin: 0 0 24px 0 !important;
|
||||
font-family: var(--font-manrope), sans-serif !important;
|
||||
}
|
||||
|
||||
.custom-blog-readmore-arrow {
|
||||
transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1) !important;
|
||||
}
|
||||
|
||||
.custom-blog-card:hover .custom-blog-readmore-arrow {
|
||||
transform: translateX(5px) !important;
|
||||
}
|
||||
|
||||
.custom-blog-img-container {
|
||||
position: relative !important;
|
||||
width: 100% !important;
|
||||
@@ -201,23 +195,21 @@ export default function BlogGrid() {
|
||||
<div className="custom-blog-card">
|
||||
{/* Text Block at Top */}
|
||||
<div className="flex flex-col">
|
||||
{/* Date */}
|
||||
<span className="custom-blog-date">
|
||||
{blog.date}
|
||||
</span>
|
||||
|
||||
{/* Thin divider line */}
|
||||
<div className="custom-blog-divider" />
|
||||
|
||||
{/* Bold Title */}
|
||||
<h3 className="custom-blog-title">
|
||||
{blog.title}
|
||||
</h3>
|
||||
|
||||
|
||||
{/* Description Excerpt */}
|
||||
<p className="custom-blog-excerpt">
|
||||
{blog.excerpt}
|
||||
</p>
|
||||
|
||||
{/* Read More */}
|
||||
<span className="custom-blog-readmore">
|
||||
Read More
|
||||
<span aria-hidden="true" className="custom-blog-readmore-arrow">→</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Image at Bottom */}
|
||||
|
||||
@@ -10,6 +10,7 @@ export default function BlogsHero() {
|
||||
font-family: var(--font-manrope), sans-serif !important;
|
||||
font-size: clamp(34px, 5.5vw, 68px) !important;
|
||||
font-weight: 850 !important;
|
||||
line-height: 1.08 !important;
|
||||
text-transform: uppercase !important;
|
||||
letter-spacing: -1.5px !important;
|
||||
margin: 0 !important;
|
||||
@@ -30,22 +31,11 @@ export default function BlogsHero() {
|
||||
{/* Title / Heading for Blogs */}
|
||||
<div style={{ textAlign: "center", color: "#fff", zIndex: 5 }}>
|
||||
<h1 className="blogs-hero-title">
|
||||
Our <span style={{ color: "#C01227" }}>Blogs</span>
|
||||
Delivering Trust.<br />
|
||||
<span style={{ color: "#C01227" }}>Beyond Boundaries</span>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="elementor-element elementor-element-91be79f elementor-widget__width-auto elementor-absolute elementor-widget elementor-widget-logico_breadcrumbs"
|
||||
style={{ position: "absolute", bottom: "40px", left: "50%", transform: "translateX(-50%)", zIndex: 10 }}
|
||||
>
|
||||
<div className="elementor-widget-container">
|
||||
<nav className="breadcrumbs" style={{ background: "rgba(255, 255, 255, 0.1)", backdropFilter: "blur(10px)", padding: "10px 24px", borderRadius: "30px", border: "1px solid rgba(255, 255, 255, 0.15)" }}>
|
||||
<Link href="/" style={{ color: "#fff", fontWeight: 600 }}>Home</Link>
|
||||
<span className="delimiter" style={{ color: "rgba(255, 255, 255, 0.6)", margin: "0 8px" }}>/</span>
|
||||
<span className="current" style={{ color: "#C01227", fontWeight: 700 }}>Blogs</span>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -77,7 +77,7 @@ export default function CompetitiveEdge() {
|
||||
<div className="advantage-eyebrow-container">
|
||||
<span className="advantage-eyebrow">/ DoorMile wins/</span>
|
||||
</div>
|
||||
<h2 className="moat-heading" data-text="WHERE DOORMILE SITS AND WHY IT WINS">WHERE DOORMILE SITS AND WHY IT WINS</h2>
|
||||
<h2 className="moat-heading" data-text="WHERE DOORMILE WINS">WHERE DOORMILE WINS</h2>
|
||||
<p className="moat-desc">
|
||||
A side-by-side technical capabilities comparison showing how operational fleet ownership and dynamic AI planning disrupt basic aggregators.
|
||||
</p>
|
||||
|
||||
@@ -207,7 +207,7 @@ export default function EVLogisticSection() {
|
||||
|
||||
.ev-logistic-kicker {
|
||||
font-size: 14px !important;
|
||||
font-weight: 500 !important;
|
||||
font-weight: 400 !important;
|
||||
line-height: 2.1429em !important;
|
||||
letter-spacing: 0px !important; /* Expands to 3px on scroll */
|
||||
text-transform: lowercase !important;
|
||||
@@ -464,7 +464,7 @@ export default function EVLogisticSection() {
|
||||
>
|
||||
{/* Top Header Row with / features / kicker */}
|
||||
<div className="ev-logistic-header">
|
||||
<div className="ev-logistic-kicker">/ features /</div>
|
||||
<div className="ev-logistic-kicker">/ Build Electric Vehicles /</div>
|
||||
</div>
|
||||
|
||||
<div className="ev-logistic-body-grid">
|
||||
|
||||
@@ -5,11 +5,11 @@ import React, { useState, useEffect } from "react";
|
||||
export default function HowItWorksHero() {
|
||||
const [activeSlide, setActiveSlide] = useState(0);
|
||||
|
||||
// Auto-slide every 6 seconds
|
||||
// Auto-slide every 7 seconds — slower, more readable, professional pacing
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setActiveSlide((prev) => (prev === 0 ? 1 : 0));
|
||||
}, 6000);
|
||||
}, 7000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
@@ -77,11 +77,23 @@ export default function HowItWorksHero() {
|
||||
|
||||
.elementor-element.elementor-element-6c7cbcb .text-content {
|
||||
text-align: center !important;
|
||||
max-width: 800px !important;
|
||||
max-width: 820px !important;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
/* Larger, more readable hero subtitle on large/4K screens */
|
||||
.elementor-element.elementor-element-6c7cbcb .content-slider-item-text p {
|
||||
font-size: clamp(16px, 1.35vw, 23px) !important;
|
||||
line-height: 1.65 !important;
|
||||
}
|
||||
|
||||
@media (min-width: 1025px) {
|
||||
/* Match Home's hero frame so the floating navbar sits with the same
|
||||
breathing space. Home (.elementor-61) frames the hero card at 20px;
|
||||
this page falls through to the shared kit's 32px base. */
|
||||
.elementor-element.elementor-element-741f56c {
|
||||
padding: 20px !important;
|
||||
}
|
||||
.elementor-element.elementor-element-6c7cbcb .owl-carousel.owl-theme .content-item {
|
||||
height: 800px !important;
|
||||
min-height: 800px !important;
|
||||
|
||||
@@ -8,11 +8,11 @@ export default function IndexHero() {
|
||||
const [activeSlide, setActiveSlide] = useState(0);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Auto-slide every 6 seconds
|
||||
// Auto-slide every 7 seconds — slower, more readable, professional pacing
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setActiveSlide((prev) => (prev === 0 ? 1 : 0));
|
||||
}, 6000);
|
||||
}, 7000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
@@ -94,12 +94,18 @@ export default function IndexHero() {
|
||||
|
||||
.logico-content-slider-widget .text-content {
|
||||
width: 100% !important;
|
||||
max-width: min(680px, 100%) !important;
|
||||
max-width: min(780px, 100%) !important;
|
||||
box-sizing: border-box !important;
|
||||
padding-left: 15px !important;
|
||||
padding-right: 15px !important;
|
||||
}
|
||||
|
||||
/* Larger, more readable hero subtitle on large/4K screens */
|
||||
.logico-content-slider-widget .content-slider-item-text p {
|
||||
font-size: clamp(16px, 1.35vw, 23px) !important;
|
||||
line-height: 1.65 !important;
|
||||
}
|
||||
|
||||
/* Responsive slider heights */
|
||||
.logico-content-slider-widget .owl-stage-outer {
|
||||
height: 800px !important;
|
||||
|
||||
@@ -11,14 +11,14 @@ export default function IndustrySolutions() {
|
||||
|
||||
<div className="elementor-element elementor-element-f64bd88 e-con-full e-flex cut-corner-no sticky-container-off e-con e-child" data-id="f64bd88" data-element_type="container" data-e-type="container">
|
||||
<div className="elementor-element elementor-element-5ed2dbb e-con-full e-flex cut-corner-no sticky-container-off e-con e-child" data-id="5ed2dbb" data-element_type="container" data-e-type="container">
|
||||
<div className="elementor-element elementor-element-c8162c4 elementor-widget elementor-widget-logico_heading industry-section-label" data-id="c8162c4" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default" style={{paddingLeft: "50px"}}>
|
||||
<div className="elementor-element elementor-element-c8162c4 elementor-widget elementor-widget-logico_heading industry-section-label" data-id="c8162c4" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
|
||||
<style dangerouslySetInnerHTML={{ __html: `
|
||||
/* Minimal section label — matches the "/ Doormile Approach /" pattern */
|
||||
.industry-section-label {
|
||||
width: 100%;
|
||||
}
|
||||
.industry-section-label > .elementor-widget-container {
|
||||
max-width: 1740px;
|
||||
max-width: 100%;
|
||||
margin: 12px 0 50px 0;
|
||||
padding: 0 0 14px 0;
|
||||
border-style: solid;
|
||||
@@ -60,17 +60,9 @@ export default function IndustrySolutions() {
|
||||
data-element_type="widget"
|
||||
data-e-type="widget"
|
||||
data-widget_type="logico_heading.default"
|
||||
style={{marginLeft: "50px"}}
|
||||
>
|
||||
<div className="elementor-widget-container" style={{ margin: "30px 0 0 0"}}>
|
||||
<style dangerouslySetInnerHTML={{ __html: `
|
||||
@media (min-width: 1024px) {
|
||||
.industry-title-single-line {
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
}
|
||||
`}} />
|
||||
<h3 className="logico-title industry-title-single-line" style={{ fontSize: "clamp(28px, 3.5vw, 48px)", lineHeight: "1.1", fontWeight: 800, textTransform: "uppercase" }}>
|
||||
<h3 className="logico-title" style={{ fontSize: "clamp(28px, 3.5vw, 48px)", lineHeight: "1.1", fontWeight: 800, textTransform: "uppercase", maxWidth: "900px" }}>
|
||||
<ScrollReveal delay={0.05} duration={0.8} yOffset={25}>
|
||||
Smart solutions built exclusively for your <span style={{ color: "#c01227" }}>industry</span>
|
||||
</ScrollReveal>
|
||||
|
||||
@@ -252,8 +252,16 @@ export default function IntelligenceGrid() {
|
||||
/* Buttery-Smooth Hardware-Accelerated 3D AI Logistics Timeline Styles */
|
||||
.roadmap-hero-section {
|
||||
position: relative;
|
||||
background: #09090b !important;
|
||||
width: 100%;
|
||||
background: #09090b !important;
|
||||
/* Stay WIDE and immersive — span nearly the full viewport, inset only
|
||||
by the site's standard left/right gutter (40px desktop, 32/24 on
|
||||
smaller screens) so the dark band never touches the viewport edge.
|
||||
No narrow max-width: the roadmap timeline + 4 milestone cards keep
|
||||
the large content area. Auto margins keep the gutters equal. */
|
||||
width: calc(100% - 80px);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 24px;
|
||||
padding: 100px 40px;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Manrope', sans-serif;
|
||||
@@ -299,7 +307,9 @@ export default function IntelligenceGrid() {
|
||||
}
|
||||
|
||||
.roadmap-hero-section .container {
|
||||
max-width: 1320px;
|
||||
/* Fill the wide section so the timeline + cards span most of the
|
||||
available width (no narrow content cap). */
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
@@ -683,6 +693,7 @@ export default function IntelligenceGrid() {
|
||||
/* Responsive Constraints */
|
||||
@media (max-width: 1024px) {
|
||||
.roadmap-hero-section {
|
||||
width: calc(100% - 64px); /* 32px gutter */
|
||||
padding: 80px 24px;
|
||||
}
|
||||
|
||||
@@ -698,6 +709,7 @@ export default function IntelligenceGrid() {
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.roadmap-hero-section {
|
||||
width: calc(100% - 48px); /* 24px gutter */
|
||||
padding: 60px 16px;
|
||||
}
|
||||
|
||||
|
||||
284
src/components/sections/LegalDocument.tsx
Normal file
284
src/components/sections/LegalDocument.tsx
Normal file
@@ -0,0 +1,284 @@
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
/**
|
||||
* Shared layout for the legal pages (Privacy Policy, Terms of Service, Cookie
|
||||
* Policy) so all three stay pixel-consistent. Content is passed in as structured
|
||||
* blocks; this component owns the hero, the desktop sticky table of contents and
|
||||
* the 800px reading column described in the design spec.
|
||||
*/
|
||||
|
||||
export type LegalBlock =
|
||||
| { type: "p"; text: React.ReactNode }
|
||||
| { type: "lead"; text: React.ReactNode }
|
||||
| { type: "h3"; text: string }
|
||||
| { type: "ul"; items: React.ReactNode[] };
|
||||
|
||||
export type LegalSection = {
|
||||
heading: string;
|
||||
blocks: LegalBlock[];
|
||||
};
|
||||
|
||||
export type LegalDocumentProps = {
|
||||
title: string;
|
||||
lastUpdated: string;
|
||||
intro: React.ReactNode;
|
||||
sections: LegalSection[];
|
||||
};
|
||||
|
||||
/** Stable, URL-safe id from a section heading (for TOC anchors). */
|
||||
function slug(heading: string): string {
|
||||
return heading
|
||||
.toLowerCase()
|
||||
.replace(/&/g, "and")
|
||||
.replace(/[^a-z0-9]+/g, "-")
|
||||
.replace(/(^-|-$)/g, "");
|
||||
}
|
||||
|
||||
function Block({ block }: { block: LegalBlock }) {
|
||||
switch (block.type) {
|
||||
case "lead":
|
||||
return <p className="dm-legal__lead">{block.text}</p>;
|
||||
case "p":
|
||||
return <p className="dm-legal__p">{block.text}</p>;
|
||||
case "h3":
|
||||
return <h3 className="dm-legal__h3">{block.text}</h3>;
|
||||
case "ul":
|
||||
return (
|
||||
<ul className="dm-legal__ul">
|
||||
{block.items.map((item, i) => (
|
||||
<li key={i}>{item}</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default function LegalDocument({ title, lastUpdated, intro, sections }: LegalDocumentProps) {
|
||||
return (
|
||||
<section className="dm-legal" aria-label={title}>
|
||||
<div className="dm-legal__wrap">
|
||||
{/* Desktop sticky table of contents */}
|
||||
<aside className="dm-legal__toc" aria-label="On this page">
|
||||
<div className="dm-legal__toc-inner">
|
||||
<p className="dm-legal__toc-label">On this page</p>
|
||||
<nav>
|
||||
<ul>
|
||||
{sections.map((s) => (
|
||||
<li key={s.heading}>
|
||||
<a href={`#${slug(s.heading)}`}>{s.heading}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<div className="dm-legal__main">
|
||||
<header className="dm-legal__hero">
|
||||
<h1 className="dm-legal__title">{title}</h1>
|
||||
<p className="dm-legal__updated">Last Updated: {lastUpdated}</p>
|
||||
<p className="dm-legal__lead">{intro}</p>
|
||||
</header>
|
||||
|
||||
<article className="dm-legal__content">
|
||||
{sections.map((s) => (
|
||||
<section key={s.heading} id={slug(s.heading)} className="dm-legal__section">
|
||||
<h2 className="dm-legal__h2">{s.heading}</h2>
|
||||
{s.blocks.map((b, i) => (
|
||||
<Block key={i} block={b} />
|
||||
))}
|
||||
</section>
|
||||
))}
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>{styles}</style>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
/** Renders the recurring "contact us through our Contact page" link. */
|
||||
export function ContactLink() {
|
||||
return (
|
||||
<Link href="/contact" className="dm-legal__link">
|
||||
Contact page
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = `
|
||||
.dm-legal {
|
||||
background: #ffffff;
|
||||
color: #334155;
|
||||
/* Top padding clears the fixed/absolute floating navbar (~104px) + breathing room. */
|
||||
padding: clamp(132px, 16vh, 184px) 0 clamp(72px, 10vw, 96px);
|
||||
font-family: var(--font-manrope), system-ui, -apple-system, sans-serif;
|
||||
}
|
||||
|
||||
.dm-legal__wrap {
|
||||
max-width: 1180px;
|
||||
margin: 0 auto;
|
||||
padding: 0 clamp(20px, 5vw, 40px);
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
/* ---- Sticky table of contents (desktop only) ---- */
|
||||
.dm-legal__toc { display: none; }
|
||||
|
||||
@media (min-width: 1080px) {
|
||||
.dm-legal__wrap {
|
||||
grid-template-columns: 248px minmax(0, 800px);
|
||||
justify-content: center;
|
||||
gap: 64px;
|
||||
}
|
||||
.dm-legal__toc { display: block; }
|
||||
}
|
||||
|
||||
.dm-legal__toc-inner { position: sticky; top: 128px; }
|
||||
.dm-legal__toc-label {
|
||||
margin: 0 0 14px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.dm-legal__toc nav ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
|
||||
.dm-legal__toc nav a {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
color: #64748b;
|
||||
text-decoration: none;
|
||||
border-left: 2px solid transparent;
|
||||
padding-left: 12px;
|
||||
transition: color 0.2s ease, border-color 0.2s ease;
|
||||
}
|
||||
.dm-legal__toc nav a:hover { color: #c01227; border-left-color: #c01227; }
|
||||
|
||||
/* ---- Reading column (max 800px) ---- */
|
||||
.dm-legal__main { min-width: 0; max-width: 800px; }
|
||||
|
||||
.dm-legal__hero { margin-bottom: clamp(40px, 6vw, 56px); }
|
||||
.dm-legal__title {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
/* !important / text-transform override the global ".elementor-kit-5 h1"
|
||||
(uppercase + kit font-size) so headings render in normal case at the spec sizes. */
|
||||
font-size: clamp(40px, 6vw, 60px) !important;
|
||||
font-weight: 800 !important;
|
||||
line-height: 1.08 !important;
|
||||
letter-spacing: -0.02em !important;
|
||||
text-transform: none !important;
|
||||
color: #0f172a !important;
|
||||
}
|
||||
.dm-legal__updated {
|
||||
margin: 16px 0 0;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.dm-legal__lead {
|
||||
margin: 24px 0 0;
|
||||
font-size: clamp(18px, 1.6vw, 20px);
|
||||
line-height: 1.7;
|
||||
color: #475569;
|
||||
}
|
||||
.dm-legal__hero .dm-legal__lead { margin-top: 24px; }
|
||||
|
||||
/* ---- Sections ---- */
|
||||
.dm-legal__content { display: flex; flex-direction: column; }
|
||||
.dm-legal__section { padding-top: 32px; }
|
||||
.dm-legal__section:first-child { padding-top: 0; }
|
||||
|
||||
.dm-legal__h2 {
|
||||
margin: 0 0 16px !important;
|
||||
padding: 0 !important;
|
||||
font-size: clamp(24px, 3vw, 32px) !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1.2 !important;
|
||||
letter-spacing: -0.01em !important;
|
||||
text-transform: none !important;
|
||||
color: #0f172a !important;
|
||||
/* Offset anchor jumps so the heading isn't hidden under the fixed navbar. */
|
||||
scroll-margin-top: 120px;
|
||||
}
|
||||
.dm-legal__h3 {
|
||||
margin: 24px 0 8px !important;
|
||||
padding: 0 !important;
|
||||
font-size: 20px !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1.35 !important;
|
||||
text-transform: none !important;
|
||||
color: #0f172a !important;
|
||||
}
|
||||
.dm-legal__p {
|
||||
margin: 0 0 16px;
|
||||
font-size: 18px;
|
||||
line-height: 1.7;
|
||||
color: #334155;
|
||||
}
|
||||
.dm-legal__p:last-child { margin-bottom: 0; }
|
||||
|
||||
.dm-legal__ul { margin: 4px 0 16px; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 10px; }
|
||||
.dm-legal__ul li {
|
||||
position: relative;
|
||||
padding-left: 26px;
|
||||
font-size: 18px;
|
||||
line-height: 1.7;
|
||||
color: #334155;
|
||||
}
|
||||
/* Extra .dm-legal prefix raises specificity above the global theme rule
|
||||
".logico-front-end ul li:before" (a fontello glyph), so our clean red dot
|
||||
replaces the inherited checkmark marker. */
|
||||
.dm-legal .dm-legal__ul li::before {
|
||||
content: "" !important;
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 0.62em;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
background: #c01227;
|
||||
font-size: 0;
|
||||
}
|
||||
/* TOC links are inside a <ul> too — suppress the same inherited glyph marker. */
|
||||
.dm-legal .dm-legal__toc nav li::before { content: none !important; }
|
||||
|
||||
.dm-legal__link { color: #c01227; font-weight: 600; text-decoration: none; border-bottom: 1px solid rgba(192,18,39,0.35); }
|
||||
.dm-legal__link:hover { border-bottom-color: #c01227; }
|
||||
|
||||
@media (max-width: 1079px) {
|
||||
.dm-legal__main { margin: 0 auto; }
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
Navbar visibility — LEGAL PAGES ONLY.
|
||||
This <style> block is rendered exclusively by LegalDocument, which only mounts
|
||||
on /privacy-policy, /terms-of-service and /cookie-policy. So although the rule
|
||||
targets the global #masthead, it is physically absent from every other page's
|
||||
HTML and cannot affect them — no global CSS file is touched.
|
||||
|
||||
Why it's needed: the desktop logo and nav links are white and the navbar bar is
|
||||
transparent at the top of the page. Over the dark heroes used elsewhere that's
|
||||
fine, but on these white pages the navbar vanishes. Give the bar the same dark
|
||||
glass fill the rest of the site already shows on scroll. Desktop only — the
|
||||
mobile logo is black-on-transparent and already legible here.
|
||||
============================================================ */
|
||||
@media (min-width: 1025px) {
|
||||
#masthead .elementor-element.elementor-element-466de1b {
|
||||
background: rgba(40, 40, 40, 0.75) !important;
|
||||
-webkit-backdrop-filter: blur(12px) !important;
|
||||
backdrop-filter: blur(12px) !important;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.08) !important;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16) !important;
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -99,11 +99,11 @@ export default function MileTruthHero() {
|
||||
.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(16px, 1.8vw, 20px) !important;
|
||||
font-size: clamp(17px, 1.6vw, 23px) !important;
|
||||
font-weight: 500 !important;
|
||||
line-height: 1.6 !important;
|
||||
line-height: 1.65 !important;
|
||||
margin: 0 auto !important;
|
||||
max-width: 800px;
|
||||
max-width: 820px;
|
||||
}
|
||||
.miletruth-hero .slide-content {
|
||||
display: flex !important;
|
||||
|
||||
@@ -10,7 +10,7 @@ export default function Miles3() {
|
||||
/* =====================================================================
|
||||
How It Works · "Doormile connects first, mid, and last mile" section
|
||||
Self-contained recreation of the original Elementor design
|
||||
(source: public/css/sections/section-miles3.css + kit-5 typography).
|
||||
(originally Elementor section CSS, now inlined below + in /public/css/site.css).
|
||||
Explicit flex/grid values because the Elementor framework reads them
|
||||
from CSS custom properties that aren't set in this rebuild.
|
||||
===================================================================== */
|
||||
@@ -25,7 +25,7 @@ export default function Miles3() {
|
||||
margin: 20px 20px 0 20px;
|
||||
background-color: #1F1F1F;
|
||||
border-radius: 25px 25px 0 0;
|
||||
padding: 150px 0 0 0;
|
||||
padding: 90px 0 0 0;
|
||||
}
|
||||
/* Boxed inner — centered, original content width */
|
||||
.elementor-element-c36a604 > .e-con-inner {
|
||||
@@ -165,7 +165,7 @@ export default function Miles3() {
|
||||
.logico-front-end .elementor-element-63a9de5 .logico-title { font-size: clamp(40px, 5vw, 60px); }
|
||||
}
|
||||
@media (max-width: 1020px) {
|
||||
.elementor-element-c36a604 { margin: 15px 15px 0 15px; padding: 100px 0 0 0; }
|
||||
.elementor-element-c36a604 { margin: 15px 15px 0 15px; padding: 76px 0 0 0; }
|
||||
.elementor-element-77d1265 { padding: 0 30px; }
|
||||
.elementor-element-4add972 { grid-template-columns: repeat(2, 1fr); gap: 50px 40px; }
|
||||
.logico-front-end .elementor-element-63a9de5 .logico-title { font-size: clamp(34px, 6vw, 52px); }
|
||||
|
||||
@@ -8,11 +8,7 @@ export default function OurTeam() {
|
||||
position: "COO & Operational Specialist",
|
||||
image: "/images/Investor.png",
|
||||
},
|
||||
{
|
||||
name: "Fazul Ilahi",
|
||||
position: "CTO & Technology Specialist",
|
||||
image: "/images/Fazul.png",
|
||||
},
|
||||
|
||||
{
|
||||
name: "Parthiban",
|
||||
position: "CGO & Growth Specialist",
|
||||
@@ -22,6 +18,11 @@ export default function OurTeam() {
|
||||
name: "Aravinth",
|
||||
position: "CFO & Finance Specialist",
|
||||
image: "/images/Aravinth.png",
|
||||
},
|
||||
{
|
||||
name: "Fazul Ilahi",
|
||||
position: "CTO & Technology Specialist",
|
||||
image: "/images/Fazul.png",
|
||||
},
|
||||
{
|
||||
name: "Suriya Kumar",
|
||||
@@ -48,6 +49,9 @@ export default function OurTeam() {
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-left: clamp(20px, 4vw, 50px) !important;
|
||||
padding-right: clamp(20px, 4vw, 50px) !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Breathing room above and below the "Meet our the best crew" heading. */
|
||||
@@ -65,38 +69,40 @@ export default function OurTeam() {
|
||||
filter: grayscale(0%);
|
||||
}
|
||||
|
||||
/* Self-contained layout (does not rely on the cached vendor CSS). */
|
||||
/* Grid: three columns that wrap, with tightened row/column gaps. */
|
||||
/* Grid: five columns that wrap, with tightened row/column gaps. */
|
||||
.team-listing-wrapper.team-grid-listing {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 -16px -40px;
|
||||
}
|
||||
.team-listing-wrapper.team-grid-listing .team-item-wrapper {
|
||||
width: 33.3333%;
|
||||
width: 20%;
|
||||
padding: 0 16px;
|
||||
margin-bottom: 40px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@media (max-width: 1020px) {
|
||||
@media (max-width: 1200px) {
|
||||
.team-listing-wrapper.team-grid-listing .team-item-wrapper { width: 33.3333%; }
|
||||
}
|
||||
@media (max-width: 800px) {
|
||||
.team-listing-wrapper.team-grid-listing .team-item-wrapper { width: 50%; }
|
||||
}
|
||||
@media (max-width: 660px) {
|
||||
@media (max-width: 480px) {
|
||||
.team-listing-wrapper.team-grid-listing .team-item-wrapper { width: 100%; }
|
||||
}
|
||||
|
||||
/* Card: photo on the LEFT, name/position on the RIGHT (side by side). */
|
||||
|
||||
/* Card: photo on top, name/position at the bottom (down to image). */
|
||||
.team-listing-wrapper.team-grid-listing .team-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 22px;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
/* Compact portrait photo. Extra .team-item in the selector raises the
|
||||
specificity so it beats the cached vendor rule (width: 45.65%). */
|
||||
.team-listing-wrapper.team-grid-listing .team-item .team-item-media {
|
||||
flex-shrink: 0;
|
||||
width: 160px;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
.team-listing-wrapper.team-grid-listing .team-item .post-media {
|
||||
@@ -113,7 +119,7 @@ export default function OurTeam() {
|
||||
object-fit: cover;
|
||||
}
|
||||
.team-listing-wrapper.team-grid-listing .team-item .team-item-content {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
`}} />
|
||||
@@ -128,7 +134,7 @@ export default function OurTeam() {
|
||||
|
||||
<div style={{ alignSelf: "flex-start", width: "100%" }} className="elementor-element elementor-element-c46350e elementor-widget__width-initial elementor-widget elementor-widget-logico_heading" data-id="c46350e" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
|
||||
<div className="elementor-widget-container">
|
||||
<h3 className="logico-title" style={{ textAlign: "left" }}>Meet our the best crew</h3>
|
||||
<h3 className="logico-title" style={{ textAlign: "left" }}>Meet crew</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -136,7 +142,7 @@ export default function OurTeam() {
|
||||
<div className="elementor-widget-container">
|
||||
<div className="logico-team-listing-widget">
|
||||
<div className="archive-listing">
|
||||
<div className="archive-listing-wrapper team-listing-wrapper team-grid-listing columns-3">
|
||||
<div className="archive-listing-wrapper team-listing-wrapper team-grid-listing columns-5">
|
||||
|
||||
{teamMembers.map((member, i) => (
|
||||
<div key={i} className="team-item-wrapper post-2866 team type-team status-publish has-post-thumbnail hentry">
|
||||
@@ -159,10 +165,7 @@ export default function OurTeam() {
|
||||
<div className="team-item-position" dangerouslySetInnerHTML={{ __html: member.position }}></div>
|
||||
<div className="team-item-socials">
|
||||
<ul className="team-socials wrapper-socials">
|
||||
<li><a href="https://www.facebook.com/" target="_blank" rel="noreferrer" className="fab fa-facebook-f"></a></li>
|
||||
<li><a href="https://x.com/" target="_blank" rel="noreferrer" className="fab fa-x-twitter"></a></li>
|
||||
<li><a href="https://www.linkedin.com/" target="_blank" rel="noreferrer" className="fab fa-linkedin-in"></a></li>
|
||||
<li><a href="https://www.youtube.com/" target="_blank" rel="noreferrer" className="fab fa-youtube"></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,11 +5,11 @@ import React, { useState, useEffect } from "react";
|
||||
export default function SolutionsHero() {
|
||||
const [activeSlide, setActiveSlide] = useState(0);
|
||||
|
||||
// Auto-slide every 6 seconds
|
||||
// Auto-slide every 7 seconds — slower, more readable, professional pacing
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setActiveSlide((prev) => (prev === 0 ? 1 : 0));
|
||||
}, 6000);
|
||||
}, 7000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
@@ -77,11 +77,23 @@ export default function SolutionsHero() {
|
||||
|
||||
.elementor-element.elementor-element-6c7cbcb .text-content {
|
||||
text-align: center !important;
|
||||
max-width: 800px !important;
|
||||
max-width: 820px !important;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
/* Larger, more readable hero subtitle on large/4K screens */
|
||||
.elementor-element.elementor-element-6c7cbcb .content-slider-item-text p {
|
||||
font-size: clamp(16px, 1.35vw, 23px) !important;
|
||||
line-height: 1.65 !important;
|
||||
}
|
||||
|
||||
@media (min-width: 1025px) {
|
||||
/* Match Home's hero frame so the floating navbar sits with the same
|
||||
breathing space. Home (.elementor-61) frames the hero card at 20px;
|
||||
this page falls through to the shared kit's 32px base. */
|
||||
.elementor-element.elementor-element-741f56c {
|
||||
padding: 20px !important;
|
||||
}
|
||||
.elementor-element.elementor-element-6c7cbcb .owl-carousel.owl-theme .content-item {
|
||||
height: 800px !important;
|
||||
min-height: 800px !important;
|
||||
|
||||
@@ -265,7 +265,7 @@ export default function WomenSection() {
|
||||
<div className="elementor-element elementor-element-90cc867 e-con-full e-flex cut-corner-no sticky-container-off e-con e-child" data-id="90cc867" data-element_type="container" data-e-type="container">
|
||||
<div className="elementor-element elementor-element-24c0280 elementor-widget__width-inherit elementor-widget elementor-widget-logico_heading" data-id="24c0280" data-element_type="widget" data-e-type="widget" data-widget_type="logico_heading.default">
|
||||
<div className="elementor-widget-container">
|
||||
<div className="logico-title">/ Success Stories /</div>
|
||||
<div className="logico-title">/ Women Empowerment /</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ const styles = `
|
||||
margin: 0 auto 0;
|
||||
}
|
||||
|
||||
/* Cancel the global "section { padding: 6rem 0 }" (custom-frontend.min.css): both
|
||||
/* Cancel the global "section { padding: 6rem 0 }" (consolidated into /public/css/site.css): both
|
||||
this wrapper and the nested .dm-opt are sections, so that 96px top+bottom stacked
|
||||
into large empty bands above / between the workflows. These are full-bleed pinned
|
||||
experiences whose cards butt together via their own insets — no section padding. */
|
||||
|
||||
@@ -118,7 +118,7 @@ const styles = `
|
||||
margin: 0 auto 0;
|
||||
}
|
||||
|
||||
/* Cancel the global "section { padding: 6rem 0 }" (custom-frontend.min.css): both
|
||||
/* Cancel the global "section { padding: 6rem 0 }" (consolidated into /public/css/site.css): both
|
||||
this wrapper and the nested .dm-lb are sections, so that 96px top+bottom stacked
|
||||
into large empty bands above / between the workflows. These are full-bleed pinned
|
||||
experiences whose cards butt together via their own insets — no section padding. */
|
||||
|
||||
@@ -118,7 +118,7 @@ const styles = `
|
||||
margin: 0 auto 0;
|
||||
}
|
||||
|
||||
/* Cancel the global "section { padding: 6rem 0 }" (custom-frontend.min.css): both
|
||||
/* Cancel the global "section { padding: 6rem 0 }" (consolidated into /public/css/site.css): both
|
||||
this wrapper and the nested .dm-st are sections, so that 96px top+bottom stacked
|
||||
into large empty bands above / between the workflows. These are full-bleed pinned
|
||||
experiences whose cards butt together via their own insets — no section padding. */
|
||||
|
||||
Reference in New Issue
Block a user