1// Illustrative clinic workflows, not live activity or processing-speed claims. 2export const inboundParallelCalls=[7,3,5,14,9]; 3export const inboundTasks = [ 4 {id:'answer',action:`Answer ${inboundParallelCalls[0]} incoming calls`,detail:'Family practice + specialty clinics',working:'In parallelâ¦',result:`${inboundParallelCalls[0]} answered`}, 5 {id:'booking',action:'Book 3 new appointments',detail:'Match provider, visit type and availability',working:'Finding timesâ¦',result:'3 booked'}, 6 {id:'reschedule',action:'Reschedule 2 visits',detail:'Keep the right provider and duration',working:'Updating timesâ¦',result:'2 rescheduled'}, 7 {id:'intake',action:'Complete 1 pain-clinic intake',detail:'Pain history and prior treatments',working:'Taking intakeâ¦',result:'Saved to EMR'}, 8 {id:'specialty',action:'Forward a dermatology referral',detail:'To the referral department',working:'Routing requestâ¦',result:'Forwarded'}, 9 {id:'billing',action:'Answer a specialty billing question',detail:'Clinic-approved consultation fees',working:'Checking feesâ¦',result:'Patient informed'} 10]; 11export const clamp=(value,min=0,max=1)=>Math.max(min,Math.min(max,value)); 12export const ease=value=>{const t=clamp(value);return t*t*(3-2*t);}; 13export const inboundCycleMs=15000; 14const cadence=2000,firstComplete=2500,completedHold=620,swipeDuration=550,archiveFade=200,shiftDuration=540,arrivalGap=1000; 15// Accelerate all the way out: a slow lead-in followed by a fast exit, without a braking tail. 16const swipeEase=value=>{const t=clamp(value);return t*t*t;}; 17const completeAt=index=>firstComplete+index*cadence; 18const clearAt=index=>completeAt(index)+completedHold+swipeDuration+archiveFade; 19const enterAt=index=>index<3?index*arrivalGap:clearAt(index-3); 20const restartFade=500,restartAt=inboundCycleMs-restartFade; 21 22// Fill 1 â 2 â 3, replace the oldest row three times without resizing, 23// then drain 3 â 2 â 1. Hold the empty one-row space briefly before the next fade-in. 24export function inboundFrame(elapsedMs,staticMode=false){ 25 const elapsed=Math.max(0,elapsedMs),cycle=Math.floor(elapsed/inboundCycleMs),time=elapsed%inboundCycleMs; 26 const startingNext=!staticMode&&time>=restartAt; 27 const displayCycle=cycle+(startingNext?1:0),parallelCalls=inboundParallelCalls[displayCycle%inboundParallelCalls.length]; 28 const shift=index=>ease((time-clearAt(index))/shiftDuration); 29 const rows=inboundTasks.map((originalTask,index)=>{ 30 const task=index===0?{...originalTask,action:`Answer ${parallelCalls} incoming calls`,result:`${parallelCalls} answered`}:originalTask; 31 // The last row clears at 13.87s; wait 630ms, then fade the first in over 500ms. 32 // Keep it visible across the clock boundary rather than entering twice. 33 if(!staticMode&&index===0&&time>=restartAt)return {...task,open:ease((time-restartAt)/restartFade),position:0, 34 archive:0,taskOpacity:1,state:'working',doneProgress:0,title:task.action,status:task.working}; 35 const birth=enterAt(index),age=time-birth,finish=completeAt(index),clear=clearAt(index); 36 const present=age>=0&&time<clear; 37 const entry=index===0?1:ease(age/shiftDuration); 38 const swipe=(time-finish-completedHold)/swipeDuration; 39 const archive=staticMode?0:swipeEase(swipe); 40 const open=staticMode?1:present?entry*(1-ease((time-clear+archiveFade)/archiveFade)):0; 41 const done=staticMode||time>=finish; 42 const position=index-inboundTasks.slice(0,index).reduce((sum,_,previous)=>sum+shift(previous),0); 43 return {...task,open,position:staticMode?index:position, 44 archive, 45 // Follow distance, so the row stays readable through the slow start and 46 // dissolves during the fast departure instead of fading before it moves. 47 taskOpacity:staticMode?1:1-ease((archive-.08)/.92), 48 state:!present&&!staticMode?'waiting':done?'done':'working', 49 doneProgress:staticMode?1:ease((time-finish)/300), 50 title:task.action,status:done?task.result:task.working}; 51 }); 52 // Keep one row of space at the handoff; the window never contracts to its header. 53 const heightRows=staticMode?inboundTasks.length:1+ease((time-arrivalGap)/shiftDuration)+ease((time-2*arrivalGap)/shiftDuration) 54 -shift(3)-shift(4); 55 const completed=staticMode?inboundTasks.length:startingNext?0:inboundTasks.filter((_,i)=>time>=completeAt(i)).length; 56 const allComplete=completed===inboundTasks.length; 57 const heading=allComplete?'MEDI · All tasks complete':`MEDI · ${parallelCalls} calls in parallel`; 58 return {rows,heightRows,completed,cycle,parallelCalls,allComplete,heading}; 59} 60 61// Distances are viewport-height percentages. Keep the first card's travel; 62// give outbound and messaging a longer expansion and a brief settled interval. 63export const deckScenes=[
64 {expand:22,hold:0,exit:50}, 65 {expand:30,hold:6,exit:50}, 66 {expand:30,hold:20,exit:0} 67].map((scene,index,scenes)=>({...scene,start:scenes.slice(0,index).reduce((sum,s)=>sum+s.expand+s.hold+s.exit,0)})); 68export const deckTravelVh=deckScenes.reduce((sum,s)=>sum+s.expand+s.hold+s.exit,0); 69export const deckAnchors=deckScenes.map(scene=>scene.start/deckTravelVh); 70export function deckFrame(progress){ 71 const travel=clamp(progress)*deckTravelVh; 72 const arrivals=deckScenes.map(scene=>ease((travel-scene.start)/scene.expand)); 73 const [first,second]=deckScenes.slice(0,2).map(scene=>ease((travel-scene.start-scene.expand-scene.hold)/scene.exit)); 74 // Each card settles at 96.5%, then has its own short expansion before leaving. 75 const scales=[.965+.035*arrivals[0]-.035*first, 76 .94+.025*first+.035*arrivals[1]-.035*second, 77 .88+.06*first+.025*second+.035*arrivals[2]]; 78 return {arrivals,scales,first,second,active:first<.82?0:second<.82?1:2}; 79}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.