function AudienceView({state,dispatch,slideRef:externalSlideRef,rewardTier}){
  const flat=useMemo(()=>flattenSlides(state.show,state.redFlags,state.extrasBypassed,state.bonusSections),[state.show,state.redFlags,state.extrasBypassed,state.bonusSections]);
  const slide=flat[state.currentSlide];
  const prevSlideRef=useRef(null);
  const localSlideRef=useRef(null);
  const[audioReady,setAudioReady]=useState(false);
  const[overlayDismissed,setOverlayDismissed]=useState(false);
  // Use external ref if provided (for timer sync), otherwise local
  const slideRef=externalSlideRef||localSlideRef;

  function unlockAudio(){initAudio();if(actx&&actx.state==='suspended')actx.resume();setAudioReady(true);setOverlayDismissed(true)}

  // Auto-dismiss the full-screen audio prompt after 3s. Show stays usable; if audio
  // never unlocks (iOS, no tap), a small corner pill stays as a hint.
  useEffect(function(){if(audioReady||overlayDismissed)return;var t=setTimeout(function(){setOverlayDismissed(true)},3000);return function(){clearTimeout(t)}},[audioReady,overlayDismissed]);

  useEffect(()=>{
    if(!slide)return;
    const el=slideRef.current;
    if(!el)return;
    // Reset timer on slide change
    stopTimerSystem();
    // Remove old transition classes
    el.className='S on';
    void el.offsetHeight;
    el.classList.add(tx(slide.type));
    // Sound
    sfx(slide.type,state.muted);
    // Particles
    stopParticles();
    if(slide.type==='receipt_rain')startParticles('rain');
    if(slide.type==='last_line'||slide.type==='endcard')startParticles('flutter');
    prevSlideRef.current=state.currentSlide;
  },[state.currentSlide,slide]);

  if(!slide)return <div className="audience-view"><div className="S on"><div className="D hp" style={{fontSize:'clamp(60px,12vw,180px)'}}>LOADING...</div></div></div>;

  const revealed=(state.revealState[slide.id]||'hidden')==='revealed';

  return (
    <div className="audience-view">
      {!audioReady&&!overlayDismissed&&<div onClick={unlockAudio} style={{position:'fixed',inset:0,zIndex:9999,background:'var(--void)',display:'flex',alignItems:'center',justifyContent:'center',cursor:'pointer'}}>
        <div style={{fontFamily:"'Space Mono',monospace",fontSize:'clamp(28px,4vw,80px)',color:'#fff',textTransform:'uppercase',letterSpacing:'.1em'}}>TAP TO ENABLE AUDIO</div>
      </div>}
      {!audioReady&&overlayDismissed&&<div onClick={unlockAudio} style={{position:'fixed',top:12,right:12,zIndex:9998,padding:'4px 8px',background:'rgba(0,0,0,.6)',border:'1px solid rgba(255,255,255,.2)',color:'rgba(255,255,255,.6)',fontFamily:"'Space Mono',monospace",fontSize:10,letterSpacing:'.1em',textTransform:'uppercase',cursor:'pointer'}} title="Tap to enable audio">🔇 AUDIO OFF</div>}
      <div ref={slideRef} className="S on">
        <SlideRenderer slide={slide} revealed={revealed}/>
      </div>
      <div id="sbug" className={(state.showScoreboard?'on':'')+(state.scoreboardPosition==='top'?' top':'')}>
        <div className="team"><span className="lbl">CYAN</span><span className="sc-cy">{state.scores[0]}</span></div>
        <div className="vs">VS</div>
        <div className="team"><span className="sc-pk">{state.scores[1]}</span><span className="lbl">PINK</span></div>
      </div>
      <RewardTierOverlay tier={rewardTier}/>
    </div>
  );
}
