All Prompts
All Prompts

sectioncalculatorforminteractivemodalquizresponsiveglassmodern
Revenue Leak Calculator with Modal & Quiz
Калькулятор утечки дохода с модальным окном и викториной. Интерактивный раздел для клиник, рассчитывает доход, предлагает викторину и сбор email.
Prompt
<div class="revenue-leak-calculator-wrapper">
<style>@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap');
.revenue-leak-calculator-wrapper {
font-family: 'Inter', 'Helvetica Neue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
}
/* Clean Scrollbar */
.revenue-leak-calculator-wrapper ::-webkit-scrollbar { width: 8px; }
.revenue-leak-calculator-wrapper ::-webkit-scrollbar-track { background: #f1f5f9; }
.revenue-leak-calculator-wrapper ::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }
.revenue-leak-calculator-wrapper .glass-card {
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
background: rgba(255,255,255,0.98);
}
.revenue-leak-calculator-wrapper input[type=number]::-webkit-inner-spin-button,
.revenue-leak-calculator-wrapper input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.revenue-leak-calculator-wrapper input[type=range] {
-webkit-appearance: none;
background: transparent;
}
.revenue-leak-calculator-wrapper input[type=range]::-webkit-slider-thumb {
-webkit-appearance:none;
height:20px;
width:20px;
border-radius:50%;
background:#0EA5E9;
cursor:pointer;
margin-top:-8px;
box-shadow:0 2px 6px rgba(14,165,233,0.3);
}
.revenue-leak-calculator-wrapper input[type=range]::-webkit-slider-runnable-track {
width:100%;
height:6px;
cursor:pointer;
background:#EE8F0;
border-radius:4px;
}
.revenue-leak-calculator-wrapper input[type=checkbox] {
accent-color:#0B1120;
cursor:pointer;
}
/* Modal overlay */
.revenue-leak-calculator-wrapper .pcp-modal-overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(11,17,32,0.65);
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
z-index: 9999;
align-items: center;
justify-content: center;
padding: 1rem;
}
.revenue-leak-calculator-wrapper .pcp-modal-overlay.pcp-open {
display: flex;
}
.revenue-leak-calculator-wrapper .pcp-modal-content {
background: #fff;
border-radius: 1.25rem;
padding: 2rem;
max-width: 560px;
width: 100%;
box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);
position: relative;
transform: scale(0.95);
opacity: 0;
transition: transform 0.25s ease, opacity 0.25s ease;
max-height: 90vh;
overflow-y: auto;
}
.revenue-leak-calculator-wrapper .pcp-modal-overlay.pcp-open .pcp-modal-content {
transform: scale(1);
opacity: 1;
}
/* Privacy sub-panel */
.revenue-leak-calculator-wrapper .pcp-privacy-panel {
display: none;
position: absolute;
inset: 0;
background: #fff;
border-radius: 1.25rem;
padding: 1.75rem;
flex-direction: column;
overflow: hidden;
z-index: 10;
}
.revenue-leak-calculator-wrapper .pcp-privacy-panel.pcp-open {
display: flex;
}
.revenue-leak-calculator-wrapper .pcp-privacy-scroll {
overflow-y: auto;
flex: 1;
max-height: 52vh;
padding-right: 4px;
}
/* Quiz selection */
.revenue-leak-calculator-wrapper .quiz-option.is-selected {
background: #EFF6FF !important;
border-color: #0EA5E9 !important;
color: #0EA5E9 !important;
font-weight: 800 !important;
}</style>
<section class="py-12 md:py-20 bg-slate-50">
<div class="max-w-[1000px] mx-auto px-4 sm:px-6">
<div class="text-center mb-12">
<h2 class="text-[36px] md:text-[44px] font-extrabold text-slate-900 mb-3 tracking-tight">Calculate Your Exact Revenue Leak</h2>
<p class="text-[16px] md:text-[18px] text-slate-600 font-medium max-w-2xl mx-auto">
<span class="text-sky-500">Net Profit & Capacity Adjusted</span>
</p>
</div>
<div class="glass-card p-6 md:p-10 rounded-[24px] shadow-xl border border-white/60 relative overflow-hidden">
<div class="flex justify-center mb-10">
<div class="bg-slate-100 p-1.5 rounded-xl inline-flex shadow-inner border border-slate-200/50">
<button type="button" class="btn-aesthetics px-6 md:px-8 py-2.5 rounded-lg text-[14px]
font-bold text-slate-900 bg-white shadow-sm ring-1
ring-slate-200 transition-all">Aesthetics Clinic</button>
<button type="button" class="btn-dental px-6 md:px-8 py-2.5 rounded-lg text-[14px]
font-medium text-slate-600 hover:text-slate-900
hover:bg-slate-200/50 transition-all">Dental Practice</button>
</div>
</div>
<div class="grid md:grid-cols-2 gap-x-12 gap-y-10">
<div class="space-y-8">
<div class="flex items-center gap-2 mb-2 border-b border-slate-100 pb-3">
<iconify-icon icon="ph:funnel-bold" class="text-sky-500 text-lg"></iconify-icon>
<h3 class="text-[12px] font-bold uppercase text-slate-600 tracking-widest">Funnel Inputs</h3>
</div>
<div>
<label class="block text-[14px] font-semibold text-slate-900 mb-2">Monthly Enquiries (New Leads)</label>
<input type="number" class="input-enquiries w-full bg-white border border-slate-200
rounded-xl px-4 py-3.5 text-slate-900 text-[16px] font-bold
focus:outline-none focus:border-sky-500 focus:ring-2
focus:ring-sky-500/20 transition-all" value="160" min="1" />
</div>
<div>
<div class="flex justify-between mb-3 items-end">
<label class="block text-[14px] font-semibold text-slate-900">Conversion Rate</label>
<span class="display-rate text-[20px] font-bold text-sky-500">25%</span>
</div>
<input type="range" class="input-rate w-full mb-3" min="1" max="99" value="25" />
<div class="flex items-start justify-between flex-wrap gap-2">
<div class="benchmark-badge inline-flex items-center gap-1.5 px-3 py-1.5
rounded-lg bg-emerald-50 text-emerald-700 border
border-emerald-100 transition-colors duration-300">
<iconify-icon icon="ph:trophy-bold" class="text-sm"></iconify-icon>
<span class="text-[11px] font-bold">Industry Standard</span>
</div>
<span class="text-[11px] text-slate-400 font-medium mt-1.5">Based on segment data</span>
</div>
</div>
<div>
<label class="block text-[14px] font-semibold text-slate-900 mb-2">Avg. Treatment Value</label>
<div class="relative">
<span class="absolute left-4 top-1/2 -translate-y-1/2 text-slate-400 font-bold">£</span>
<input type="number" class="input-value w-full bg-white border border-slate-200
rounded-xl pl-9 pr-4 py-3.5 text-slate-900 text-[16px]
font-bold focus:outline-none focus:border-sky-500
focus:ring-2 focus:ring-sky-500/20 transition-all" value="1500" min="1" />
</div>
</div>
</div>
<div class="space-y-8">
<div class="flex items-center gap-2 mb-2 border-b border-slate-100 pb-3">
<iconify-icon icon="ph:scales-bold" class="text-sky-500 text-lg"></iconify-icon>
<h3 class="text-[12px] font-bold uppercase text-slate-600 tracking-widest">Economic Constraints</h3>
</div>
<div>
<label class="flex justify-between items-center mb-2">
<span class="text-[14px] font-semibold text-slate-900">Profit Margin (Contribution)</span>
<span class="text-[11px] font-medium text-slate-400 italic">Net after COGS/Ads</span>
</label>
<div class="relative">
<input type="number" class="input-margin w-full bg-white border border-slate-200
rounded-xl px-4 py-3.5 text-slate-900 text-[16px] font-bold
focus:outline-none focus:border-sky-500 focus:ring-2
focus:ring-sky-500/20 transition-all" value="30" min="1" max="99" />
<span class="absolute right-4 top-1/2 -translate-y-1/2 text-slate-400 font-bold">%</span>
</div>
</div>
<div>
<label class="block text-[14px] font-semibold text-slate-900 mb-2">Spare Capacity (Slots/Month)</label>
<input type="number" class="input-capacity w-full bg-white border border-slate-200
rounded-xl px-4 py-3.5 text-slate-900 text-[16px] font-bold
focus:outline-none focus:border-sky-500 focus:ring-2
focus:ring-sky-500/20 transition-all" value="25" min="0" />
<p class="text-[11px] text-slate-400 mt-2">Maximum additional patients you can handle.</p>
</div>
<div>
<label class="block text-[14px] font-semibold text-slate-900 mb-2">Recovery Potential</label>
<div class="flex bg-slate-100 rounded-lg p-1">
<button type="button" class="recovery-btn flex-1 py-2 rounded text-[12px] font-medium
text-slate-600 hover:bg-white hover:shadow-sm transition-all
border border-transparent" data-val="0.2">
<br />
<span class="text-[10px] opacity-70">20%</span>
</button>
<button type="button" class="recovery-btn flex-1 py-2 rounded text-[12px] font-bold
text-white bg-slate-900 shadow-sm transition-all transform
scale-105" data-val="0.35">
<br />
<span class="text-[10px] opacity-70">35%</span>
</button>
<button type="button" class="recovery-btn flex-1 py-2 rounded text-[12px] font-medium
text-slate-600 hover:bg-white hover:shadow-sm transition-all
border border-transparent" data-val="0.5">
<br />
<span class="text-[10px] opacity-70">50%</span>
</button>
</div>
</div>
<div class="pt-2">
<button type="button" class="btn-calculate group relative w-full overflow-hidden
rounded-xl bg-slate-900 py-4 text-white shadow-lg
shadow-slate-900/20 transition-all hover:bg-slate-800
hover:shadow-xl hover:-translate-y-0.5">
<span class="relative flex items-center justify-center gap-2 text-[16px] font-bold">
<iconify-icon icon="ph:arrow-right-bold" class="group-hover:translate-x-1 transition-transform"></iconify-icon>
</span>
</button>
</div>
</div>
</div>
<div class="results-panel mt-12 transition-all duration-700 ease-out
opacity-0 translate-y-8 max-h-0 overflow-hidden
pointer-events-none border-t border-slate-100 pt-10">
<div class="flex justify-center mb-10">
<div class="bg-white p-1 rounded-full inline-flex items-center
cursor-pointer select-none border border-slate-200 shadow-sm
toggle-wrapper">
<span class="label-gross px-5 py-2 rounded-full text-[13px] font-semibold text-slate-600 transition-all">Gross Revenue</span>
<div class="w-14 h-7 bg-slate-200 rounded-full mx-1 relative transition-colors duration-300 toggle-track">
<div class="absolute left-1 top-1 bg-white w-5 h-5 rounded-full
shadow-md transition-all duration-300 transform toggle-knob"></div>
</div>
<span class="label-net px-5 py-2 rounded-full text-[13px] font-bold
text-slate-900 bg-slate-50 shadow-inner transition-all">Net Profit (Realizable)</span>
</div>
</div>
<div class="quiz-section mb-8">
<div class="quiz-prompt bg-blue-50 border border-blue-100 rounded-xl p-5
flex flex-col sm:flex-row sm:items-center sm:justify-between
gap-4">
<div>
<h4 class="text-[15px] font-bold text-slate-900">Refine your diagnosis?</h4>
<p class="text-[13px] text-slate-600">Answer 3 quick questions to personalise your Leak Map.</p>
</div>
<button type="button" class="btn-start-quiz px-4 py-2 bg-white border border-blue-200
text-sky-500 font-bold text-[13px] rounded-lg
hover:bg-blue-50 transition-colors shadow-sm">Start 30s Diagnostic</button>
</div>
<div class="quiz-panel hidden bg-white border border-slate-200 rounded-xl p-6 relative">
<button type="button" class="btn-quiz-close absolute top-4 right-4 text-slate-300 hover:text-slate-900 transition-colors">
<iconify-icon icon="ph:x-bold"></iconify-icon>
</button>
<div class="quiz-container"></div>
</div>
</div>
<div class="bg-white rounded-2xl border border-slate-200 p-6 md:p-8 shadow-sm mb-8">
<div class="mb-6">
<h3 class="text-[18px] font-bold text-slate-900">Your Leak Map</h3>
<p class="text-[14px] text-slate-600 mt-1 leading-relaxed">
<span class="leak-source italic text-slate-400">Based on industry heuristics.</span>
</p>
</div>
<div class="flex h-3 rounded-full overflow-hidden bg-slate-100 mb-8">
<div class="bar-q bg-emerald-500 h-full transition-all duration-1000 ease-out w-1/3"></div>
<div class="bar-e bg-teal-500 h-full transition-all duration-1000 ease-out w-1/3"></div>
<div class="bar-n bg-orange-500 h-full transition-all duration-1000 ease-out w-1/3"></div>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-y-6 md:gap-x-8">
<div class="relative pl-5 border-l-[3px] border-emerald-100 hover:border-emerald-300 transition-colors group">
<div class="absolute -left-[7px] top-1 w-3 h-3 rounded-full bg-emerald-500 ring-4 ring-white"></div>
<div class="text-[14px] font-bold text-slate-900 mb-1 group-hover:text-emerald-700 transition-colors">Qualification & Fit</div>
<div class="val-q text-[17px] font-bold text-emerald-600 mb-2 tracking-tight">£0 / month</div>
<p class="text-[13px] text-slate-600 leading-relaxed">Enquiries that never become viable opportunities.</p>
</div>
<div class="relative pl-5 border-l-[3px] border-teal-100 hover:border-teal-300 transition-colors group">
<div class="absolute -left-[7px] top-1 w-3 h-3 rounded-full bg-teal-500 ring-4 ring-white"></div>
<div class="text-[14px] font-bold text-slate-900 mb-1 group-hover:text-teal-700 transition-colors">Engagement & Follow-up</div>
<div class="val-e text-[17px] font-bold text-teal-600 mb-2 tracking-tight">£0 / month</div>
<p class="text-[13px] text-slate-600 leading-relaxed">Leak caused by slow response and inconsistent follow-up.</p>
</div>
<div class="relative pl-5 border-l-[3px] border-orange-100 hover:border-orange-300 transition-colors group">
<div class="absolute -left-[7px] top-1 w-3 h-3 rounded-full bg-orange-500 ring-4 ring-white"></div>
<div class="text-[14px] font-bold text-slate-900 mb-1 group-hover:text-orange-700 transition-colors">No-shows & Drop-off</div>
<div class="val-n text-[17px] font-bold text-orange-600 mb-2 tracking-tight">£0 / month</div>
<p class="text-[13px] text-slate-600 leading-relaxed">Leak caused by appointment drop-off and missed confirmations.</p>
</div>
</div>
<div class="mt-8 pt-6 border-t border-slate-100 text-center md:text-left
flex flex-col md:flex-row items-center gap-3">
<div class="text-[14px] text-slate-600">
<span class="result-recoverable-inline text-[16px] font-bold text-slate-900">~£0/month</span>
</div>
<div class="capacity-warning hidden inline-flex items-center gap-1.5
px-3 py-1 bg-red-50 text-red-600 text-[11px] font-bold
rounded-full border border-red-100">
<iconify-icon icon="ph:warning-bold"></iconify-icon>
</div>
</div>
</div>
<div class="bg-slate-50 rounded-2xl border border-slate-200 p-6 md:p-8 shadow-sm mb-8">
<div class="mb-6">
<h3 class="text-[18px] font-bold text-slate-900">Your Fastest Wins</h3>
<p class="text-[14px] text-slate-600 mt-1">
<span class="font-semibold text-slate-900">biggest leakage points</span>
</p>
</div>
<div class="wins-container grid gap-4"></div>
</div>
<button type="button" class="btn-get-report group relative w-full overflow-hidden
rounded-xl bg-emerald-600 py-4 text-white shadow-lg
shadow-emerald-600/20 transition-all hover:bg-emerald-700
hover:shadow-emerald-600/30 hover:-translate-y-0.5">
<span class="relative flex items-center justify-center gap-2 text-[16px] font-bold">
<iconify-icon icon="ph:arrow-right-bold" class="group-hover:translate-x-1 transition-transform"></iconify-icon>
</span>
</button>
</div>
</div>
</div>
</section>
<div class="pcp-modal-overlay">
<div class="pcp-modal-content">
<div class="pcp-state-form">
<div class="mb-6">
<h3 class="text-[22px] font-extrabold text-slate-900 mb-1">Get your personalised leak report</h3>
<p class="text-[14px] text-slate-600">We'll email your full breakdown — no pitch, just the numbers.</p>
</div>
<div class="space-y-4">
<div>
<label class="text-[13px] font-bold text-slate-900 mb-1.5 block">
<span class="text-red-500">*</span>
</label>
<input type="email" class="pcp-email w-full border border-slate-200 rounded-xl px-4
py-3 text-[14px] focus:outline-none focus:border-sky-500
focus:ring-1 focus:ring-sky-500 transition-all" placeholder="name@clinic.com" />
<div class="pcp-email-error text-[11px] text-red-500 mt-1 hidden font-medium">Please enter a valid email address.</div>
</div>
<div>
<label class="text-[13px] font-bold text-slate-900 mb-1.5 block">
<span class="text-[11px] font-normal text-slate-400">(optional)</span>
</label>
<input type="text" class="pcp-clinic w-full border border-slate-200 rounded-xl px-4
py-3 text-[14px] focus:outline-none focus:border-sky-500
focus:ring-1 focus:ring-sky-500 transition-all" placeholder="Your Practice" />
</div>
<div class="pt-1">
<div class="flex items-start gap-3">
<input type="checkbox" class="pcp-privacy-check mt-0.5 w-4 h-4 rounded border-slate-300 flex-shrink-0" />
<label class="text-[12px] text-slate-600 leading-snug">
<button type="button" class="pcp-open-privacy underline text-slate-900 font-semibold hover:text-sky-500 transition-colors ml-0.5">Privacy Policy</button>
<span class="text-red-500 font-bold ml-0.5">*</span>
</label>
</div>
<div class="pcp-privacy-error text-[11px] text-red-500 mt-1.5 ml-7 hidden font-medium">Please accept the privacy policy to continue.</div>
</div>
<div class="flex items-start gap-3">
<input type="checkbox" class="pcp-marketing-check mt-0.5 w-4 h-4 rounded border-slate-300 flex-shrink-0" />
<label class="text-[12px] text-slate-600 leading-snug">
<span class="text-slate-400">(optional)</span>
</label>
</div>
</div>
<div class="flex gap-3 mt-8">
<button type="button" class="pcp-btn-cancel flex-1 py-3 text-[14px] font-bold
text-slate-600 bg-slate-50 hover:bg-slate-100 rounded-xl
transition-colors border border-slate-200">Cancel</button>
<button type="button" class="pcp-btn-submit flex-1 py-3 bg-slate-900 text-white
rounded-xl text-[14px] font-bold hover:bg-slate-800
transition-colors shadow-lg shadow-slate-900/10">Send my report</button>
</div>
<div class="pcp-submit-error text-[12px] text-red-600 mt-4 hidden font-semibold text-center"></div>
</div>
<div class="pcp-state-success hidden text-center py-4">
<div class="w-16 h-16 bg-emerald-500 rounded-full flex items-center
justify-center mx-auto mb-5 ring-8 ring-emerald-100">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
</div>
<h3 class="text-[20px] font-extrabold text-slate-900 mb-2">Request received — thank you</h3>
<p class="text-[14px] text-slate-600 mb-8 px-4 leading-relaxed">We'll be in touch shortly with your personalised breakdown.</p>
<div class="grid gap-3">
<button type="button" class="pcp-btn-see-pricing w-full py-3 bg-slate-900 text-white
rounded-xl text-[14px] font-bold hover:bg-slate-800
transition-colors text-center block">See pricing</button>
<a href="/" class="w-full py-3 border border-slate-200 rounded-xl text-[14px]
font-bold text-slate-600 hover:bg-slate-50 transition-colors
text-center block">Back to homepage</a>
<button type="button" class="pcp-btn-close-success w-full py-2.5 text-[12px]
font-semibold text-slate-400 hover:text-slate-900
transition-colors">Close</button>
</div>
</div>
<div class="pcp-privacy-panel">
<div class="flex items-center justify-between mb-4 flex-shrink-0">
<h4 class="text-[17px] font-extrabold text-slate-900">Privacy Policy</h4>
<button type="button" class="pcp-close-privacy text-slate-300 hover:text-slate-900 transition-colors p-1">
<iconify-icon icon="ph:x-bold" class="text-lg"></iconify-icon>
</button>
</div>
<div class="pcp-privacy-scroll text-[12px] text-slate-600 leading-relaxed pr-2">
<p class="mb-3">
<span class="font-bold text-slate-900">Peak Clarity Point Ltd</span>
</p>
<div class="mb-3">
<div class="font-bold text-slate-900 mb-1">What we collect</div>
<ul class="list-disc pl-5 space-y-1">
<li>Email address and clinic name</li>
<li>Calculator inputs and results (your economic diagnosis data)</li>
<li>Optional marketing consent choice</li>
</ul>
</div>
<div class="mb-3">
<div class="font-bold text-slate-900 mb-1">Why we use it</div>
<ul class="list-disc pl-5 space-y-1">
<li>Respond to enquiries and arrange diagnostic calls</li>
<li>Send relevant service information related to your request</li>
<li>Maintain website functionality and improve experience</li>
</ul>
</div>
<div class="mb-3">
<div class="font-bold text-slate-900 mb-1">Retention</div>
<p>
<span class="font-semibold text-slate-900">24 months</span>
</p>
</div>
<div class="mb-3">
<div class="font-bold text-slate-900 mb-1">Your rights</div>
<p>You can access, correct, delete, restrict, port your data, or withdraw consent at any time. We respond within one month.</p>
</div>
<div class="mb-4">
<div class="font-bold text-slate-900 mb-1">Contact</div>
<p>
<span class="font-semibold text-slate-900">info@peakclaritypoint.com</span>
<br />
</p>
</div>
<a href="https://peakclaritypoint.com/privacy-policy" target="_blank" rel="noopener" class="flex items-center justify-center gap-2 w-full py-2.5 border
border-slate-200 rounded-xl text-[13px] font-bold
text-slate-900 hover:bg-slate-50 transition-colors mb-2">
<iconify-icon icon="ph:arrow-square-out-bold" class="text-sm"></iconify-icon>
</a>
</div>
<div class="flex-shrink-0 mt-4">
<button type="button" class="pcp-accept-privacy w-full py-3 bg-slate-900 text-white
rounded-xl text-[14px] font-bold hover:bg-slate-800
transition-colors">Got it — close</button>
</div>
</div>
</div>
</div>
<script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js"></script>
<script>(function () {
const wrapper = document.currentScript.previousElementSibling;
while (wrapper && !wrapper.classList.contains('revenue-leak-calculator-wrapper')) {
wrapper = wrapper.previousElementSibling;
}
if (!wrapper) return;
const PRESETS = {
aesthetics: { enquiries: 160, rate: 25, value: 1500, margin: 30, capacity: 25 },
dental: { enquiries: 200, rate: 35, value: 2200, margin: 35, capacity: 20 }
};
const BENCHMARKS = {
dental: { p20: 30, avg: 45, top: 65 },
aesthetics: { p20: 20, avg: 35, top: 50 }
};
const WIN_STRATEGIES = {
e: { id:"engagement", color:"border-teal-500", title:"Speed-to-lead + follow-up sequence", desc:"Automate the first-touch + structured follow-up so enquiries don't go cold.", action:"Fixes Engagement Leak" },
q: { id:"qualification", color:"border-emerald-500", title:"Pre-qualification + message clarity", desc:"Filter and route enquiries to the right pathway to stop wasting time on low-fit leads.", action:"Fixes Qualification Leak" },
n: { id:"noshow", color:"border-orange-500", title:"Confirmation workflows + deposit systems", desc:"Reduce drop-off spikes using multi-channel reminders and frictionless deposits.", action:"Fixes No-Show Leak" }
};
const QUIZ_DATA = [
{ id:"responseTime", q:"How fast do you typically reply to new leads?", opts:[{ l:"< 15 mins", impact:{ e:0 } }, { l:"Same Day", impact:{ e:0.1 } }, { l:"Next Day+", impact:{ e:0.2 } }] },
{ id:"followUp", q:"How many times do you follow up if they don't answer?",opts:[{ l:"6+ times", impact:{ e:0 } }, { l:"2-5 times", impact:{ e:0.1 } }, { l:"0-1 times", impact:{ e:0.25 } }] },
{ id:"noShow", q:"What does your no-show rate feel like?", opts:[{ l:"Low (<5%)", impact:{ n:0 } }, { l:"Avg (10-15%)",impact:{ n:0.1 } }, { l:"High (20%+)",impact:{ n:0.2 } }] }
];
let activePreset = "aesthetics";
let isNetView = false;
let recoveryFactor = 0.35;
let quizWeights = null;
let quizAnswers = {};
let lastMetrics = null;
const $ = sel => wrapper.querySelector(sel);
const isValidEmail = e => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e);
const fmtMoney = n => "£" + Math.round(n).toLocaleString("en-GB");
const els = {
btnAesth:$(".btn-aesthetics"), btnDent:$(".btn-dental"),
inEnq:$(".input-enquiries"), inRate:$(".input-rate"), inVal:$(".input-value"),
inMarg:$(".input-margin"), inCap:$(".input-capacity"),
dispRate:$(".display-rate"), badge:$(".benchmark-badge"),
recBtns:wrapper.querySelectorAll(".recovery-btn"),
btnCalc:$(".btn-calculate"),
results:$(".results-panel"),
toggleWrapper:$(".toggle-wrapper"), toggleTrack:$(".toggle-track"), toggleKnob:$(".toggle-knob"),
labelGross:$(".label-gross"), labelNet:$(".label-net"),
barQ:$(".bar-q"), barE:$(".bar-e"), barN:$(".bar-n"),
valQ:$(".val-q"), valE:$(".val-e"), valN:$(".val-n"),
resInline:$(".result-recoverable-inline"), capWarn:$(".capacity-warning"),
winsContainer:$(".wins-container"), leakSource:$(".leak-source"),
quizPrompt:$(".quiz-prompt"), quizPanel:$(".quiz-panel"),
quizContainer:$(".quiz-container"),
btnStartQuiz:$(".btn-start-quiz"), btnQuizClose:$(".btn-quiz-close"),
btnContinue:$(".btn-get-report"),
overlay:$(".pcp-modal-overlay"), modalContent:$(".pcp-modal-content"),
stateForm:$(".pcp-state-form"), stateSuccess:$(".pcp-state-success"),
inEmail:$(".pcp-email"), inClinic:$(".pcp-clinic"),
inPrivacyCheck:$(".pcp-privacy-check"), inMarketingCheck:$(".pcp-marketing-check"),
emailError:$(".pcp-email-error"), privacyError:$(".pcp-privacy-error"), submitError:$(".pcp-submit-error"),
btnCancel:$(".pcp-btn-cancel"), btnSubmit:$(".pcp-btn-submit"),
btnCloseSuccess:$(".pcp-btn-close-success"),
privacyPanel:$(".pcp-privacy-panel"),
btnOpenPrivacy:$(".pcp-open-privacy"),
btnClosePrivacy:$(".pcp-close-privacy"),
btnAcceptPrivacy:$(".pcp-accept-privacy"),
};
function calculate() {
const enq = parseFloat(els.inEnq.value) || 0;
const rate = parseFloat(els.inRate.value) || 0;
const val = parseFloat(els.inVal.value) || 0;
const margin = parseFloat(els.inMarg.value) || 0;
let capacity = parseFloat(els.inCap.value);
if (isNaN(capacity) || capacity < 0) capacity = 50;
const converted = enq * (rate / 100);
const lost = enq - converted;
let recoveredLeads = lost * recoveryFactor;
const isCapped = recoveredLeads > capacity;
if (isCapped) recoveredLeads = capacity;
const grossMonthly = recoveredLeads * val;
const netMonthly = grossMonthly * (margin / 100);
const displayMonthly = isNetView ? netMonthly : grossMonthly;
let w = { q:0.30, e:0.45, n:0.25 };
if (quizWeights) {
const total = quizWeights.q + quizWeights.e + quizWeights.n;
w = { q:quizWeights.q/total, e:quizWeights.e/total, n:quizWeights.n/total };
}
return { enq, rate, val, margin, capacity, displayMonthly, isCapped,
leakQ: displayMonthly * w.q,
leakE: displayMonthly * w.e,
leakN: displayMonthly * w.n,
weights: w };
}
function renderWins(m) {
const leaks = [
{ id:"q", val:m.leakQ, strategy:WIN_STRATEGIES.q },
{ id:"e", val:m.leakE, strategy:WIN_STRATEGIES.e },
{ id:"n", val:m.leakN, strategy:WIN_STRATEGIES.n }
].sort((a,b) => b.val - a.val);
els.winsContainer.innerHTML = leaks.slice(0,2).map((item, idx) => {
const s = item.strategy;
return `<div class="bg-white p-5 rounded-xl border-l-[4px] ${s.color} shadow-sm transition-all hover:shadow-md">
<div class="flex justify-between items-start mb-1">
<div class="text-[14px] font-bold text-slate-900">${s.title}
<span class="block text-[11px] font-normal text-slate-600 mt-0.5">Recover up to <span class="font-bold text-slate-900">${fmtMoney(item.val)}/mo</span></span>
</div>
${idx===0?'<span class="bg-slate-900 text-white text-[10px] px-2 py-0.5 rounded font-bold uppercase tracking-wide">High Impact</span>':''}
</div>
<div class="text-[13px] text-slate-600 mb-3 leading-relaxed mt-2">${s.desc}</div>
<div class="flex items-center gap-2">
<iconify-icon icon="ph:check-circle-fill" class="text-emerald-600 text-sm"></iconify-icon>
<span class="text-[12px] font-semibold text-slate-900">${s.action}</span>
</div>
</div>`;
}).join("");
}
function render(scroll=true) {
lastMetrics = calculate();
const m = lastMetrics;
els.valQ.textContent = fmtMoney(m.leakQ) + " / month";
els.valE.textContent = fmtMoney(m.leakE) + " / month";
els.valN.textContent = fmtMoney(m.leakN) + " / month";
els.resInline.textContent = "~" + fmtMoney(m.displayMonthly) + "/month";
els.barQ.style.width = (m.weights.q * 100) + "%";
els.barE.style.width = (m.weights.e * 100) + "%";
els.barN.style.width = (m.weights.n * 100) + "%";
els.capWarn.classList.toggle("hidden", !m.isCapped);
renderWins(m);
els.results.classList.remove("opacity-0","translate-y-8","max-h-0","pointer-events-none");
els.results.classList.add("opacity-100","translate-y-0","max-h-[2200px]","pointer-events-auto");
if (scroll) setTimeout(() => els.results.scrollIntoView({ behavior:"smooth", block:"start" }), 100);
}
function renderQuiz() {
els.quizContainer.innerHTML = QUIZ_DATA.map((q,i) => `
<div class="mb-5 last:mb-0" data-qid="${q.id}">
<p class="text-[14px] font-semibold text-slate-900 mb-2">${i+1}. ${q.q}</p>
<div class="grid grid-cols-3 gap-2">
${q.opts.map((opt,oi) => `<button type="button" class="quiz-option px-2 py-2 border border-slate-200 rounded text-[12px] text-slate-600 hover:border-sky-500 hover:text-sky-500 transition-all" data-qid="${q.id}" data-oid="${oi}">${opt.l}</button>`).join("")}
</div>
</div>`).join("");
els.quizContainer.querySelectorAll(".quiz-option").forEach(btn => {
btn.addEventListener("click", function() {
const qId = this.getAttribute("data-qid");
const oIdx = parseInt(this.getAttribute("data-oid"), 10);
els.quizContainer.querySelectorAll(`.quiz-option[data-qid="${qId}"]`).forEach(b => b.classList.remove("is-selected"));
this.classList.add("is-selected");
quizAnswers[qId] = QUIZ_DATA.find(q => q.id === qId).opts[oIdx];
if (Object.keys(quizAnswers).length === QUIZ_DATA.length) {
calculateQuizWeights();
setTimeout(() => {
els.quizPanel.classList.add("hidden");
els.quizPrompt.classList.remove("hidden");
const h4 = els.quizPrompt.querySelector("h4");
h4.textContent = "Diagnosis Applied ✓";
h4.classList.add("text-emerald-600");
els.leakSource.scrollIntoView({ behavior:"smooth", block:"center" });
}, 450);
}
});
});
}
function calculateQuizWeights() {
let base = { q:0.25, e:0.35, n:0.20 };
Object.values(quizAnswers).forEach(ans => {
if (ans.impact.e) base.e += ans.impact.e;
if (ans.impact.q) base.q += ans.impact.q;
if (ans.impact.n) base.n += ans.impact.n;
});
quizWeights = base;
els.leakSource.textContent = "Personalised based on your diagnosis.";
render(false);
}
function updateBenchmark() {
const rate = parseFloat(els.inRate.value);
const b = BENCHMARKS[activePreset];
let text, bg, color, border;
if (rate < b.p20) { text="Needs Attention"; bg="bg-orange-50"; color="text-orange-700"; border="border-orange-100"; }
else if (rate < b.avg) { text="Below Average"; bg="bg-orange-50"; color="text-orange-600"; border="border-orange-100"; }
else if (rate < b.top) { text="Industry Standard"; bg="bg-blue-50"; color="text-blue-700"; border="border-blue-100"; }
else { text="Elite Performance"; bg="bg-emerald-50"; color="text-emerald-700";border="border-emerald-100";}
els.badge.className = `inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border transition-colors duration-300 ${bg} ${color} ${border}`;
els.badge.querySelector("span").textContent = text;
els.dispRate.textContent = rate + "%";
}
function toggleNetView() {
isNetView = !isNetView;
if (isNetView) {
els.toggleTrack.classList.replace("bg-slate-200","bg-emerald-500");
els.toggleKnob.style.transform = "translateX(28px)";
els.labelNet.classList.add("text-slate-900","bg-white","shadow-sm");
els.labelNet.classList.remove("text-slate-600","bg-slate-50","shadow-inner");
els.labelGross.classList.add("text-slate-600");
els.labelGross.classList.remove("text-slate-900","bg-white","shadow-sm","font-bold");
} else {
els.toggleTrack.classList.replace("bg-emerald-500","bg-slate-200");
els.toggleKnob.style.transform = "translateX(0px)";
els.labelGross.classList.add("text-slate-900","bg-white","shadow-sm","font-bold");
els.labelGross.classList.remove("text-slate-600");
els.labelNet.classList.add("text-slate-600","bg-slate-50","shadow-inner");
els.labelNet.classList.remove("text-slate-900","bg-white","shadow-sm");
}
if (lastMetrics) render(false);
}
function setRecovery(val, btn) {
recoveryFactor = parseFloat(val);
els.recBtns.forEach(b => b.className = "recovery-btn flex-1 py-2 rounded text-[12px] font-medium text-slate-600 hover:bg-white hover:shadow-sm transition-all border border-transparent");
btn.className = "recovery-btn flex-1 py-2 rounded text-[12px] font-bold text-white bg-slate-900 shadow-sm transition-all transform scale-105";
if (lastMetrics) render(false);
}
function applyPreset(type) {
activePreset = type;
const p = PRESETS[type];
els.inEnq.value = p.enquiries;
els.inRate.value = p.rate;
els.inVal.value = p.value;
els.inMarg.value = p.margin;
els.inCap.value = p.capacity;
if (type === "aesthetics") {
els.btnAesth.className = "px-6 md:px-8 py-2.5 rounded-lg text-[14px] font-bold text-slate-900 bg-white shadow-sm ring-1 ring-slate-200 transition-all";
els.btnDent.className = "px-6 md:px-8 py-2.5 rounded-lg text-[14px] font-medium text-slate-600 hover:text-slate-900 hover:bg-slate-200/50 transition-all";
} else {
els.btnDent.className = "px-6 md:px-8 py-2.5 rounded-lg text-[14px] font-bold text-slate-900 bg-white shadow-sm ring-1 ring-slate-200 transition-all";
els.btnAesth.className = "px-6 md:px-8 py-2.5 rounded-lg text-[14px] font-medium text-slate-600 hover:text-slate-900 hover:bg-slate-200/50 transition-all";
}
quizWeights = null;
quizAnswers = {};
els.leakSource.textContent = "Based on industry heuristics.";
const h4 = els.quizPrompt.querySelector("h4");
h4.textContent = "Refine your diagnosis?";
h4.classList.remove("text-emerald-600");
els.quizPanel.classList.add("hidden");
els.quizPrompt.classList.remove("hidden");
updateBenchmark();
els.results.classList.add("opacity-0","pointer-events-none");
}
function openModal() {
if (!lastMetrics) render(false);
els.stateForm.classList.remove("hidden");
els.stateSuccess.classList.add("hidden");
els.privacyPanel.classList.remove("pcp-open");
els.inEmail.value = "";
els.inClinic.value = "";
els.inPrivacyCheck.checked = false;
els.inMarketingCheck.checked = false;
els.emailError.classList.add("hidden");
els.privacyError.classList.add("hidden");
els.submitError.classList.add("hidden");
els.btnSubmit.disabled = false;
els.btnSubmit.textContent = "Send my report";
els.overlay.classList.add("pcp-open");
document.body.style.overflow = "hidden";
setTimeout(() => els.inEmail.focus(), 300);
}
function closeModal() {
els.overlay.classList.remove("pcp-open");
document.body.style.overflow = "";
}
function openPrivacy() {
els.privacyPanel.classList.add("pcp-open");
}
function closePrivacy() {
els.privacyPanel.classList.remove("pcp-open");
}
function showSuccess() {
els.stateForm.classList.add("hidden");
els.stateSuccess.classList.remove("hidden");
els.privacyPanel.classList.remove("pcp-open");
els.modalContent.scrollTop = 0;
}
async function submitReport() {
const email = els.inEmail.value.trim();
const clinic = els.inClinic.value.trim() || "My Clinic";
const privacyConsent = els.inPrivacyCheck.checked;
const marketingOk = els.inMarketingCheck.checked;
let valid = true;
if (!isValidEmail(email)) {
els.emailError.classList.remove("hidden");
valid = false;
} else {
els.emailError.classList.add("hidden");
}
if (!privacyConsent) {
els.privacyError.classList.remove("hidden");
valid = false;
} else {
els.privacyError.classList.add("hidden");
}
if (!valid) return;
els.submitError.classList.add("hidden");
els.btnSubmit.disabled = true;
els.btnSubmit.textContent = "Sending…";
const m = lastMetrics || calculate();
let quizSummary = "Not taken";
if (Object.keys(quizAnswers).length > 0) {
quizSummary = Object.values(quizAnswers).map(a => a.l).join(", ");
}
const payload = {
email, clinic, preset: activePreset,
recoveryFactor, isNetView, marketingConsent: marketingOk, privacyConsent,
quizSummary,
inputs: { enquiries:m.enq, conversionRate:m.rate, avgValue:m.val, profitMargin:m.margin, capacity:m.capacity },
results: { totalMonthly:Math.round(m.displayMonthly), qualification:Math.round(m.leakQ), engagement:Math.round(m.leakE), noshows:Math.round(m.leakN), capacityCapped:!!m.isCapped }
};
const host = (location.hostname || "").toLowerCase();
const isProduction = host.includes("netlify.app") || host.includes("peakclaritypoint.com");
if (!isProduction) {
setTimeout(() => showSuccess(), 600);
return;
}
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 9000);
try {
const res = await fetch("/.netlify/functions/send-economic-report", {
method:"POST",
headers:{ "Content-Type":"application/json" },
body: JSON.stringify(payload),
signal: controller.signal
});
clearTimeout(timeout);
if (!res.ok) { const t = await res.text(); throw new Error(t || "Request failed"); }
showSuccess();
} catch (err) {
clearTimeout(timeout);
els.submitError.textContent = "Couldn't send right now — please try again.";
els.submitError.classList.remove("hidden");
els.btnSubmit.disabled = false;
els.btnSubmit.textContent = "Send my report";
}
}
els.btnAesth.addEventListener("click", () => applyPreset("aesthetics"));
els.btnDent.addEventListener("click", () => applyPreset("dental"));
els.inRate.addEventListener("input", updateBenchmark);
els.btnCalc.addEventListener("click", () => render(true));
els.toggleWrapper.addEventListener("click", toggleNetView);
els.recBtns.forEach(btn => btn.addEventListener("click", () => setRecovery(btn.dataset.val, btn)));
els.btnStartQuiz.addEventListener("click", () => {
quizAnswers = {};
els.quizPrompt.classList.add("hidden");
els.quizPanel.classList.remove("hidden");
renderQuiz();
});
els.btnQuizClose.addEventListener("click", () => {
els.quizPanel.classList.add("hidden");
els.quizPrompt.classList.remove("hidden");
});
els.btnContinue.addEventListener("click", openModal);
els.btnCancel.addEventListener("click", closeModal);
els.btnCloseSuccess.addEventListener("click", closeModal);
wrapper.querySelector(".pcp-btn-see-pricing").addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
closeModal();
setTimeout(() => {
const target = document.getElementById("pricing") || document.querySelector("[id*='pricing']");
if (target) {
const y = target.getBoundingClientRect().top + window.pageYOffset - 80;
window.scrollTo({ top: y, behavior: "smooth" });
}
}, 250);
});
els.btnSubmit.addEventListener("click", submitReport);
els.btnOpenPrivacy.addEventListener("click", openPrivacy);
els.btnClosePrivacy.addEventListener("click", closePrivacy);
els.btnAcceptPrivacy.addEventListener("click", closePrivacy);
els.overlay.addEventListener("click", e => {
if (e.target === els.overlay) closeModal();
});
document.addEventListener("keydown", e => {
if (e.key !== "Escape") return;
if (els.privacyPanel.classList.contains("pcp-open")) { closePrivacy(); return; }
if (els.overlay.classList.contains("pcp-open")) { closeModal(); return; }
});
applyPreset("aesthetics");
updateBenchmark();
})();</script>
</div>