update how it works card update
This commit is contained in:
@@ -7,7 +7,7 @@ import Navbar from './components/ui/Navbar'
|
||||
import FirstMile from './components/sections/FirstMile'
|
||||
import MidMile from './components/sections/MidMile'
|
||||
import LastMile from './components/sections/LastMile'
|
||||
import Analytics from './components/sections/Analytics'
|
||||
import Promise from './components/sections/Promise'
|
||||
import { useSceneStore } from './store/useSceneStore'
|
||||
import './styles/experience.css'
|
||||
|
||||
@@ -145,8 +145,10 @@ export default function Experience3D() {
|
||||
<div className="sections-overlay-container">
|
||||
<FirstMile active={scrollProgress >= 0.02 && scrollProgress < 0.14} />
|
||||
<MidMile active={scrollProgress >= 0.38 && scrollProgress < 0.50} />
|
||||
<LastMile active={scrollProgress >= 0.80 && scrollProgress < 0.92} />
|
||||
<Analytics active={scrollProgress >= 0.94} />
|
||||
<LastMile active={scrollProgress >= 0.78 && scrollProgress < 0.875} />
|
||||
{/* Final card: reveals as the journey closes (fills the slot the old
|
||||
workflow timeline card used to occupy — no blank gap). */}
|
||||
<Promise active={scrollProgress >= 0.90} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
import React from 'react'
|
||||
import RevealCard from '../ui/RevealCard'
|
||||
|
||||
export default function Analytics({ active }) {
|
||||
return (
|
||||
<RevealCard active={active} id="analytics-section">
|
||||
<div className="section-badge">Workflow</div>
|
||||
<h2 className="section-title">Doormile Insights</h2>
|
||||
<h3 className="section-subtitle">3-Mile Logistics Ecosystem</h3>
|
||||
|
||||
<div className="workflow-steps">
|
||||
<div className="workflow-step">
|
||||
<div className="step-number-container">
|
||||
<span className="step-number">01</span>
|
||||
<div className="step-line"></div>
|
||||
</div>
|
||||
<div className="step-content">
|
||||
<h4 className="step-title">First Mile</h4>
|
||||
<p className="step-description">Incoming shipments are securely loaded, checked, and consolidated at initial fulfillment hubs.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="workflow-step">
|
||||
<div className="step-number-container">
|
||||
<span className="step-number">02</span>
|
||||
<div className="step-line"></div>
|
||||
</div>
|
||||
<div className="step-content">
|
||||
<h4 className="step-title">Mid Mile</h4>
|
||||
<p className="step-description">Consolidated goods travel between primary distribution nodes via optimized express transit corridors.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="workflow-step">
|
||||
<div className="step-number-container">
|
||||
<span className="step-number">03</span>
|
||||
</div>
|
||||
<div className="step-content">
|
||||
<h4 className="step-title">Last Mile</h4>
|
||||
<p className="step-description">Local delivery units organize doorstep routes to transport packages to final customers.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</RevealCard>
|
||||
)
|
||||
}
|
||||
@@ -9,9 +9,10 @@ export default function LastMile({ active }) {
|
||||
const lenis = useSceneStore((state) => state.lenis)
|
||||
|
||||
const handleClose = () => {
|
||||
// Smoothly scroll to 97% progress, which is inside the Analytics Dashboard section.
|
||||
// Smoothly scroll to 92% progress, which lands on the analytics-dashboard
|
||||
// view where the closing promise card is revealed.
|
||||
// Relative to the experience spacer (the section sits below the page hero).
|
||||
lenis?.scrollTo(progressToScrollY(0.97), { duration: 1.5 })
|
||||
lenis?.scrollTo(progressToScrollY(0.92), { duration: 1.5 })
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -22,12 +23,19 @@ export default function LastMile({ active }) {
|
||||
<p className="section-description">{config.description}</p>
|
||||
<div className="section-metrics">
|
||||
<div className="metric-item">
|
||||
<span className="metric-value">12.5 min</span>
|
||||
<span className="metric-label">Avg. Delivery window</span>
|
||||
<span className="metric-value">99.4%</span>
|
||||
<span className="metric-label">On-Time Delivery</span>
|
||||
</div>
|
||||
<div className="metric-item">
|
||||
<span className="metric-value">99.4%</span>
|
||||
<span className="metric-label">On-Time Rate</span>
|
||||
<span className="metric-value">12.5 min</span>
|
||||
<span className="metric-label">Avg. Doorstep Time</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="section-supporting">
|
||||
<span className="supporting-dot"></span>
|
||||
<div className="supporting-text">
|
||||
<span className="supporting-value">Real-Time visibility</span>
|
||||
<span className="supporting-label">Live GPS · Active now</span>
|
||||
</div>
|
||||
</div>
|
||||
<button className="section-close-btn" onClick={handleClose}>
|
||||
|
||||
@@ -20,14 +20,38 @@ export default function MidMile({ active }) {
|
||||
<h2 className="section-title">{config.title}</h2>
|
||||
<h3 className="section-subtitle">{config.subtitle}</h3>
|
||||
<p className="section-description">{config.description}</p>
|
||||
<div className="section-metrics">
|
||||
<div className="metric-item">
|
||||
<span className="metric-value">4.2 hr</span>
|
||||
<span className="metric-label">Avg. Transit Time</span>
|
||||
{/* Enterprise information strip — icon + title + description rows with
|
||||
subtle hairline separators (no KPI cards / oversized statistics).
|
||||
Keeps the `section-metrics` class so the RevealCard entrance stagger
|
||||
still treats it as a single animated block. */}
|
||||
<div className="section-metrics mm-info-strip">
|
||||
<div className="mm-info-row">
|
||||
<span className="mm-info-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<rect x="1" y="3" width="15" height="13"></rect>
|
||||
<polygon points="16 8 20 8 23 11 23 16 16 16 16 8"></polygon>
|
||||
<circle cx="5.5" cy="18.5" r="2.5"></circle>
|
||||
<circle cx="18.5" cy="18.5" r="2.5"></circle>
|
||||
</svg>
|
||||
</span>
|
||||
<div className="mm-info-content">
|
||||
<h4 className="mm-info-title">Vehicles In Transit</h4>
|
||||
<p className="mm-info-text">A live view of active vehicles moving shipments between regional distribution hubs.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="metric-item">
|
||||
<span className="metric-value">220 kw</span>
|
||||
<span className="metric-label">Solar Output (Self-powered)</span>
|
||||
<div className="mm-info-row">
|
||||
<span className="mm-info-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<line x1="16.5" y1="9.4" x2="7.5" y2="4.21"></line>
|
||||
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
|
||||
<polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
|
||||
<line x1="12" y1="22.08" x2="12" y2="12"></line>
|
||||
</svg>
|
||||
</span>
|
||||
<div className="mm-info-content">
|
||||
<h4 className="mm-info-title">Packages In Transit</h4>
|
||||
<p className="mm-info-text">Real-time visibility into parcels currently moving through the mid-mile network.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button className="section-close-btn" onClick={handleClose}>
|
||||
|
||||
29
src/modules/how-it-works-3d/components/sections/Promise.jsx
Normal file
29
src/modules/how-it-works-3d/components/sections/Promise.jsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import React from 'react'
|
||||
import RevealCard from '../ui/RevealCard'
|
||||
|
||||
/**
|
||||
* Promise — Final card
|
||||
* ---------------------------------------------------------------------------
|
||||
* Closing-statement card and the final beat of the experience, revealed as the
|
||||
* journey closes (right after Stage 03 — Last Mile). It's a regular centred
|
||||
* in-experience overlay card (same chrome as the others) — NOT a separate
|
||||
* scroll section — so the camera, scene, and scroll timing are untouched.
|
||||
*/
|
||||
export default function Promise({ active }) {
|
||||
return (
|
||||
<RevealCard active={active} id="promise-section">
|
||||
<div className="section-badge">The Doormile Promise</div>
|
||||
<h2 className="section-title promise-title">
|
||||
One Connected System.
|
||||
<br />
|
||||
One Promise Kept.
|
||||
</h2>
|
||||
<span className="promise-divider" aria-hidden></span>
|
||||
<p className="section-description promise-desc">
|
||||
Stop managing three separate logistics services. Doormile unifies first,
|
||||
mid and last mile into a single intelligent delivery system powered by
|
||||
MileTruth™ AI.
|
||||
</p>
|
||||
</RevealCard>
|
||||
)
|
||||
}
|
||||
@@ -7,8 +7,10 @@ export default function Navbar() {
|
||||
const lenis = useSceneStore((state) => state.lenis)
|
||||
|
||||
const handleNavClick = (index) => {
|
||||
// Map index (0, 1, 2, 3) to the stable parking progress percentages (0.0, 0.38, 0.76, 0.97).
|
||||
const sectionFractions = [0, 0.38, 0.76, 0.97]
|
||||
// Map index (0, 1, 2, 3) to the stable parking progress percentages.
|
||||
// The last lands on the analytics-dashboard view, where the closing promise
|
||||
// card is revealed as the user finishes the final stretch of scroll.
|
||||
const sectionFractions = [0, 0.38, 0.76, 0.92]
|
||||
const targetProgress = sectionFractions[index]
|
||||
// Relative to the experience spacer (the section sits below the page hero).
|
||||
lenis?.scrollTo(progressToScrollY(targetProgress), { duration: 1.5 })
|
||||
|
||||
@@ -10,10 +10,12 @@ export default function RevealCard({ children, active, id, className = "" }) {
|
||||
|
||||
// Find all target children inside the card to create a staggered entrance
|
||||
const animTargets = card.querySelectorAll(
|
||||
'.section-badge, .section-title, .section-subtitle, .section-description, .section-metrics, .section-close-btn, .workflow-step'
|
||||
'.section-badge, .section-title, .section-subtitle, .section-description, .section-metrics, .section-supporting, .section-close-btn'
|
||||
)
|
||||
|
||||
const isAnalytics = id === 'analytics-section'
|
||||
// The promise card (the final card) is centred, so its reveal/exit tweens
|
||||
// must preserve the -50%/-50% centring offset.
|
||||
const isCentered = id === 'promise-section'
|
||||
|
||||
if (active) {
|
||||
// Clean up any ongoing animations first
|
||||
@@ -21,8 +23,8 @@ export default function RevealCard({ children, active, id, className = "" }) {
|
||||
|
||||
// Animate card container in
|
||||
gsap.to(card, {
|
||||
xPercent: isAnalytics ? -50 : 0,
|
||||
yPercent: isAnalytics ? -50 : 0,
|
||||
xPercent: isCentered ? -50 : 0,
|
||||
yPercent: isCentered ? -50 : 0,
|
||||
y: 0,
|
||||
scale: 1,
|
||||
opacity: 1,
|
||||
@@ -52,9 +54,9 @@ export default function RevealCard({ children, active, id, className = "" }) {
|
||||
|
||||
// Animate card container out
|
||||
gsap.to(card, {
|
||||
xPercent: isAnalytics ? -50 : 0,
|
||||
yPercent: isAnalytics ? -50 : 0,
|
||||
y: isAnalytics ? 18 : 20,
|
||||
xPercent: isCentered ? -50 : 0,
|
||||
yPercent: isCentered ? -50 : 0,
|
||||
y: isCentered ? 18 : 20,
|
||||
scale: 0.96,
|
||||
opacity: 0,
|
||||
duration: 0.5,
|
||||
@@ -78,8 +80,8 @@ export default function RevealCard({ children, active, id, className = "" }) {
|
||||
className={`section-panel ${active ? 'active' : ''} ${className}`}
|
||||
style={{
|
||||
opacity: 0,
|
||||
transform: id === 'analytics-section'
|
||||
? 'translate(-50%, -50%) translateY(18px) scale(0.96)'
|
||||
transform: id === 'promise-section'
|
||||
? 'translate(-50%, -50%) translateY(18px) scale(0.96)'
|
||||
: 'translateY(20px) scale(0.96)',
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -19,7 +19,7 @@ export const sections = [
|
||||
id: 'last-mile',
|
||||
title: 'Last Mile Delivery',
|
||||
subtitle: 'Doorstep Courier Services',
|
||||
description: 'Local delivery units take over, planning optimal paths to transport packages directly to customer doorsteps.',
|
||||
description: 'Local courier fleets take over for the final leg — MileTruth™ AI sequences the fastest doorstep routes and keeps every package tracked through to a confirmed delivery.',
|
||||
progressStart: 0.5,
|
||||
progressEnd: 0.75,
|
||||
},
|
||||
|
||||
@@ -30,6 +30,17 @@
|
||||
--dm-card-shadow: 0 24px 60px -28px rgba(15, 23, 42, 0.45);
|
||||
--dm-font-head: var(--font-space-grotesk), var(--font-manrope), system-ui, sans-serif;
|
||||
--dm-font-body: var(--font-manrope), system-ui, -apple-system, sans-serif;
|
||||
|
||||
/* Container spacing — matches the site's full-width section frame
|
||||
(.custom-standard-hero-container used by Contact/About/CTA: full width,
|
||||
no max-width cap, 20px gutters, 25px radius). The stage spans ~98% of the
|
||||
viewport with standard gutters rather than sitting in a narrow centred box.
|
||||
Values scale down responsively. */
|
||||
--hiw-max-width: none;
|
||||
--hiw-gutter: 20px;
|
||||
--hiw-gap-top: 20px;
|
||||
--hiw-gap-bottom: 20px;
|
||||
--hiw-radius: 25px;
|
||||
}
|
||||
|
||||
/* ---- Section shell + self-managed fixed pin ---- */
|
||||
@@ -44,26 +55,38 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* The stage is inset to sit inside the site's content container: a centred
|
||||
max-width box with left/right gutters and equal top/bottom spacing. The SAME
|
||||
inset is applied in every pin state (absolute-top → fixed → absolute-bottom)
|
||||
so the stage never jumps at the pin hand-offs. Scroll progress and stage
|
||||
maths are driven by the separate 900vh spacer (#scroll-trigger-trigger), so
|
||||
insetting the stage doesn't touch them. Horizontal centring uses
|
||||
left/right:0 + margin:auto (not transform) so it composes with the existing
|
||||
translateZ(0) GPU layer. The 3D scene is not scaled — the canvas simply fills
|
||||
the smaller framed box and CameraRig already adapts FOV to the aspect. */
|
||||
.dm-hiw-3d-stage {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
top: var(--hiw-gap-top);
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
right: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: calc(100% - 2 * var(--hiw-gutter));
|
||||
max-width: var(--hiw-max-width);
|
||||
height: calc(100vh - var(--hiw-gap-top) - var(--hiw-gap-bottom));
|
||||
overflow: hidden;
|
||||
border-radius: var(--hiw-radius);
|
||||
will-change: transform;
|
||||
transform: translateZ(0);
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
.dm-hiw-3d.is-pinned .dm-hiw-3d-stage {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.dm-hiw-3d.is-after .dm-hiw-3d-stage {
|
||||
position: absolute;
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
bottom: var(--hiw-gap-bottom);
|
||||
}
|
||||
|
||||
.dm-hiw-3d .canvas-wrapper {
|
||||
@@ -194,27 +217,273 @@
|
||||
.dm-hiw-3d #last-mile-section {
|
||||
left: clamp(24px, 5vw, 72px);
|
||||
}
|
||||
/* ===========================================================================
|
||||
Stage 02 — Mid Mile Hub: premium enterprise dashboard card.
|
||||
Scoped entirely to #mid-mile-section so the other three stage cards keep the
|
||||
unified chrome. UI only — no transform/animation/scene/scroll changes (the
|
||||
GSAP reveal still targets the same .section-* classes, which are preserved).
|
||||
Sizes use clamp() so they scale down gracefully without fighting the shared
|
||||
responsive rules below.
|
||||
=========================================================================== */
|
||||
.dm-hiw-3d #mid-mile-section {
|
||||
right: clamp(24px, 5vw, 72px);
|
||||
/* Only marginally larger than the sibling side panels (Stage 01/03 are
|
||||
min(404px, 37vw)) — ~13% wider to hold the extra info, not dominant. */
|
||||
width: min(456px, 41vw);
|
||||
max-height: calc(100vh - 120px);
|
||||
padding: clamp(22px, 2.4vw, 30px) clamp(24px, 2.8vw, 34px) clamp(20px, 2.2vw, 26px);
|
||||
/* Clean glassmorphism white surface with subtle transparency. */
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-top: 3px solid var(--dm-red); /* thin red accent along the top edge */
|
||||
box-shadow: 0 32px 72px -30px rgba(15, 23, 42, 0.5);
|
||||
}
|
||||
/* Final ecosystem panel — same card system, centred, a touch wider for its
|
||||
timeline, and reduced from the old 500px so it no longer blocks the scene. */
|
||||
.dm-hiw-3d #analytics-section {
|
||||
|
||||
/* ---- Header: stronger hierarchy ---- */
|
||||
.dm-hiw-3d #mid-mile-section .section-badge {
|
||||
font-size: 12px !important;
|
||||
letter-spacing: 0.22em !important;
|
||||
margin: 0 0 10px !important;
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .section-title {
|
||||
font-size: clamp(28px, 2.5vw, 40px) !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1.07 !important;
|
||||
letter-spacing: -0.025em !important;
|
||||
margin: 0 0 7px !important;
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .section-subtitle {
|
||||
font-size: clamp(14.5px, 1.2vw, 16px) !important;
|
||||
font-weight: 600 !important;
|
||||
color: var(--dm-body) !important;
|
||||
margin: 0 0 13px !important;
|
||||
}
|
||||
|
||||
/* ---- Description: larger, more readable, contained measure ---- */
|
||||
.dm-hiw-3d #mid-mile-section .section-description {
|
||||
font-size: clamp(14.5px, 1.15vw, 16px) !important;
|
||||
line-height: 1.72 !important;
|
||||
max-width: 44ch !important;
|
||||
margin: 0 0 6px !important;
|
||||
}
|
||||
|
||||
/* ---- Stage 02 information strip ----------------------------------------
|
||||
Replaces the KPI/metric look with a clean enterprise info panel: a
|
||||
full-width column of icon + title + description rows divided by subtle
|
||||
hairlines. Scoped to #mid-mile-section so the shared .section-metrics /
|
||||
.metric-* styling on the other cards is untouched. The ID specificity also
|
||||
overrides the base `.section-metrics` flex-row + border styling that still
|
||||
rides along on the retained class. */
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-strip {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
width: 100%; /* full-width content row */
|
||||
border-top: 1px solid rgba(15, 23, 42, 0.08);
|
||||
padding-top: 4px;
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
padding: 11px 0;
|
||||
}
|
||||
/* Subtle separator between rows only (not above the first / below the last). */
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-row + .mm-info-row {
|
||||
border-top: 1px solid rgba(15, 23, 42, 0.07);
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-icon {
|
||||
flex-shrink: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 10px;
|
||||
background: var(--dm-red-soft);
|
||||
color: var(--dm-red);
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-icon svg {
|
||||
width: 21px;
|
||||
height: 21px;
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding-top: 1px;
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-title {
|
||||
font-family: var(--dm-font-head) !important;
|
||||
font-size: 15px !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1.3 !important;
|
||||
letter-spacing: -0.01em !important;
|
||||
color: var(--dm-ink) !important;
|
||||
margin: 0 0 3px !important;
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-text {
|
||||
font-family: var(--dm-font-body) !important;
|
||||
font-size: 13.5px !important;
|
||||
font-weight: 400 !important;
|
||||
line-height: 1.58 !important;
|
||||
color: var(--dm-body) !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
/* ---- Metrics: a simple horizontal row sitting DIRECTLY on the card surface —
|
||||
no nested tiles / boxed containers. A thin divider rule above separates it
|
||||
from the description; within each metric the icon sits to the left of the
|
||||
value, with the label directly beneath it. Compact + uncluttered. ---- */
|
||||
.dm-hiw-3d #mid-mile-section .section-metrics {
|
||||
/* The strip is a vertical column; rows space themselves via their own
|
||||
padding, so no large flex gap (this was a major source of extra height). */
|
||||
gap: 0;
|
||||
border-top: 1px solid rgba(15, 23, 42, 0.1);
|
||||
margin-top: 14px;
|
||||
padding-top: 12px;
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .metric-item {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-template-rows: auto auto;
|
||||
column-gap: 12px;
|
||||
row-gap: 3px;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
/* Compact icon chip, vertically centred against the value/label stack. */
|
||||
.dm-hiw-3d #mid-mile-section .metric-icon {
|
||||
grid-row: 1 / span 2;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: clamp(36px, 3vw, 42px);
|
||||
height: clamp(36px, 3vw, 42px);
|
||||
margin: 0;
|
||||
border-radius: 11px;
|
||||
background: var(--dm-red-soft);
|
||||
color: var(--dm-red);
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .metric-icon svg {
|
||||
width: 56%;
|
||||
height: 56%;
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .metric-value {
|
||||
grid-column: 2;
|
||||
align-self: end;
|
||||
font-size: clamp(26px, 2.4vw, 34px) !important;
|
||||
line-height: 1 !important;
|
||||
letter-spacing: -0.02em !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .metric-label {
|
||||
grid-column: 2;
|
||||
align-self: start;
|
||||
font-size: 10.5px !important;
|
||||
letter-spacing: 0.1em !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
/* ---- CTA: larger red pill with subtle shadow + hover lift ---- */
|
||||
.dm-hiw-3d #mid-mile-section .section-close-btn {
|
||||
margin-top: 16px;
|
||||
font-size: clamp(14px, 1vw, 15px);
|
||||
font-weight: 600;
|
||||
padding: clamp(12px, 1vw, 15px) clamp(24px, 2vw, 30px);
|
||||
box-shadow: 0 16px 30px -12px rgba(192, 18, 39, 0.6);
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .section-close-btn svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
/* Tablet/mobile: relax the contained measure and tighten the KPI tiles so the
|
||||
larger desktop styling above never overflows the bottom-docked card. */
|
||||
@media (max-width: 1024px) {
|
||||
.dm-hiw-3d #mid-mile-section .section-description {
|
||||
max-width: none !important;
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .section-metrics {
|
||||
margin-top: 12px;
|
||||
padding-top: 10px;
|
||||
gap: 0;
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .section-close-btn {
|
||||
margin-top: 14px;
|
||||
}
|
||||
}
|
||||
/* Closing promise card — a centred card occupying the final slot. */
|
||||
.dm-hiw-3d #promise-section {
|
||||
left: 50%;
|
||||
right: auto;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%) translateY(18px) scale(0.97);
|
||||
width: min(400px, 90vw);
|
||||
max-height: calc(100vh - 140px);
|
||||
width: min(1060px, 92vw);
|
||||
max-height: calc(100vh - 110px);
|
||||
}
|
||||
/* Closing-statement card — the final key message of the journey, scaled to the
|
||||
authority of the page hero. The card spans most of the viewport width (small
|
||||
left/right margins) so the headline can run wide; padding is kept lean so the
|
||||
headline — not whitespace — dominates. */
|
||||
.dm-hiw-3d #promise-section {
|
||||
width: min(1060px, 92vw) !important; /* wide: uses most of the viewport */
|
||||
padding: 36px 56px !important;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center; /* centre the group vertically */
|
||||
align-items: center; /* centre the group horizontally */
|
||||
}
|
||||
/* Kicker/subtitle — bumped ~+25% to sit in proportion with the larger headline. */
|
||||
.dm-hiw-3d #promise-section .section-badge {
|
||||
display: block !important;
|
||||
font-size: 15px !important;
|
||||
letter-spacing: 0.2em !important;
|
||||
margin: 0 0 18px !important;
|
||||
}
|
||||
/* Dominant headline — matches the hero scale: up to 80px, uppercase, heavy
|
||||
weight, tight hero leading + word-spacing. This is the visual anchor of the
|
||||
card and the strongest type on the screen. */
|
||||
/* Scoped under #promise-section (ID specificity) so it reliably overrides the
|
||||
shared `.section-title` base rule, which is declared later in the file. */
|
||||
.dm-hiw-3d #promise-section .promise-title {
|
||||
font-size: clamp(40px, 6vw, 80px) !important;
|
||||
font-weight: 800 !important;
|
||||
line-height: 1.1 !important;
|
||||
letter-spacing: -0.03em !important;
|
||||
word-spacing: -0.03em !important;
|
||||
text-transform: uppercase !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
/* Real, flex-centred divider element — exactly under the headline centre. */
|
||||
.dm-hiw-3d .promise-divider {
|
||||
display: block;
|
||||
width: 76px;
|
||||
height: 3px;
|
||||
border-radius: 999px;
|
||||
background: var(--dm-red);
|
||||
margin: 24px auto;
|
||||
}
|
||||
/* Supporting paragraph — hero body scale (20px) on a wide measure so it reads
|
||||
as a balanced two-to-three line statement instead of wrapping too early.
|
||||
Scoped under #promise-section so it overrides the later `.section-description`
|
||||
base rule. */
|
||||
.dm-hiw-3d #promise-section .promise-desc {
|
||||
margin: 0 auto !important;
|
||||
max-width: 760px !important;
|
||||
font-size: 20px !important;
|
||||
line-height: 1.7 !important;
|
||||
}
|
||||
|
||||
/* ---- Unified card — all four stages share this exact chrome ---- */
|
||||
.dm-hiw-3d .section-panel {
|
||||
position: absolute;
|
||||
width: min(340px, 31vw);
|
||||
max-height: calc(100vh - 168px); /* never taller than the viewport */
|
||||
width: min(404px, 37vw);
|
||||
max-height: calc(100vh - 140px); /* never taller than the viewport */
|
||||
overflow-y: auto;
|
||||
padding: 24px 26px 26px;
|
||||
padding: 34px 36px 34px;
|
||||
background: var(--dm-card-bg);
|
||||
backdrop-filter: blur(0px);
|
||||
-webkit-backdrop-filter: blur(0px);
|
||||
@@ -247,53 +516,53 @@
|
||||
font-size: 10.5px !important;
|
||||
text-transform: uppercase !important;
|
||||
font-weight: 700 !important;
|
||||
letter-spacing: 0.14em !important;
|
||||
letter-spacing: 0.16em !important;
|
||||
color: var(--dm-red) !important;
|
||||
margin: 0 0 10px !important;
|
||||
margin: 0 0 12px !important;
|
||||
}
|
||||
.dm-hiw-3d .section-title {
|
||||
font-family: var(--dm-font-head) !important;
|
||||
font-size: clamp(18px, 1.45vw, 22px) !important;
|
||||
font-size: clamp(19px, 1.55vw, 24px) !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1.15 !important;
|
||||
letter-spacing: -0.015em !important;
|
||||
line-height: 1.18 !important;
|
||||
letter-spacing: -0.018em !important;
|
||||
text-transform: none !important;
|
||||
color: var(--dm-ink) !important;
|
||||
margin: 0 0 4px !important;
|
||||
margin: 0 0 6px !important;
|
||||
}
|
||||
.dm-hiw-3d .section-subtitle {
|
||||
font-family: var(--dm-font-body) !important;
|
||||
font-size: 13px !important;
|
||||
font-weight: 500 !important;
|
||||
line-height: 1.35 !important;
|
||||
letter-spacing: 0 !important;
|
||||
line-height: 1.4 !important;
|
||||
letter-spacing: 0.005em !important;
|
||||
text-transform: none !important;
|
||||
color: var(--dm-muted) !important;
|
||||
margin: 0 0 14px !important;
|
||||
margin: 0 0 16px !important;
|
||||
}
|
||||
.dm-hiw-3d .section-description {
|
||||
font-family: var(--dm-font-body) !important;
|
||||
font-size: 13px !important;
|
||||
font-size: 13.5px !important;
|
||||
font-weight: 400 !important;
|
||||
line-height: 1.55 !important;
|
||||
line-height: 1.62 !important;
|
||||
color: var(--dm-body) !important;
|
||||
margin: 0 0 18px !important;
|
||||
margin: 0 0 20px !important;
|
||||
}
|
||||
.dm-hiw-3d .section-metrics {
|
||||
display: flex;
|
||||
gap: 18px;
|
||||
gap: 20px;
|
||||
border-top: 1px solid rgba(15, 23, 42, 0.08);
|
||||
padding-top: 16px;
|
||||
padding-top: 18px;
|
||||
}
|
||||
.dm-hiw-3d .metric-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
gap: 4px;
|
||||
flex: 1;
|
||||
}
|
||||
.dm-hiw-3d .metric-value {
|
||||
font-family: var(--dm-font-head) !important;
|
||||
font-size: 18px !important;
|
||||
font-size: 19px !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1.1 !important;
|
||||
letter-spacing: -0.01em !important;
|
||||
@@ -304,11 +573,58 @@
|
||||
font-size: 9.5px !important;
|
||||
font-weight: 600 !important;
|
||||
text-transform: uppercase !important;
|
||||
letter-spacing: 0.07em !important;
|
||||
letter-spacing: 0.08em !important;
|
||||
color: var(--dm-muted) !important;
|
||||
}
|
||||
.dm-hiw-3d .font-green .metric-value { color: #1f9d57 !important; }
|
||||
|
||||
/* Supporting metric (e.g. Last Mile real-time driver tracking) — a full-width
|
||||
live-status row that sits beneath the two headline metrics. */
|
||||
.dm-hiw-3d .section-supporting {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 11px;
|
||||
margin-top: 14px;
|
||||
padding: 11px 14px;
|
||||
background: rgba(31, 157, 87, 0.07);
|
||||
border: 1px solid rgba(31, 157, 87, 0.18);
|
||||
border-radius: 12px;
|
||||
}
|
||||
.dm-hiw-3d .supporting-dot {
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 50%;
|
||||
background-color: #1f9d57;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 0 0 0 rgba(31, 157, 87, 0.5);
|
||||
animation: dmHiwPulseDot 2s cubic-bezier(0.16, 1, 0.3, 1) infinite;
|
||||
}
|
||||
.dm-hiw-3d .supporting-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
.dm-hiw-3d .supporting-value {
|
||||
font-family: var(--dm-font-head) !important;
|
||||
font-size: 12.5px !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1.15 !important;
|
||||
letter-spacing: -0.005em !important;
|
||||
color: var(--dm-ink) !important;
|
||||
}
|
||||
.dm-hiw-3d .supporting-label {
|
||||
font-family: var(--dm-font-body) !important;
|
||||
font-size: 10px !important;
|
||||
font-weight: 600 !important;
|
||||
letter-spacing: 0.04em !important;
|
||||
color: #1f9d57 !important;
|
||||
}
|
||||
@keyframes dmHiwPulseDot {
|
||||
0% { box-shadow: 0 0 0 0 rgba(31, 157, 87, 0.45); }
|
||||
70% { box-shadow: 0 0 0 7px rgba(31, 157, 87, 0); }
|
||||
100% { box-shadow: 0 0 0 0 rgba(31, 157, 87, 0); }
|
||||
}
|
||||
|
||||
/* ---- Animations (keyframes left global; uniquely named) ---- */
|
||||
@keyframes dmHiwScrollWheel {
|
||||
0% { top: 6px; opacity: 1; height: 6px; }
|
||||
@@ -324,62 +640,15 @@
|
||||
50% { transform: translateX(8px); }
|
||||
}
|
||||
|
||||
/* ---- Final-panel timeline (inside #analytics-section) ---- */
|
||||
.dm-hiw-3d .workflow-steps {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.dm-hiw-3d .workflow-step { display: flex; gap: 14px; }
|
||||
.dm-hiw-3d .step-number-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 24px;
|
||||
}
|
||||
.dm-hiw-3d .step-number {
|
||||
font-family: var(--dm-font-head);
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
color: var(--dm-red);
|
||||
background: var(--dm-red-soft);
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid rgba(192, 18, 39, 0.2);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.dm-hiw-3d .step-line {
|
||||
width: 2px;
|
||||
flex-grow: 1;
|
||||
background: linear-gradient(to bottom, var(--dm-red) 0%, rgba(192, 18, 39, 0.12) 100%);
|
||||
margin: 5px 0;
|
||||
min-height: 16px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.dm-hiw-3d .step-content { flex-grow: 1; padding-bottom: 14px; }
|
||||
.dm-hiw-3d .step-title {
|
||||
font-family: var(--dm-font-head) !important;
|
||||
font-size: 14px !important;
|
||||
font-weight: 700 !important;
|
||||
line-height: 1.2 !important;
|
||||
color: var(--dm-ink) !important;
|
||||
margin: 1px 0 3px !important;
|
||||
}
|
||||
.dm-hiw-3d .step-description {
|
||||
font-family: var(--dm-font-body) !important;
|
||||
font-size: 12px !important;
|
||||
line-height: 1.5 !important;
|
||||
color: var(--dm-body) !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
/* ---- Responsive ---- */
|
||||
@media (max-width: 1024px) {
|
||||
/* Moderate gutters on tablet (radius matches the site's tablet section card). */
|
||||
.dm-hiw-3d {
|
||||
--hiw-gutter: 16px;
|
||||
--hiw-gap-top: 16px;
|
||||
--hiw-gap-bottom: 16px;
|
||||
--hiw-radius: 22px;
|
||||
}
|
||||
.dm-hiw-3d .sections-overlay-container {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
@@ -387,28 +656,45 @@
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
.dm-hiw-3d .section-panel {
|
||||
padding: 20px 22px 22px;
|
||||
padding: 26px 28px 28px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
/* Tablet/mobile: cards bottom-centred so the truck/scene stays visible above. */
|
||||
.dm-hiw-3d #first-mile-section,
|
||||
.dm-hiw-3d #mid-mile-section,
|
||||
.dm-hiw-3d #last-mile-section,
|
||||
.dm-hiw-3d #analytics-section {
|
||||
.dm-hiw-3d #promise-section {
|
||||
left: 50% !important;
|
||||
right: auto !important;
|
||||
top: auto !important;
|
||||
bottom: 64px !important;
|
||||
transform: translateX(-50%) translateY(18px) scale(0.97) !important;
|
||||
width: min(380px, calc(100vw - 40px)) !important;
|
||||
max-height: calc(100vh - 200px) !important;
|
||||
width: min(460px, calc(100vw - 32px)) !important;
|
||||
max-height: calc(100vh - 180px) !important;
|
||||
}
|
||||
.dm-hiw-3d #first-mile-section.active,
|
||||
.dm-hiw-3d #mid-mile-section.active,
|
||||
.dm-hiw-3d #last-mile-section.active,
|
||||
.dm-hiw-3d #analytics-section.active {
|
||||
.dm-hiw-3d #promise-section.active {
|
||||
transform: translateX(-50%) translateY(0) scale(1) !important;
|
||||
}
|
||||
/* Tablet: keep the promise card wider than the stage cards so the larger
|
||||
headline still runs wide and balanced. */
|
||||
.dm-hiw-3d #promise-section {
|
||||
width: min(760px, calc(100vw - 40px)) !important;
|
||||
padding: 30px 40px !important;
|
||||
}
|
||||
.dm-hiw-3d #promise-section .section-badge {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
.dm-hiw-3d #promise-section .promise-title {
|
||||
font-size: clamp(34px, 5.4vw, 54px) !important;
|
||||
line-height: 1.08 !important;
|
||||
}
|
||||
.dm-hiw-3d #promise-section .promise-desc {
|
||||
font-size: 18px !important;
|
||||
max-width: 640px !important;
|
||||
}
|
||||
.dm-hiw-3d .side-navigation {
|
||||
bottom: 12px;
|
||||
top: auto;
|
||||
@@ -430,10 +716,17 @@
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
/* Slimmest gutters on phones — matches the hero's mobile frame. */
|
||||
.dm-hiw-3d {
|
||||
--hiw-gutter: 12px;
|
||||
--hiw-gap-top: 12px;
|
||||
--hiw-gap-bottom: 12px;
|
||||
--hiw-radius: 16px;
|
||||
}
|
||||
.dm-hiw-3d .section-panel,
|
||||
.dm-hiw-3d #analytics-section {
|
||||
padding: 16px 18px 18px !important;
|
||||
width: min(340px, calc(100vw - 28px)) !important;
|
||||
.dm-hiw-3d #promise-section {
|
||||
padding: 20px 20px 20px !important;
|
||||
width: min(360px, calc(100vw - 24px)) !important;
|
||||
bottom: 56px !important;
|
||||
}
|
||||
.dm-hiw-3d .section-badge {
|
||||
@@ -441,7 +734,18 @@
|
||||
margin-bottom: 6px !important;
|
||||
}
|
||||
.dm-hiw-3d .section-title {
|
||||
font-size: 18px !important;
|
||||
font-size: 19px !important;
|
||||
}
|
||||
.dm-hiw-3d #promise-section .section-badge {
|
||||
font-size: 12.5px !important;
|
||||
}
|
||||
.dm-hiw-3d #promise-section .promise-title {
|
||||
font-size: clamp(28px, 8.5vw, 34px) !important;
|
||||
line-height: 1.08 !important;
|
||||
}
|
||||
.dm-hiw-3d #promise-section .promise-desc {
|
||||
font-size: 16px !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
.dm-hiw-3d .section-subtitle {
|
||||
font-size: 12.5px !important;
|
||||
@@ -458,8 +762,17 @@
|
||||
}
|
||||
.dm-hiw-3d .metric-value { font-size: 16px !important; }
|
||||
.dm-hiw-3d .metric-label { font-size: 9px !important; }
|
||||
.dm-hiw-3d .step-title { font-size: 13px !important; }
|
||||
.dm-hiw-3d .step-description { font-size: 11.5px !important; }
|
||||
/* Stage 02 info strip stays a tidy hairline-divided column on small screens
|
||||
(overrides the shared .section-metrics !important gap/padding above). */
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-strip {
|
||||
gap: 0 !important;
|
||||
padding-top: 2px !important;
|
||||
}
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-row { padding: 13px 0; gap: 13px; }
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-icon { width: 36px; height: 36px; }
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-icon svg { width: 19px; height: 19px; }
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-title { font-size: 14px !important; }
|
||||
.dm-hiw-3d #mid-mile-section .mm-info-text { font-size: 12.5px !important; }
|
||||
.dm-hiw-3d .side-navigation {
|
||||
bottom: 8px !important;
|
||||
gap: 12px !important;
|
||||
@@ -469,17 +782,17 @@
|
||||
.dm-hiw-3d #first-mile-section,
|
||||
.dm-hiw-3d #mid-mile-section,
|
||||
.dm-hiw-3d #last-mile-section,
|
||||
.dm-hiw-3d #analytics-section {
|
||||
.dm-hiw-3d #promise-section {
|
||||
left: 50% !important;
|
||||
right: auto !important;
|
||||
bottom: 56px !important;
|
||||
width: min(340px, calc(100vw - 28px)) !important;
|
||||
width: min(360px, calc(100vw - 24px)) !important;
|
||||
transform: translateX(-50%) translateY(18px) scale(0.97) !important;
|
||||
}
|
||||
.dm-hiw-3d #first-mile-section.active,
|
||||
.dm-hiw-3d #mid-mile-section.active,
|
||||
.dm-hiw-3d #last-mile-section.active,
|
||||
.dm-hiw-3d #analytics-section.active {
|
||||
.dm-hiw-3d #promise-section.active {
|
||||
transform: translateX(-50%) translateY(0) scale(1) !important;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user