/* global React */
const { useState, useEffect, useRef } = React;
const ICONS = {
arrowRight: "M5 12h14M13 5l7 7-7 7",
arrowUpRight: "M7 17 17 7M7 7h10v10",
check: "M20 6 9 17l-5-5",
plus: "M12 5v14M5 12h14",
minus: "M5 12h14",
close: "M18 6 6 18M6 6l12 12",
chevronDown: "m6 9 6 6 6-6",
chevronRight: "M9 18l6-6-6-6",
chevronLeft: "M15 18l-6-6 6-6",
chevronUp: "m6 15 6-6 6 6",
calendar: "M3 6a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zM16 2v4M8 2v4M3 10h18",
clock: "M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zM12 6v6l4 2",
users: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2M9 3a4 4 0 1 0 0 8 4 4 0 0 0 0-8zM22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75",
user: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2M12 3a4 4 0 1 0 0 8 4 4 0 0 0 0-8z",
grad: "M22 10v6M2 10l10-5 10 5-10 5zM6 12v5c3 3 9 3 12 0v-5",
mapPin: "M20 10c0 7-8 12-8 12s-8-5-8-12a8 8 0 1 1 16 0zM12 7a3 3 0 1 0 0 6 3 3 0 0 0 0-6z",
phone: "M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6A19.8 19.8 0 0 1 2 4.2 2 2 0 0 1 4 2h3a2 2 0 0 1 2 1.7c0 1.2.3 2.3.6 3.3a2 2 0 0 1-.4 2L8 10.2a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2-.4c1 .3 2.1.5 3.3.6a2 2 0 0 1 1.7 2z",
mail: "M2 6a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2zM22 7l-10 6L2 7",
search: "M11 3a8 8 0 1 0 0 16 8 8 0 0 0 0-16zM21 21l-4.3-4.3",
star: "M12 2l3 7h7l-6 4 2 7-6-4-6 4 2-7-6-4h7z",
starFill: "M12 2l3 7h7l-6 4 2 7-6-4-6 4 2-7-6-4h7z",
play: "M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20z",
playTri: "m10 8 6 4-6 4z",
playSolid: "M8 5v14l11-7z",
hand: "M18 11V6a2 2 0 1 0-4 0v5M14 10V4a2 2 0 1 0-4 0v10M10 10.5V6a2 2 0 1 0-4 0v8M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.9-6-2.8L2 17",
target: "M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zM12 7a5 5 0 1 0 0 10 5 5 0 0 0 0-10zM12 10a2 2 0 1 0 0 4 2 2 0 0 0 0-4z",
shield: "M12 2 4 5v7c0 5 3.5 9 8 10 4.5-1 8-5 8-10V5z",
sparkle: "M12 2v6M12 16v6M2 12h6M16 12h6M5 5l4 4M15 15l4 4M19 5l-4 4M9 15l-5 4",
edit: "M11 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7M18.5 2.5a2.1 2.1 0 1 1 3 3L12 15l-4 1 1-4z",
trash: "M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6",
menu: "M3 6h18M3 12h18M3 18h18",
award: "M12 15a7 7 0 1 0 0-14 7 7 0 0 0 0 14zM8.21 13.89 7 23l5-3 5 3-1.21-9.12",
book: "M4 19.5A2.5 2.5 0 0 1 6.5 17H20V2H6.5A2.5 2.5 0 0 0 4 4.5zM20 22H6.5a2.5 2.5 0 0 1 0-5H20",
video: "M23 7l-7 5 7 5zM1 5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2z",
image: "M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zM8.5 10a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM21 15l-5-5L5 21",
quote: "M3 21c3 0 7-1 7-8V5c0-1.25-.75-2-2-2H4c-1.25 0-2 .75-2 2v6c0 1.25.75 2 2 2h3c0 3-1 5-4 5M14 21c3 0 7-1 7-8V5c0-1.25-.75-2-2-2h-4c-1.25 0-2 .75-2 2v6c0 1.25.75 2 2 2h3c0 3-1 5-4 5",
whatsapp: "M12 2a10 10 0 0 0-8.5 15.2L2 22l4.9-1.4A10 10 0 1 0 12 2zM8.5 7.5c.3 0 .5.1.7.3l1 2c.1.3 0 .5-.2.8l-.6.7c-.2.2-.3.5-.1.8 1 1.7 2.4 3.1 4.1 4 .3.2.6.1.8-.1l.7-.6c.3-.2.5-.3.8-.2l2 1c.2.1.3.3.3.6v2c0 .3-.3.6-.6.6-5 0-9-4-9-9 0-.3.3-.6.6-.6z",
instagram: "M17.5 6.5v.01M7 2h10a5 5 0 0 1 5 5v10a5 5 0 0 1-5 5H7a5 5 0 0 1-5-5V7a5 5 0 0 1 5-5zM12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8z",
youtube: "M22.5 6.5a3 3 0 0 0-2-2C18.5 4 12 4 12 4s-6.5 0-8.5.5a3 3 0 0 0-2 2C1 8.5 1 12 1 12s0 3.5.5 5.5a3 3 0 0 0 2 2c2 .5 8.5.5 8.5.5s6.5 0 8.5-.5a3 3 0 0 0 2-2c.5-2 .5-5.5.5-5.5s0-3.5-.5-5.5zM10 15V9l5.2 3z",
facebook: "M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z",
zap: "M13 2l-9 12h7l-1 8 9-12h-7z",
clipboard: "M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2M9 2h6a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H9a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1z",
heart: "M20.8 4.6a5.5 5.5 0 0 0-7.8 0L12 5.7l-1-1a5.5 5.5 0 0 0-7.8 7.8l1 1 7.8 7.8 7.8-7.8 1-1a5.5 5.5 0 0 0 0-7.8z",
layers: "m12 2-10 6 10 6 10-6zM2 17l10 6 10-6M2 12l10 6 10-6",
activity: "M22 12h-4l-3 9L9 3l-3 9H2",
checkCircle: "M22 11.08V12a10 10 0 1 1-5.93-9.14M22 4 12 14.01l-3-3",
};
function Icon({ name, size = 20, className = "", filled = false, style = {}, color }) {
const d = ICONS[name];
if (!d) return null;
const colorStyle = color ? { color, ...style } : style;
if (name === 'playSolid' || (filled && name === 'starFill')) {
return (
);
}
return (
);
}
function Button({ variant = "primary", size = "md", icon, iconLeft, children, onClick, type, className = "", style: styleExtra = {} }) {
const base = {
display: "inline-flex", alignItems: "center", gap: 8, border: 0, cursor: "pointer",
fontFamily: "inherit", fontWeight: 600, letterSpacing: "-0.005em",
borderRadius: 8, transition: "all 200ms cubic-bezier(.2,.8,.2,1)",
textDecoration: "none",
};
const sizes = {
sm: { padding: "8px 14px", fontSize: 13 },
md: { padding: "12px 22px", fontSize: 15 },
lg: { padding: "15px 28px", fontSize: 16 },
};
const variants = {
primary: { background: "var(--omt-green)", color: "#fff" },
secondary: { background: "#fff", color: "var(--text-primary)", border: "1.5px solid var(--border-default)" },
dark: { background: "#1F2A27", color: "#fff" },
ghost: { background: "transparent", color: "var(--text-primary)" },
onDark: { background: "#fff", color: "var(--text-primary)" },
ghostOnDark: { background: "rgba(255,255,255,.08)", color: "#fff", border: "1.5px solid rgba(255,255,255,.18)" },
};
return (
);
}
function Eyebrow({ children, tone = "brand" }) {
return (
{children}
);
}
function Chip({ active, onClick, children, tone }) {
return (
);
}
function Card({ children, padding = 24, radius = 20, style = {}, onClick, hoverable }) {
const [hover, setHover] = useState(false);
return (
setHover(true)} onMouseLeave={() => setHover(false)}
style={{
background: "#fff", borderRadius: radius, padding,
boxShadow: hover && hoverable ? "var(--shadow-hover)" : "var(--shadow-card)",
transform: hover && hoverable ? "translateY(-2px)" : "translateY(0)",
transition: "all 200ms cubic-bezier(.2,.8,.2,1)",
cursor: onClick || hoverable ? "pointer" : "default",
...style,
}}>{children}
);
}
function Photo({ ratio = "16/10", label, style = {}, dark = false, icon, src }) {
const labelEl = label && (
{label}
);
const iconEl = icon && (
);
if (src) {
return (

{iconEl}
{labelEl}
);
}
return (

{iconEl}
{labelEl}
);
}
const COURSES_VERSION = "v2-2026";
const DEFAULT_COURSES = [
{
id: "radiologija-ekstremiteta",
title: "Radiologija ekstremiteta u fizioterapiji",
region: "Dijagnostika",
level: "Srednji / Napredni",
duration: "2 dana",
hours: "16h",
price: "Na upitu",
startDate: "06.06.2026",
spots: "Ograničen broj mesta",
badge: "Predstojeci",
instructor: "Aleksandar Bisić D.O.O.",
location: "OMT Centar · Beograd",
techniques: ["RTG analiza", "MRI interpretacija", "CT skeniranje", "Scintigrafija"],
description: "Medicinsko snimanje kao alat fizioterapeuta — dijagnostikovanje MSK povreda, vođenje rehabilitacije i integracija radiologije u kliničku praksu.",
curriculum: [
"Gornji ekstremitet — anatomija i najučestalije MSK patologije",
"Analiza RTG, MR i CT snimaka gornjeg ekstremiteta",
"Donji ekstremitet — anatomija i najučestalije MSK patologije",
"Analiza RTG, MR, CT i scintigrafije donjeg ekstremiteta",
"Prikazi slučaja i klinička primena nalaza",
"Integracija radiologije u fizioterapeutski plan",
"Povezivanje snimaka sa kliničkim pregledom i anamnezom",
],
active: true,
imageUrl: "assets/kurs-radiologija.jpeg",
},
{
id: "masterklas-kiropraktike",
title: "Masterklas kiropraktike",
region: "Kiropraktika",
level: "Napredni",
duration: "6 dana",
hours: "48h",
price: "Na upitu",
startDate: "26.08.2026",
spots: "Ograničen broj mesta",
badge: "Predstojeci",
instructor: "Prof. Dr. Jemerson José Polli Oliveira",
location: "Beograd, Srbija",
techniques: ["COX tehnika", "SOT tehnika", "Aktivator metoda", "Tompson drop tehnika"],
description: "Sveobuhvatni masterklas koji premošćava jaz između osnovnih tehnika i elitne kliničke izvrsnosti — od novorođenčadi do profesionalnih sportista.",
curriculum: [
"COX tehnika — fleksija/distrakcija za nehiruršku dekompresiju diska",
"SOT (sakro-okcipitalna tehnika) — kranijalni rad i balansiranje karlice",
"Aktivator metoda — precizna instrumentalna podešavanja",
"Tompson (drop) tehnika — unapređenje mehanike zglobova",
"Sportska medicina — prevencija povreda i unapređenje performansi",
"Trudnoća i prenatalna nega — karlična ravnoteža i neurobiomehanika",
"Pedijatrija i bebe — protokoli za kičmu u razvoju",
],
active: true,
imageUrl: "assets/kurs-kiropraktika.jpeg",
},
{
id: "pens-2-akupunktura",
title: "Moderna medicinska akupunktura — PENS 2",
region: "Akupunktura",
level: "Napredni",
duration: "3 dana",
hours: "24h",
price: "Na upitu",
startDate: "Jesen 2026",
spots: "Ograničen broj mesta",
badge: "Predstojeci",
instructor: "Boško Gardašević",
location: "OMT Centar · Beograd",
techniques: ["Elektroakupunktura", "Sportska akupunktura", "Pelvic pain", "Migrene"],
description: "Napredni nivo medicinske akupunkture — dijagnostika i lečenje bolova u mišićno-koštanom sistemu, glavobolja, migrena i neuroloških stanja.",
curriculum: [
"Petak: Bolovi u kukovima i SIZ-u (pelvic pain) — praktični trening",
"Petak: Glavobolje — teorija i praktični trening",
"Petak: Elektroakupunktura — neurološka stanja",
"Subota: Migrena — teorija i napredni praktični trening",
"Subota: Spinalna segmentalna disfunkcija (sciatica)",
"Nedelja: Mb Bechterew, tinnitus, ožiljci, periostakupunktura",
"Nedelja: Sportska akupunktura i Peripheral Nerve Compression Syndromes",
],
active: true,
imageUrl: "assets/kurs-pens.jpeg",
},
];
const DEFAULT_BLOGS = [
{ id:"b-1", title:"Zašto individualna obuka pobeđuje grupne kurseve", excerpt:"Grupni kurs daje znanje. Individualni rad gradi veštinu. Razlika je ogromna — i vaša palpacija to oseća.", read:"10 min", cat:"Klinička praksa", featured:true, active:true, date:"15.03.2026", imageUrl:"" },
{ id:"b-2", title:"HVLA tehnike: kada i kako ih bezbedno primeniti", excerpt:"Pravilna sila, pravi ugao, pravi momenat. Sve ostalo je šansa, ne tehnika.", read:"7 min", cat:"Tehnike", featured:false, active:true, date:"02.03.2026", imageUrl:"" },
{ id:"b-3", title:"Ergonomija osteopate: kako raditi 20 godina bez povrede", excerpt:"Telo je vaš instrument. Naučite da ga štitite pre nego što počne da boli.", read:"6 min", cat:"Karijera", featured:false, active:true, date:"18.02.2026", imageUrl:"" },
{ id:"b-4", title:"O.A.A. C0-C1-C2: vodič kroz gornji cervikalni region", excerpt:"Najsloženiji zglobovi kičme. Najzahtevnija tehnika. Najvrednije savladati.", read:"9 min", cat:"Anatomija", featured:false, active:true, date:"05.02.2026", imageUrl:"" },
{ id:"b-5", title:"Visceralne tehnike: nevidljivi sloj osteopatije", excerpt:"Organi imaju pokretljivost. Fascija pamti traumu. Visceralni pristup menja sve.", read:"8 min", cat:"Tehnike", featured:false, active:true, date:"22.01.2026", imageUrl:"" },
{ id:"b-6", title:"Komunikacija sa pacijentom: objašnjavanje MR i plana lečenja", excerpt:"Pacijent koji razume plan — sarađuje. Saradnja gradi poverenje. Poverenje leči.", read:"5 min", cat:"Komunikacija", featured:false, active:true, date:"10.01.2026", imageUrl:"" },
];
const BLOGS_VERSION = "1";
function useBlogs() {
const [blogs, setBlogs] = useState(() => {
try {
const ver = localStorage.getItem("omt-blogs-ver");
if (ver === BLOGS_VERSION) {
const raw = localStorage.getItem("omt-blogs");
if (raw) return JSON.parse(raw);
}
} catch {}
return DEFAULT_BLOGS;
});
useEffect(() => {
try {
localStorage.setItem("omt-blogs", JSON.stringify(blogs));
localStorage.setItem("omt-blogs-ver", BLOGS_VERSION);
} catch {}
}, [blogs]);
return [blogs, setBlogs];
}
function useCourses() {
const [courses, setCourses] = useState(() => {
try {
const ver = localStorage.getItem("omt-courses-ver");
if (ver === COURSES_VERSION) {
const raw = localStorage.getItem("omt-courses");
if (raw) return JSON.parse(raw);
}
} catch {}
return DEFAULT_COURSES;
});
useEffect(() => {
try {
localStorage.setItem("omt-courses", JSON.stringify(courses));
localStorage.setItem("omt-courses-ver", COURSES_VERSION);
} catch {}
}, [courses]);
return [courses, setCourses];
}
function useBreakpoint() {
const [w, setW] = useState(typeof window !== 'undefined' ? window.innerWidth : 1200);
useEffect(() => {
const fn = () => setW(window.innerWidth);
window.addEventListener('resize', fn);
return () => window.removeEventListener('resize', fn);
}, []);
return { isMobile: w < 640, isTablet: w >= 640 && w < 1024, isDesktop: w >= 1024, w };
}
function useReveal(threshold=0.15){
const ref=React.useRef(null);
const [visible,setVisible]=React.useState(false);
React.useEffect(()=>{
const el=ref.current;if(!el)return;
const obs=new IntersectionObserver(([e])=>{if(e.isIntersecting){setVisible(true);obs.disconnect();}},{threshold});
obs.observe(el);return()=>obs.disconnect();
},[]);
return[ref,visible];
}
function Stars({count=5,total=5}){return React.createElement('span',{style:{display:'inline-flex',gap:2,color:'#D9A21A'}},Array.from({length:total}).map((_,i)=>React.createElement(Icon,{key:i,name:'starFill',size:13,filled:true,style:{opacity:i