Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion web/src/pages/LandingPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const stats = [
{ value: "47", suffix: "s", label: "Avg time to diagnose" },
{ value: "1,240", suffix: "+", label: "Faults resolved" },
{ value: "12", suffix: "x", label: "Faster than manual triage" },
{ value: "0", suffix: "", label: "Data leakage" },
];

function useInView(threshold = 0.15) {
Expand Down Expand Up @@ -99,6 +100,7 @@ export default function LandingPage() {
const [pipelineRef, pipelineVisible] = useInView(0.1);
const [featuresRef, featuresVisible] = useInView(0.1);
const [stepsRef, stepsVisible] = useInView(0.1);
const [problemsRef, problemsVisible] = useInView(0.1);

return (
<div className={styles.page}>
Expand Down Expand Up @@ -131,7 +133,28 @@ export default function LandingPage() {
<div className={styles.heroCorner} />
</section>

{/* ── Stats ── */}
<section className={styles.problemsSection} id="problems">
<div className={styles.problemsInner}>
<div className={styles.problemsLeft}>
<h2 className={styles.problemsHeadline}>The Hidden Cost of Legacy Downtime</h2>
</div>
<div className={styles.problemsRight} ref={problemsRef}>
<div className={`${styles.problemCard} ${styles.fadeUp} ${problemsVisible ? styles.fadeUpVisible : ""}`} style={{ transitionDelay: "0ms" }}>
<h3>Hours lost to manual searches</h3>
<p>Technicians waste hours digging though dusty, 500 page physical manuals or fragmented PDFs to translate a single PLC fault code.</p>
</div>
<div className={`${styles.problemCard} ${styles.fadeUp} ${problemsVisible ? styles.fadeUpVisible : ""}`} style={{ transitionDelay: "150ms" }}>
<h3>The tribal knowledge expiry</h3>
<p>Critical maintenance workarounds live only in the heads of senior engineers. When they retire or exit the plant floor, operational wisdom is permanently lost.</p>
</div>
<div className={`${styles.problemCard} ${styles.fadeUp} ${problemsVisible ? styles.fadeUpVisible : ""}`} style={{ transitionDelay: "300ms" }}>
<h3>Trilingual friction</h3>
<p>Mismatches between machine logs, manufacturer documentation, and technician field languages (English, French, Arabic) create costly communication bottlenecks.</p>
</div>
</div>
</div>
</section>

<section className={styles.statsSection} ref={statsRef}>
<div className={styles.statsInner}>
{stats.map((s, i) => (
Expand Down
97 changes: 87 additions & 10 deletions web/src/pages/LandingPage.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@

.hero {
position: relative;
padding: 140px 24px 120px;
padding: 80px 24px 160px;
text-align: center;
overflow: hidden;
isolation: isolate;
Expand Down Expand Up @@ -203,11 +203,9 @@
background: var(--surface);
}

/* ── Stats bar ── */

.statsSection {
padding: 0 24px;
margin-top: -20px;
position: relative;
z-index: 2;
}
Expand All @@ -216,7 +214,7 @@
max-width: 1000px;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-columns: repeat(5, 1fr);
gap: 0;
background: var(--surface);
border: 1px solid var(--border-color);
Expand Down Expand Up @@ -257,6 +255,7 @@
.statVisible:nth-child(2) { transition-delay: 100ms; }
.statVisible:nth-child(3) { transition-delay: 200ms; }
.statVisible:nth-child(4) { transition-delay: 300ms; }
.statVisible:nth-child(5) { transition-delay: 400ms; }

.statValue {
font-family: "ALTGumbo", system-ui, sans-serif;
Expand Down Expand Up @@ -284,13 +283,11 @@
transition: color 0.35s;
}

/* ── Pipeline section ── */

.pipelineSection {
padding: 96px 0;
}

/* ── Features section ── */

.featuresSection {
padding: 96px 0;
Expand All @@ -304,7 +301,6 @@
gap: 24px;
}

/* ── How it works section ── */

.howSection {
padding: 96px 0;
Expand All @@ -329,7 +325,6 @@
flex-direction: column;
gap: 0;
position: relative;
padding-left: 20px;
}

.steps::before {
Expand Down Expand Up @@ -392,7 +387,6 @@
transition: color 0.35s;
}

/* ── CTA section ── */

.ctaSection {
padding: 120px 24px;
Expand Down Expand Up @@ -438,7 +432,6 @@
transition: color 0.35s;
}

/* ── Fade-up animation ── */

.fadeUp {
opacity: 0;
Expand All @@ -450,3 +443,87 @@
opacity: 1;
transform: translateY(0);
}


.problemsSection {
padding: 120px 24px;
position: relative;
}

.problemsInner {
max-width: 1200px;
margin: 0 auto;
display: flex;
gap: 80px;
align-items: flex-start;
}

.problemsLeft {
flex: 1;
position: sticky;
top: 140px;
max-width: 480px;
}

.problemsHeadline {
font-family: "ALTGumbo", system-ui, sans-serif;
font-size: 48px;
font-weight: 700;
line-height: 1.1;
color: var(--text-primary);
margin: 0;
letter-spacing: -0.015em;
transition: color 0.35s;
}

.problemsRight {
flex: 1;
display: flex;
flex-direction: column;
gap: 32px;
}

.problemCard {
background: var(--surface);
border: 1px solid var(--border-color);
padding: 40px;
border-radius: 16px;
box-shadow: var(--shadow-sm);
transition: transform 0.3s ease, box-shadow 0.3s ease, background 0.35s, border-color 0.35s;
}

.problemCard:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-md);
}

.problemCard h3 {
font-family: "ALTGumbo", system-ui, sans-serif;
font-size: 24px;
font-weight: 700;
color: var(--text-primary);
margin: 0 0 16px;
transition: color 0.35s;
}

.problemCard p {
color: var(--text-muted);
font-family: "ALTGumbo", system-ui, sans-serif;
font-size: 16px;
line-height: 1.6;
margin: 0;
transition: color 0.35s;
}

@media (max-width: 900px) {
.problemsInner {
flex-direction: column;
gap: 48px;
}
.problemsLeft {
position: relative;
top: 0;
max-width: 100%;
}
}

Loading