function qSz(t){const l=(t||'').length;if(l<=4)return'clamp(72px,22vw,280px)';if(l<=8)return'clamp(56px,16vw,220px)';if(l<=14)return'clamp(36px,10vw,170px)';if(l<=20)return'clamp(28px,7vw,130px)';return'clamp(22px,5vw,90px)'}
function aSz(t){const l=(t||'').length;if(l<=8)return'clamp(40px,11vw,160px)';if(l<=14)return'clamp(32px,8vw,130px)';if(l<=20)return'clamp(28px,6.5vw,100px)';if(l<=28)return'clamp(22px,5vw,80px)';if(l<=38)return'clamp(18px,3.8vw,62px)';if(l<=50)return'clamp(16px,3vw,48px)';return'clamp(14px,2.5vw,36px)'}
function tx(type){switch(type){case'source_q':case'acronym_q':case'fluency_line':case'bonus_marker':return't-slam';case'source_a':case'acronym_a':case'fluency_source':case'doa_verdict_dead':case'doa_verdict_alive':return't-punch';case'round_title':case'verdict':case'intermission':case'last_line':case'endcard':return't-breath';case'receipt_rain':return't-shake';case'crate_drop':return't-fade';default:return't-fade'}}
function esc(s){return(s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')}
// Strip " - Title" from a source string at render time so the title (which is
// the answer for music cards) is never displayed. "Coldplay - Viva la Vida" -> "Coldplay".
function stripSrc(s){if(typeof s!=='string')return s;var i=s.indexOf(' - ');return i<0?s:s.slice(0,i).trimEnd()}
function nwStyle(){return{maxWidth:'calc(100% - 32px)',padding:'2vh 16px',overflowWrap:'break-word',wordBreak:'break-word'}}

function AttractSlide({slide}){
  return <div className="D hp" style={{fontSize:'clamp(120px,40vw,350px)',animation:'pulse 2s ease-in-out infinite'}}>{slide.content.primary||'L'}</div>;
}
function FishbowlSlide({slide}){
  return <><div className="nb nb-pk"></div><div className="D hp" style={{fontSize:'clamp(28px,6vw,64px)',marginBottom:16,padding:'0 8%'}}>{slide.content.primary}</div><div className="M hs" style={{fontSize:'clamp(12px,2.5vw,22px)',padding:'0 8%'}}>{slide.content.secondary||''}</div></>;
}
function RedFlagSlide({slide}){
  return <><div className="nb nb-pk"></div><div className="D hp" style={{fontSize:'clamp(28px,6vw,64px)',color:'var(--signal)',textShadow:'var(--glow-signal)',marginBottom:16,padding:'0 8%'}}>{slide.content.primary}</div><div className="M hs" style={{fontSize:'clamp(12px,2.5vw,22px)',color:'var(--text-secondary)',padding:'0 8%'}}>{slide.content.secondary||''}</div></>;
}
function RoundTitleSlide({slide}){
  return <><div className="D hw" style={{fontSize:'clamp(50px,10vw,150px)',marginBottom:10}}>{slide.content.primary||''}</div>{slide.content.secondary?<BMText text={slide.content.secondary} className="D hw" maxWVw={90} maxHVh={30}/>:null}</>;
}
function TierTitleSlide({slide}){
  const lines=(slide.content.secondary||'').split('|').map(l=>l.trim());
  return <><div className="nb nb-wh"></div><div className="D hs" style={{fontSize:'clamp(28px,4vw,56px)',marginBottom:16,padding:'0 5%'}}>{slide.content.primary||''}</div><div className="rule"></div><div className="M" style={{color:'rgba(255,255,255,.5)',fontSize:'clamp(18px,2.2vw,28px)',lineHeight:'2.2'}}>{lines.map((l,i)=><div key={i}>{l}</div>)}</div></>;
}
function BonusMarkerSlide({slide}){
  return <><div className="nb nb-gd"></div><div className="D hg" style={{fontSize:'clamp(36px,8vw,120px)',padding:'0 8%'}}>{slide.content.primary||''}</div></>;
}
function SourceQSlide({slide,revealed}){
  var ans=stripSrc(slide.content.answer);
  return <><div className="nb nb-pk"></div><div className="tb pk"></div><BMText text={slide.content.primary||''} className="D hw" maxWVw={90} maxHVh={50}/>{ans?<div className={'answer'+(revealed?' revealed':'')} style={{position:'absolute',bottom:80,left:'50%',transform:'translateX(-50%)',fontFamily:"'Space Mono',monospace",fontSize:'clamp(18px,2.8vw,36px)',color:'var(--wh)',textTransform:'uppercase',letterSpacing:'.06em'}}>{ans}</div>:null}</>;
}
function SourceASlide({slide}){
  return <><div className="nb nb-wh"></div><BMText text={slide.content.primary||''} className="D hw" maxWVw={90} maxHVh={55}/></>;
}
function AcronymQSlide({slide,revealed}){
  var src=stripSrc(slide.content.source);
  return <><div className="nb nb-cy"></div><div className="tb cy"></div><BMText text={slide.content.primary||''} className="D hw" maxHVh={45} lsEm={0.08}/>{src?<div className="srcbar">{src}</div>:null}{slide.content.answer?<div className={'answer'+(revealed?' revealed':'')} style={{position:'absolute',bottom:120,left:'50%',transform:'translateX(-50%)',fontFamily:"'Space Mono',monospace",fontSize:'clamp(18px,2.8vw,36px)',color:'var(--wh)',textTransform:'uppercase',letterSpacing:'.06em',textAlign:'center',maxWidth:'80%'}}>{slide.content.answer}</div>:null}</>;
}
function AcronymASlide({slide}){
  return <><div className="nb nb-pk"></div><BMText text={slide.content.primary||''} className="D hw" maxWVw={90} maxHVh={50}/>{slide.content.secondary?<div className="srcbar">{slide.content.secondary}</div>:null}</>;
}
function FluencyLineSlide({slide}){
  return <><div className="nb nb-wh"></div><BMText text={slide.content.primary||''} className="D hw" maxWVw={90} maxHVh={55}/></>;
}
function FluencySourceSlide({slide}){
  return <BMText text={stripSrc(slide.content.primary)||''} className="D hw" maxWVw={90} maxHVh={55}/>;
}
function ScoreSlide({slide}){
  return <><div className="D hw" style={{fontSize:'clamp(28px,4vw,56px)'}}>{slide.content.primary||''}</div>{slide.content.secondary?<div className="M hs" style={{fontSize:'clamp(12px,1.5vw,18px)',marginTop:14}}>{slide.content.secondary}</div>:null}</>;
}
function IntermissionSlide({slide}){
  const qrRef=useRef(null);
  // QR sends people to the Product Waitlist signup (Klaviyo list VA4QYX, surfaced
  // via the branded /waitlist redirect on the Shopify store). Intermission is the
  // moment they're bored and scanning — most receptive to the list + deck signup.
  // UTM matches companion + launcher so Klaviyo attributes signups correctly.
  const waitlistUrl='https://lineconic.com/waitlist?utm_source=live-app&utm_medium=web&utm_campaign=show&utm_content=intermission';
  useEffect(()=>{if(qrRef.current)drawQR(qrRef.current,waitlistUrl)},[]);
  return <><div className="D hw" style={{fontSize:'clamp(40px,7vw,100px)',marginBottom:20}}>{slide.content.primary||''}</div><div className="M hs" style={{fontSize:'clamp(14px,2vw,24px)',marginBottom:30}}>{slide.content.secondary||''}</div><canvas ref={qrRef} width={400} height={400} style={{imageRendering:'pixelated',width:'clamp(200px,28vw,320px)',height:'clamp(200px,28vw,320px)',border:'5px solid rgba(255,255,255,.3)'}}></canvas><a href={waitlistUrl} target="_blank" rel="noopener" className="M" style={{color:'rgba(255,255,255,.5)',fontSize:'clamp(16px,2.5vw,28px)',marginTop:16,letterSpacing:'.1em',textDecoration:'none'}}>JOIN THE LIST &rarr; LINECONIC.COM/WAITLIST</a></>;
}
function DoaVoteSlide({slide}){
  const[liveVotes,setLiveVotes]=useState({dead:0,alive:0});
  useEffect(()=>{
    if(!fbdb)return;
    var key=(slide.content.primary||'').replace(/[^a-zA-Z0-9]/g,'_');
    if(!key)return;
    var ref=fbdb.ref('votes/'+key);
    ref.on('value',snap=>{var v=snap.val()||{};setLiveVotes({dead:v.dead||0,alive:v.alive||0})});
    return()=>ref.off();
  },[slide.content.primary]);
  const total=liveVotes.dead+liveVotes.alive;const dp=total>0?Math.round(liveVotes.dead/total*100):50;const ap=total>0?100-dp:50;
  return <><div className="nb nb-wh"></div><BMText text={slide.content.primary||''} className="D hw" maxWVw={90} maxHVh={35} style={{marginBottom:30}}/><div style={{width:'70%',maxWidth:600}}><div style={{display:'flex',justifyContent:'space-between',marginBottom:8}}><span className="M" style={{color:'var(--pk)',fontSize:'clamp(12px,1.5vw,18px)',letterSpacing:'.1em'}}>DEAD</span><span className="M" style={{color:'var(--cy)',fontSize:'clamp(12px,1.5vw,18px)',letterSpacing:'.1em'}}>ALIVE</span></div><div style={{width:'100%',height:'clamp(24px,4vh,40px)',background:'rgba(255,255,255,.05)',border:'1px solid rgba(255,255,255,.1)',position:'relative',overflow:'hidden'}}><div style={{position:'absolute',left:0,top:0,bottom:0,width:dp+'%',background:'linear-gradient(90deg,var(--pk),rgba(255,0,127,.3))',transition:'width .6s cubic-bezier(.4,0,.2,1)'}}></div><div style={{position:'absolute',right:0,top:0,bottom:0,width:ap+'%',background:'linear-gradient(270deg,var(--cy),rgba(0,255,255,.3))',transition:'width .6s cubic-bezier(.4,0,.2,1)'}}></div></div><div style={{display:'flex',justifyContent:'space-between',marginTop:8}}><span className="M" style={{color:'var(--pk)',fontSize:'clamp(18px,3vw,36px)'}}>{dp}%</span><span className="M" style={{color:'var(--cy)',fontSize:'clamp(18px,3vw,36px)'}}>{ap}%</span></div></div></>;
}
function WarningSlide({slide}){return <div className="D hw" style={{fontSize:'clamp(60px,12vw,180px)'}}>{slide.content.primary||''}</div>}
function BlackoutSlide(){return null}
function TransitionBeatSlide(){return null}
function DoaRefSlide({slide}){return <><div className="nb nb-wh"></div><BMText text={slide.content.primary||''} className="D hw" maxWVw={90} maxHVh={55}/></>}
function DoaVerdictDeadSlide({slide}){return <><div className="nb nb-pk"></div><div className="D hp" style={{fontSize:'clamp(80px,18vw,260px)'}}>{slide.content.primary||''}</div></>}
function DoaVerdictAliveSlide({slide}){return <><div className="nb nb-cy"></div><div className="D hc" style={{fontSize:'clamp(80px,18vw,260px)'}}>{slide.content.primary||''}</div></>}
function HotseatRulesSlide({slide}){
  const lines=(slide.content.secondary||'').split('|').map(l=>l.trim());
  return <><div className="nb nb-wh"></div><div className="D hw" style={{fontSize:'clamp(24px,3.5vw,48px)',marginBottom:12}}>{slide.content.primary||''}</div><div className="rule"></div><div className="M hs" style={{fontSize:'clamp(14px,1.8vw,22px)',lineHeight:2}}>{lines.map((l,i)=><div key={i}>{l}</div>)}</div></>;
}
function HotseatPromptSlide({slide}){var src=stripSrc(slide.content.source);return <><div className="nb nb-cy"></div><div className="tb cy"></div><BMText text={slide.content.primary||''} className="D hc" maxWVw={90} maxHVh={45}/>{src?<div className="srcbar">{src}</div>:null}</>}
function VerdictSlide({slide}){return <div className="D hw" style={{fontSize:'clamp(60px,12vw,180px)'}}>{slide.content.primary||''}</div>}
function SentenceSlide({slide}){
  const lines=(slide.content.secondary||'').split('|').map(l=>l.trim());
  return <><div className="D hw" style={{fontSize:'clamp(36px,6vw,80px)',marginBottom:20}}>{slide.content.primary||''}</div><div className="M hs" style={{fontSize:'clamp(14px,2vw,24px)'}}>{lines.map((l,i)=><div key={i} style={{marginBottom:8}}>{l}</div>)}</div></>;
}
function ReceiptRainSlide({slide}){return <div className="D hp" style={{fontSize:'clamp(50px,12vw,160px)',animation:'rain .8s ease-in-out infinite',zIndex:4,position:'relative'}}>{slide.content.primary||''}</div>}
function CrateDropSlide(){return <div className="crate-container"><div className="crate"><div className="crate-lid"></div><div className="crate-body"><div className="crate-interior"><div className="crate-L">L</div></div></div></div></div>}
function LastLineSlide({slide}){return <><div className="nb nb-wh"></div><BMText text={slide.content.primary||''} className="D hw" maxWVw={90} maxHVh={55}/></>}
function EndcardSlide({slide}){return <><div className="D hp" style={{fontSize:'clamp(100px,30vw,300px)',marginBottom:12}}>{slide.content.primary||'L'}</div><div className="M hs" style={{fontSize:'clamp(12px,1.5vw,18px)'}}>{slide.content.secondary||''}</div></>}
function AnswerSheetSlide({slide}){
  const items=(slide.content.secondary||'').split('|').map(a=>a.trim());
  const n=items.length;
  const vh=Math.min(70/n/1.6,6);
  const sz='clamp(16px,'+vh.toFixed(1)+'vh,48px)';
  return <><div className="nb nb-wh"></div><div className="D hw" style={{fontSize:'clamp(18px,2.5vw,32px)',marginBottom:8,paddingTop:'2%'}}>{slide.content.primary||''}</div><div className="rule"></div><div className="ans-list" style={{lineHeight:1.6,maxHeight:'none',overflow:'hidden'}}>{items.map((a,i)=><div key={i} className={a.includes('[')?'bonus':''} style={{fontSize:sz}}>{(i+1)+'. '+a}</div>)}</div></>;
}

function CheckinSlide({slide}){
  const eventId=slide.content&&slide.content.eventId||'';
  const baseUrl=slide.content&&slide.content.primary||'lineconic.live/play';
  const fullUrl=eventId?baseUrl+'?event='+eventId:baseUrl;
  const subtitle=slide.content&&slide.content.secondary||'SCAN TO PLAY ALONG';
  const qrRef=useRef(null);
  useEffect(function(){
    if(!qrRef.current)return;
    var qr=qrcode(0,'M');
    qr.addData('https://'+fullUrl);
    qr.make();
    var img=document.createElement('img');
    img.src=qr.createDataURL(8,0);
    img.style.width='min(50vw,50vh)';
    img.style.height='auto';
    img.style.imageRendering='pixelated';
    qrRef.current.textContent='';
    qrRef.current.appendChild(img);
  },[fullUrl]);
  return <><div ref={qrRef}></div><p className="M" style={{fontSize:'clamp(1rem,2.5vw,1.5rem)',letterSpacing:'.1em',textTransform:'uppercase',opacity:.8,marginTop:'var(--space-05)'}}>{subtitle}</p></>;
}

// ═══════════════════════════════════════
// SLIDE RENDERER DISPATCHER
// ═══════════════════════════════════════
const RENDERERS={
  attract:AttractSlide,fishbowl:FishbowlSlide,red_flag:RedFlagSlide,round_title:RoundTitleSlide,tier_title:TierTitleSlide,
  bonus_marker:BonusMarkerSlide,source_q:SourceQSlide,source_a:SourceASlide,acronym_q:AcronymQSlide,
  acronym_a:AcronymASlide,fluency_line:FluencyLineSlide,fluency_source:FluencySourceSlide,
  score:ScoreSlide,intermission:IntermissionSlide,doa_vote:DoaVoteSlide,warning:WarningSlide,
  blackout:BlackoutSlide,transition_beat:TransitionBeatSlide,doa_ref:DoaRefSlide,
  doa_verdict_dead:DoaVerdictDeadSlide,doa_verdict_alive:DoaVerdictAliveSlide,
  hotseat_rules:HotseatRulesSlide,hotseat_prompt:HotseatPromptSlide,verdict:VerdictSlide,
  sentence:SentenceSlide,receipt_rain:ReceiptRainSlide,crate_drop:CrateDropSlide,
  last_line:LastLineSlide,endcard:EndcardSlide,answer_sheet:AnswerSheetSlide,
  checkin:CheckinSlide,
};

function SlideRenderer({slide,revealed}){
  const Comp=RENDERERS[slide.type];
  if(!Comp)return null;
  return <Comp slide={slide} revealed={revealed}/>;
}
