/* ============================================================
   SHADOW STEP — app-motion
   Lenis smooth scroll + GSAP3 / ScrollTrigger orchestration.
   Waits for card islands, then choreographs all 7 sections.
   ============================================================ */
(function(){
  const SS = window.SS = window.SS || {};
  const REDUCED = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  const TOUCH = window.matchMedia('(hover: none), (pointer: coarse)').matches;
  gsap.registerPlugin(ScrollTrigger);

  /* Responsive fit scale for the pinned deep-dive card (Section 3).
     Reserves vertical room top + bottom so the phase heading and the
     closing line never sit on top of the card — mobile-first. */
  function computeCardFit(){
    const vh = window.innerHeight, vw = window.innerWidth;
    const h = (vh - 300) / 520;   // ~150px clearance top + bottom
    const w = (vw - 28)  / 360;   // side gutters on narrow screens
    return Math.max(0.5, Math.min(1, h, w));
  }
  let cardFit = computeCardFit();
  window.addEventListener('resize', () => { cardFit = computeCardFit(); });

  function start(){
    if(!window.gsap){ return setTimeout(start, 60); }
    SS.heroVar = localStorage.getItem('ss-hero') || 'scatter';
    document.querySelectorAll('#switcher button').forEach(b=>{
      b.classList.toggle('on', b.dataset.hero===SS.heroVar);
      b.addEventListener('click', ()=>{
        document.querySelectorAll('#switcher button').forEach(x=>x.classList.remove('on'));
        b.classList.add('on'); SS.heroVar=b.dataset.hero;
        localStorage.setItem('ss-hero', SS.heroVar);
        applyHeroLayout(SS.heroVar, true, true);
        ScrollTrigger.refresh();
      });
    });

    if(REDUCED){ reducedMode(); return; }

    initLenis();
    boot();
    setupWelcome();
    setupMap();
    setupCardSection();
    setupFeed();
    setupCarousel();
    setupCTA();
    setupSecIndex();
    setupScrollLinks();

    // re-measure once fonts + islands settle
    setTimeout(()=>ScrollTrigger.refresh(), 400);
    setTimeout(()=>ScrollTrigger.refresh(), 1200);
  }

  /* ── Lenis ──────────────────────────────────────── */
  let lenis;
  function initLenis(){
    lenis = new Lenis({ lerp:0.09, wheelMultiplier:1, smoothWheel:true });
    SS.lenis = lenis;
    lenis.on('scroll', ScrollTrigger.update);
    gsap.ticker.add((t)=>lenis.raf(t*1000));
    gsap.ticker.lagSmoothing(0);
    lenis.stop(); // until boot completes
  }

  /* ── Boot overlay ───────────────────────────────── */
  function boot(){
    const boot = document.getElementById('boot');
    const line = boot.querySelector('.bootline');
    const tl = gsap.timeline();
    tl.to(line,{opacity:1,duration:.5})
      .to({},{duration:.9})
      .to(line,{opacity:0,duration:.4})
      .to(boot,{autoAlpha:0,duration:.6,onComplete:()=>{ boot.style.display='none'; lenis && lenis.start(); }})
      .add(()=>heroIntro(), '-=0.2');
  }

  /* ════ SECTION 0 — VOID ═══════════════════════════ */
  function layoutPos(L, stage){
    const w = stage.clientWidth, h = stage.clientHeight;
    return { x:(L.x-50)/100*w, y:(L.y-50)/100*h };
  }
  function applyHeroLayout(v, animate, fromSwitch){
    const L = SS.heroLayouts[v] || SS.heroLayouts.scatter;
    const stage = document.getElementById('voidStage');
    const hero = document.getElementById('heroCard');
    const heroP = layoutPos(L.hero, stage);
    const heroVars = { xPercent:-50, yPercent:-50, x:heroP.x, y:heroP.y, scale:L.hero.scale, rotationY:0, z:L.hero.z, autoAlpha:1 };
    const scVars = (el,cfg)=>{ const p=layoutPos(cfg,stage); return {
      xPercent:-50, yPercent:-50, x:p.x, y:p.y, scale:cfg.scale, z:cfg.z,
      rotation:cfg.rot||0, filter:`blur(${cfg.blur||0}px)`, autoAlpha:cfg.hide?0:1 }; };
    if(animate){
      gsap.to(hero, { ...heroVars, duration:1, ease:'power3.inOut' });
      SS.scatterEls.forEach((el,i)=>{ const cfg=L.scatter[i%L.scatter.length]; gsap.to(el, {...scVars(el,cfg), duration:1, ease:'power3.inOut', delay:i*0.04}); });
    } else {
      gsap.set(hero, heroVars);
      SS.scatterEls.forEach((el,i)=>{ const cfg=L.scatter[i%L.scatter.length]; gsap.set(el, scVars(el,cfg)); });
    }
  }
  SS.applyHeroLayout = applyHeroLayout;

  function heroIntro(){
    const stage=document.getElementById('voidStage');
    const hero=document.getElementById('heroCard');
    const L=SS.heroLayouts[SS.heroVar]||SS.heroLayouts.scatter;
    // initial: hero hidden small center, scatter stacked center hidden, grid flat
    gsap.set('#voidGrid',{autoAlpha:0, scale:1.4});
    gsap.set('#voidMark',{opacity:0, visibility:'visible', scale:1.15});
    gsap.set(hero,{xPercent:-50,yPercent:-50,x:0,y:0,scale:.7,z:0,autoAlpha:0});
    gsap.set(SS.scatterEls,{xPercent:-50,yPercent:-50,x:0,y:0,scale:.5,z:-200,autoAlpha:0,filter:'blur(6px)'});
    gsap.set('#heroCopy .reveal',{autoAlpha:0,y:24});
    gsap.set('#scrollCue',{autoAlpha:0});

    const tl=gsap.timeline();
    tl.to('#voidGrid',{autoAlpha:1,scale:1,duration:1.6,ease:'power2.out'})
      .to('#voidMark',{opacity:.025,scale:1,duration:1.6,ease:'power2.out'},'<')
      .to(hero,{autoAlpha:1,scale:L.hero.scale,duration:1.1,ease:'power3.out'},'-=1.0')
      .add(()=>{ // line-reveal header
        gsap.to('#heroCopy .reveal',{autoAlpha:1,y:0,duration:.7,stagger:.14,ease:'power3.out'});
      },'-=0.2')
      .add(()=>scanSweep('#voidScan','#voidStage'),'-=0.4')
      // ZOOM-OUT reveal of the scattered city
      .add(()=>{ applyHeroLayout(SS.heroVar, true); }, '+=0.25')
      .to('#scrollCue',{autoAlpha:1,duration:.6},'+=0.6');

    if(SS.heroVar==='monolith') scanSweepLoop('#voidScan','#voidStage');

    heroParallax();
    heroScrollParallax();
  }

  function scanSweep(sel, stageSel){
    const stage=document.querySelector(stageSel);
    gsap.fromTo(sel,{x:0,autoAlpha:0},{x:stage.clientWidth,autoAlpha:1,duration:2.0,ease:'power1.inOut',
      onComplete:()=>gsap.to(sel,{autoAlpha:0,duration:.3})});
  }
  function scanSweepLoop(sel,stageSel){
    const stage=document.querySelector(stageSel);
    gsap.fromTo(sel,{x:0,autoAlpha:.9},{x:stage.clientWidth,duration:3.4,ease:'none',repeat:-1});
  }

  function heroParallax(){
    if(TOUCH) return;
    const gridX=gsap.quickTo('#voidGrid','x',{duration:.8,ease:'power2'});
    const gridY=gsap.quickTo('#voidGrid','y',{duration:.8,ease:'power2'});
    const scX=gsap.quickTo('#scatter','x',{duration:1.1,ease:'power2'});
    const scY=gsap.quickTo('#scatter','y',{duration:1.1,ease:'power2'});
    const mkX=gsap.quickTo('#voidMark','x',{duration:1.4,ease:'power2'});
    window.addEventListener('pointermove',(e)=>{
      const dx=(e.clientX/window.innerWidth-.5), dy=(e.clientY/window.innerHeight-.5);
      gridX(dx*-30); gridY(dy*-30); scX(dx*48); scY(dy*48); mkX(dx*-18);
    });
  }
  function heroScrollParallax(){
    gsap.to('#voidGrid',{yPercent:18,ease:'none',scrollTrigger:{trigger:'#void',start:'top top',end:'bottom top',scrub:true}});
    gsap.to('#voidMark',{yPercent:-30,ease:'none',scrollTrigger:{trigger:'#void',start:'top top',end:'bottom top',scrub:true}});
    gsap.to('#scatter',{yPercent:-12,ease:'none',scrollTrigger:{trigger:'#void',start:'top top',end:'bottom top',scrub:true}});
    gsap.to('#heroCard',{yPercent:8,autoAlpha:.2,ease:'none',scrollTrigger:{trigger:'#void',start:'top top',end:'70% top',scrub:true}});
  }

  /* ════ SECTION 1 — WELCOME ════════════════════════ */
  function setupWelcome(){
    gsap.set('#welcome .reveal',{autoAlpha:0,y:30});
    ScrollTrigger.create({ trigger:'#welcome', start:'top 64%', once:true, onEnter:()=>{
      gsap.to('#welcome .kicker',{autoAlpha:1,y:0,duration:.6,ease:'power3.out'});
      gsap.to('#bootDialog',{autoAlpha:1,y:0,duration:.8,ease:'power3.out',delay:.1});
    }});
    // confirm → acknowledge in the boot dialog hint
    const hint=document.querySelector('#bootDialog .bd-hint');
    const confirm=()=>{
      const inp=document.getElementById('cityInput');
      if(inp && !inp.value) inp.value='your city';
      if(hint){ hint.textContent='court located · the city is watching'; }
    };
    document.getElementById('welcomeYes').addEventListener('click', confirm);
    document.getElementById('cityInput').addEventListener('keydown',e=>{ if(e.key==='Enter')confirm(); });
  }

  /* ════ SECTION 2 — THE MAP (real Mapbox overworld) ═ */
  // Chennai POIs (mirrors the published Midnight Court map). g = marker glyph.
  const MAP_POIS = [
    {g:'T',lng:80.2604,lat:13.0514,status:'live'},   {g:'T',lng:80.2288,lat:12.9743,status:'dormant'},
    {g:'T',lng:80.2318,lat:13.0080,status:'dormant'},{g:'C',lng:80.2742,lat:13.0449,status:'live'},
    {g:'C',lng:80.2525,lat:12.9897,status:'live'},   {g:'C',lng:80.2108,lat:13.0876,status:'dormant'},
    {g:'C',lng:80.2384,lat:13.0526,status:'dormant'},{g:'C',lng:80.2076,lat:12.9056,status:'dormant'},
    {g:'C',lng:80.2432,lat:12.8942,status:'live'},   {g:'C',lng:80.2288,lat:13.0000,status:'dormant'},
    {g:'C',lng:80.2339,lat:13.0304,status:'locked'}, {g:'C',lng:80.2218,lat:12.9825,status:'locked'},
    {g:'C',lng:80.2366,lat:13.0304,status:'locked'}, {g:'G',lng:80.2151,lat:13.0682,status:'dormant'},
    {g:'G',lng:80.2268,lat:13.0383,status:'dormant'},{g:'G',lng:80.2236,lat:12.9827,status:'dormant'},
    {g:'G',lng:80.2271,lat:13.0071,status:'dormant'},{g:'G',lng:80.2382,lat:12.8965,status:'dormant'},
    {g:'S',lng:80.2208,lat:12.9845,status:'dormant'},{g:'S',lng:80.2456,lat:12.8903,status:'dormant'},
    {g:'P',lng:80.2242,lat:12.9897,status:'dormant'},{g:'P',lng:80.2406,lat:12.9968,status:'dormant'},
    {g:'+',lng:80.2135,lat:13.0777,status:'dormant'},{g:'+',lng:80.2288,lat:12.9897,status:'dormant'},
    {g:'+',lng:80.2344,lat:13.0512,status:'dormant'}
  ];

  function initMap(){
    if(SS.map || !window.mapboxgl) return SS.map;
    try{
      mapboxgl.accessToken = 'pk.eyJ1IjoibWVyY2F0b3IyMyIsImEiOiJjbXB1czhqeDUxbGV1MnNzbHB5ZXhkNWR4In0.vFrh1QHR1VMhXPzci1yPEQ';
      const map = new mapboxgl.Map({
        container:'mapGL',
        style:'mapbox://styles/mercator23/cmpvcsm0x000k01r38sme3z4k',
        center:[80.2267,13.0807], zoom:11.0, pitch:22, bearing:0,
        interactive:false, attributionControl:false, fadeDuration:120
      });
      SS.map = map;
      map.on('load', ()=>{
        const home=document.createElement('div'); home.className='ss-marker home';
        new mapboxgl.Marker({element:home}).setLngLat([80.2707,13.0827]).addTo(map);
        MAP_POIS.forEach(p=>{
          const el=document.createElement('div');
          el.className='ss-marker '+(p.status==='live'?'live':p.status==='locked'?'locked':'dormant');
          el.textContent=p.g;
          new mapboxgl.Marker({element:el}).setLngLat([p.lng,p.lat]).addTo(map);
        });
      });
      map.on('error', e=>{ if(e&&e.error) console.warn('Mapbox:', e.error.message||e.error); });
    }catch(e){ console.warn('Mapbox init failed', e); }
    return SS.map;
  }
  SS.initMap = initMap;

  function setupMap(){
    const REVEAL=['#ent-court','#ent-gym','#ent-rehab','#ent-bounty'];
    gsap.set(REVEAL,{autoAlpha:0,scale:.86,y:18});
    gsap.set(['#mapCap1','#mapCap2'],{autoAlpha:0,y:16});
    gsap.set('#mapLogo',{autoAlpha:0,scale:1.1});
    gsap.set('#mapReticle',{autoAlpha:0});

    const map=initMap();

    // constant scan beam
    const stageW=()=>document.getElementById('map').clientWidth;
    gsap.fromTo('#mapScan',{x:-10},{x:stageW()+10,duration:3.2,ease:'none',repeat:-1});

    // camera presets — each entity card points to its real venue type
    const WIDE  ={center:[80.2267,13.0807],zoom:11.0,pitch:22,bearing:0};
    const COURT ={center:[80.2742,13.0449],zoom:15.2,pitch:52,bearing:-24}; // Marina Loop Court · LIVE
    const GYM   ={center:[80.2268,13.0383],zoom:15.4,pitch:55,bearing:28};  // Iron Park Gym · T. Nagar
    const REHAB ={center:[80.2344,13.0512],zoom:15.3,pitch:48,bearing:-12}; // Apex Rehab · Nungambakkam
    const BOUNTY={center:[80.2432,12.8942],zoom:15.9,pitch:62,bearing:46};  // Hoopstars Academy · OMR

    const fly =(c,dur)=>{ try{ if(map) map.flyTo({...c,duration:dur*1000,curve:1.5,essential:true}); }catch(e){} };
    const jump=(c)=>{ try{ if(map) map.jumpTo(c); }catch(e){} };

    const reticleIn =()=>gsap.fromTo('#mapReticle',{autoAlpha:0,scale:1.35},{autoAlpha:1,scale:1,duration:.5,ease:'power3.out'});
    const reticleOut=()=>gsap.to('#mapReticle',{autoAlpha:0,duration:.35});

    const tl=gsap.timeline({paused:true,
      onUpdate:()=>{ document.getElementById('mapProgress').style.width=(tl.progress()*100).toFixed(1)+'%'; }});

    // SHOT 1 — wide establishing
    tl.add(()=>jump(WIDE))
      .to('#mapCap1',{autoAlpha:1,y:0,duration:.7},'+=0.4')
      .to('#mapCap1',{autoAlpha:0,duration:.5},'+=1.6')
    // SHOT 2 — community court
      .add(()=>fly(COURT,2.4))
      .to({},{duration:2.0})
      .add(reticleIn)
      .to('#ent-court',{autoAlpha:1,scale:1,y:0,duration:.6,ease:'back.out(1.4)'},'-=0.2')
      .to({},{duration:1.5})
      .add(reticleOut)
      .to('#ent-court',{autoAlpha:0,scale:.9,duration:.4},'<')
    // SHOT 3 — gym
      .add(()=>fly(GYM,2.4))
      .to({},{duration:2.0})
      .add(reticleIn)
      .to('#ent-gym',{autoAlpha:1,scale:1,y:0,duration:.6,ease:'back.out(1.4)'},'-=0.2')
      .to({},{duration:1.5})
      .add(reticleOut)
      .to('#ent-gym',{autoAlpha:0,scale:.9,duration:.4},'<')
    // SHOT 4 — auth / recovery centre
      .add(()=>fly(REHAB,2.4))
      .to({},{duration:2.0})
      .add(reticleIn)
      .to('#ent-rehab',{autoAlpha:1,scale:1,y:0,duration:.6,ease:'back.out(1.4)'},'-=0.2')
      .to({},{duration:1.5})
      .add(reticleOut)
      .to('#ent-rehab',{autoAlpha:0,scale:.9,duration:.4},'<')
    // SHOT 5 — bounty quest (dramatic)
      .add(()=>fly(BOUNTY,2.6))
      .to({},{duration:2.2})
      .add(reticleIn)
      .to('#ent-bounty',{autoAlpha:1,scale:1.05,y:0,duration:.7,ease:'back.out(1.6)'},'-=0.2')
      .to('#mapCap2',{autoAlpha:1,y:0,duration:.6},'-=0.3')
      .to({},{duration:1.7})
      .add(reticleOut)
      .to(['#ent-bounty','#mapCap2'],{autoAlpha:0,duration:.5},'<')
    // SHOT 6 — pull back out + logo
      .add(()=>fly(WIDE,2.5))
      .to('#mapGL',{autoAlpha:.45,duration:1.1,ease:'power2.inOut'},'-=1.4')
      .to('#mapLogo',{autoAlpha:1,scale:1,duration:1.0,ease:'power3.out'},'-=0.7')
      .to({},{duration:1.2})
      .to('#mapLogo',{autoAlpha:0,scale:.96,duration:.6})
      .to('#mapGL',{autoAlpha:1,duration:.6},'-=0.3');

    SS.mapTL=tl;
    const mapST = ScrollTrigger.create({
      trigger:'#map', start:'top top', end:'+=150%', pin:true, pinSpacing:true,
      onEnter:()=>{
        if(tl._played) return; tl._played=true;
        const go=()=>{ tl.play(0); autoFlyThrough(); };
        if(map && map.loaded && map.loaded()) go();
        else if(map){ map.once('idle',go); setTimeout(()=>{ if(tl.progress()===0) go(); },3500); }
        else go();
      },
    });
    SS.mapST = mapST;

    /* ── Guided flow ──────────────────────────────────
       The map is a self-playing cinematic, so plain scrolling through the
       pin felt disconnected. We now glide the page through the pinned
       fly-through in sync with the timeline and slide straight into the
       next section. Any user scroll/touch instantly takes back control. */
    function autoFlyThrough(){
      if(TOUCH || !lenis) return;            // touch: let the finger drive
      const dur = Math.max(7, tl.duration()); // seconds — matches the cinematic
      lenis.scrollTo(mapST.end, { duration:dur, easing:t=>t });
    }
    // Flow IN — once the map is clearly committed, glide it up to lock at top.
    ScrollTrigger.create({ trigger:'#map', start:'top 38%', once:true,
      onEnter:()=>{ if(!TOUCH && lenis && !tl._played) lenis.scrollTo('#map',{duration:1.0}); } });
  }

  /* ════ SECTION 3 — THE CARD ═══════════════════════ */
  function setupCardSection(){
    const sets={1:'#anno-1',2:'#anno-2',3:'#anno-3'};
    let phase=0;
    const phaseLabel={0:'',1:'<b>01</b> · THE IDENTITY LAYER',2:'<b>02</b> · THE PERFORMANCE LAYER',3:'<b>03</b> · THE RECORD',4:''};
    function showSet(n){
      Object.values(sets).forEach(s=>gsap.to(s,{autoAlpha:0,duration:.3}));
      gsap.set('#cardCloser',{autoAlpha:0});
      if(n>=1 && n<=3){
        const root=document.querySelector(sets[n]);
        gsap.to(root,{autoAlpha:1,duration:.3});
        const annos=root.querySelectorAll('.anno');
        gsap.fromTo(annos,{autoAlpha:0,y:14},{autoAlpha:1,y:0,duration:.5,stagger:.1,ease:'power3.out'});
        annos.forEach(a=>{ const d=a.querySelector('.dash'); gsap.fromTo(d,{width:0},{width:80,duration:.5,delay:.2,ease:'power2.out'}); });
      }
    }
    function setPhase(n){
      if(n===phase) return; phase=n;
      document.getElementById('cardPhase').innerHTML=phaseLabel[n]||'';
      gsap.to('#cardPhase',{autoAlpha:n>=1&&n<=3?1:0,duration:.3});
      const wantBack = (n===3);
      if(SS.deepBack!==wantBack && n!==4) SS.flipDeep(wantBack);
      if(n===4){
        if(SS.deepBack) SS.flipDeep(false);
        SS.setDeepInteractive(true);
        Object.values(sets).forEach(s=>gsap.to(s,{autoAlpha:0,duration:.3}));
        gsap.to('#cardCloser',{autoAlpha:1,duration:.6,ease:'power3.out'});
      } else {
        SS.deepInteractive=false; SS.setDeepInteractive(false);
        showSet(n);
      }
    }

    const st = ScrollTrigger.create({
      trigger:'#card', start:'top top', end:'+=340%', pin:true, pinSpacing:true, scrub:1,
      onUpdate:(self)=>{
        const p=self.progress;
        // entrance
        const e=gsap.utils.clamp(0,1,p/0.12);
        gsap.set('#deepCard',{scale:cardFit*(0.82+0.18*e), autoAlpha:e});
        if(p<0.14) setPhase(0);
        else if(p<0.36) setPhase(1);
        else if(p<0.60) setPhase(2);
        else if(p<0.84) setPhase(3);
        else setPhase(4);
      },
    });
    SS.cardST=st;
  }

  /* ════ SECTION 4 — THE FEED ═══════════════════════ */
  function setupFeed(){
    gsap.set('#feed .reveal',{autoAlpha:0,y:28});
    ScrollTrigger.create({trigger:'#feed .feed-head',start:'top 72%',once:true,onEnter:()=>
      gsap.to('#feed .reveal',{autoAlpha:1,y:0,duration:.7,stagger:.12,ease:'power3.out'})});
    const items=gsap.utils.toArray('#feed .item');
    gsap.set(items,{autoAlpha:0,y:40});
    items.forEach((it)=>{
      ScrollTrigger.create({trigger:it,start:'top 84%',once:true,onEnter:()=>{
        gsap.to(it,{autoAlpha:1,y:0,duration:.7,ease:'power3.out'});
        const scan=it.querySelector('.scan');
        gsap.fromTo(scan,{x:0,autoAlpha:.9},{x:it.clientWidth,duration:.9,ease:'power1.inOut',onComplete:()=>gsap.set(scan,{autoAlpha:0})});
      }});
    });
  }

  /* ════ SECTION 5 — CAROUSEL ═══════════════════════ */
  function setupCarousel(){
    const track=document.getElementById('carTrack');
    const slides=gsap.utils.toArray('#carousel .cslide');
    const dots=gsap.utils.toArray('#carNav i');
    const carousel=document.getElementById('carousel');
    gsap.set('#carousel .car-head .reveal',{autoAlpha:0,y:24});

    // deal-out intro
    let dealt=false;
    ScrollTrigger.create({trigger:'#carousel',start:'top 60%',once:true,onEnter:()=>{
      gsap.to('#carousel .car-head .reveal',{autoAlpha:1,y:0,duration:.7,stagger:.12,ease:'power3.out'});
      if(!dealt){ dealt=true;
        gsap.fromTo(slides,{autoAlpha:0,y:80,rotation:(i)=>(i-1)*4,scale:.8},
          {autoAlpha:1,y:0,rotation:0,scale:1,duration:.8,stagger:.08,ease:'power3.out'});
      }
    }});

    function tint(i){
      const hue=SS.carHues[i]||'#C41E1E';
      carousel.style.background=`radial-gradient(120% 90% at 50% 42%, ${hexA(hue,.14)} 0%, var(--black-warm) 62%)`;
    }
    function active(){
      const c=track.scrollLeft+track.clientWidth/2;
      let best=0,bd=1e9;
      slides.forEach((s,i)=>{ const sc=s.offsetLeft+s.offsetWidth/2; const d=Math.abs(sc-c); if(d<bd){bd=d;best=i;}
        const dist=Math.min(1,d/(track.clientWidth*.5));
        gsap.set(s,{scale:1-dist*0.12, autoAlpha:1-dist*0.45});
      });
      dots.forEach((dt,i)=>dt.classList.toggle('on',i===best));
      tint(best);
    }
    track.addEventListener('scroll',()=>requestAnimationFrame(active),{passive:true});
    dots.forEach((dt,i)=>dt.addEventListener('click',()=>{
      const s=slides[i]; track.scrollTo({left:s.offsetLeft-(track.clientWidth-s.offsetWidth)/2,behavior:'smooth'});
    }));
    setTimeout(active,300); setTimeout(active,1000);

    // drag to scroll (desktop)
    if(!TOUCH){
      let down=false,sx=0,sl=0;
      track.addEventListener('pointerdown',e=>{down=true;sx=e.clientX;sl=track.scrollLeft;track.setPointerCapture(e.pointerId);track.style.cursor='grabbing';});
      track.addEventListener('pointermove',e=>{ if(down) track.scrollLeft=sl-(e.clientX-sx); });
      const up=()=>{down=false;track.style.cursor='';};
      track.addEventListener('pointerup',up); track.addEventListener('pointercancel',up);
    }
    // keep carousel from hijacking vertical scroll via wheel on the track? leave native.
  }

  /* ════ SECTION 6 — CTA ════════════════════════════ */
  function setupCTA(){
    gsap.set('#cta .reveal',{autoAlpha:0,y:30});
    ScrollTrigger.create({trigger:'#cta',start:'top 60%',once:true,onEnter:()=>
      gsap.to('#cta .reveal',{autoAlpha:1,y:0,duration:.7,stagger:.1,ease:'power3.out'})});

    const form=document.getElementById('ctaForm');
    form.addEventListener('submit',e=>{
      e.preventDefault();
      const email=document.getElementById('ctaEmail').value.trim();
      if(!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)){
        gsap.fromTo('#ctaForm',{x:-6},{x:0,duration:.4,ease:'elastic.out(1,0.3)'});
        document.querySelector('#ctaForm .field').style.borderColor='var(--red-flare)';
        return;
      }
      const inner=document.getElementById('ctaInner');
      const result=document.getElementById('ctaResult');
      gsap.to(inner,{autoAlpha:0,y:-20,duration:.5,onComplete:()=>{
        inner.style.display='none'; result.style.display='block';
        SS.genCard();
        document.getElementById('draftNum').textContent='#'+(1000+Math.floor(Math.random()*900));
        gsap.fromTo('#genCard',{autoAlpha:0,scale:.7,rotationY:-60},{autoAlpha:1,scale:1,rotationY:0,duration:1.1,ease:'power3.out'});
        gsap.fromTo('#ctaResult .draftno,#ctaResult .draftsub,#ctaResult .share',{autoAlpha:0,y:20},{autoAlpha:1,y:0,duration:.6,stagger:.12,delay:.5,ease:'power3.out'});
        ScrollTrigger.refresh();
      }});
    });
    document.getElementById('againBtn').addEventListener('click',()=>{
      SS.genCard();
      gsap.fromTo('#genCard',{autoAlpha:0,scale:.8,rotationY:-50},{autoAlpha:1,scale:1,rotationY:0,duration:.9,ease:'power3.out'});
      document.getElementById('draftNum').textContent='#'+(1000+Math.floor(Math.random()*900));
    });
    document.getElementById('shareBtn').addEventListener('click',function(){
      const t=this.textContent; this.textContent='Copied to clipboard';
      try{navigator.clipboard&&navigator.clipboard.writeText('I just entered the Shadow Step draft. '+document.getElementById('draftNum').textContent);}catch(e){}
      setTimeout(()=>this.textContent=t,1600);
    });
  }

  /* ── helpers ────────────────────────────────────── */
  function hexA(hex,a){ const h=hex.replace('#',''); const r=parseInt(h.slice(0,2),16),g=parseInt(h.slice(2,4),16),b=parseInt(h.slice(4,6),16); return `rgba(${r},${g},${b},${a})`; }

  /* ── Section index dots ─────────────────────────── */
  function setupSecIndex(){
    const dots=gsap.utils.toArray('#secIndex i');
    gsap.utils.toArray('main .section').forEach(sec=>{
      ScrollTrigger.create({trigger:sec,start:'top 50%',end:'bottom 50%',
        onToggle:self=>{ if(self.isActive){ const i=+sec.dataset.i; dots.forEach(d=>d.classList.toggle('on',+d.dataset.i===i)); } }});
    });
  }

  /* ── Scroll-to links ────────────────────────────── */
  function setupScrollLinks(){
    document.body.addEventListener('click',e=>{
      const t=e.target.closest('[data-scroll]'); if(!t) return;
      const target=document.querySelector(t.dataset.scroll); if(!target) return;
      if(lenis) lenis.scrollTo(target,{offset:0,duration:1.6}); else target.scrollIntoView();
    });
  }

  /* ── Reduced-motion: static end-states ──────────── */
  function reducedMode(){
    document.getElementById('boot').style.display='none';
    applyHeroLayout(SS.heroVar,false);
    gsap.set('#voidGrid',{autoAlpha:1});
    gsap.set('#voidMark',{opacity:.025, visibility:'visible'});
    document.querySelectorAll('.reveal').forEach(el=>{el.style.opacity=1;el.style.transform='none';});
    document.getElementById('heroCard').style.opacity=1;
    // map static end-state: real map (wide), 4 entities laid out + caption
    if(SS.initMap) SS.initMap();
    gsap.set('#mapWorld',{autoAlpha:1});
    gsap.set('#mapReticle',{autoAlpha:0});
    const ents=['#ent-court','#ent-gym','#ent-rehab','#ent-bounty']; const pos=[[28,30],[70,30],[30,70],[72,70]];
    ents.forEach((id,i)=>{const e=document.querySelector(id);e.style.left=pos[i][0]+'%';e.style.top=pos[i][1]+'%';gsap.set(e,{autoAlpha:1,scale:.92});});
    gsap.set('#mapCap1',{autoAlpha:1});
    // card: front, annotations set 1 visible, interactive
    gsap.set('#deepCard',{autoAlpha:1,scale:cardFit}); SS.setDeepInteractive(true);
    gsap.set('#anno-1',{autoAlpha:1}); document.querySelectorAll('#anno-1 .anno').forEach(a=>{a.style.opacity=1;a.querySelector('.dash').style.width='80px';});
    gsap.set('#cardCloser',{autoAlpha:1});
    // feed + carousel visible
    gsap.set('#feed .item',{autoAlpha:1,y:0});
    gsap.set('#carousel .cslide',{autoAlpha:1,y:0});
    setupScrollLinks();
    // CTA form still functional
    setupCTA();
  }

  /* boot when cards are ready */
  if(SS.scatterEls) start();
  else window.addEventListener('ss-cards-ready', start, {once:true});
})();
