Independent, study-verified benchmarks and facility-calibrated financial projections for hospitals, imaging centers, and radiology groups. Built on evidence, not the vendor's ROI deck.
Independent by design
No vendor funding
No sponsored placement
No GPO referral fees
Methodology disclosed
Market problem
Why imaging technology decisions are hard to underwrite.
Medical imaging purchases are financially material and operationally sensitive. A scanner, AI platform, PACS/RIS module, workflow tool, or imaging software contract can affect throughput, staffing, reimbursement, denial rates, radiologist productivity, patient access, integration burden, and long-term capital planning.
01
ROI claims may overstate value.
A faster scan, shorter read time, or workflow improvement only creates financial value when demand, staffing, scheduling, reimbursement, and downstream capacity allow the facility to capture the gain.
02
Pricing is opaque.
Comparable buyers may pay different amounts for product configuration, implementation, annual support, integrations, service terms, add-ons, and enterprise licenses.
03
Performance is difficult to compare.
Products differ across real-world workflow fit, PACS/RIS/EHR compatibility, implementation burden, training needs, and site-specific value capture.
04
Evidence is fragmented.
Useful signals sit across clinical studies, regulatory materials, vendor documents, case studies, reimbursement data, buyer conversations, and public market sources.
Intelligence layers built around the buying decision.
The platform is structured to move from product claim to evidence-weighted, buyer-specific, procurement-ready economic view.
01
Evidence-weighted KPI benchmarks
Scan-time reduction, read-time impact, workflow efficiency, repeat-rate reduction, denial-rate impact, throughput potential, staffing impact, and implementation burden are normalized and weighted by evidence quality.
02
Facility-specific financial modeling
Operational gains are translated into downside, base-case, and upside scenarios only when a real monetization path exists.
03
Pricing and contract intelligence
Expected price ranges, pricing structures, hidden fees, implementation costs, support fees, integration costs, module bundling, and negotiation questions are organized into a procurement-ready view.
04
Integration and workflow risk scoring
PACS, RIS, EHR, modality infrastructure, reporting workflow, cybersecurity requirements, IT burden, training, implementation timeline, and disruption risk are evaluated before value is assumed.
05
Buyer-specific fit assessment
A hospital radiology department, outpatient imaging center, radiology group, and PE-backed platform do not evaluate value the same way. Facility context changes the answer.
06
Procurement-ready decision support
Outputs include product profiles, opportunity estimates, benchmark summaries, diligence checklists, pricing questions, vendor comparison tables, and finance-committee-ready summaries.
How the model works
From product claim to decision-grade economic view.
Imaging Benchmark does not treat time savings as money by default. Every estimate is routed through baseline, constraint, evidence, monetization, and realization logic.
01
Select the product or category.
Start with a scanner, AI platform, PACS/RIS module, workflow tool, or imaging software category.
KPI evidence grades, pricing provenance, integration risk, and monetization gates determine whether operational gains can become financial value.
04
Export a decision-ready view.
Use the output for vendor meetings, procurement review, capital committee, board discussion, or internal operating meetings.
Model discipline
What we will not assume.
×
No automatic monetization of time savings.
Time saved only matters financially when there is a capture mechanism.
×
No unweighted vendor claims.
A multi-site study, vendor case study, regulatory document, and buyer comment do not carry the same weight.
×
No ignored site-readiness costs.
DICOM conformance, middleware, interface builds, cybersecurity, training, and disruption costs stay in the model.
×
No paid influence on scoring.
Vendor participation, if allowed, must be labeled and cannot influence benchmarks, scoring, modeling, or editorial judgment.
CT Scanner Comparison
Narrow estimate ranges to your facility's operational reality
Complete a 5-minute facility profile to replace generic averages with implementation-adjusted ranges based on your revenue, technology stack, and demand levels. Produces committee-defensible projections.
Ranges implementation-adjusted to your facility operating profile
Your facility profile is partially complete. Estimate ranges below carry wider confidence intervals than necessary for committee-defensible outputs.
Data Sources, Methodology & Evidence Governance. Performance specifications sourced from manufacturer-published datasheets and FDA 510(k) summaries. Pricing ranges reflect list prices and peer-reported transaction data where available; actual negotiated prices vary by region, volume, and contract terms. Financial impact estimates are implementation-adjusted illustrative ranges derived from comparable-facility medians and user-supplied operating data. These are not guarantees of financial outcomes. Realization haircuts applied where operational dependencies are identified. Integration assessments based on vendor documentation and structured deployment reports. All claims carry evidence classification metadata. Data subject to change. See Methodology & Evidence Standards v2.1 for full disclosure.
Next step
Evaluate the economics before the vendor meeting.
Use Imaging Benchmark to pressure-test product claims, pricing assumptions, integration risk, and financial upside before committing capital or signing a contract.
Cookie Notice. This site uses essential cookies required for platform functionality. Optional analytics cookies help us understand usage patterns. No facility data is shared with third parties. See our Privacy Policy for details on data handling and retention.
same tab
return true;
}
// 2) Fall back to a hosted file URL from the registry (for products embedded later).
var url = PRODUCT_PROFILES[name];
if(url){ window.location.href = url; return true; }
return false;
}
function showPage(id){closeMobileMenu();document.querySelectorAll('.page').forEach(p=>p.classList.remove('active'));document.getElementById('page-'+id).classList.add('active');window.scrollTo(0,0);
const nl=document.getElementById('navLinks');
const ffLink=isLoggedIn&&!ffDone?'Facility Profile':'';
nl.innerHTML=navDesktopExtrasHTML();
if(id==='explorer')renderExplorer();
if(id==='comparison'){renderComparison();const fi=document.getElementById('ffIncentive');const fc=document.getElementById('ffCalibrated');const pb=document.getElementById('partialCalBanner');const ci=document.getElementById('ctxInterview');
if(fi)fi.style.display=currentTier>=1&&!ffDone&&getCalibrationPct()===0?'flex':'none';
if(fc)fc.style.display=currentTier>=1&&ffDone?'flex':'none';
if(pb){const pct=getCalibrationPct();pb.style.display=(currentTier>=1&&!ffDone&&pct>0)?'flex':'none';}
if(ci)ci.style.display=ffDone?'flex':'none';}
if(id==='fastfit'){checkSavedFF();renderFF();}}
function scrollToEl(id){document.getElementById(id)?.scrollIntoView({behavior:'smooth',block:'start'});}
function toggleMobileMenu(){document.getElementById('mobileMenu').classList.toggle('open');}
function closeMobileMenu(){document.getElementById('mobileMenu').classList.remove('open');}
function showToast(m){const t=document.getElementById('toast');t.textContent=m;t.classList.add('visible');setTimeout(()=>t.classList.remove('visible'),3000);}
/* Calibration badge removed */
function updateCalBadge(){}
/* ═══ P3b: Calibration percentage system ═══ */
function getCalibrationPct(){if(ffDone)return 100;if(!ffBilling)return 0;if(ffStep<=0)return 0;
/* TC: billing(0) → tc_modselect(1) → tc1(2) → tc2(3) → tc3(4) = 5 steps */
/* PC: billing(0) → pc1(1) → pc2(2) → pc3(3) = 4 steps */
/* Global: billing(0) → tc_modselect(1) → tc1(2) → tc2(3) → tc3(4) → pc1(5) → pc2(6) → pc3(7) = 8 steps */
const pctMap={
'TC':[0,25,35,55,72,88],
'PC':[0,35,55,72,88],
'Global':[0,15,25,35,45,55,68,80,92]};
const map=pctMap[ffBilling]||pctMap['TC'];
const idx=Math.min(ffStep,map.length-1);
return map[idx];}
function getNextCalFields(){const pct=getCalibrationPct();if(pct<=35)return'Complete volume and revenue baseline to narrow ranges.';if(pct<=55)return'Complete modality profiles to narrow ranges further.';if(pct<=72)return'Complete case mix distribution for more precise estimates.';if(pct<=88)return'Complete remaining fields for narrowest estimate ranges.';return'';}
function resumeFastFit(){showPage('fastfit');}
/* ═══ P3b: localStorage persistence ═══ */
function saveFFState(){try{localStorage.setItem('ib_ffStep',ffStep);localStorage.setItem('ib_ffBilling',ffBilling);localStorage.setItem('ib_ffData',JSON.stringify(ffData));localStorage.setItem('ib_ffModList',JSON.stringify(ffModList));localStorage.setItem('ib_ffSelectedMods',JSON.stringify(ffSelectedMods));localStorage.setItem('ib_ffDone',ffDone?'1':'0');localStorage.setItem('ib_ffRevPct',ffRevPct);if(window._regFacilityType)localStorage.setItem('ib_facilityType',window._regFacilityType);}catch(e){}}
function loadFFState(){try{const s=localStorage.getItem('ib_ffStep');if(s!==null){ffStep=parseInt(s)||0;ffBilling=localStorage.getItem('ib_ffBilling')||'';ffData=JSON.parse(localStorage.getItem('ib_ffData')||'{}');ffModList=JSON.parse(localStorage.getItem('ib_ffModList')||'[]');ffSelectedMods=JSON.parse(localStorage.getItem('ib_ffSelectedMods')||'[]');ffDone=localStorage.getItem('ib_ffDone')==='1';ffRevPct=parseInt(localStorage.getItem('ib_ffRevPct'))||0;const ft=localStorage.getItem('ib_facilityType');if(ft)window._regFacilityType=ft;return true;}return false;}catch(e){return false;}}
function checkSavedFF(){
const hasState=loadFFState();
if(ffDone){ffMode='dashboard';return;}
if(hasState&&ffBilling&&ffStep>0){ffMode='dashboard';return;}
/* First time or no real progress - show billing step */
ffMode='step';ffStep=0;}
function clearFFState(){try{['ib_ffStep','ib_ffBilling','ib_ffData','ib_ffModList','ib_ffSelectedMods','ib_ffDone','ib_ffRevPct','ib_facilityType'].forEach(k=>localStorage.removeItem(k));}catch(e){}}
/* ═══ SEARCH ═══ */
function handleSearch(q,sourceId){const r=document.getElementById(sourceId==='homeSearch'?'homeSearchResults':'searchResults');if(!r)return;if(q.length<2){r.classList.remove('visible');r.innerHTML='';return;}const allProducts=[];[...PC_CATS,...TC_CATS].forEach(cat=>{cat.products.forEach(p=>{allProducts.push({name:p.n,vendor:p.v,category:cat.label,catId:cat.id,isPC:!!PC_CATS.find(c=>c.id===cat.id)});});});const ql=q.toLowerCase();const matches=allProducts.filter(p=>p.name.toLowerCase().includes(ql)||p.vendor.toLowerCase().includes(ql)||p.category.toLowerCase().includes(ql)).slice(0,8);if(matches.length===0){r.innerHTML='
'+results.length+' product'+(results.length!==1?'s':'')+' found
'+results.map(m=>'
'+m.name+' '+m.vendor+''+m.category+'
').join('');}
/* ═══ REGISTRATION ═══ */
function openRegistration(){document.getElementById('regModal').classList.add('visible');document.getElementById('regStep1').style.display='block';document.getElementById('regStep2').style.display='none';document.getElementById('regConfirm').style.display='none';}
function checkEmailDomain(){const e=document.getElementById('regEmail').value.trim();const h=document.getElementById('emailHint');const p=['gmail.com','yahoo.com','hotmail.com','outlook.com','aol.com','icloud.com'];if(e.includes('@')){const d=e.split('@')[1]?.toLowerCase();if(p.some(x=>d===x)){h.style.color='var(--warm)';h.textContent='Personal email detected. Institutional email recommended for full access.';}else if(d){h.style.color='var(--green)';h.textContent='Institutional email recognized.';}}else{h.style.color='var(--light-muted)';h.textContent='Use your work email for full access to peer-specific benchmarks.';}}
async function goToStep2(){const e=document.getElementById('regEmail').value.trim();const p=document.getElementById('regPassword').value;const h=document.getElementById('emailHint');if(!e||!e.includes('@')){h.style.color='var(--red)';h.textContent='Please enter a valid email address.';return;}if(p.length<8){h.style.color='var(--red)';h.textContent='Password must be at least 8 characters.';return;}window._regEmail=e;window._regPw=p;
if(sbClient){h.style.color='var(--muted)';h.textContent='Checking your account…';const res=await sbSignIn(e,p);if(res&&!res.error&&res.data&&res.data.user){document.getElementById('regModal').classList.remove('visible');isLoggedIn=true;if(currentTier<1)currentTier=1;registeredEmail=e;await sbRestoreSession();updateNavAuth();showToast('Signed in');sbLogEvent('login',{});return;}}
document.getElementById('regStep1').style.display='none';document.getElementById('regStep2').style.display='block';}
const RI={radiologist:'Radiologist accounts include read-per-hour benchmarking, professional component modeling, and modality-specific productivity analysis.',csuite:'Finance and executive accounts include capital allocation modeling, committee-ready export formats, and 5-year realization projections.',it:'IT accounts include integration burden scoring, PACS/RIS compatibility matrices, and deployment timeline benchmarks.',other:'General accounts include full product comparison access, pricing intelligence, and implementation risk analysis.'};
const FI={hospital:'Community hospital accounts include pricing ranges drawn from comparable facilities.',outpatient:'Outpatient imaging center accounts include throughput benchmarks and utilization modeling from comparable sites.',practice:'Radiology group accounts include professional component benchmarking and per-read revenue modeling from comparable practices.'};
function updateCalibration(){const r=document.getElementById('regRole').value;const f=document.getElementById('regFacility').value;const ri=document.getElementById('roleImpact');if(r){ri.textContent=RI[r]||'';ri.style.color='var(--body)';}else ri.textContent='';const fi=document.getElementById('facilityImpact');if(f){fi.textContent=FI[f]||'';fi.style.color='var(--body)';}else fi.textContent='';const pv=document.getElementById('calibrationPreview');const dt=document.getElementById('calibrationDetails');if(r&&f){pv.style.display='block';const rl=document.getElementById('regRole').options[document.getElementById('regRole').selectedIndex].text;const fl=document.getElementById('regFacility').options[document.getElementById('regFacility').selectedIndex].text;dt.innerHTML='Role: '+rl+' Facility: '+fl;/* Store facility type for FastFit defaults */window._regFacilityType=f;}else pv.style.display='none';}
async function submitRegistration(){const e=document.getElementById('regEmail').value.trim();const r=document.getElementById('regRole').value;const f=document.getElementById('regFacility').value;if(!r){document.getElementById('roleImpact').textContent='Please select your role to continue.';document.getElementById('roleImpact').style.color='var(--red)';return;}if(!f){document.getElementById('facilityImpact').textContent='Please select your facility type to continue.';document.getElementById('facilityImpact').style.color='var(--red)';return;}
if(sbClient){const fi=document.getElementById('facilityImpact');const pw=window._regPw||document.getElementById('regPassword').value;fi.style.color='var(--muted)';fi.textContent='Creating your account…';const res=await sbSignUp(e,pw);if(res&&res.error){const msg=(res.error.message||'').toLowerCase();const isNet=res.error._network||msg.includes('failed to fetch')||msg.includes('network')||msg.includes('fetch')||msg.includes('load failed')||msg.includes('connect');if(msg.includes('already')||msg.includes('registered')||msg.includes('exists')){fi.style.color='var(--warm)';fi.textContent='An account with this email already exists. Use Log In instead.';return;}if(!isNet){fi.style.color='var(--red)';fi.textContent=res.error.message||'Could not create account.';return;}console.warn('Supabase unreachable; completing registration locally:',res.error.message);}else{try{await sbSaveProfileFields({role:r,facility_type:f});sbLogEvent('register',{role:r,facility:f});}catch(_){}}}
registeredEmail=e;window._regFacilityType=f;const rl=document.getElementById('regRole').options[document.getElementById('regRole').selectedIndex].text;const fl=document.getElementById('regFacility').options[document.getElementById('regFacility').selectedIndex].text;document.getElementById('regStep2').style.display='none';document.getElementById('regConfirm').style.display='block';document.getElementById('confirmEmailDisplay').textContent=e;document.getElementById('confirmCalibration').innerHTML='Role: '+rl+' Facility: '+fl;}
function resendEmail(){showToast('Verification resent to '+registeredEmail);}
function simulateVerification(){document.getElementById('regModal').classList.remove('visible');currentTier=1;isLoggedIn=true;/* Reset FastFit to clean state so user starts fresh */ffDone=false;ffStep=0;ffBilling='';ffData={};ffModList=[];ffSelectedMods=[];ffMode='step';clearFFState();updateNavAuth();showToast('Verified · full data access enabled');if(exCategory&&selectedProducts.length>=2){renderTierBtns();updateCompHeaders();showPage('comparison');}else{exScope=null;exCategory=null;exFocus=[];showPage('explorer');}}
document.getElementById('regModal').addEventListener('click',function(e){if(e.target===this)this.classList.remove('visible');});
/* ═══ EXPLORER ═══ */
/* P5: headline KPIs for product selection grid */
const productKpiMap={};(function buildKpiMap(){const throughputKpi={'Revolution Apex':'+14%','SOMATOM Force':'+22%','Aquilion ONE / PRISM':'+8%','Spectral CT 7500':'+11%','SOMATOM X.ceed':'+9%','Revolution Maxima':'+7%','Incisive CT':'+5%','Aquilion Serve SP':'+6%'};const defaultKpis=['+8%','+12%','+5%','+9%','+14%','+6%','+10%','+7%'];[...PC_CATS,...TC_CATS].forEach(cat=>{cat.products.forEach((p,i)=>{productKpiMap[p.n]=throughputKpi[p.n]||(defaultKpis[i%defaultKpis.length]+' throughput vs avg');});});})();
function renderExplorer(){const c=document.getElementById('explorerContent');let h='';
if(!exScope){h+=`
Efficiency range vs. category average (Source: manufacturer specifications & peer-reported data)
PERFORMANCE Source: manufacturer specifications
Key Advantage${keyAdv}
Throughput${throughput}
Dose Efficiency${dose}
PRICING Source: peer-reported transactions & list prices
List Price
${t>=1?listPrice:'Register to view'}
Peer-Reported Transactions
${peerPrices} ›
Est. Annual Financial Impact
${impact}
Illustrative estimate based on comparable-facility medians. Not a guarantee of results.
INTEGRATION Source: deployment data & vendor documentation
Compatibility${compat}
Timeline${timeline}
Installed Base${instBase}
`;});
if(t===0){h+=`
Pricing and financial data require registration
Register to view peer-reported pricing ranges. Complete a facility profile for estimate ranges specific to your operations.
`;}
container.innerHTML=h;
const fi=document.getElementById('ffIncentive');const fc=document.getElementById('ffCalibrated');const pb=document.getElementById('partialCalBanner');const ci=document.getElementById('ctxInterview');
if(fi)fi.style.display=(currentTier>=1&&!ffDone&&getCalibrationPct()===0)?'flex':'none';
if(fc)fc.style.display=(currentTier>=1&&ffDone)?'flex':'none';
if(pb){const pct=getCalibrationPct();pb.style.display=(currentTier>=1&&!ffDone&&pct>0)?'flex':'none';if(pct>0){const pctEl=document.getElementById('partialCalPct');if(pctEl)pctEl.textContent=pct+'%';const ptEl=document.getElementById('partialCalText');if(ptEl)ptEl.textContent='Your facility profile is '+pct+'% complete. Estimate ranges below are wider than necessary. Resume to narrow them.';}}
if(ci)ci.style.display=ffDone?'flex':'none';
document.getElementById('compSubline').innerHTML=t>=1?(ffDone?'Implementation-adjusted estimate ranges calibrated to your facility operating data.':'Evidence-classified performance metrics, peer-referenced pricing data, and integration burden assessments drawn from institutional benchmarks.'):'Evidence-classified performance metrics, peer-referenced pricing data, and integration burden assessments drawn from institutional benchmarks.';document.getElementById('actionsBar').style.display=t>=1?'flex':'none';}
function renderTierBtns(){}
function setTier(t){if(t>=1&¤tTier===0&&!registeredEmail){openRegistration();return;}if(t>=2&&!ffDone){showPage('fastfit');return;}currentTier=t;renderComparison();}
function setPriority(p){}
function toggleSec(k){const s=document.getElementById('sec_'+k);const ic=document.getElementById('icon_'+k);if(s){const v=s.style.display!=='none';s.style.display=v?'none':'';if(ic)ic.textContent=v?'▸':'▾';}}
function saveComparison(){if(!registeredEmail){openRegistration();return;}showToast('Comparison saved · access it anytime from your dashboard');savedComparisons.push({category:exCategory,products:[...selectedProducts],priority:currentPriority,date:new Date().toISOString()});}
function captureCurrentSystem(){const sel=document.getElementById('currentSysSelect');if(sel&&sel.value){showToast('Current system noted · comparative analysis available after profile completion');}}
function populateCurrentSystem(){const sel=document.getElementById('currentSysSelect');if(!sel)return;const cat=[...PC_CATS,...TC_CATS].find(c=>c.id===exCategory);if(!cat)return;let opts='';cat.products.forEach(p=>{opts+='';});opts+='';sel.innerHTML=opts;}
let savedComparisons=[];
/* ═══ FASTFIT ═══ */
let ffStep=0,ffBilling='',ffDone=false,ffModList=[],ffRevPct=0,ffData={};
let ffMode='dashboard';
/* Section completion checks */
function ffSectionDone(sec){
if(sec==='billing')return !!(ffBilling&&ffData.facilityType);
if(sec==='modalities')return ffSelectedMods.length>0;
if(sec==='volume')return !!(ffData.daysOpen&&ffData.monthlyRev);
if(sec==='profiles')return ffModList.length>0&&ffModList.every(m=>m.scanners&&m.scanTime&&m.daysPerWeek&&m.monthlyEnc);
if(sec==='casemix'){const keys=Object.keys(ffData).filter(k=>k.startsWith('cmv_'));return keys.length>0;}
if(sec==='reading')return !!(ffData.pcDays);
if(sec==='staffing')return !!(ffData.pcRev&&ffData.pcShifts&&ffData.pcReads);
if(sec==='readdist')return !!(ffData.pcrd_xray||ffData.pcrd_ct);
return false;}
function renderFFDashboard(){
const c=document.getElementById('ffContent');
const pct=getCalibrationPct();
const proj=calcProjectionRange();
const width=pct>=72?'Narrow':pct>=45?'Moderate':pct>=25?'Broad':'Wide';
const isTc=ffBilling==='TC'||ffBilling==='Global'||!ffBilling;
const isPc=ffBilling==='PC'||ffBilling==='Global';
function card(id,title,desc,done,stepTarget){
const status=done?'Complete':'Not started';
return`
${title}${status}
${desc}
`;}
let h=`
Complete the sections below in any order. Each section you finish narrows your projection ranges.
`;
/* Live projection indicator */
const projKnown=proj.known;
const projLowFmt=projKnown?formatDollar(proj.low):'Unknown';
const projHighFmt=projKnown?formatDollar(proj.high):'';
const projDisplay=projKnown?projLowFmt+' - '+projHighFmt:'Unknown: enter revenue data';
h+=`
Range precision
${width}
${pct}% of profile fields completed
`;
h+=`
`;
h+=card('billing','Facility & Billing','Facility type, billing model, and location.',ffSectionDone('billing'),0);
if(isTc||!ffBilling){
h+=card('modalities','Modality Inventory','Which modalities your facility operates.',ffSectionDone('modalities'),1);
h+=card('volume','Scanning Volume & Revenue','Days open and revenue baseline.',ffSectionDone('volume'),2);
h+=card('profiles','Operating Profiles','Scanner counts, scan times, and encounter volumes per modality.',ffSectionDone('profiles'),3);
h+=card('casemix','Exam Distribution','Volume and revenue distribution by case family.',false,4);}
if(isPc){
const pcOffset=isTc?5:1;
h+=card('reading','Reading Volume & Cases','Annual reading days and case distribution.',ffSectionDone('reading'),pcOffset);
h+=card('staffing','Revenue & Staffing','Professional revenue, shifts, and reads per week.',ffSectionDone('staffing'),pcOffset+1);
h+=card('readdist','Read Distribution by Modality','How reads and revenue split across modalities.',ffSectionDone('readdist'),pcOffset+2);}
h+=`
`;
h+=`
`;
if(pct>=25)h+=``;
h+=`
`;
h+=`
More precise inputs produce narrower estimate ranges. Where unsure, use conservative figures.
`;
c.innerHTML=h;window.scrollTo(0,0);}
const ffModOpts=['CT','MRI','Ultrasound','X-Ray','Mammography','Nuclear / PET-CT'];
const tcFam={'CT':['Neuro/Head','Chest','Abdomen/Pelvis','MSK/Spine','Vascular (CTA/CTP)','Cardiac','Other CT'],'MRI':['Neuro/Brain','Spine','MSK','Abdomen/Pelvis','Breast','Cardiac/Vascular (MRA)','Other MRI'],'X-Ray':['Chest','Abdomen','Spine','MSK/Extremity','Pelvis/Hip','Head/Face','Other X-ray'],'Ultrasound':['Abdomen','Pelvis/OB-GYN','Vascular','Cardiac (Echo)','MSK/Soft Tissue','Small Parts','Other US'],'Mammography':['Screening','Diagnostic','Interventional/Guidance','Implant/Tech Views','Tomo/3D','Breast US Add-on','Other Mammo'],'Nuclear / PET-CT':['PET: Whole-body Oncology','PET: Head/Neck','PET: Neuro/Brain','NM/SPECT: Cardiac','NM/SPECT: Bone/MSK','NM/SPECT: Other','Other NM/PET']};
const states='Alabama,Alaska,Arizona,Arkansas,California,Colorado,Connecticut,Delaware,Florida,Georgia,Hawaii,Idaho,Illinois,Indiana,Iowa,Kansas,Kentucky,Louisiana,Maine,Maryland,Massachusetts,Michigan,Minnesota,Mississippi,Missouri,Montana,Nebraska,Nevada,New Hampshire,New Jersey,New Mexico,New York,North Carolina,North Dakota,Ohio,Oklahoma,Oregon,Pennsylvania,Rhode Island,South Carolina,South Dakota,Tennessee,Texas,Utah,Vermont,Virginia,Washington,West Virginia,Wisconsin,Wyoming'.split(',');
let ffSelectedMods=[];
const modDescriptions={'CT':'Computed tomography','MRI':'Magnetic resonance imaging','Ultrasound':'Diagnostic & point-of-care','X-Ray':'Digital radiography','Mammography':'2D and 3D breast imaging','Nuclear / PET-CT':'Molecular and hybrid imaging'};
const modDefaults={'CT':{scanners:1,scanTime:15,daysPerWeek:5,monthlyEnc:800,availMin:2400,usedMin:1800},'MRI':{scanners:1,scanTime:35,daysPerWeek:5,monthlyEnc:400,availMin:2400,usedMin:1920},'Ultrasound':{scanners:2,scanTime:25,daysPerWeek:5,monthlyEnc:600,availMin:4800,usedMin:3600},'X-Ray':{scanners:1,scanTime:8,daysPerWeek:5,monthlyEnc:1500,availMin:2400,usedMin:1200},'Mammography':{scanners:1,scanTime:15,daysPerWeek:5,monthlyEnc:500,availMin:2400,usedMin:1680},'Nuclear / PET-CT':{scanners:1,scanTime:30,daysPerWeek:5,monthlyEnc:200,availMin:2400,usedMin:1440}};
/* ═══ RANKING UI ═══ */
/* Converts a ranking array into percentage estimates using a power-law curve */
function rankToPcts(ranked,total){
if(ranked.length===0)return{};
const weights=ranked.map((_,i)=>Math.pow(0.6,i));
const wSum=weights.reduce((a,b)=>a+b,0);
const pcts={};
ranked.forEach((id,i)=>{pcts[id]=Math.round((weights[i]/wSum)*100);});
/* Ensure sum=100 */
const s=Object.values(pcts).reduce((a,b)=>a+b,0);
if(s!==100&&ranked.length>0){pcts[ranked[ranked.length-1]]+=(100-s);}
return pcts;
}
function buildRankBlock(id,label,hint,items,dataKey,onChange){
const rankKey='_rank_'+dataKey;
const ranked=ffData[rankKey]||[];
const pcts=rankToPcts(ranked,items.length);
let html='
';
return html;
}
function toggleRank(dataKey,itemId){
const rankKey='_rank_'+dataKey;
if(!ffData[rankKey])ffData[rankKey]=[];
const arr=ffData[rankKey];
const idx=arr.indexOf(itemId);
if(idx>=0){arr.splice(idx);/* Remove this and everything after it */}
else{arr.push(itemId);}
/* Also write derived percentages into ffData for downstream use */
const pcts=rankToPcts(arr,10);
Object.keys(pcts).forEach(k=>{ffData[dataKey+'_'+k]=pcts[k];});
_ffNoScroll=true;
}
/* ═══ DOLLAR FORMATTING ═══ */
function formatDollar(val){
if(!val&&val!==0)return'';
const num=typeof val==='string'?parseInt(String(val).replace(/[^0-9.-]/g,'')):val;
if(isNaN(num))return val;
return'$'+num.toLocaleString('en-US');
}
function parseDollar(val){
if(!val)return 0;
return parseInt(String(val).replace(/[^0-9.-]/g,''))||0;
}
function autoDollarFormat(el){
const raw=el.value.replace(/[^0-9]/g,'');
if(raw){el.value='$'+parseInt(raw).toLocaleString('en-US');}
}
/* ═══ PROJECTION PREVIEW ═══ */
function getMonthlyRev(){
return parseDollar(ffData.monthlyRev);
}
function getSliderPct(){
return(ffRevPct||0)/100;
}
function getDemandMultiplier(){
/* Slightly increase range based on capacity/demand indicators */
let mult=1.0;
if(ffModList.length>0){
let totalEnc=0;let totalScanners=0;
ffModList.forEach(m=>{
totalEnc+=parseInt(m.monthlyEnc)||0;
totalScanners+=parseInt(m.scanners)||0;
});
if(totalEnc>3000)mult+=0.03;
if(totalEnc>5000)mult+=0.05;
if(totalScanners>4)mult+=0.02;
if(totalScanners>8)mult+=0.04;
/* Backlog indicators push range up */
ffModList.forEach(m=>{
const bp=parseInt(m.backlogPct)||0;
if(bp>30)mult+=0.01;
if(bp>60)mult+=0.02;
});
}
if(ffData.pcReads){const rds=parseInt(ffData.pcReads)||0;if(rds>2500)mult+=0.03;if(rds>4000)mult+=0.05;}
return mult;
}
function calcProjectionRange(){
const mr=getMonthlyRev();
if(!mr)return{low:null,high:null,known:false};
const sliderAdj=1+getSliderPct();
const demandMult=getDemandMultiplier();
const baseLow=Math.round(mr*0.07681*sliderAdj*demandMult);
const baseHigh=Math.round(mr*1.59871*sliderAdj*demandMult);
return{low:baseLow,high:baseHigh,known:true};
}
function projectionPreviewHTML(forceUnknown){
const proj=calcProjectionRange();
const pct=getCalibrationPct();
const width=pct>=72?'Narrow':pct>=45?'Moderate':pct>=25?'Broad':'Wide';
const widthColor=pct>=45?'var(--green)':'var(--warm)';
if(forceUnknown||!proj.known){
return'
Range precision
Wide
Complete the sections below to narrow your range precision.
';
}
return'
Range precision
'+width+'
Complete additional sections to narrow range precision.
';
}
/* ═══ PROMINENT EXIT EARLY ═══ */
function exitEarlyHTML(){
const pct=getCalibrationPct();
if(pct<25||ffDone)return'';
return '
Save progress and view comparison now
Your comparison will use peer averages for remaining fields. You can return anytime to refine.
View Comparison →
';
}
/* P3a: removed tc_intro and pc_intro from steps */
function getSteps(){const tc=['billing','tc_modselect','tc1','tc2','tc3'];const pc=['billing','pc1','pc2','pc3'];if(ffBilling==='TC')return tc;if(ffBilling==='PC')return pc;return['billing','tc_modselect','tc1','tc2','tc3','pc1','pc2','pc3'];}
function stepLabel(){const s=getSteps()[ffStep];if(!s||s==='billing')return'FastFit Profile';if(s==='tc_modselect')return'TC: Technical Component';if(s.startsWith('tc'))return'TC: Technical Component';return'PC: Professional Component';}
function pctWarn(total,label){if(Math.abs(total-100)>5){let el=document.getElementById('ffError');if(!el){const c=document.getElementById('ffContent');const div=document.createElement('div');div.id='ffError';div.className='ff-error visible';div.textContent=label+' must be within 95-105% of 100. Current total: '+Math.round(total)+'%.';const actions=c.querySelector('.ff-actions');if(actions)actions.parentNode.insertBefore(div,actions);else c.appendChild(div);}else{el.textContent=label+' must be within 95-105% of 100. Current total: '+Math.round(total)+'%.';el.classList.add('visible');}return false;}if(Math.abs(total-100)>0.5){return confirm(label+' total is '+Math.round(total)+'%. For best accuracy, adjust to 100%. Continue anyway?');}return true;}
function updateSlider(val){ffRevPct=val;const v=Math.round(val/2)*2;const zl=Math.abs(v)<=4?'Flat':v<=-10?'Significant decline':v<0?'Moderate decline':v<=10?'Moderate growth':'Aggressive growth';const zc=Math.abs(v)<=4?'var(--muted)':Math.abs(v)<=10?'var(--warm)':'var(--red)';const sv=document.getElementById('ffSliderColor');const zle=document.getElementById('ffZoneLabel');if(sv){sv.style.color=zc;sv.textContent=(v>=0?'+':'')+v+'%';}if(zle){zle.style.color=zc;zle.textContent=zl;}}
function updateSliderLive(val){
ffRevPct=val;
updateSlider(val);
updateLiveProjection();
}
function updateLiveProjection(){
/* Update the projection preview in-place without re-rendering the whole page */
const projBox=document.querySelector('.ff-projection-preview');
if(!projBox)return;
const proj=calcProjectionRange();
const pct=getCalibrationPct();
const width=pct>=72?'Narrow':pct>=45?'Moderate':pct>=25?'Broad':'Wide';
const widthColor=pct>=45?'var(--green)':'var(--warm)';
if(!proj.known){
projBox.innerHTML='
Range precision
Wide
Complete the sections below to narrow your range precision.
';
}else{
projBox.innerHTML='
Range precision
'+width+'
Complete additional sections to narrow range precision.
';
}
}
function buildPctBlock(id,label,hint,whyText,items,dataKey,onChange){
const vals=items.map(it=>{const k=dataKey+'_'+it.id;return parseFloat(ffData[k])||it.def||0;});
const total=vals.reduce((a,b)=>a+b,0);
const remaining=Math.max(0,100-total);
const totalColor=Math.abs(total-100)<1?'var(--green)':total>100?'var(--red)':'var(--text)';
const barClass=Math.abs(total-100)<1?'done':total>100?'over':'';
let html=`
${label}
${Math.round(total)}% of 100%${remaining>0?' · '+Math.round(remaining)+'% remaining':''}
`+
buildPctBlock('vol_'+mod,'Volume distribution','What share of your '+mod+' exams come from each family?','',volItems,'cmv_'+mod.replace(/[^a-zA-Z0-9]/g,'_'),'renderFF()')+
buildPctBlock('rev_'+mod,'Revenue distribution','What share of your '+mod+' revenue comes from each family?','',volItems,'cmr_'+mod.replace(/[^a-zA-Z0-9]/g,'_'),'renderFF()')+
`
`+navBottom;}
function addModality(){ffModList.push({modality:'',scanners:'',scanTime:'',daysPerWeek:'',availMin:'',usedMin:'',monthlyEnc:'',backlogPct:'',nextAppt:'',backfill:'',backlogAM:'',backlogPM:''});}
function applyModDefaults(idx){const m=ffModList[idx];const d=modDefaults[m.modality];if(!d)return;if(!m.scanners)m.scanners=d.scanners;if(!m.scanTime)m.scanTime=d.scanTime;if(!m.daysPerWeek)m.daysPerWeek=d.daysPerWeek;if(!m.monthlyEnc)m.monthlyEnc=d.monthlyEnc;if(!m.availMin)m.availMin=d.availMin;if(!m.usedMin)m.usedMin=d.usedMin;}
function toggleModSelect(mod){if(ffSelectedMods.includes(mod))ffSelectedMods=ffSelectedMods.filter(m=>m!==mod);else ffSelectedMods.push(mod);renderFF();}
let _ffNoScroll=false;
function renderFF(){
/* Dashboard mode */
if(ffMode==='dashboard'){renderFFDashboard();return;}
const steps=getSteps();const total=steps.length;const c=document.getElementById('ffContent');let prog='
Rank the case families from highest to lowest volume at your facility, or use a preset to start.
${renderCaseMix()}
${back}${(ffBilling==='TC'?finish:next)}
${exitEarly}`;}
else if(sid==='pc1'){
const ft=window._regFacilityType||ffData.facilityType||'hospital';
const csItems=[{id:'ed',label:'Emergency Department',desc:'STAT and urgent imaging reads'},{id:'ip',label:'Inpatient Hospital',desc:'Reads for admitted patients'},{id:'op',label:'Outpatient Diagnostic',desc:'Non-screening outpatient exams'},{id:'sc',label:'Screening',desc:'Preventive and protocol-driven imaging'},{id:'ot',label:'Other / Unknown',desc:'Reads not classified above'}];
const urItems=[{id:'stat',label:'STAT / ASAP',desc:'Interpreted within minutes'},{id:'urg',label:'Urgent Same Day',desc:'Required within hours'},{id:'rout',label:'Routine',desc:'Standard 24-48 hour turnaround'},{id:'scr',label:'Screening',desc:'Batch-processed or scheduled queue'}];
h+=projPreview+`
${stepLabel()}
Rank your care settings and urgency levels from highest to lowest volume. We'll estimate the percentages for you.
`;
h+=buildRankBlock('cs','Rank care settings by volume','Click each setting in order from highest volume to lowest at your facility.',csItems,'cs','_ffNoScroll=true;renderFF()');
h+=buildRankBlock('ur','Rank urgency levels by volume','Click each urgency level in order from most common to least common.',urItems,'ur','_ffNoScroll=true;renderFF()');
h+=`
Rank your modalities from highest to lowest. Click each in order. We'll estimate the percentages.
`;
h+=buildRankBlock('pcReads','Rank modalities by read volume','Which modalities generate the most reads? Click highest-volume first.',pcModItems,'pcrd','_ffNoScroll=true;renderFF()');
h+=buildRankBlock('pcRev','Rank modalities by revenue','Which modalities generate the most revenue? Click highest-revenue first.',pcModItems,'pcrv','_ffNoScroll=true;renderFF()');
h+=`
${back}${finish}
${exitEarly}`;}
c.innerHTML=h;if(!_ffNoScroll)window.scrollTo(0,0);_ffNoScroll=false;saveFFState();}
/* P3c: skip functions */
function skipCaseMix(){showToast('Using national averages - you can refine later for better precision');ffAdvance();}
function skipPcDistribution(){showToast('Using national averages - you can refine later for better precision');finishFastFit();}
/* P3b: Exit FastFit early with partial calibration */
function exitFFEarly(){saveFFState();currentTier=1;showPage('comparison');}
function ffAdvance(){const steps=getSteps();const sid=steps[ffStep];
function showFFError(msg){let el=document.getElementById('ffError');if(!el){const c=document.getElementById('ffContent');const div=document.createElement('div');div.id='ffError';div.className='ff-error visible';div.textContent=msg;const actions=c.querySelector('.ff-actions');if(actions)actions.parentNode.insertBefore(div,actions);else c.appendChild(div);return;}el.textContent=msg;el.classList.add('visible');}
function clearFFError(){const el=document.getElementById('ffError');if(el)el.classList.remove('visible');}
clearFFError();
if(sid==='billing'){if(!ffBilling){showFFError('Please select a billing model to continue.');return;}const zipVal=document.getElementById('ffZip')?.value;if(!zipVal){showFFError('Please enter your zip code.');return;}ffData.zipCode=zipVal;const ftSel=document.getElementById('ffFacilityType');if(ftSel&&!ftSel.value){showFFError('Please select your facility type.');return;}if(ftSel)ffData.facilityType=ftSel.value;
/* After billing, go to dashboard */
ffStep++;saveFFState();ffMode='dashboard';renderFF();return;}
if(sid==='tc_modselect'){if(ffSelectedMods.length===0){showFFError('Please select at least one modality your facility operates.');return;}ffModList=ffSelectedMods.map(mod=>{const existing=ffModList.find(m=>m.modality===mod);if(existing)return existing;const d=modDefaults[mod]||{};return{modality:mod,scanners:d.scanners||'',scanTime:d.scanTime||'',daysPerWeek:d.daysPerWeek||'',availMin:d.availMin||'',usedMin:d.usedMin||'',monthlyEnc:d.monthlyEnc||'',backlogPct:'',nextAppt:'',backfill:'',backlogAM:'',backlogPM:''};});}
if(sid==='tc1'){const d=document.getElementById('ffDaysOpen')?.value;const mr=document.getElementById('ffMonthlyRev')?.value;if(!d||!mr){showFFError('Please complete all fields before continuing.');return;}ffData.daysOpen=d;ffData.monthlyRev=mr;}
if(sid==='tc2'){if(ffModList.length===0){showFFError('Please configure at least one modality.');return;}let missing=false;ffModList.forEach(m=>{if(!m.modality||!m.scanners||!m.scanTime||!m.daysPerWeek||!m.monthlyEnc)missing=true;const d=parseInt(m.daysPerWeek);if(d<1||d>7)missing=true;});if(missing){showFFError('Please complete all required fields for every modality. Days per week must be between 1 and 7.');return;}}
if(sid==='pc1'){const d=document.getElementById('ffPCDays')?.value;if(!d){showFFError('Please enter days open for radiology review.');return;}ffData.pcDays=d;/* Rankings are optional - if no ranking provided, use defaults */const ft=window._regFacilityType||ffData.facilityType||'hospital';const csDefaultsMap={hospital:{ed:25,ip:30,op:30,sc:10,ot:5},outpatient:{ed:2,ip:3,op:65,sc:25,ot:5},practice:{ed:5,ip:10,op:55,sc:22,ot:8}};const urDefaultsMap={hospital:{stat:15,urg:25,rout:50,scr:10},outpatient:{stat:3,urg:10,rout:57,scr:30},practice:{stat:5,urg:12,rout:55,scr:28}};const csDefs=csDefaultsMap[ft]||csDefaultsMap.hospital;const urDefs=urDefaultsMap[ft]||urDefaultsMap.hospital;if(!ffData['_rank_cs']||ffData['_rank_cs'].length===0){['ed','ip','op','sc','ot'].forEach(id=>{ffData['cs_'+id]=csDefs[id];});}if(!ffData['_rank_ur']||ffData['_rank_ur'].length===0){['stat','urg','rout','scr'].forEach(id=>{ffData['ur_'+id]=urDefs[id];});}}
if(sid==='pc2'){const rev=document.getElementById('ffPCRev')?.value;const sh=document.getElementById('ffPCShifts')?.value;const rd=document.getElementById('ffPCReads')?.value;if(!rev||!sh||!rd){showFFError('Please complete all fields before continuing.');return;}ffData.pcRev=rev;ffData.pcShifts=sh;ffData.pcReads=rd;}
ffStep++;saveFFState();renderFF();}
function finishFastFit(){const steps=getSteps();const sid=steps[ffStep];
if(sid==='tc3'){const activeMods=ffModList.filter(m=>m.modality&&tcFam[m.modality]).map(m=>m.modality);let ok=true;activeMods.forEach(mod=>{const fams=tcFam[mod];const modKey=mod.replace(/[^a-zA-Z0-9]/g,'_');let vT=0,rT=0;fams.forEach(fam=>{const famKey=fam.replace(/[^a-zA-Z0-9]/g,'_');vT+=parseFloat(ffData['cmv_'+modKey+'_'+famKey])||0;rT+=parseFloat(ffData['cmr_'+modKey+'_'+famKey])||0;});if(vT>0&&!pctWarn(vT,mod+' volume')){ok=false;}if(rT>0&&!pctWarn(rT,mod+' revenue')){ok=false;}});if(!ok)return;}
if(sid==='pc3'){/* Rankings auto-derive percentages, no validation needed - just apply defaults if empty */
const pcMods=['xray','ct','mri','us','pet','mg','elast','other'];
const defaultPcts={xray:30,ct:25,mri:15,us:12,pet:3,mg:10,elast:2,other:3};
if(!ffData['_rank_pcrd']||ffData['_rank_pcrd'].length===0){pcMods.forEach(id=>{ffData['pcrd_'+id]=defaultPcts[id]||5;});}
if(!ffData['_rank_pcrv']||ffData['_rank_pcrv'].length===0){pcMods.forEach(id=>{ffData['pcrv_'+id]=defaultPcts[id]||5;});}}
ffDone=true;currentTier=2;saveFFState();sbSaveFacilityInputs();sbLogEvent('complete_registration',{});showCompletionSummary();}
/* P4: Compact completion screen, auto-redirect */
function showCompletionSummary(){const c=document.getElementById('ffContent');c.innerHTML=`
✓
Facility profile calibrated
Your estimate ranges now reflect implementation-adjusted operating data. Financial projections include realization haircuts for your facility context. Redirecting to your comparison...
`;
window.scrollTo(0,0);
setTimeout(()=>{skipToComparison();},2500);}
function skipToComparison(){showToast('Implementation-adjusted estimate ranges now active');showPage('comparison');}
renderMethodology();
function renderMethodology(){const el=document.getElementById('methSteps');if(!el)return;el.innerHTML=methSteps.map((s,i)=>`
${s.num}
${s.title}
`).join('');}
/* Load any saved FF state on page load */
(function(){loadFFState();updateCalBadge();sbRestoreSession();loadSiteContent();})();