/* 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 ( {name === 'play' && } ); } 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 (
{label {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