// Salersons — warm dark, color photos, smooth serif, champagne gold accent const { useEffect, useRef, useState } = React; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "accent": "#D4A86A", "photos": true, "heroItalFont": "aBigDeal", "heroScale": 0.8, "heroVariant": "A", "heroSub": "Sales recruiting out of Limassol. Israeli desks first — then Cyprus, Bulgaria, Serbia, Dubai and Manila when the offer on the table is better.", "manifestoVariant": "A", "applyHeading": "Send the CV.", "applySub": "We read every line. If your numbers say what we hope they say, you'll hear back the same day with a floor worth your time.", "industriesIntro": "Five floors. One brief.", "locationsIntro": "Six Locations.", "closingVariant": "A" }/*EDITMODE-END*/; // ───── Data ───── const INDUSTRIES = [ { name: "Forex", align: 0, size: "clamp(54px, 13vw, 156px)", italic: true }, { name: "Crypto", align: 28, size: "clamp(60px, 14vw, 168px)", italic: false }, { name: "CFDs", align: 8, size: "clamp(48px, 11vw, 132px)", italic: true }, { name: "Fintech", align: 36, size: "clamp(56px, 13vw, 156px)", italic: false }, { name: "iGaming", align: 14, size: "clamp(50px, 12vw, 144px)", italic: true }, ]; const CITIES = [ { name: "Israel", tag: "primary", size: "clamp(64px, 16vw, 192px)", anchor: true, align: 0 }, { name: "Cyprus", tag: "international",size: "clamp(44px, 10vw, 124px)", align: 18 }, { name: "Bulgaria", tag: "international",size: "clamp(46px, 10vw, 132px)", align: 6 }, { name: "Serbia", tag: "international",size: "clamp(42px, 9vw, 116px)", align: 24 }, { name: "Dubai", tag: "international",size: "clamp(48px, 11vw, 144px)", align: 10 }, { name: "Philippines", tag: "international",size: "clamp(40px, 9vw, 112px)", align: 30 }, ]; const SECTIONS = [ { id: "hero", img: "assets/scene1-telaviv.webp" }, { id: "apply", img: "assets/scene6-desk.webp" }, { id: "about", img: "assets/about-silhouette.webp" }, { id: "industries", img: "assets/scene2-trading.webp" }, { id: "process", img: "assets/scene3-headset.webp" }, { id: "locations", img: "assets/scene5-globe.webp" }, { id: "closing", img: "assets/scene1-telaviv.webp" }, ]; const PHOTO_URLS = [...new Set(SECTIONS.map(s => s.img))]; // ───── Copy variants ───── const HERO_VARIANTS = { A: { l1: "Sales floors", l2: "are hiring", l3: "closers." }, B: { l1: "The desks", l2: "that pay", l3: "in dollars." }, C: { l1: "Your numbers", l2: "deserve a floor", l3: "that pays them." }, }; const MANIFESTO_VARIANTS = { A: We don't coach you. We don't run prep calls. We read your numbers, we know every floor that's hiring, and we put you on the one where your closes are worth the most — then we step back., B: We are not a database. We are not a CV blast. We meet you, we read the work you've already done, and we match you to the desk that pays it what it's worth — nothing more, nothing less., C: Forget the LinkedIn voice. Forget the prep call. Walk us through your last desk, and we'll show you the one that should have been paying you in the first place — if it's on our books, it's yours to take., }; const CLOSING_VARIANTS = { A: Your next desk is already open., B: Send what you've closed. We'll send where you go next., C: The right floor pays in real money., }; // ───── Directional reveal ───── function useReveal() { useEffect(() => { const all = [...document.querySelectorAll(".reveal")]; const pending = new Set(all); let lastY = window.scrollY; let direction = "down"; const tick = () => { const y = window.scrollY; if (y > lastY + 1) direction = "down"; else if (y < lastY - 1) direction = "up"; lastY = y; const vh = window.innerHeight; for (const el of [...pending]) { const r = el.getBoundingClientRect(); if (r.top < vh * 0.92 && r.bottom > 0) { // Set direction-aware starting offset, then trigger transition to 0 el.style.transform = direction === "down" ? "translateY(28px)" : "translateY(-28px)"; // Force browser to commit the inline style as starting frame el.offsetHeight; // eslint-disable-line requestAnimationFrame(() => { el.classList.add("in"); el.style.transform = ""; }); pending.delete(el); } } }; let ticking = false; const onScroll = () => { if (!ticking) { ticking = true; requestAnimationFrame(() => { tick(); ticking = false; }); } }; tick(); window.addEventListener("scroll", onScroll, { passive: true }); window.addEventListener("resize", onScroll); return () => { window.removeEventListener("scroll", onScroll); window.removeEventListener("resize", onScroll); }; }, []); } // ───── Active photo (rAF + bounding rect — IO unreliable in this iframe) ───── function useActivePhoto() { const [active, setActive] = useState(SECTIONS[0].img); useEffect(() => { const sections = SECTIONS .map(s => ({ s, el: document.getElementById(s.id) })) .filter(x => x.el); const pick = () => { const vh = window.innerHeight; const probe = vh * 0.45; let best = sections[0]; let bestDist = Infinity; for (const item of sections) { const r = item.el.getBoundingClientRect(); if (r.bottom < 0 || r.top > vh) continue; const center = r.top + r.height / 2; const dist = Math.abs(center - probe); if (dist < bestDist) { bestDist = dist; best = item; } } if (best) setActive(best.s.img); }; let ticking = false; const onScroll = () => { if (!ticking) { ticking = true; requestAnimationFrame(() => { pick(); ticking = false; }); } }; pick(); window.addEventListener("scroll", onScroll, { passive: true }); window.addEventListener("resize", onScroll); return () => { window.removeEventListener("scroll", onScroll); window.removeEventListener("resize", onScroll); }; }, []); return active; } // ───── Photo layer ───── function PhotoStack({ enabled }) { const active = useActivePhoto(); if (!enabled) return
; return (
{PHOTO_URLS.map(url => (
))}
); } // ───── Sections ───── function Nav() { return ( ); } function Hero({ variant, sub }) { const v = HERO_VARIANTS[variant] || HERO_VARIANTS.A; return (

