fix workflow section

This commit is contained in:
2026-07-13 15:10:13 +05:30
parent 333460525a
commit 7587c622c3
7 changed files with 270 additions and 20 deletions

View File

@@ -42,6 +42,9 @@ export interface EVStat {
decimals?: number;
suffix: string;
label: string;
/** Optional static text override — when set, renders this text instead of
* an animated CountUp (for non-numeric KPI concepts, e.g. "QUBO"). */
text?: string;
}
/** Accent theming for the dashboard column so it matches the scene on the left
@@ -83,10 +86,19 @@ interface EVSectionProps {
* static homepage feature list. The bottom stat bar is dropped in this mode
* to avoid repeating the metrics. */
metrics?: EVStat[];
/** Optional distinct copy for the bottom `.evnd__bar` strip in dashboard
* mode. Defaults to reusing `metrics` (WF1/WF2 behaviour) when omitted. */
barStats?: EVStat[];
/** Heading above the dashboard, e.g. "PERFORMANCE INSIGHT". */
cardsHeading?: string;
/** Accent theme for the dashboard column (defaults to the section red). */
cardsTheme?: EVCardsTheme;
/** Dashboard system label, top-right of the header row. Defaults to "AI ENGINE". */
sysLabel?: string;
/** Extra class appended to `.evnd__imgwrap`, for workflow-specific media
* sizing overrides (e.g. video object-fit) defined in the caller's own
* scoped <style> tag rather than here. */
mediaClassName?: string;
}
/* ---- Default content = original homepage EV Logistics section ---- */
@@ -260,11 +272,13 @@ function DashboardPanel({
features,
heading,
theme,
sysLabel = "AI ENGINE",
}: {
metrics: EVStat[];
features: EVFeature[];
heading?: string;
theme?: EVCardsTheme;
sysLabel?: string;
}) {
const themeVars = theme
? ({
@@ -287,7 +301,7 @@ function DashboardPanel({
<span className="evnd__dash-livedot" />
{heading}
</span>
<span className="evnd__dash-sys">AI ENGINE</span>
<span className="evnd__dash-sys">{sysLabel}</span>
</div>
)}
@@ -295,12 +309,16 @@ function DashboardPanel({
<div className="evnd__dash-kpis">
{metrics.map((m) => (
<div className="evnd__kpi" key={m.label}>
<CountUp
value={m.value}
decimals={m.decimals}
suffix={m.suffix}
className="evnd__kpi-val"
/>
{m.text ? (
<b className="evnd__kpi-val evnd__kpi-val--text">{m.text}</b>
) : (
<CountUp
value={m.value}
decimals={m.decimals}
suffix={m.suffix}
className="evnd__kpi-val"
/>
)}
<span className="evnd__kpi-label">{m.label}</span>
</div>
))}
@@ -342,11 +360,15 @@ export default function EVSection({
ariaLabel,
mediaSlot,
metrics,
barStats,
cardsHeading,
cardsTheme,
sysLabel,
mediaClassName,
}: EVSectionProps) {
const bannerRef = useRef<HTMLDivElement>(null);
const useDashboard = !!metrics && metrics.length > 0;
const isVideo = image.endsWith(".mp4");
/* In dashboard mode the workflow's accent theme is applied at the .evnd
section level so the shared animated network backdrop (below) is tinted to
@@ -595,13 +617,31 @@ export default function EVSection({
background: #ef4444;
}
/* ---- Heading → content gap ----
Deliberately set here (on the wrapper div) rather than as
margin-bottom on .evnd__title (the <h2>): a global site.css rule
(.logico-front-end h2:not([class*="logico-title-h"]):last-child)
outweighs .evnd__title's own specificity and zeroes any bottom
margin placed on the heading itself, since the h2 is always the
last child of .evnd__heading. Setting it here sidesteps that
collision and gives every workflow section + Fleet Strategy one
shared, consistent gap. */
.evnd__heading {
margin-bottom: 40px;
}
@media (max-width: 991px) and (min-width: 768px) {
.evnd__heading {
margin-bottom: 34px;
}
}
.evnd__title {
color: #fff !important;
font-weight: 800 !important;
font-size: clamp(32px, 3.8vw, 48px) !important;
line-height: 1.15 !important;
letter-spacing: -0.01em;
margin: 0 0 36px 0;
margin: 0;
}
@media (min-width: 768px) {
.evnd__title {
@@ -867,6 +907,13 @@ export default function EVSection({
font-size: 12.5px;
letter-spacing: 0.01em;
}
/* Non-numeric KPI concepts (EVStat.text) — same gradient treatment as
the counted values, sized down so short codes/words don't inherit
the numeric clamp() meant for 2-3 digit figures. */
.evnd__kpi-val--text {
font-size: clamp(18px, 1.6vw, 22px) !important;
letter-spacing: 0.02em;
}
/* ============================================================
Large-screen layout balance (WF1/WF2 dashboard only, ≥1440px).
@@ -1041,6 +1088,14 @@ export default function EVSection({
text-transform: none;
opacity: 0.9;
}
/* Non-numeric bar values (EVStat.text) — the bar's numeric clamp()
(up to 56px) is too large for words/phrases; size down and let
longer phrases (e.g. "Cost + Distance + SLA") wrap cleanly. */
.evnd__bar-val--text {
font-size: clamp(16px, 1.8vw, 22px);
line-height: 1.25;
white-space: normal;
}
@keyframes evndGlow { 0%,100% { opacity: 0.75; } 50% { opacity: 1; } }
@@ -1052,7 +1107,6 @@ export default function EVSection({
@media (max-width: 991px) {
.evnd { padding: 48px 32px 56px; }
.evnd__grid { grid-template-columns: 1fr; gap: 40px; }
.evnd__title { margin-bottom: 28px; }
.evnd__features { gap: 14px; }
/* Stacked: KPI row can spread to 4-up since it now has full width. */
.evnd__dash-kpis { grid-template-columns: repeat(4, 1fr); }
@@ -1331,7 +1385,7 @@ export default function EVSection({
<div
className={`evnd__inner${useDashboard ? " evnd__inner--cards" : ""}${
useDashboard && !mediaSlot ? " evnd__inner--img" : ""
useDashboard && !mediaSlot && !isVideo ? " evnd__inner--img" : ""
}`}
>
<div className="evnd__heading">
@@ -1345,7 +1399,7 @@ export default function EVSection({
{/* MAIN GRID */}
<div
className={`evnd__grid${useDashboard ? " evnd__grid--cards" : ""}${
useDashboard && !mediaSlot ? " evnd__grid--img" : ""
useDashboard && !mediaSlot && !isVideo ? " evnd__grid--img" : ""
}`}
>
{/* Left column */}
@@ -1353,11 +1407,11 @@ export default function EVSection({
<div className="evnd__media">
<div className="evnd__glow" />
<div
className={`evnd__imgwrap${mediaSlot ? " evnd__imgwrap--media" : ""}${image.endsWith(".mp4") ? " evnd__imgwrap--video" : ""}`}
className={`evnd__imgwrap${mediaSlot ? " evnd__imgwrap--media" : ""}${isVideo ? " evnd__imgwrap--video" : ""}${mediaClassName ? ` ${mediaClassName}` : ""}`}
>
{mediaSlot ? (
mediaSlot
) : image.endsWith(".mp4") ? (
) : isVideo ? (
<video
className="evnd__video"
autoPlay
@@ -1401,6 +1455,7 @@ export default function EVSection({
features={features}
heading={cardsHeading}
theme={cardsTheme}
sysLabel={sysLabel}
/>
) : (
<div className="evnd__features">
@@ -1434,15 +1489,19 @@ export default function EVSection({
all breakpoints. In dashboard mode it summarises the same workflow
metrics; the homepage section uses its own stat set. */}
<div className="evnd__bar">
{(useDashboard ? metrics! : stats).map((s) => (
{(useDashboard ? (barStats ?? metrics!) : stats).map((s) => (
<div className="evnd__bar-item" key={s.label}>
<span className="evnd__bar-label">{s.label}</span>
<CountUp
value={s.value}
decimals={s.decimals}
suffix={s.suffix}
className="evnd__bar-val"
/>
{s.text ? (
<b className="evnd__bar-val evnd__bar-val--text">{s.text}</b>
) : (
<CountUp
value={s.value}
decimals={s.decimals}
suffix={s.suffix}
className="evnd__bar-val"
/>
)}
</div>
))}
</div>

View File

@@ -196,6 +196,26 @@ export default function EmpowermentHowItWorks() {
}
}
/* ---- Mobile title-to-description gap fix ----
.ehw-step-title is an <h3>, so it's matched by a global,
unscoped site.css rule (.logico-front-end h3:not(...) { margin:
0 0 30px }) that outranks this component's own single-class
".ehw-step-title { margin: 0 0 22px }" by specificity — bumping
the real margin-bottom to 30px everywhere, not just here. There
is no min-height, space-between, or fixed row height anywhere in
this component; the gap is purely that extra 8px of margin
reading as oversized once every other element around it (kicker,
description line-height) is tightly spaced. Overridden with
!important, matching how every other property on this selector
already has to defeat the same global rule. Scoped to mobile
only, per spec — desktop/tablet are left exactly as they were
(still resolving to the global 30px; out of scope here). */
@media (max-width: 767px) {
.ehw-step-title {
margin-bottom: 16px !important;
}
}
@media (max-width: 480px) {
.ehw-section { padding-top: 48px; padding-bottom: 68px; }
}

View File

@@ -100,6 +100,32 @@ export default function EmpowermentStory() {
margin: 0;
}
/* ---- Desktop-only inner spacing compaction ----
.esy-section never set its own padding, so it was silently
inheriting 96px top/bottom from the global bare-tag "section"
padding rule (6rem 0) in site.css — stacking with .esy-inner's
own clamp(60-98px) padding into a huge, unbalanced inset. Cancel
that leak here. Also tighten .esy-inner's own padding and widen its
max-width (so a fixed padding, not a narrow centered column,
controls the left/right inset at every desktop width) — and bring
min-height down to match the now-tighter natural content height,
since the old 690px floor was itself forcing extra empty space
once the padding was reduced. Scoped to desktop only; tablet/
mobile keep their original spacing untouched below. */
@media (min-width: 1025px) {
.esy-section {
padding: 0;
min-height: clamp(420px, 38vw, 500px);
}
.esy-inner {
max-width: 1900px;
padding-top: 64px;
padding-bottom: 56px;
padding-left: 64px;
padding-right: 64px;
}
}
@media (max-width: 1024px) {
.esy-section { width: calc(100% - 24px); border-radius: 22px; }
.esy-inner { grid-template-columns: 1fr; align-items: start; }

View File

@@ -200,6 +200,26 @@
margin: 0;
}
/* ---- Step 04 / Step 05 title-alignment fix ----
.stepBottom sits in .step's 1fr grid row with align-self:end, so its
title starts wherever the leftover space above it runs out — driven by
its OWN content height, not a shared position. Steps 01-03's
descriptions wrap to 3 lines, giving .stepBottom a natural height of
~101px; "Destination Hub" (04) and "EV Last-Mile" (05) wrap to only 2
lines (~79px) at several desktop widths, so under that same
end-alignment they're left with ~22px more leftover space above them
and their titles land visibly lower. Reserving that same ~101px on
.stepBottom for these two steps only — a floor, not a cap, so it's
inert wherever their content is already taller — reproduces Steps
01-03's exact title position without touching their CSS, the shared
grid, or align-self. */
@media (min-width: 1200px) {
.step:nth-child(4) .stepBottom,
.step:nth-child(5) .stepBottom {
min-height: 102px;
}
}
@media (max-width: 1024px) {
.headerRow {
flex-direction: column;

View File

@@ -0,0 +1,123 @@
"use client";
import React from "react";
import EVSection, { EVStat, EVBadge, EVFeature, EVCardsTheme } from "./EVSection";
/* Violet / Electric Purple — distinct from WF1 (cyan/teal) and WF2 (red/crimson). */
const THEME: EVCardsTheme = {
accent: "#7C5CFF",
accent2: "#4C3AE3",
glow: "rgba(124,92,255,0.20)",
};
/**
* Workflow 4 — Quantum Intelligence (hybrid split-screen).
*
* • Left — video: the hybrid optimization / energy-landscape visual.
* • Right — a COMPACT DASHBOARD: a quick KPI row (QUBO / Global / Hybrid /
* Multi) over feature cards describing the encode → energy
* landscape → global minimum → hybrid intelligence pipeline,
* sitting on the animated network backdrop (violet).
*
* Messaging is deliberately framed as work-in-progress ("building",
* "exploring") rather than a shipped quantum-computing claim.
*/
const METRICS: EVStat[] = [
{ text: "QUBO", value: 0, suffix: "", label: "Problem Model" },
{ text: "GLOBAL", value: 0, suffix: "", label: "Minimum Search" },
{ text: "HYBRID", value: 0, suffix: "", label: "Intelligence" },
{ text: "MULTI", value: 0, suffix: "", label: "Objective" },
];
/* Distinct copy for the bottom capability bar (not a repeat of the KPI row —
* Workflow 4's brief specifies separate content for each). */
const BAR_STATS: EVStat[] = [
{ text: "Multi-Rider", value: 0, suffix: "", label: "Dynamic Routing" },
{ text: "Optimized", value: 0, suffix: "", label: "Time Windows" },
{ text: "Real-Time", value: 0, suffix: "", label: "Fleet Balancing" },
{ text: "Cost + Distance + SLA", value: 0, suffix: "", label: "Objectives" },
];
const ico = (path: React.ReactNode) => (
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
{path}
</svg>
);
const FEATURES: EVFeature[] = [
{
icon: ico(
<>
<rect x="3" y="3" width="7" height="7" />
<rect x="14" y="3" width="7" height="7" />
<rect x="14" y="14" width="7" height="7" />
<rect x="3" y="14" width="7" height="7" />
</>,
),
title: "Encode the Problem",
desc: "Rider assignments, delivery sequences, capacity, traffic, service time, and SLA constraints become part of one mathematical optimization model.",
},
{
icon: ico(<path d="m8 3 4 8 5-5 5 15H2L8 3z" />),
title: "Build the Energy Landscape",
desc: "Each feasible routing solution is represented as a state with its own energy through a QUBO formulation.",
},
{
icon: ico(
<>
<circle cx="12" cy="12" r="9" />
<circle cx="12" cy="12" r="5" />
<circle cx="12" cy="12" r="1" />
</>,
),
title: "Search the Global Minimum",
desc: "Optimization becomes the search for the lowest-energy state instead of evaluating route combinations one by one.",
},
{
icon: ico(
<>
<polygon points="12 2 2 7 12 12 22 7 12 2" />
<polyline points="2 17 12 22 22 17" />
<polyline points="2 12 12 17 22 12" />
</>,
),
title: "Hybrid Intelligence",
desc: "Classical algorithms, AI models, and quantum optimization work together using the right computational model for each problem.",
},
];
const BADGES: EVBadge[] = [
{ value: "QUBO", label: "PROBLEM MODEL" },
{ value: "HYBRID", label: "INTELLIGENCE" },
];
export default function Workflow4() {
return (
<EVSection
ariaLabel="Workflow 4 — Quantum Intelligence"
gapBottom
image="/videos/Doormile-quantum-video3.mp4"
cardTitle="BUILDING QUANTUM INTELLIGENCE"
cardSubtitle="Exploring a hybrid optimization layer that treats routing as an energy landscape, not a search problem."
eyebrow="/ Quantum Intelligence /"
titleLead="FROM ROUTE SEARCH. "
titleAccent="TO ENERGY MINIMIZATION."
imageAlt="Hybrid quantum-classical optimization engine visualizing an energy landscape"
metrics={METRICS}
barStats={BAR_STATS}
features={FEATURES}
cardsHeading="Quantum Intelligence"
sysLabel="HYBRID ENGINE"
cardsTheme={THEME}
badges={BADGES}
mediaClassName="evnd__imgwrap--wf4"
/>
);
}