/* Motion · site primitives — shared atoms.
`window.MPOS_BASE` (set inline in each HTML before scripts load) controls
how relative asset URLs are resolved; for root pages it's "./" and for
nested pages like funkcje/*.html it's "../". */
const { useState, useEffect, useRef, useCallback } = React;
const baseUrl = (p) => (window.MPOS_BASE || "./") + p;
function Container({ className = "", children, ...rest }) {
return (
{children}
);
}
function Button({ variant = "primary", size = "md", as = "button", href, children, className = "", ...rest }) {
const cls = `mpos-btn mpos-btn-${variant} mpos-btn-${size} ${className}`;
if (as === "a" || href) {
return {children};
}
return ;
}
/* Brand mark — small standalone "M" SVG (extracted from the brand mark).
Drawn inline so it's path-independent and pixel-crisp. */
function LogoMark({ size = 28 }) {
return (
);
}
function Logo({ variant = "dark" }) {
return (
Motion
);
}
/* Stroke-icon component using Lucide-style SVG paths. */
const ICONS = {
check: ,
checkCircle: <>>,
arrowRight: ,
arrowLeft: ,
play: ,
bolt: ,
zap: ,
wifi: <>>,
wifiOff: <>>,
layers: <>>,
barChart: <>>,
pieChart: <>>,
receipt: <>>,
creditCard: <>>,
store: <>>,
coffee: <>>,
utensils: <>>,
shieldCheck: <>>,
users: <>>,
user: <>>,
trendingUp: <>>,
printer: <>>,
smartphone: <>>,
tablet: <>>,
chevronDown: ,
chevronRight: ,
chevronLeft: ,
plus: <>>,
minus: ,
x: <>>,
menu: <>>,
search: <>>,
quote: <>>,
jpk: <>>,
package: <>>,
tag: <>>,
tags: <>>,
percent: <>>,
gift: <>>,
truck: <>>,
refresh: <>>,
rotateCcw: <>>,
alertCircle: <>>,
helpCircle: <>>,
fileText: <>>,
clock: <>>,
cpu: <>>,
database: <>>,
history: <>>,
filter: ,
download: <>>,
star: ,
monitor: <>>,
building: <>>,
lock: <>>,
globe: <>>,
cash: <>>,
banknote: <>>,
link: <>>,
send: <>>,
};
function Icon({ name, size = 20, color = "currentColor", strokeWidth = 1.75, className = "", style }) {
const path = ICONS[name];
if (!path) return null;
return (
);
}
function Eyebrow({ children, className = "" }) {
return {children}
;
}
/* Reveal: opacity-fade entrance, gates on intersection. */
function Reveal({ children, delay = 0, className = "" }) {
const ref = useRef(null);
const [shown, setShown] = useState(true);
useEffect(() => {
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
const el = ref.current;
if (!el) return;
const r = el.getBoundingClientRect();
if (r.top >= window.innerHeight) {
setShown(false);
const io = new IntersectionObserver((entries) => {
entries.forEach((e) => { if (e.isIntersecting) { setShown(true); io.disconnect(); } });
}, { threshold: 0.05, rootMargin: "0px 0px -10% 0px" });
io.observe(el);
return () => io.disconnect();
}
}, []);
return (
{children}
);
}
Object.assign(window, { Container, Button, Logo, LogoMark, Icon, Eyebrow, Reveal, baseUrl });