{v.l1} {v.l2} {v.l3}

{sub}

); } function Apply({ heading, sub }) { // Real lead capture. Posts to the same /api/lead.php sink as Apply.html with // three-layer delivery (fetch -> beacon -> native form POST) so a submit is // never silently dropped. Field names are snake_case to match lead.php / GAS. const ENDPOINT = "/api/lead.php"; // Same EU/EEA region test as the pixel gate (see ). When true the // browser pixel never loaded, so we tell the server (eu_region=1) to skip // server-side CAPI too, keeping the EU-block consistent on both sides. const EU_REGION = (() => { try { const tz = (window.Intl && Intl.DateTimeFormat().resolvedOptions().timeZone) || ""; return /^Europe\//.test(tz) || tz === "Atlantic/Reykjavik" || tz === "Atlantic/Canary" || tz === "Atlantic/Madeira" || tz === "Atlantic/Azores"; } catch (e) { return false; } })(); const MAX_BYTES = 5 * 1024 * 1024; const ACCEPT_EXTS = ["pdf", "doc", "docx", "rtf", "odt", "txt"]; const ACCEPT_ATTR = ".pdf,.doc,.docx,.rtf,.odt,.txt,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"; const [sending, setSending] = useState(false); const [sent, setSent] = useState(false); const [cvName, setCvName] = useState(""); const [cvWarn, setCvWarn] = useState(""); const fileRef = useRef(null); const onFileChange = (e) => { const f = e.target.files && e.target.files[0]; if (!f) { setCvName(""); setCvWarn(""); return; } const ext = (f.name.split(".").pop() || "").toLowerCase(); if (f.size > MAX_BYTES) { setCvWarn("File too large (max 5 MB). Choose a smaller one."); setCvName(""); if (fileRef.current) fileRef.current.value = ""; return; } if (!ACCEPT_EXTS.includes(ext)) { setCvWarn("Unsupported format. Use PDF, DOC, DOCX, RTF, ODT, or TXT."); setCvName(""); if (fileRef.current) fileRef.current.value = ""; return; } setCvWarn(""); setCvName(f.name + " · " + (f.size / 1024 / 1024).toFixed(2) + " MB"); }; const onSubmit = async (e) => { e.preventDefault(); // Validation is advisory only. NEVER preventDefault-and-return on a bad // field — that silently drops the lead. We always attempt delivery and // let lead.php validate softly. See form_submit_handler_pattern memory. const form = e.currentTarget; const data = new FormData(form); data.append("source", "home-apply"); data.append("submitted_at", new Date().toISOString()); setSending(true); // Layer 1: fetch. try { const res = await fetch(ENDPOINT, { method: "POST", body: data }); if (res.ok) { // Browser-side Lead with eventID = server lead_id, so Meta dedupes it // against the CAPI Lead. Guarded: window.fbq is undefined for EU // visitors where the pixel never loaded, so this is a no-op there. try { const j = await res.json(); if (window.fbq && j && j.lead_id) { window.fbq("track", "Lead", {}, { eventID: j.lead_id }); } } catch (e) { /* server CAPI still records the Lead */ } setSent(true); return; } } catch (err) { /* fall through */ } // Layer 2: sendBeacon (fires even mid-navigation; covers a fetch failure). // Note: a large CV may exceed the beacon cap; layer 3 then takes over. try { if (navigator.sendBeacon && navigator.sendBeacon(ENDPOINT, data)) { setSent(true); return; } } catch (err) { /* fall through */ } // Layer 3: native POST. Last resort, never a silent drop. setSending(false); form.submit(); }; return (

{heading}

{sub}

{sent ? (

Got it.

A real person reads every line and will be back to you within one business day. Check your inbox for a confirmation note.

) : (
{cvWarn ? ( {cvWarn} ) : null}

Want to share more? Use the full application →

)}
); } function About({ variant }) { const body = MANIFESTO_VARIANTS[variant] || MANIFESTO_VARIANTS.A; return (

{body}

Salersons · since 2021
); } function Industries({ intro }) { return (

{intro}

{INDUSTRIES.map((it, i) => (
{it.name}
))}
); } function Process() { return (

We evaluate.
You earn.

We listen.

One conversation. What you've closed, what you actually want, what you'll never do again.

We evaluate.

Your numbers, your hours, your language pairs — read against every desk we know is hiring in Israel and abroad.

We match.

Not a CV blast. A direct intro to the floor where your skill set commands the highest comp on offer right now.

You close.

We step back. Your job is to do what you've always done. Ours is to make sure the seat was worth taking.

); } function Locations({ intro }) { return (

{intro}

{CITIES.map((c, i) => (
{c.name} {c.tag}
))}
); } function Closing({ variant }) { const h = CLOSING_VARIANTS[variant] || CLOSING_VARIANTS.A; return (
When you're ready

{h}

Send your CV
); } function Footer() { return (
Salersons.

Spyrou Kyprianou 25, Limassol 4001, Cyprus
support@salersons.com · +357 25 808 100

Candidates
Legal

Salersons acts as an introduction agent between sales professionals and licensed employers. We do not employ candidates directly and we are not party to any employment contract you sign with a hiring company. Compensation figures discussed during the process reflect what a hiring desk has indicated and are subject to change at their sole discretion. Outcomes vary; nothing on this site constitutes a guarantee of placement, salary, or relocation. Any information you share is held in confidence and used only to introduce you to vetted employers who match your stated criteria.

© 2026 Salersons · Limassol Privacy  ·  Terms
); } // ───── App ───── function App() { // Design tokens are baked in at export time. The live tweaks panel was a // designer-only tool (tweaks-panel.jsx) and is not shipped to production. const t = TWEAK_DEFAULTS; useReveal(); useEffect(() => { const r = document.documentElement; r.style.setProperty("--accent", t.accent); r.style.setProperty("--hero-ital", `"${t.heroItalFont || "aBigDeal"}"`); r.style.setProperty("--hero-scale", String(t.heroScale ?? 1)); }, [t.accent, t.heroItalFont, t.heroScale]); return (