/* Landing page component — Rubin */ /* global React, window */ const { useState, useEffect } = React; // Scroll-reveal: attach `.in` to any `.reveal` element as it enters the viewport. function useScrollReveal() { useEffect(() => { const els = document.querySelectorAll('.reveal'); if (!els.length) return; if (!('IntersectionObserver' in window)) { els.forEach(el => el.classList.add('in')); return; } const io = new IntersectionObserver(entries => { entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } }); }, { rootMargin: '0px 0px -12% 0px', threshold: 0.12 }); els.forEach(el => io.observe(el)); return () => io.disconnect(); }, []); } function Landing() { const tweaks = window.useTweaks ? window.useTweaks(window.TWEAK_DEFAULTS) : [window.TWEAK_DEFAULTS, () => {}]; const [t, setT] = tweaks; const lang = (t && t.lang) || 'en'; const c = window.LANDING_COPY[lang]; const setLang = l => setT('lang', l); useScrollReveal(); return (
); } // ─── Nav ──────────────────────────────────────────────────────────── function Nav({ c, lang, setLang }) { return (
Rubin
{c.nav.login} {c.nav.demo}
); } // ─── Hero ─────────────────────────────────────────────────────────── function Hero({ c }) { const [a, b, em, rest] = c.hero.title; // Compute live stats from window.TRAINS if available const trains = (window.TRAINS || []).filter(x => x.status === 'enroute'); const totalRev = trains.reduce((s, x) => s + x.revenue, 0); const totalCap = trains.reduce((s, x) => s + x.capacity, 0); const totalSold = trains.reduce((s, x) => s + x.soldSeats, 0); const loadPct = totalCap ? Math.round((totalSold / totalCap) * 100) : 0; const revFmt = totalRev >= 1_000_000 ? (totalRev / 1_000_000).toFixed(2) + ' mln zł' : Math.round(totalRev / 1000) + ' tys. zł'; return (
{c.hero.eyebrow}

{a}
{b}{em}{rest}

{c.hero.sub}

{c.hero.primary} → {c.hero.secondary} · {c.hero.note}
RUBIN · LIVE FEED PL · CZ · DE
Revenue · today
{revFmt}+4.8%
Load factor
{loadPct}%+3.1pp
Trains · live
{trains.length}
); } // ─── Ticker ───────────────────────────────────────────────────────── function Ticker({ c }) { const items = [...c.ticker, ...c.ticker]; // duplicate for seamless loop return (
{items.map((it, i) => (
{it.k} · {it.v} {it.n} {it.d}
))}
); } // ─── Problem ──────────────────────────────────────────────────────── function Problem({ c }) { const [a, em, rest] = c.problem.title; return (
{c.problem.label.split(' / ')[0]} / {c.problem.label.split(' / ')[1]}

{a}{em}{rest}

{c.problem.sub}

{c.problem.cards.map((card, i) => (
{card.big[0]}{card.big[1]}
{card.t}
{card.d}
{card.src}
))}
); } // ─── Capabilities ─────────────────────────────────────────────────── function Capabilities({ c }) { const [a, em, rest] = c.caps.title; const vizMap = { curve: , pricing: , compete: , matrix: , }; return (
{c.caps.label.split(' / ')[0]} / {c.caps.label.split(' / ')[1]}

{a}{em}{rest}

{c.caps.sub}

{c.caps.items.map((it, i) => (
{it.num} {it.tag}
{it.title}
{it.desc}
    {it.bullets.map((b, j) =>
  • {b}
  • )}
{vizMap[it.viz]}
))}
); } // ─── How ──────────────────────────────────────────────────────────── function HowItWorks({ c }) { const [a, em, rest] = c.how.title; return (
{c.how.label.split(' / ')[0]} / {c.how.label.split(' / ')[1]}

{a}{em}{rest}

{c.how.cols.map((col, i) => (
{col.step}

{col.t}

{col.p}

{col.sources.map((s, j) => {s})}
))}
); } // ─── Demo band ────────────────────────────────────────────────────── function DemoBand({ c }) { const [a, em, rest] = c.demo.title; return (
{c.demo.label}

{a}{em}{rest}

{c.demo.sub}

{c.demo.sub2}

{c.demo.cta} →
rubin.rail · control room
); } // ─── Audiences ────────────────────────────────────────────────────── function Audiences({ c }) { const [a, em, rest] = c.audiences.title; return (
{c.audiences.label}

{a}{em}{rest}

{c.audiences.ops.icon}

{c.audiences.ops.h}

{c.audiences.ops.pitch}

    {c.audiences.ops.bullets.map((b, i) =>
  • {b}
  • )}
{c.audiences.inv.icon}

{c.audiences.inv.h}

{c.audiences.inv.pitch}

    {c.audiences.inv.bullets.map((b, i) =>
  • {b}
  • )}
); } // ─── Metrics ──────────────────────────────────────────────────────── function Metrics({ c }) { const [a, em, rest] = c.metrics.title; return (
{c.metrics.label}

{a}{em}{rest}

{c.metrics.sub}

{c.metrics.items.map((m, i) => (
{m.v[0]}{m.v[1]}
{m.l}
{m.d}
))}
); } // ─── CTA ──────────────────────────────────────────────────────────── function CTA({ c }) { return (

{c.cta.h[0]}

{c.cta.p}

); } // ─── Footer ───────────────────────────────────────────────────────── function Footer({ c }) { return ( ); } window.Landing = Landing;