import { useState } from "react"; /* ── Data ── */ const CHAMPS = [ { id: "1", name: "Zero Gravity", subtitle: "International Pole Exotic Championship", org: "Zero Gravity Team", dates: "May 30, 2026", location: "Minsk, Belarus", venue: "Prime Hall", address: "Pr. Pobeditelei, 65", disciplines: [ { name: "Exotic Pole Dance", performanceReq: "70% floor & mid-level, 30% upper level", categories: [ { name: "Beginners", duration: "2:00–3:00", eligibility: "Up to 2 yrs, no instructor/pro background", type: "solo" }, { name: "Amateur", duration: "2:30–3:00", eligibility: "2–4 yrs, no instructor/pro background", type: "solo" }, { name: "Semi-Pro", duration: "2:50–3:20", eligibility: "3+ yrs, instructor OR pro OR prizes in Amateur", type: "solo" }, { name: "Profi", duration: "3:00–3:30", eligibility: "4+ yrs, instructor OR pro OR prizes in Semi-Pro", type: "solo" }, { name: "Elite", duration: "3:00–4:00", eligibility: "3+ prizes in Profi OR widely known", type: "solo" }, { name: "Duets & Groups", duration: "3:00–4:20", eligibility: "Open to all levels", type: "group" }, ]}, { name: "Pole Art", performanceReq: "60% floor & mid-level, 40% upper level", categories: [ { name: "Amateur", duration: "2:30–3:00", eligibility: "Up to 2 yrs, no instructor/pro background", type: "solo" }, { name: "Semi-Pro", duration: "2:50–3:20", eligibility: "3+ yrs, instructor OR pro OR prizes in Amateur", type: "solo" }, { name: "Profi", duration: "3:00–3:30", eligibility: "4+ yrs, instructor OR pro OR prizes in Semi-Pro", type: "solo" }, ]}, ], fees: { videoSelection: "50 BYN / 1,500 RUB", championship: { solo: "280 BYN / 7,500 RUB", duet: "210 BYN / 5,800 RUB pp", group: "190 BYN / 4,500 RUB pp" }, refundNote: "Non-refundable. All fees are charitable contributions." }, videoReqs: { minDuration: "1:30", editing: "No editing or splicing", maxAge: "Less than 1 year old", note: "Must reflect your level" }, judging: [ { name: "Image", max: 10, desc: "Costume, hair, makeup, originality" }, { name: "Artistry", max: 10, desc: "Charisma, stage presence, emotion" }, { name: "Choreography", max: 10, desc: "Body control, complexity, originality" }, { name: "Musicality", max: 10, desc: "Timing, feeling, accent play" }, { name: "Technique", max: 10, desc: "Clean execution, transitions, tricks" }, { name: "Overall", max: 10, desc: "General impression" }, { name: "Synchronicity", max: 10, desc: "Duets only" }, ], penalties: [ { name: "Missed element", points: -2 }, { name: "Fall", points: -2 }, { name: "Leaving stage", consequence: "DQ" }, { name: "Exposure", consequence: "DQ" }, { name: "Substance influence", consequence: "DQ" }, { name: "No special shoes", consequence: "DQ" }, ], venueSpecs: { poles: "2 (Static & Spinning)", poleHeight: "3.5 m", poleDiameter: "42 mm", stageSize: "6m × 14m" }, costumeRules: ["Neat and well-fitted", "No advertising", "No spikes/sharp objects", "No thongs/sheer/pasties", "Specialized shoes for Exotic", "Creativity is scored"], generalRules: ["Must be 18+", "No medical contraindications", "Valid life & health insurance", "No lotions/bronzers 24h before", "Grip aids allowed (no wax/rosin)", "Judges' decision is final", "Organizers may change your category"], prizes: ["1st–3rd in each category", "Nominations per block", "Medals, diplomas, sponsor prizes", "All get participation diplomas", "1st Elite → judge next champ"], resultsChannels: ["Email", "Instagram", "Telegram"], applicationDeadline: "August 22, 2026", formUrl: "https://docs.google.com/forms/d/e/1FAIpQLSfLaNg5Sf2QMAI6anpMrnLu-2qYfT3tdwh0dsynQFn8xMhi2g/viewform", status: "registration_open", accent: "#D4145A", image: "💃", }, { id: "2", name: "Pole Star", subtitle: "National Pole Championship", org: "Pole Star Events", dates: "Jul 12–13, 2026", location: "Moscow, Russia", venue: "Crystal Hall", disciplines: [{ name: "Exotic Pole Dance", categories: [ { name: "Amateur", duration: "2:30–3:00", eligibility: "2–4 years", type: "solo" }, { name: "Profi", duration: "3:00–3:30", eligibility: "4+ years", type: "solo" }, ]}], fees: { videoSelection: "2,000 RUB", championship: { solo: "8,000 RUB" } }, videoReqs: { minDuration: "1:00", editing: "No editing", maxAge: "6 months" }, status: "upcoming", applicationDeadline: "Jun 1, 2026", accent: "#7C3AED", image: "⭐", }, ]; const STEPS = [ { id: "s1", label: "Review rules & eligibility", icon: "📋", detect: "auto", detectLabel: "Auto: tracked in app" }, { id: "s2", label: "Select category", icon: "🏷️", detect: "auto", detectLabel: "Auto: saved in app" }, { id: "s3", label: "Record video (min 1:30)", icon: "🎬", detect: "manual", detectLabel: "You confirm" }, { id: "s4", label: "Submit video selection form", icon: "📤", detect: "email", detectLabel: "Auto: Gmail confirmation" }, { id: "s5", label: "Pay video selection fee", icon: "💳", warn: true, detect: "receipt", detectLabel: "Upload receipt → Org confirms" }, { id: "s6", label: "Results (auto-detected)", icon: "🤖", detect: "auto", detectLabel: "Auto: Instagram OCR" }, { id: "s7", label: "Pay championship fee", icon: "💰", warn: true, detect: "receipt", detectLabel: "Upload receipt → Org confirms" }, { id: "s8", label: 'Fill "About Me" form', icon: "👤", detect: "email", detectLabel: "Auto: Gmail confirmation" }, { id: "s9", label: "Confirm insurance", icon: "🛡️", detect: "receipt", detectLabel: "Upload doc → Org confirms" }, { id: "s10", label: "Submit music & performance", icon: "🎶", detect: "email", detectLabel: "Auto: Gmail confirmation" }, ]; const USER = { name: "Alex", city: "Moscow", disciplines: ["Pole Exotic", "Pole Art"], experienceYears: 3, isInstructor: false, instagram: "@alex_pole" }; const NOTIFICATIONS = [ { id: "n1", type: "category_change", champ: "Zero Gravity", from: "Amateur", to: "Semi-Pro", field: "Level", date: "Feb 24, 2026", read: false, message: "Your level was changed from Amateur to Semi-Pro by the organizer." }, { id: "n2", type: "payment_confirmed", champ: "Zero Gravity", date: "Feb 23, 2026", read: false, message: "Your video selection fee payment has been confirmed." }, { id: "n3", type: "result", champ: "Zero Gravity", date: "Feb 22, 2026", read: true, message: "Video selection results are out! You passed! 🎉" }, { id: "n4", type: "deadline", champ: "Zero Gravity", date: "Feb 20, 2026", read: true, message: "Reminder: registration deadline is Aug 22, 2026." }, ]; const MY_REGISTRATIONS = [ { champId: "1", discipline: "Exotic Pole Dance", category: "Semi-Pro", status: "in_progress", currentStep: 4, stepsCompleted: 3, nextAction: "Submit video selection form", deadline: "Aug 22, 2026" }, { champId: "2", discipline: "Exotic Pole Dance", category: "Profi", status: "planned", currentStep: 1, stepsCompleted: 0, nextAction: "Review rules & eligibility", deadline: "Jun 1, 2026" }, ]; /* ── Theme ── */ const c = { bg: "#08070D", card: "#12111A", cardH: "#1A1926", brd: "#1F1E2E", text: "#F2F0FA", dim: "#5E5C72", mid: "#8F8DA6", accent: "#D4145A", accentS: "rgba(212,20,90,0.10)", green: "#10B981", greenS: "rgba(16,185,129,0.10)", yellow: "#F59E0B", yellowS: "rgba(245,158,11,0.10)", purple: "#8B5CF6" }; const f = { d: "'Playfair Display',Georgia,serif", b: "'DM Sans','Segoe UI',sans-serif", m: "'JetBrains Mono',monospace" }; /* ── Shared ── */ const Badge = ({ status }) => { const m = { registration_open: { l: "REG OPEN", c: c.green, b: c.greenS }, upcoming: { l: "UPCOMING", c: c.yellow, b: c.yellowS } }; const s = m[status] || m.upcoming; return {s.l}; }; const Chip = ({ text, color = c.mid, bg = c.card, border = c.brd }) => {text}; const Info = ({ icon, text }) => {icon} {text}; const ST = ({ children, right }) =>

