/* global React, useApp, useReveal */ const { useState, useEffect, useRef } = React; /* ========================================================== SECTION: Two wavelengths — SVG cross-section + spectrum + waveform ========================================================== */ function WavelengthsSection() { const { t } = useApp(); const copy = t.wavelengths; const [wl, setWl] = useState(850); // 630 or 850 const ref = useReveal(); const is630 = wl === 630; // Realistic penetration depth as fraction of visible 20mm range: // 630nm → ~1mm (stops in upper dermis) = 0.20 // 850nm → ~8-10mm (deep into muscle) = 0.78 const depth = is630 ? 0.22 : 0.80; return (
{/* ambient orbs */}
); } /* ------------- SVG skin cross-section ------------- */ function SkinCrossSection({ wl, depth, layerLabels }) { const is630 = wl === 630; // Panel band: y 0–70. Skin zones 70–780, label zone 780–800. const panelH = 70; const skinStart = panelH; const skinEnd = 780; const skinH = skinEnd - skinStart; // 710 // Layers scaled by anatomical proportion (not 1:1 — compressed for readability): // Naskórek 4%, Skóra wł. 22%, Podskórna 28%, Mięśnie 32%, Stawy 14% const proportions = [0.04, 0.22, 0.28, 0.32, 0.14]; const layers = []; let acc = skinStart; const palettes = [ ["#f0d4c0", "#d8a898"], // naskórek ["#c89685", "#8a5e50"], // skóra właściwa ["#e0c090", "#b88860"], // podskórna (fat) ["#8a3a28", "#521c12"], // mięśnie ["#d8c2a2", "#8c7258"], // stawy (bone/cartilage) ]; const mmLabels = ["0.1 mm", "1.5 mm", "5 mm", "15 mm", "30 mm+"]; for (let i=0; i<5; i++) { const h = proportions[i] * skinH; layers.push({ name: layerLabels[i], y1: acc, y2: acc + h, c1: palettes[i][0], c2: palettes[i][1], mm: mmLabels[i], }); acc += h; } const beamEndY = skinStart + depth * skinH; const beamColor = is630 ? "#ff3850" : "#c41528"; const beamCore = is630 ? "#ff6b78" : "#ee2838"; const haloColor = is630 ? "#ff4a57" : "#c41020"; // depth ruler — labeled in mm, mapped to the viewBox const rulerMarks = [ { mm: "0", y: skinStart }, { mm: "1", y: skinStart + 0.04 * skinH }, { mm: "3", y: skinStart + 0.18 * skinH }, { mm: "8", y: skinStart + 0.40 * skinH }, { mm: "20", y: skinStart + 0.75 * skinH }, { mm: "50+", y: skinEnd }, ]; const nbBeams = 7; const beamXs = [...Array(nbBeams)].map((_, i) => 96 + i * 68); // cell particles: 630 in upper zones, 850 in muscle depth const particles = is630 ? [...Array(20)].map((_, i) => ({ x: 70 + (i * 29) % 480, y: skinStart + 0.06 * skinH + (i * 11) % (0.18 * skinH), r: 1.5 + (i % 3) * 0.6, d: (i % 6) * 0.12, color: "#ffc694", })) : [...Array(26)].map((_, i) => ({ x: 60 + (i * 23) % 500, y: skinStart + 0.52 * skinH + (i * 13) % (0.22 * skinH), r: 2 + (i % 3) * 0.8, d: (i % 5) * 0.14, color: "#ffa070", })); return ( {layers.map((l, i) => ( ))} {/* Background depth gradient — very dark skin tone beyond layers */} {/* LED panel at top */} {/* diode row */} {[...Array(9)].map((_, i) => { const x = 80 + i * 55; return ( ); })} {/* panel highlight */} {/* Skin layers */} {layers.map((l, i) => ( {/* subtle texture bands */} {i === 1 && [...Array(8)].map((_, k) => ( ))} {i === 3 && [...Array(6)].map((_, k) => ( ))} {/* boundary */} ))} {/* Photon beams — glow layer */} {beamXs.map((x, i) => ( ))} {/* Photon beams — core */} {beamXs.map((x, i) => ( ))} {/* Cell activity particles */} {particles.map((p, i) => ( ))} {/* Active depth line */} {/* Layer labels on right */} {layers.map((l, i) => ( {l.name} {l.mm} ))} {/* Depth ruler */} {rulerMarks.map((m, i) => ( {m.mm} ))} mm ); } /* ------------- Spectrum bar with animated marker ------------- */ function SpectrumBar({ wl }) { const pos = ((wl - 600) / 300) * 100; // percent const marks = [ { nm: 600, l: "600" }, { nm: 630, l: "630", active: wl === 630 }, { nm: 700, l: "700" }, { nm: 800, l: "800" }, { nm: 850, l: "850", active: wl === 850 }, { nm: 900, l: "900" }, ]; return (
Spektrum · nm {wl === 630 ? "Red visible" : "Near-infrared"}
{/* Color spectrum bar */}
{/* Tick marks */} {marks.map((m, i) => { const x = ((m.nm - 600) / 300) * 100; return (
{m.l}
); })} {/* Animated marker */}
); } /* ------------- Oscilloscope waveform ------------- */ function WaveformDisplay({ wl }) { // Shorter λ = more cycles in fixed window. // 630nm: 9 cycles; 850nm: 5 cycles (frequency proportional to 1/λ) const cycles = wl === 630 ? 9 : 5; const amp = 14; const w = 320; const h = 64; const points = []; for (let i = 0; i <= 160; i++) { const x = (i / 160) * w; const y = h/2 + Math.sin((i/160) * cycles * Math.PI * 2) * amp; points.push(`${x},${y.toFixed(2)}`); } const path = "M" + points.join(" L"); const color = wl === 630 ? "#ff3848" : "#c41528"; const freqTHz = wl === 630 ? "476" : "353"; return (
{/* scan line */} ); } /* ========================================================== SECTION: How it works — 10 min session, 3 steps + live timer ========================================================== */ function HowItWorksSection() { const { t } = useApp(); const copy = t.howItWorks; const ref = useReveal(); const [secs, setSecs] = useState(600); const [running, setRunning] = useState(false); useEffect(() => { if (!running) return; if (secs <= 0) { setRunning(false); return; } const id = setTimeout(() => setSecs((s) => s - 1), 1000); return () => clearTimeout(id); }, [running, secs]); const mm = String(Math.floor(secs/60)).padStart(2,"0"); const ss = String(secs%60).padStart(2,"0"); const pct = 1 - secs/600; return (
{copy.eyebrow}

{copy.title}

{copy.subtitle}

{/* Timer */}
{/* Progress ring */}
{copy.timerLabel}
{mm}:{ss}
{copy.steps.map((s, i) => (
{s.n}

{s.t}

{s.d}

))}
); } /* ========================================================== SECTION: Products — 3 cards, hover glow ========================================================== */ function ProductsSection() { const { t } = useApp(); const copy = t.products; const ref = useReveal(); return (
{copy.eyebrow}

{copy.title}

{copy.subtitle}

{copy.items.map((p) => ) }
); } function ProductCard({ p, cta }) { const [hover, setHover] = useState(false); const stripeUrl = (window.LUMAFLEX_CONFIG?.stripe?.[p.slug]) || ""; const href = stripeUrl || "#compare"; const target = stripeUrl ? "_blank" : undefined; const rel = stripeUrl ? "noopener" : undefined; return (
setHover(true)} onMouseLeave={() => setHover(false)} style={{ background:"#f5f5f7", borderRadius: 22, padding: 32, position:"relative", overflow:"hidden", transition:"all 400ms cubic-bezier(0.28,0,0.22,1)", transform: hover ? "translateY(-4px)" : "translateY(0)", }}>
{p.tag}

{p.name}

{p.price}
{p.priceSub}
{p.name}

{p.desc}

{p.specs}
{cta}
); } Object.assign(window, { WavelengthsSection, HowItWorksSection, ProductsSection });