/* ActiveFit360 marketing — Home page */
const NS_home = window.Activefit360DesignSystem_d87766;
/* ---- shared section heading (exposed for other pages) ---- */
function SectionHead({ eyebrow, title, sub, center, action, onAction }) {
const { Button } = NS_home;
return (
{eyebrow &&
{eyebrow}{center && }
}
{title}
{sub &&
{sub}
}
{action &&
} onClick={onAction}>{action}}
);
}
window.SectionHead = SectionHead;
/* ---- reviews carousel — continuous marquee ---- */
if (typeof document !== 'undefined' && !document.getElementById('af-rev-css')) {
const s = document.createElement('style'); s.id = 'af-rev-css';
s.textContent = `
.af-rev-stage{ position:relative; overflow:hidden; }
.af-rev-track{ display:flex; gap:20px; width:max-content; }
.af-rev-card{ flex:0 0 auto; width:clamp(260px,34vw,340px); background:#fff;
border:1px solid var(--border-soft); border-radius:var(--radius-xl);
box-shadow:var(--shadow-sm); padding:clamp(18px,2vw,26px); }
.af-rev-fade-l{ position:absolute; left:0; top:0; bottom:0; width:64px; z-index:2; pointer-events:none;
background:linear-gradient(90deg, var(--surface-page) 10%, transparent); }
.af-rev-fade-r{ position:absolute; right:0; top:0; bottom:0; width:64px; z-index:2; pointer-events:none;
background:linear-gradient(270deg, var(--surface-page) 10%, transparent); }
`;
document.head.appendChild(s);
}
function ReviewsCarousel({ rows = 3 }) {
const { Avatar } = NS_home;
const I = window.Icon;
const reviews = window.AF_REVIEWS;
// Split reviews into rows
const rowData = rows === 1
? [reviews]
: [
reviews.filter((_, i) => i % 3 === 0),
reviews.filter((_, i) => i % 3 === 1),
reviews.filter((_, i) => i % 3 === 2),
];
const speeds = [0.38, 0.42, 0.35];
const dirs = [1, -1, 1];
function MarqueeRow({ items, direction = 1, speed = 0.4 }) {
const trackRef = React.useRef(null);
const pausedRef = React.useRef(false);
const posRef = React.useRef(0);
const resumeTimer = React.useRef(null);
const loop = [...items, ...items, ...items, ...items];
const pause = () => { pausedRef.current = true; };
const resumeSoon = (ms = 3000) => { clearTimeout(resumeTimer.current); resumeTimer.current = setTimeout(() => { pausedRef.current = false; }, ms); };
React.useEffect(() => {
let raf;
const tick = () => {
const el = trackRef.current;
if (el && !pausedRef.current) {
posRef.current += speed * direction;
const quarter = el.scrollWidth / 4;
if (posRef.current >= quarter) posRef.current -= quarter;
if (posRef.current < 0) posRef.current += quarter;
el.style.transform = `translateX(-${posRef.current}px)`;
}
raf = requestAnimationFrame(tick);
};
raf = requestAnimationFrame(tick);
return () => cancelAnimationFrame(raf);
}, []);
return (
{ pausedRef.current = false; }}
onTouchStart={pause} onTouchEnd={() => resumeSoon()}
onPointerDown={pause} onPointerUp={() => resumeSoon()}>
{loop.map((r, idx) => (
{[0,1,2,3,4].map(n => )}
"{r.text}"
{r.name}
Verified · {r.source || 'Zocdoc'}
))}
);
}
return (
1 ? 'linear-gradient(to bottom, transparent, black 8%, black 92%, transparent)' : undefined,
WebkitMaskImage: rows > 1 ? 'linear-gradient(to bottom, transparent, black 8%, black 92%, transparent)' : undefined }}>
{rowData.map((items, i) => (
))}
);
}
window.ReviewsCarousel = ReviewsCarousel;
/* ---- hero ---- */
function Hero({ onBook, onNavigate }) {
const { Button, Badge } = NS_home;
const I = window.Icon;
const bullets = [
['user', 'One-on-one care with a licensed PT — never rushed'],
['calendar-check', 'Direct access — no physician referral needed'],
['map-pin', 'In-clinic, in-home, or virtual visits'],
];
return (
{/* copy */}
{[0,1,2,3,4].map(n => )}
Holistic Physical Therapy
Recover. Strengthen. Thrive.
Personalized, one-on-one physical therapy in Naperville — built around your body, your goals, and your life.
{bullets.map(([icon, text]) => (
{text}
))}
} onClick={onBook}>Book an Appointment
} onClick={() => onNavigate('services')}>Explore Services
{/* founder photo + floating cards */}
Nikita Goyal, PT, MS
Founder · 10+ yrs experience
{[0,1,2,3,4].map(n => )}
“She is the best!”
— Verified Zocdoc patient
No referral needed
{/* mobile trust strip — replaces the hidden floating cards on small screens */}
{[
['stethoscope', 'Nikita Goyal, PT, MS', 'Founder · 10+ yrs experience'],
['star', '“She is the best!”', 'Verified Zocdoc patient'],
['check', 'No referral needed', null],
].map(([icon, title, sub], i) => (
))}
);
}
/* ---- care delivery models ---- */
function CareModels() {
const { Card } = NS_home;
const I = window.Icon;
return (
{window.AF_CARE_MODELS.map(m => (
{m.title}
{m.tagline}
{m.features.map(f => (
-
{f}
))}
))}
);
}
/* ---- core services: auto-scrolling marquee carousel ---- */
if (typeof document !== 'undefined' && !document.getElementById('af-svc-css')) {
const s = document.createElement('style'); s.id = 'af-svc-css';
s.textContent = `
.af-svc-stage{ position:relative; padding:0 60px; }
.af-svc-scroller{ display:flex; gap:20px; overflow-x:auto;
padding:6px 2px 8px; -ms-overflow-style:none; scrollbar-width:none; scroll-behavior:auto; }
.af-svc-scroller::-webkit-scrollbar{ display:none; }
.af-svc-card{ flex:0 0 auto; width:clamp(248px, 70vw, 288px); }
.af-svc-arrow{ position:absolute; top:50%; transform:translateY(-50%); z-index:3; width:48px; height:48px;
border-radius:50%; border:1px solid var(--border-soft); background:#fff;
box-shadow:var(--shadow-md); cursor:pointer; display:inline-flex;
align-items:center; justify-content:center; color:var(--ink-900); transition:var(--transition-base); }
.af-svc-arrow:hover{ color:var(--green-700); border-color:var(--green-300); box-shadow:var(--shadow-lg); }
.af-svc-arrow--l{ left:4px; } .af-svc-arrow--r{ right:4px; }
.af-svc-edge{ position:absolute; top:0; bottom:14px; width:40px; z-index:2; pointer-events:none; }
.af-svc-edge--l{ left:60px; background:linear-gradient(90deg, var(--surface-page), transparent); }
.af-svc-edge--r{ right:60px; background:linear-gradient(270deg, var(--surface-page), transparent); }
@media (max-width:640px){ .af-svc-stage{ padding:0; } .af-svc-arrow{ display:none; } .af-svc-edge{ display:none; } }
`;
document.head.appendChild(s);
}
function CoreServices({ onNavigate }) {
const { Card } = NS_home;
const I = window.Icon;
const items = window.AF_SERVICES;
const loop = [...items, ...items];
const ref = React.useRef(null);
const pausedRef = React.useRef(false);
const resumeTimer = React.useRef(null);
const [active, setActive] = React.useState(0);
const cardStep = () => {
const el = ref.current; if (!el) return 1;
const c = el.querySelector('.af-svc-card');
return c ? c.offsetWidth + 20 : 1;
};
// continuous slow marquee
React.useEffect(() => {
let raf;
const tick = () => {
const el = ref.current;
if (el && !pausedRef.current) {
el.scrollLeft += 0.6;
const half = el.scrollWidth / 2;
if (el.scrollLeft >= half) el.scrollLeft -= half;
}
raf = requestAnimationFrame(tick);
};
raf = requestAnimationFrame(tick);
return () => cancelAnimationFrame(raf);
}, []);
const onScroll = () => {
const el = ref.current; if (!el) return;
const idx = Math.round(el.scrollLeft / cardStep());
setActive(((idx % items.length) + items.length) % items.length);
};
const pause = () => { pausedRef.current = true; };
const resumeSoon = (ms = 2600) => {
clearTimeout(resumeTimer.current);
resumeTimer.current = setTimeout(() => { pausedRef.current = false; }, ms);
};
const nudge = (dir) => { ref.current?.scrollBy({ left: dir * cardStep(), behavior: 'smooth' }); pause(); resumeSoon(); };
const toCard = (i) => { ref.current?.scrollTo({ left: i * cardStep(), behavior: 'smooth' }); pause(); resumeSoon(); };
return (
onNavigate('services')} />
{ pausedRef.current = false; }}
onTouchStart={pause} onTouchEnd={() => resumeSoon()} onPointerDown={pause} onPointerUp={() => resumeSoon()}>
{loop.map((s, i) => (
onNavigate('services')} style={{ cursor: 'pointer', height: '100%' }}>
{s.title}
{s.desc}
))}
{/* dot indicators */}
{items.map((s, i) => (
);
}
/* ---- payment options ---- */
function PaymentOptions() {
const { Badge } = NS_home;
const I = window.Icon;
return (
{window.AF_PAYMENTS.map(p => (
{p.featured &&
Most popular}
{p.title}
{p.blurb}
{p.points.map(pt => (
-
{pt}
))}
))}
Please reach out to confirm your coverage — we’re happy to help.
);
}
/* ---- reviews section wrapper ---- */
function ReviewsSection({ onNavigate }) {
return (
Top-Rated
Physical Therapy>} />
} onClick={() => onNavigate('reviews')}>Read all reviews
);
}
function HomePage({ onBook, onNavigate }) {
return (
);
}
Object.assign(window, { HomePage });