{children}

{right && {right}}
; const Cd = ({ children, style: s }) =>
{children}
; function Tabs({ tabs, active, onChange, accent: ac }) { return
{tabs.map(t =>
onChange(t)} style={{ fontFamily: f.m, fontSize: 10, fontWeight: 600, letterSpacing: 0.4, color: active === t ? ac || c.accent : c.dim, background: active === t ? `${ac || c.accent}15` : "transparent", border: `1px solid ${active === t ? `${ac || c.accent}30` : "transparent"}`, padding: "5px 12px", borderRadius: 16, cursor: "pointer", whiteSpace: "nowrap" }}>{t}
)}
; } function Nav({ active, onChange }) { return
{[{ id: "home", i: "🏠", l: "Home" }, { id: "my", i: "🎯", l: "My Champs" }, { id: "search", i: "🔍", l: "Search" }, { id: "profile", i: "👤", l: "Profile" }].map(x =>
onChange(x.id)} style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 2, cursor: "pointer", opacity: active === x.id ? 1 : 0.35 }}>{x.i}{x.l}
)}
; } function Hdr({ title, subtitle, onBack, right }) { return
{onBack &&
}

{title}

{subtitle &&

{subtitle}

}
{right}
; } /* ── Home ── */ function Home({ onTap, onNotifications }) { const unread = NOTIFICATIONS.filter(n => !n.read).length; return
🔔 {unread > 0 &&
{unread}
}
} />

