diff --git a/web/src/components/PipelineDiagram.jsx b/web/src/components/PipelineDiagram.jsx index eb7ecad..93283d7 100644 --- a/web/src/components/PipelineDiagram.jsx +++ b/web/src/components/PipelineDiagram.jsx @@ -1,48 +1,53 @@ import styles from "./PipelineDiagram.module.css"; const steps = [ - { label: "Machine", desc: "Fault code emitted" }, - { label: "TORQ Agent", desc: "AI diagnoses" }, - { label: "Work Order", desc: "Trilingual PDF" }, - { label: "Supervisor", desc: "Approval queue" }, - { label: "Technician", desc: "Dispatched" }, + { label: "1. Machine", desc: "Fault code emitted" }, + { label: "2. TORQ Agent", desc: "AI diagnoses" }, + { label: "3. Work Order", desc: "Trilingual PDF" }, + { label: "4. Supervisor", desc: "Approval queue" }, + { label: "5. Technician", desc: "Dispatched" }, ]; -function ArrowRight() { - return ( -
- - - -
- ); -} - export default function PipelineDiagram() { return (
-
- {steps.map((s, i) => ( -
-
+ {/* Desktop / Tablet View */} +
+
+ + {/* The base faint line */} + + {/* The animated data pulse line */} + + +
+
+ {steps.map((s, i) => ( +
{s.label} {s.desc}
- {i < steps.length - 1 && } + ))} +
+
+ + {/* Mobile Fallback View */} +
+
+
+ {steps.map((s, i) => ( +
+ {s.label} + {s.desc}
))}
-
- - - - feedback loop — model improves with every fix - - -
); } diff --git a/web/src/components/PipelineDiagram.module.css b/web/src/components/PipelineDiagram.module.css index 38685aa..b2865bc 100644 --- a/web/src/components/PipelineDiagram.module.css +++ b/web/src/components/PipelineDiagram.module.css @@ -1,99 +1,157 @@ .wrapper { - padding: 48px 0 8px; + padding: 48px 0; + width: 100%; + max-width: 1000px; + margin: 0 auto; } -.pipeline { - display: flex; - align-items: center; - justify-content: center; - gap: 0; - flex-wrap: wrap; +.diagramDesktop { + position: relative; + width: 100%; + aspect-ratio: 10 / 6; /* 1000x600 */ } -.step { - display: flex; - align-items: center; +/* ── SVG Lines ── */ +.svgContainer { + position: absolute; + inset: 0; + pointer-events: none; + z-index: 1; +} + +.linesSvg { + width: 100%; + height: 100%; + overflow: visible; +} + +.basePath { + stroke: var(--border-color); + stroke-width: 2; + fill: none; +} + +.animatedPath { + stroke: var(--text-primary); + stroke-width: 3; + fill: none; + stroke-linecap: round; + stroke-dasharray: 20 60; + animation: flowAnimation 3s linear infinite; +} + +@keyframes flowAnimation { + 0% { + stroke-dashoffset: 80; + } + 100% { + stroke-dashoffset: 0; + } } -.box { +/* ── Nodes ── */ +.nodesContainer { + position: absolute; + inset: 0; + z-index: 2; + pointer-events: none; +} + +.node { + position: absolute; + transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; - background: var(--surface); + justify-content: center; + background: var(--bg-primary); border: 1px solid var(--border-color); - border-radius: 12px; - padding: 20px 24px; - min-width: 130px; - transition: border-color 0.3s, box-shadow 0.3s, background 0.35s; + border-radius: 50%; + padding: 16px; + width: 160px; + height: 160px; + box-shadow: var(--shadow-sm); + pointer-events: auto; + transition: transform 0.3s, box-shadow 0.3s, border-color 0.35s; + text-align: center; } -.box:hover { - border-color: var(--text-primary); +.node:hover { + transform: translate(-50%, -54%); box-shadow: var(--shadow-md); + border-color: var(--text-primary); } .label { font-family: "ALTGumbo", system-ui, sans-serif; font-weight: 700; - font-size: 15px; + font-size: 16px; color: var(--text-primary); - transition: color 0.35s; } .desc { font-family: "ALTGumbo", system-ui, sans-serif; font-weight: 400; - font-size: 11px; + font-size: 12px; color: var(--text-muted); margin-top: 6px; white-space: nowrap; - transition: color 0.35s; } -.arrow { - display: flex; - align-items: center; - padding: 0 4px; - user-select: none; -} - -.arrowSvg { - display: block; - color: var(--border-color); - transition: color 0.35s; -} +/* Positions matching viewBox="0 0 1000 600" + Path: M 100 250 L 500 50 L 900 250 L 750 500 L 250 500 Z +*/ +.node1 { left: 10%; top: 41.66%; } /* 100, 250 */ +.node2 { left: 50%; top: 8.33%; } /* 500, 50 */ +.node3 { left: 90%; top: 41.66%; } /* 900, 250 */ +.node4 { left: 75%; top: 83.33%; } /* 750, 500 */ +.node5 { left: 25%; top: 83.33%; } /* 250, 500 */ -.arrowSvg path { - stroke: currentColor; +/* ── Mobile Fallback ── */ +.diagramMobile { + display: none; + flex-direction: column; + align-items: center; + gap: 32px; + position: relative; } -.feedback { - display: flex; - justify-content: center; - margin-top: 20px; +.mobileLine { + position: absolute; + top: 0; + bottom: 0; + left: 50%; + transform: translateX(-50%); + width: 2px; + background: var(--border-color); + z-index: 1; } -.feedbackSvg { - width: 100%; - max-width: 640px; - height: 72px; +.mobileAnimatedLine { + position: absolute; + top: 0; + bottom: 0; + left: 50%; + transform: translateX(-50%); + width: 2px; + background: repeating-linear-gradient(to bottom, var(--text-primary) 0, var(--text-primary) 20px, transparent 20px, transparent 80px); + z-index: 2; + background-size: 100% 80px; + animation: scrollDown 2s linear infinite; } -.feedbackPath { - stroke: var(--border-color); - stroke-width: 2; - stroke-dasharray: 6 4; - fill: none; - transition: stroke 0.35s; +@keyframes scrollDown { + 0% { background-position: 0 -80px; } + 100% { background-position: 0 0; } } -.wrapper:hover .feedbackPath { - stroke: var(--text-muted); +.nodeMobile { + position: relative; + z-index: 3; + transform: none !important; } -.feedbackText { - font-family: "ALTGumbo", system-ui, sans-serif; - font-size: 11px; - fill: var(--text-muted); - transition: fill 0.35s; +@media (max-width: 768px) { + .diagramDesktop { display: none; } + .diagramMobile { display: flex; } } diff --git a/web/src/pages/LandingPage.jsx b/web/src/pages/LandingPage.jsx index 959a33b..5f6822a 100644 --- a/web/src/pages/LandingPage.jsx +++ b/web/src/pages/LandingPage.jsx @@ -25,7 +25,7 @@ const features = [ }, { icon: , - title: "Self-Learning", + title: "Self Learning", description: "Every fix enriches the knowledge base. The model gets smarter with each resolved fault.", }, ]; @@ -111,13 +111,13 @@ export default function LandingPage() {
- Fault-to-Fix Engine + Fault to Fix Engine

From fault code
to fixed.

- TORQ autonomously diagnoses machine faults, generates trilingual work orders, and dispatches the right technician — all in real time. + TORQ autonomously diagnoses machine faults, generates trilingual work orders, and dispatches the right technician all in real time.

@@ -166,8 +166,8 @@ export default function LandingPage() { {/* ── Pipeline ── */}
- - Pipeline + + How TORQ drives the repair