🔔 Zero Gravity — Deadline: Aug 22!

Championships {CHAMPS.map(ch => )}
; } function ChampCard({ ch, onTap }) { const [h, setH] = useState(false); return
onTap(ch)} onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)} style={{ background: h ? c.cardH : c.card, border: `1px solid ${c.brd}`, borderRadius: 16, padding: 16, cursor: "pointer", transition: "all 0.2s", transform: h ? "translateY(-2px)" : "none", boxShadow: h ? "0 8px 24px rgba(0,0,0,0.3)" : "none" }}>
{ch.image}

{ch.name}

{ch.subtitle}

{ch.disciplines &&
{ch.disciplines.map(d => )}
}
; } /* ── Championship Detail ── */ function Detail({ ch, onBack, onProgress }) { const [tab, setTab] = useState("Info"); const tabs = ["Info", "Categories", "Fees", "Judging", "Rules"]; const completedCount = 3; // mock return
{/* Hero */}
{ch.image}
{ch.applicationDeadline && } {ch.resultsChannels && }
{/* Register + Progress buttons */}
onProgress(ch)} style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, padding: "11px 12px", borderRadius: 12, background: c.card, border: `1px solid ${c.brd}`, cursor: "pointer" }}> 📋 Progress {completedCount}/{STEPS.length}
{ch.formUrl && ch.status === "registration_open" && ✍️ Register }
{/* Info */} {tab === "Info" &&
{ch.disciplines && Disciplines{ch.disciplines.map(d =>

{d.name}

{d.performanceReq &&

{d.performanceReq}

}
{d.categories.map(cat => )}
)}
} {ch.videoReqs && Video Requirements
} {ch.prizes && Prizes{ch.prizes.map((p, i) =>

🏆 {p}

)}
}
} {/* Categories */} {tab === "Categories" && ch.disciplines &&
{ch.disciplines.map(d => {d.name}{d.categories.map(cat => { const match = (USER.experienceYears >= 2 && USER.experienceYears <= 4 && !USER.isInstructor && cat.name === "Amateur") || (USER.experienceYears >= 3 && cat.name === "Semi-Pro") || cat.name === "Duets & Groups"; return
{cat.name}
{cat.duration} {match && MATCH}

{cat.eligibility}

; })}
)}

⚠️ Organizers may change your category if level doesn't match

} {/* Fees */} {tab === "Fees" && ch.fees &&
Stage 1: Video Selection
Fee{ch.fees.videoSelection}

⚠️ Non-refundable even if you don't pass

Stage 2: Championship (after passing) {Object.entries(ch.fees.championship).map(([t, a]) =>
{t}{a}
)} {ch.fees.refundNote &&

⚠️ {ch.fees.refundNote}

}
} {/* Judging */} {tab === "Judging" && ch.judging &&
Scoring (0–10 each){ch.judging.map(j =>
{j.name}0–{j.max}

{j.desc}

)}
{ch.penalties && Penalties{ch.penalties.map((p, i) =>
{p.name} {p.consequence || `${p.points}`}
)}
}
} {/* Rules + Venue */} {tab === "Rules" &&
{ch.generalRules && General{ch.generalRules.map((r, i) =>

• {r}

)}
} {ch.costumeRules && Costume & Shoes{ch.costumeRules.map((r, i) =>

• {r}

)}
} {ch.venueSpecs && Stage & Equipment
{Object.entries(ch.venueSpecs).map(([k, v]) =>

{k.replace(/([A-Z])/g, " $1")}

{v}

)}
}
}
; } /* ── Progress Screen (separate full view) ── */ function Progress({ ch, onBack }) { const [done, setDone] = useState({ s1: true, s2: true, s3: true }); const [uploads, setUploads] = useState({}); const [orgConfirmed, setOrgConfirmed] = useState({}); const cnt = Object.values(done).filter(Boolean).length; const pct = (cnt / STEPS.length) * 100; const detectColors = { auto: { c: c.green, bg: c.greenS, label: "AUTO" }, email: { c: "#60A5FA", bg: "rgba(96,165,250,0.10)", label: "GMAIL" }, receipt: { c: c.yellow, bg: c.yellowS, label: "UPLOAD" }, manual: { c: c.mid, bg: `${c.mid}15`, label: "MANUAL" } }; const handleUpload = (stepId) => { setUploads(p => ({ ...p, [stepId]: true })); }; return
{/* Summary */}
{Math.round(pct)}% {cnt} of {STEPS.length} steps
{/* Legend */}
{Object.entries(detectColors).map(([k, v]) => {v.label} )} ORG ✓
{/* Steps */} {STEPS.map((s, i) => { const d = done[s.id]; const isN = !d && cnt === i; const uploaded = uploads[s.id]; const confirmed = orgConfirmed[s.id]; const dc = detectColors[s.detect]; return
{/* Main row */}
{ if (s.detect === "manual" || s.detect === "auto") setDone(p => ({ ...p, [s.id]: !p[s.id] })); }} style={{ display: "flex", alignItems: "center", gap: 10, cursor: s.detect === "manual" || s.detect === "auto" ? "pointer" : "default", background: isN ? `${ch.accent}06` : "transparent", borderRadius: 8, padding: "2px 0" }}>
{d ? "✓" : i + 1}
{s.icon}
{s.label}
{s.warn && !d && ⚠️} {isN && NEXT}
{/* Detection method + action */} {!d &&
{dc.label} {s.detectLabel}
} {/* Upload action for receipt steps */} {!d && isN && s.detect === "receipt" &&
{!uploaded ? (
handleUpload(s.id)} style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "7px 14px", borderRadius: 8, background: `${c.yellow}15`, border: `1px solid ${c.yellow}30`, cursor: "pointer" }}> 📸 Upload receipt
) : !confirmed ? (
📸 Uploaded Waiting for org to confirm... {/* Demo: simulate org confirm */} { setOrgConfirmed(p => ({ ...p, [s.id]: true })); setDone(p => ({ ...p, [s.id]: true })); }} style={{ fontFamily: f.m, fontSize: 8, fontWeight: 700, color: c.purple, background: `${c.purple}15`, padding: "2px 8px", borderRadius: 4, cursor: "pointer" }}>Demo: Org ✓
) : null}
} {/* Email detection indicator */} {!d && isN && s.detect === "email" &&
📧 Monitoring Gmail for confirmation... {/* Demo: simulate detection */} setDone(p => ({ ...p, [s.id]: true }))} style={{ fontFamily: f.m, fontSize: 8, fontWeight: 700, color: "#60A5FA", background: "rgba(96,165,250,0.10)", padding: "2px 8px", borderRadius: 4, cursor: "pointer" }}>Demo: Detected
} {/* Auto completed indicator */} {d && s.detect === "auto" &&
✓ Auto-detected
} {d && s.detect === "email" &&
✓ Gmail confirmation received
} {d && s.detect === "receipt" &&
✓ Receipt uploaded · Org confirmed
}
; })}
{/* Auto-detection monitoring */}
🤖

Auto-Detection Active

Monitoring multiple channels

{[ { ch: "Instagram", icon: "📸", desc: "Results photo OCR", status: "Monitoring" }, { ch: "Gmail", icon: "📧", desc: "Form confirmations & results", status: "Connected" }, { ch: "Telegram", icon: "💬", desc: "Championship chat", status: "Monitoring" }, ].map(x =>
{x.icon}

{x.ch}

{x.desc}

{x.status}
)}
{/* Register */} {ch.formUrl && ch.status === "registration_open" && ✍️ Register Now }
; } /* ── My Championships ── */ function MyChamps({ onTap, onProgress }) { const active = MY_REGISTRATIONS.filter(r => r.status === "in_progress"); const planned = MY_REGISTRATIONS.filter(r => r.status === "planned"); const completed = MY_REGISTRATIONS.filter(r => r.status === "completed"); const RegCard = ({ reg }) => { const ch = CHAMPS.find(c2 => c2.id === reg.champId); if (!ch) return null; const pct = (reg.stepsCompleted / STEPS.length) * 100; const statusMap = { in_progress: { label: "IN PROGRESS", color: c.green, bg: c.greenS }, planned: { label: "PLANNED", color: c.yellow, bg: c.yellowS }, completed: { label: "COMPLETED", color: c.purple, bg: `${c.purple}15` } }; const st = statusMap[reg.status]; return {/* Color accent bar */}
{/* Header */}
{ch.image}

{ch.name}

{ch.dates} · {ch.location}

{st.label}
{/* Category */}
{/* Progress bar */}
{reg.stepsCompleted}/{STEPS.length} steps {Math.round(pct)}%
{/* Next action */} {reg.nextAction &&

Next step

{STEPS[reg.currentStep - 1]?.icon} {reg.nextAction}

} {/* Deadline */} {reg.deadline &&
Deadline: {reg.deadline}
} {/* Actions */}
onTap(ch)} style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 5, padding: "9px", borderRadius: 10, background: c.bg, border: `1px solid ${c.brd}`, cursor: "pointer" }}> ℹ️ Details
onProgress(ch)} style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 5, padding: "9px", borderRadius: 10, background: ch.accent, cursor: "pointer" }}> 📋 Progress
; }; return
{active.length > 0 && <> Active {active.map(r => )} } {planned.length > 0 && <> Planned {planned.map(r => )} } {completed.length > 0 && <> Completed {completed.map(r => )} } {MY_REGISTRATIONS.length === 0 &&
🔍

No championships yet

Browse championships and start your journey!

}
; } /* ── Notifications ── */ function Notifications({ onBack }) { const [notifs, setNotifs] = useState(NOTIFICATIONS); const markRead = (id) => setNotifs(p => p.map(n => n.id === id ? { ...n, read: true } : n)); const markAllRead = () => setNotifs(p => p.map(n => ({ ...n, read: true }))); const unread = notifs.filter(n => !n.read).length; const typeConfig = { category_change: { icon: "🔄", color: c.yellow, label: "Category Changed" }, payment_confirmed: { icon: "✅", color: c.green, label: "Payment Confirmed" }, result: { icon: "🏆", color: c.accent, label: "Results" }, deadline: { icon: "⏰", color: c.yellow, label: "Deadline Reminder" }, style_change: { icon: "🔄", color: c.purple, label: "Style Changed" }, registration_confirmed: { icon: "📋", color: c.green, label: "Registration" }, announcement: { icon: "📢", color: c.blue, label: "Announcement" }, }; return
0 ? `${unread} unread` : "All caught up ✓"} onBack={onBack} right={ unread > 0 ?
Read all
: null } />
{notifs.length === 0 &&
🔕

No notifications

You'll see updates from championships here

} {notifs.map(n => { const tc = typeConfig[n.type] || typeConfig.announcement; return
markRead(n.id)} style={{ display: "flex", gap: 12, padding: "12px 14px", borderRadius: 12, cursor: "pointer", background: n.read ? c.card : `${tc.color}08`, border: `1px solid ${n.read ? c.brd : `${tc.color}20`}`, }}>
{tc.icon}
{tc.label}
{n.date} {!n.read &&
}

{n.message}

{n.champ}

; })}
; } /* ── Search ── */ function Search({ onTap }) { const [q, setQ] = useState(""); const [fl, setFl] = useState("all"); const fs = [{ id: "all", l: "All" }, { id: "registration_open", l: "Open" }, { id: "upcoming", l: "Upcoming" }]; const res = CHAMPS.filter(ch => (!q || ch.name.toLowerCase().includes(q.toLowerCase()) || ch.location.toLowerCase().includes(q.toLowerCase())) && (fl === "all" || ch.status === fl)); return
🔍 setQ(e.target.value)} style={{ background: "transparent", border: "none", outline: "none", color: c.text, fontFamily: f.b, fontSize: 13, width: "100%" }} />
{fs.map(x =>
setFl(x.id)} style={{ fontFamily: f.m, fontSize: 10, fontWeight: 600, color: fl === x.id ? c.accent : c.dim, background: fl === x.id ? c.accentS : c.card, border: `1px solid ${fl === x.id ? `${c.accent}30` : c.brd}`, padding: "5px 12px", borderRadius: 16, cursor: "pointer" }}>{x.l}
)}
{res.length ? res.map(ch => ) :
🤷

No results

}
; } /* ── Profile ── */ function Profile() { return
💃

{USER.name}

{USER.instagram}

{[{ i: "📍", l: "City", v: USER.city }, { i: "💃", l: "Disciplines", v: USER.disciplines.join(", ") }, { i: "📅", l: "Experience", v: `${USER.experienceYears} years` }, { i: "🎓", l: "Instructor", v: USER.isInstructor ? "Yes" : "No" }].map(r => {r.i}

{r.l}

{r.v}

)}
Eligible Categories {["Amateur (Exotic)", "Semi-Pro (Exotic)", "Duets & Groups", "Amateur (Pole Art)", "Semi-Pro (Pole Art)"].map(cat =>
{cat}
)}
Stats
{[{ n: "2", l: "Champs", co: c.accent }, { n: "1", l: "Passed", co: c.green }, { n: "1", l: "Pending", co: c.yellow }].map(s =>

{s.n}

{s.l}

)}
{["Edit Profile", "Competition History", "Notifications", "Settings", "Log Out"].map((x, i, a) =>
{x}
)}
; } /* ── App Shell ── */ export default function App() { const [scr, setScr] = useState("home"); const [sel, setSel] = useState(null); const [prev, setPrev] = useState("home"); const go = (s, ch) => { setPrev(scr); setScr(s); if (ch) setSel(ch); }; const goBack = () => { setScr(prev || "home"); setSel(null); }; const render = () => { if (scr === "progress" && sel) return go("detail")} />; if (scr === "detail" && sel) return go("progress", ch)} />; if (scr === "notifications") return go("home")} />; if (scr === "my") return go("detail", ch)} onProgress={ch => go("progress", ch)} />; if (scr === "search") return go("detail", ch)} />; if (scr === "profile") return ; return go("detail", ch)} onNotifications={() => go("notifications")} />; }; const showNav = scr === "home" || scr === "search" || scr === "profile" || scr === "my"; return
9:41
●●●
{render()}
{showNav &&
; }