/* Rolo Marketing Wireframes — Variants top half (sections 1-5)
 * HeroVariants, PlatformVariants, ModulesVariants, OSVariants, DeployVariants
 */

const { useEffect, useRef, useState } = React;

/* ============================================================
 * 1. HERO
 * ============================================================ */

/* Robust hero background video.
 * React's `muted` JSX prop sets the property but not always the HTML
 * attribute — iOS Safari checks the attribute to allow autoplay. Below
 * we force the attribute via JS, explicitly call play(), retry on
 * canplay, and fall back to the next user tap on the document.
 * Together this covers: iOS Safari, Chrome Android, Safari with
 * autoplay rejected, and old iOS that needs webkit-playsinline. */
function HeroBackgroundVideo() {
  const ref = useRef(null);
  useEffect(() => {
    const v = ref.current;
    if (!v) return;
    // Force muted attribute + property + webkit-playsinline before any play attempt
    v.muted = true;
    v.defaultMuted = true;
    v.setAttribute('muted', '');
    v.setAttribute('webkit-playsinline', 'true');
    v.setAttribute('playsinline', 'true');

    let cancelled = false;
    const tryPlay = () => {
      if (cancelled || !v) return;
      const p = v.play();
      if (p && typeof p.catch === 'function') p.catch(() => {});
    };
    tryPlay();
    // Retry once the file has enough data
    v.addEventListener('canplay', tryPlay);
    v.addEventListener('loadeddata', tryPlay);
    // Fallback: first user tap anywhere on the page unblocks autoplay
    const onTap = () => tryPlay();
    document.addEventListener('touchstart', onTap, { passive: true, once: true });
    document.addEventListener('click', onTap, { once: true });

    return () => {
      cancelled = true;
      v.removeEventListener('canplay', tryPlay);
      v.removeEventListener('loadeddata', tryPlay);
      document.removeEventListener('touchstart', onTap);
      document.removeEventListener('click', onTap);
    };
  }, []);

  // Direct click-to-play handler — covers Firefox configs where the doc-wide
  // first-tap listener gets swallowed by the video element itself.
  const onTapVideo = () => {
    const v = ref.current;
    if (v && v.paused) { const p = v.play(); if (p && typeof p.catch === 'function') p.catch(() => {}); }
  };

  return (
    <video
      ref={ref}
      poster="assets/hero-poster.jpg"
      muted
      defaultMuted
      autoPlay
      loop
      playsInline
      preload="auto"
      src={window.A('heroVideo')}
      onClick={onTapVideo}
      onTouchStart={onTapVideo}
      style={{position:'absolute',inset:0,width:'100%',height:'100%',objectFit:'cover',zIndex:0}}
    />
  );
}

function HeroVariants() {
  return (
    <React.Fragment>
      {/* A — Classic centered */}
      <window.Variant
        letter="A"
        title="Centered classic"
        desc="Headline + sub stacked dead center over the video. Single gold CTA. Scroll indicator anchored to bottom. The closest read to the brief."
        notes={['Headline centered', 'Sub in lighter weight', 'One gold CTA', 'Scroll arrow bottom']}
      >
        <div className="frame wide wf-hero-frame wf-reveal" style={{padding:0,background:'#0B0B0C',color:'#FAF5E9'}}>
          <HeroBackgroundVideo />
          <div style={{position:'absolute',inset:0,background:'rgba(17,12,8,0.45)',zIndex:1}}></div>
          <div style={{position:'absolute',inset:0,display:'flex',flexDirection:'column',justifyContent:'center',alignItems:'center',textAlign:'center',padding:'0 32px',zIndex:2}}>
            <h1 style={{fontSize:'clamp(48px,7vw,108px)',fontWeight:700,letterSpacing:'-0.04em',lineHeight:0.94,margin:0,color:'#FFF',maxWidth:'18ch'}}>
              Reimagining<br/>Food Service.
            </h1>
            <p style={{fontSize:'clamp(16px,1.6vw,22px)',color:'rgba(255,255,255,0.85)',fontWeight:400,marginTop:24,maxWidth:'40ch'}}>
              Powered by Robotics and AI.
            </p>
            <a href="https://www.youtube.com/watch?v=_0YhFEbiVZA" target="_blank" rel="noopener" onClick={(e)=>{ e.preventDefault(); window.open('https://www.youtube.com/watch?v=_0YhFEbiVZA','_blank','noopener'); }} className="wf-btn gold" style={{marginTop:32,padding:'14px 28px',fontSize:14}}>See How It Works →</a>
          </div>
          <div className="wf-scroll-ind" style={{zIndex:2}}>
            <span>Scroll</span>
            <span className="arrow"></span>
          </div>
        </div>
      </window.Variant>

      {/* B — Editorial split */}
      <window.Variant
        letter="B"
        title="Editorial split"
        desc="Headline pinned top-left, CTA bottom-right, copy fragments hang off the corners. Lets the video breathe across the centre."
        notes={['Asymmetric anchors', 'Type hugs the corners', 'Mono metadata strip']}
      >
        <div className="frame wide wf-hero-frame wf-reveal" style={{padding:0,background:'#0B0B0C',color:'#FAF5E9'}}>
          <div className="wf-noise-bg"></div>
          <div style={{position:'absolute',inset:0,background:'rgba(17,12,8,0.30)'}}></div>
          <div style={{position:'absolute',inset:'40px 48px'}}>
            <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',marginBottom:32}}>
              <span className="wf-eyebrow" style={{color:'rgba(255,255,255,0.7)'}}>01 / Hero</span>
              <span className="mono" style={{fontSize:11,letterSpacing:'0.22em',textTransform:'uppercase',color:'rgba(255,255,255,0.5)'}}>Singapore · est. 2023</span>
            </div>
            <h1 style={{fontSize:'clamp(56px,8vw,128px)',fontWeight:700,letterSpacing:'-0.045em',lineHeight:0.9,margin:0,color:'#FFF',maxWidth:'14ch'}}>
              Reimagining<br/>food service.
            </h1>
          </div>
          <div style={{position:'absolute',right:48,bottom:40,textAlign:'right',maxWidth:340}}>
            <p style={{fontSize:18,color:'rgba(255,255,255,0.78)',fontWeight:400,margin:'0 0 20px',lineHeight:1.4}}>
              Powered by Robotics and AI.<br/>One platform. Four modules.
            </p>
            <a href="https://www.youtube.com/watch?v=_0YhFEbiVZA" target="_blank" rel="noopener" onClick={(e)=>{ e.preventDefault(); window.open('https://www.youtube.com/watch?v=_0YhFEbiVZA','_blank','noopener'); }} className="wf-btn gold" style={{padding:'14px 26px',fontSize:14}}>See How It Works →</a>
          </div>
          <div style={{position:'absolute',left:48,bottom:40}} className="wf-scroll-ind">
            <span>Scroll</span>
            <span className="arrow"></span>
          </div>
          <span className="wf-anno" style={{top:14,right:170,color:'#E0BD63'}}>Headline anchors NW · CTA anchors SE</span>
        </div>
      </window.Variant>

      {/* C — Stacked manifesto */}
      <window.Variant
        letter="C"
        title="Stacked manifesto"
        desc="Four short declaratives stacked like the brand's signature cadence. Sub becomes the closer line in gold. Most editorial — closest to the brochure voice."
        notes={['Robotics. Software. Food.', 'Last line in gold', 'Heavier voice / quieter UI']}
      >
        <div className="frame wide wf-hero-frame wf-reveal" style={{padding:0,background:'#0B0B0C',color:'#FAF5E9'}}>
          <div className="wf-noise-bg"></div>
          <div style={{position:'absolute',inset:0,background:'rgba(17,12,8,0.34)'}}></div>
          <div style={{position:'absolute',inset:0,display:'flex',flexDirection:'column',justifyContent:'center',padding:'0 56px',gap:8}}>
            <div style={{fontSize:'clamp(40px,5.6vw,84px)',fontWeight:700,letterSpacing:'-0.035em',lineHeight:1,textTransform:'uppercase',color:'#FFF'}}>Robotics.</div>
            <div style={{fontSize:'clamp(40px,5.6vw,84px)',fontWeight:700,letterSpacing:'-0.035em',lineHeight:1,textTransform:'uppercase',color:'#FFF'}}>Software.</div>
            <div style={{fontSize:'clamp(40px,5.6vw,84px)',fontWeight:700,letterSpacing:'-0.035em',lineHeight:1,textTransform:'uppercase',color:'#FFF'}}>Food preparation.</div>
            <div style={{fontSize:'clamp(40px,5.6vw,84px)',fontWeight:700,letterSpacing:'-0.035em',lineHeight:1,textTransform:'uppercase',color:'var(--rr-gold)'}}>Working as one.</div>
            <a href="https://www.youtube.com/watch?v=_0YhFEbiVZA" target="_blank" rel="noopener" onClick={(e)=>{ e.preventDefault(); window.open('https://www.youtube.com/watch?v=_0YhFEbiVZA','_blank','noopener'); }} className="wf-btn gold" style={{alignSelf:'flex-start',marginTop:28,padding:'12px 24px',fontSize:13}}>See How It Works →</a>
          </div>
          <div className="wf-scroll-ind">
            <span>Scroll</span>
            <span className="arrow"></span>
          </div>
          <span className="wf-anno" style={{top:14,right:20,color:'#E0BD63'}}>Manifesto cadence · last line gold</span>
        </div>
      </window.Variant>
    </React.Fragment>
  );
}
window.HeroVariants = HeroVariants;

/* ============================================================
 * 2. MICROKITCHENS PLATFORM
 * ============================================================ */
const COMPLIANCE = [
  'Certified Fire Safety','4-Stage Air Filtration','UVC Disinfection','AI Food Safety Monitoring','Active Pest Containment'
];

/* Compliance strip — lives at the bottom of the Platform section.
   Light surface variant (white section). */
function ComplianceStrip() {
  return (
    <div className="wf-compliance-strip" style={{marginTop:48,paddingTop:24,borderTop:'1px solid var(--wf-line)',display:'flex',flexWrap:'wrap',alignItems:'center',gap:'12px 10px'}}>
      <span className="wf-eyebrow" style={{flex:'none',marginRight:14}}>Compliance</span>
      {COMPLIANCE.map(c=>(
        <span key={c} className="wf-compliance-pill">
          <span className="check" aria-hidden="true">✓</span>{c}
        </span>
      ))}
    </div>
  );
}
function PlatformVariants() {
  const Stats = ({dark}) => (
    <div className="wf-row-stats">
      <span><b>200</b> meals / hr</span>
      <span><b>4</b> live modules</span>
      <span><b>30+</b> sensors</span>
      <span><b>24/7</b> uptime</span>
    </div>
  );
  return (
    <React.Fragment>
      {/* A — Per brief */}
      <window.Variant
        letter="A"
        title="Two-column · per brief"
        desc="Left: headline, body, horizontal stat strip in gold. Right: product photo with floating compliance badge."
        notes={['12-col split 6 + 6', 'Stats sit under body', 'Badge floats over photo']}
      >
        <div className="frame wf-reveal" style={{display:'grid',gridTemplateColumns:'1.05fr 1fr',gap:64,alignItems:'center'}}>
          <div>
            <span className="wf-eyebrow">MicroKitchens Platform</span>
            <h2 className="wf-h1">One platform.<br/>Endless possibilities.</h2>
            <p className="wf-lede">
              A modular autonomous food system. Four cooking modules and one operating system, deployed
              as one cell or twenty. Drop them into a campus food court, a hospital atrium, a transit hub —
              they keep running. Real food. Real throughput. Self-cleaning. Always on.
            </p>
            <div style={{marginTop:32}}><Stats /></div>
            <ComplianceStrip />
          </div>
          <div style={{position:'relative'}}>
            <div className="wf-photo wide has-img" style={{aspectRatio:'4 / 5'}}>
              <img src={window.A("platformCell")} alt="Rolo MicroKitchens cell — MicroFRY module" loading="lazy" />
            </div>
          </div>
          <span className="wf-anno" style={{top:14,right:20}}>Two-column · stats · compliance below</span>
        </div>
      </window.Variant>

      {/* B — Inverted full-bleed */}
      <window.Variant
        letter="B"
        title="Full-bleed product · copy overlay"
        desc="Photography fills the surface. Copy sits in a low-card overlay along the bottom-left. Stats wrap to a thin line over the photo."
        notes={['Photo edge-to-edge', 'Copy in inset card', 'Stats in white over image']}
      >
        <div className="frame wf-reveal" style={{padding:0,position:'relative',minHeight:560}}>
          <div className="wf-photo has-img" style={{position:'absolute',inset:0,borderRadius:0,border:'none'}}>
            <img src={window.A("platformCell")} alt="Rolo MicroKitchens cell — MicroFRY module" loading="lazy" />
          </div>
          <div style={{position:'absolute',left:32,bottom:32,right:32,background:'rgba(255,255,255,0.96)',padding:'28px 32px',borderRadius:8,border:'1px solid var(--wf-line)',maxWidth:640}}>
            <span className="wf-eyebrow">MicroKitchens Platform</span>
            <h2 className="wf-h2">One platform. Endless possibilities.</h2>
            <p className="wf-lede" style={{marginTop:14,fontSize:14}}>
              Modular autonomous food. Four cooking modules + one OS. Deployed as one cell or twenty. Self-cleaning, always on.
            </p>
            <div style={{marginTop:18}}><Stats /></div>
            <ComplianceStrip />
          </div>
          <span className="wf-anno" style={{top:14,left:20}}>Photo full-bleed · copy in floating card</span>
        </div>
      </window.Variant>

      {/* C — Stats-led */}
      <window.Variant
        letter="C"
        title="Stats-led"
        desc="Four giant numbers across the top set the scale. Photography sits in a wide strip. Copy lives below the photo — quiet, supporting."
        notes={['Numbers do the work', 'Photo strip 16:9', 'Eyebrow under copy, not over']}
      >
        <div className="frame wide wf-reveal">
          <div style={{display:'grid',gridTemplateColumns:'repeat(4,1fr)',gap:32,paddingBottom:28,borderBottom:'1px solid var(--wf-line)'}}>
            {[['200','meals / hr'],['4','live modules'],['30+','sensors'],['24/7','uptime']].map(([n,l],i)=>(
              <div key={i} style={{borderLeft:'3px solid var(--rr-gold)',paddingLeft:14}}>
                <div style={{fontSize:'clamp(40px,5vw,72px)',fontWeight:700,letterSpacing:'-0.035em',lineHeight:1,color:'var(--rr-gold)'}}>{n}</div>
                <div className="wf-stat-lbl">{l}</div>
              </div>
            ))}
          </div>
          <div style={{display:'grid',gridTemplateColumns:'1.4fr 1fr',gap:48,marginTop:36,alignItems:'start'}}>
            <div style={{position:'relative'}}>
              <div className="wf-photo wide has-img">
                <img src={window.A("platformCell")} alt="Rolo MicroKitchens cell — MicroFRY module" loading="lazy" />
              </div>
            </div>
            <div>
              <span className="wf-eyebrow">MicroKitchens Platform</span>
              <h3 style={{fontSize:28,fontWeight:700,letterSpacing:'-0.02em',lineHeight:1.05,margin:'14px 0 0'}}>One platform. Endless possibilities.</h3>
              <p className="wf-lede" style={{fontSize:14}}>
                Modular autonomous food preparation. Four cooking modules and one operating system, working as one. Self-cleaning. Always on.
              </p>
            </div>
          </div>
          <ComplianceStrip />
          <span className="wf-anno" style={{top:14,right:20}}>Stats lead · gold left rules · copy is quiet</span>
        </div>
      </window.Variant>
    </React.Fragment>
  );
}
window.PlatformVariants = PlatformVariants;

/* ============================================================
 * 3. THE 4 MODULES — cinematic
 * ============================================================ */

const MODULES = [
  { key:'fry',   name:'Micro', accent:'FRY',   color:'#FF3131', speed:'4 mins',  speedL:'per serving',
    caps:['Auto-recovery fry baskets','Oil quality sensing','Hot-hold buffer','UVC + filter cycle'],
    dishes:[
      { label:'Fried chicken',   img:window.A('fryFriedChicken') },
      { label:'Popcorn chicken', img:window.A('fryPopcornChicken') },
      { label:'Samosas',         img:window.A('frySamosas') },
      { label:'Hand-cut fries',  img:window.A('fryHandCutFries') },
      { label:'Spring rolls',    img:window.A('frySpringRolls') },
      { label:'Curry puffs',     img:window.A('fryCurryPuffs') },
      { label:'Fish & chips',    img:window.A('fryFishAndChips') },
      { label:'Churros',         img:window.A('fryChurros') },
    ] },
  { key:'pot',   name:'Micro', accent:'POT',   color:'#FFD21F', speed:'4 mins',  speedL:'per serving',
    caps:['Auto blanching + boiling','Temperature held to ±1 °C','FIFO ingredient feed','Self-cleaning cycle'],
    dishes:[
      { label:'Mushroom fettuccine', img:window.A('potMushroom') },
      { label:'Shrimp pomodoro',     img:window.A('potShrimp') },
      { label:'Pesto fusilli',       img:window.A('potPesto') },
      { label:'Duck spaghetti',      img:window.A('potDuck') },
    ] },
  { key:'green', name:'Micro', accent:'GREEN', color:'#56AB2F', speed:'50 sec',  speedL:'per bowl',
    caps:['Bowl-builder pick + place','Cold-chain compliant','Customisable recipes','Allergen separation'],
    dishes:[
      { label:'Mediterranean bowl', img:window.A('greenMediterr') },
      { label:'Chicken Caesar',     img:window.A('greenCaesar') },
      { label:'Teriyaki salmon',    img:window.A('greenSalmon') },
      { label:'Steak burrito bowl', img:window.A('greenBurrito') },
    ] },
  { key:'bev',   name:'Micro', accent:'BEV',   color:'#38B6FF', speed:'6 sec',   speedL:'per cup',
    caps:['Hot, cold, and carbonated','Per-cup ratio control','Daily auto-sanitise','30 + drink library'],
    dishes:[
      { label:'Iced mint tea',     img:window.A('bevMintTea') },
      { label:'Coconut lime',      img:window.A('bevCoconutLime') },
      { label:'Iced caramel latte', img:window.A('bevIcedLatte') },
      { label:'Sunset mocktail',   img:window.A('bevMocktail') },
    ] },
];

/* Single bowl — circle-cropped, top-down, brand brochure style.
   If `img` is provided, render the photo inside the bowl crop; otherwise the placeholder food disc. */
function Bowl({ label, img, onColor, size = 1 }) {
  return (
    <div className={"wf-bowl-wrap"} style={{minWidth:0}}>
      <div className={"wf-bowl" + (onColor ? " on-color" : "") + (img ? " has-photo" : "")}>
        <div className="wf-bowl-rim"></div>
        {img
          ? <img className="wf-bowl-photo" src={img} alt={label} loading="lazy" />
          : <div className="wf-bowl-food"></div>}
      </div>
      <div className={"wf-bowl-label" + (onColor ? " on-color" : "")}>{label}</div>
    </div>
  );
}

function CinematicModules() {
  const scrollerRef = useRef(null);
  const containerRef = useRef(null);
  const [active, setActive] = useState(0);
  const [progress, setProgress] = useState(0);
  const [isFlow, setIsFlow] = useState(() => typeof document !== 'undefined' && document.body.classList.contains('mode-flow'));
  // Mobile gets only 4 dishes per module (vs 8 for FRY on desktop) — keeps
  // the 2x2 grid balanced and saves ~50% image weight on the only module
  // that has more than 4 dishes.
  const [isMobile, setIsMobile] = useState(() => typeof window !== 'undefined' && window.matchMedia('(max-width: 720px)').matches);

  useEffect(() => {
    const mo = new MutationObserver(() => setIsFlow(document.body.classList.contains('mode-flow')));
    mo.observe(document.body, { attributes: true, attributeFilter: ['class'] });
    return () => mo.disconnect();
  }, []);

  useEffect(() => {
    const mq = window.matchMedia('(max-width: 720px)');
    const update = (e) => setIsMobile(e.matches);
    mq.addEventListener('change', update);
    return () => mq.removeEventListener('change', update);
  }, []);

  // Flow mode: always START on MicroFRY when the section enters the viewport,
  // then auto-cycle. When it leaves the viewport, reset back to FRY so the user
  // ALWAYS lands on MicroFRY the next time they scroll here (no matter where
  // the auto-cycle was when they scrolled past it).
  useEffect(() => {
    if (!isFlow) return;
    const el = containerRef.current;
    if (!el) return;
    let timer = null;
    const stop = () => { if (timer) { clearInterval(timer); timer = null; } };
    const start = () => {
      stop();
      setActive(0);
      setProgress(0);
      timer = setInterval(() => {
        setActive(a => (a + 1) % MODULES.length);
        setProgress(p => (p + 0.25) % 1);
      }, 2200);
    };
    const io = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) start();
      else { stop(); setActive(0); setProgress(0); }
    }, { threshold: 0.35 });
    io.observe(el);
    return () => { io.disconnect(); stop(); };
  }, [isFlow]);

  useEffect(() => {
    if (isFlow) return; // skip the IO in flow mode — auto-cycle drives it
    const root = scrollerRef.current;
    if (!root) return;
    const panels = Array.from(root.querySelectorAll('[data-panel]'));
    const io = new IntersectionObserver((entries) => {
      let best = null, bestRatio = 0;
      entries.forEach(e => {
        if (e.intersectionRatio > bestRatio) { best = e; bestRatio = e.intersectionRatio; }
      });
      if (best) {
        const idx = parseInt(best.target.dataset.panel, 10);
        if (!Number.isNaN(idx)) setActive(idx);
      }
    }, { root, threshold: [0.25, 0.5, 0.75, 0.9] });
    panels.forEach(p => io.observe(p));
    const onScroll = () => {
      const h = root.scrollHeight - root.clientHeight;
      setProgress(h > 0 ? root.scrollTop / h : 0);
    };
    root.addEventListener('scroll', onScroll, { passive: true });
    return () => { io.disconnect(); root.removeEventListener('scroll', onScroll); };
  }, [isFlow]);

  const mod = MODULES[active];
  return (
    <div className="wf-cinema" ref={containerRef}>
      <div className={"wf-cinema-bleed " + mod.key}></div>
      <div className="wf-cinema-progress"><div className="bar" style={{width: (progress*100) + '%'}}></div></div>
      <div className="wf-cinema-stage">
        <div className="wf-cinema-meta">
          <span>Module {String(active+1).padStart(2,'0')} / 04</span>
          <span>{mod.name}{mod.accent} · Rolo Robotics</span>
        </div>
        <div className="wf-cinema-mid" style={{'--mod-accent': mod.color}}>
          <h3 className="wf-cinema-name">
            <span className="prefix">{mod.name}</span><span className="suffix">{mod.accent}</span>
          </h3>
          <div className="wf-cinema-bowls" key={mod.key}>
            {mod.dishes.slice(0, isMobile ? 4 : 8).map((d,i)=>(
              <div key={d.label} className="wf-cinema-bowls-cell" style={{animationDelay: (120 + i*70) + 'ms'}}>
                <Bowl label={d.label} img={d.img} onColor />
              </div>
            ))}
          </div>
        </div>
        <div className="wf-cinema-foot">
          <div className="speed">
            <div className="n">{mod.speed}</div>
            <span className="l">{mod.speedL}</span>
          </div>
          <div className="caps">
            {mod.caps.map((c,i)=><span key={i}>{c}</span>)}
          </div>
        </div>
      </div>
      <div className="wf-cinema-rail" aria-hidden="true">
        {MODULES.map((m,i)=>(<span key={m.key} className={"dot" + (i === active ? ' active':'')}></span>))}
      </div>
      {!isFlow && (
        <React.Fragment>
          <div ref={scrollerRef} style={{
            position:'absolute', inset:0, overflowY:'scroll', scrollbarWidth:'thin', zIndex:10
          }}>
            {MODULES.map((m,i)=>(
              <div key={m.key} data-panel={i} style={{height:'100%', minHeight:640}}></div>
            ))}
          </div>
          <div style={{position:'absolute', bottom:14, left:'50%', transform:'translateX(-50%)', zIndex:11, pointerEvents:'none',
            fontFamily:'var(--rr-font-mono)', fontSize:10, letterSpacing:'0.22em', textTransform:'uppercase', color:'rgba(255,255,255,0.45)'}}>
            Scroll inside this frame ↓
          </div>
        </React.Fragment>
      )}
    </div>
  );
}

function ModulesVariants() {
  return (
    <React.Fragment>
      {/* A — Cinematic stacked scroll (live) */}
      <window.Variant
        letter="A"
        title="Cinematic stacked scroll · live"
        desc="Per the brief, with signature dishes. Each module = 100 vh. Accent bleeds in. League Spartan 900 name fills the left; a 2×2 of circle-cropped food bowls fades in on the right."
        notes={['100 vh per module', 'Colour bleed background', 'Live IntersectionObserver', 'Bowls fade in per module']}
        dark
      >
        <CinematicModules />
        <span className="wf-anno" style={{top:14,left:20,color:'#E0BD63'}}>Live · scroll inside frame</span>
      </window.Variant>

      {/* B — Horizontal pinned scroll */}
      <window.Variant
        letter="B"
        title="Horizontal pinned scroll · with dishes"
        desc="Page pin holds the section while a horizontal track moves through the four modules. Each panel now grounds the wordmark with a row of three signature dishes."
        notes={['Page pinned vertically', 'Horizontal scroll inside', 'Three signature dishes per module', 'Names crossfade L→R']}
        dark
      >
        <div style={{minHeight:560,padding:0,position:'relative',background:'#111110',overflow:'hidden'}}>
          <div style={{display:'flex',height:560,gap:0}}>
            {MODULES.map((m,i)=>(
              <div key={m.key} style={{flex:'0 0 78%',position:'relative',borderRight:'1px solid #2A2926',padding:'32px 48px',display:'flex',flexDirection:'column',justifyContent:'space-between',background:`linear-gradient(180deg, ${m.color}12 0%, transparent 70%)`}}>
                <div style={{display:'flex',justifyContent:'space-between',color:'rgba(255,255,255,0.65)',fontFamily:'var(--rr-font-mono)',fontSize:11,letterSpacing:'0.22em',textTransform:'uppercase'}}>
                  <span>Module {String(i+1).padStart(2,'0')} / 04</span>
                  <span>{m.speed} {m.speedL}</span>
                </div>
                <div style={{fontFamily:'var(--rr-font-module)',fontWeight:900,fontSize:'clamp(72px,8vw,140px)',lineHeight:0.85,color:'#FFF',margin:'12px 0'}}>
                  <span>{m.name}</span><span style={{color:m.color}}>{m.accent}</span>
                </div>
                <div className="wf-bowl-row">
                  {m.dishes.slice(0,3).map(d=>(<Bowl key={d.label} label={d.label} img={d.img} />))}
                </div>
                <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'6px 32px',color:'rgba(255,255,255,0.78)',fontSize:12,maxWidth:520,marginTop:16,lineHeight:1.4}}>
                  {m.caps.map((c,j)=><span key={j}>— {c}</span>)}
                </div>
              </div>
            ))}
          </div>
          <div style={{position:'absolute',bottom:14,left:0,right:0,display:'flex',justifyContent:'center',gap:6}}>
            {MODULES.map((m,i)=>(
              <span key={i} style={{width:i===0?28:14,height:2,background:i===0?'#FFF':'rgba(255,255,255,0.25)'}}></span>
            ))}
          </div>
          <span className="wf-anno" style={{top:14,left:20,color:'#E0BD63'}}>Three signature dishes per panel</span>
        </div>
      </window.Variant>

      {/* C — Photo-led catalog (replaces the type marquee — food now leads) */}
      <window.Variant
        letter="C"
        title="Photo-led catalog"
        desc="Now that food enters the story, the marquee gives way to four full-width bands. Each module band pairs a 2×2 bowl grid with its giant wordmark, speed, and capability lines. More product, less spectacle."
        notes={['4 stacked bands · no scroll trap', 'Bowl grid leads each band', 'Wordmark + speed + caps right', 'Catalog energy']}
        dark
      >
        <div style={{padding:'0',position:'relative',background:'#111110'}}>
          {MODULES.map((m,i)=>(
            <div key={m.key} className="wf-cat-band" style={{borderTop:i===0?'':'1px solid #2A2926',padding:'48px 56px',display:'grid',gridTemplateColumns:'1.05fr 1.2fr',gap:48,alignItems:'center',position:'relative',overflow:'hidden'}}>
              <div style={{position:'absolute',left:0,top:0,bottom:0,width:4,background:m.color,opacity:0.9}}></div>
              <div className="wf-bowl-grid-2">
                {m.dishes.slice(0,4).map(d=>(<Bowl key={d.label} label={d.label} img={d.img} />))}
              </div>
              <div>
                <div style={{display:'flex',justifyContent:'space-between',color:'rgba(255,255,255,0.55)',fontFamily:'var(--rr-font-mono)',fontSize:11,letterSpacing:'0.22em',textTransform:'uppercase',marginBottom:14}}>
                  <span>Module {String(i+1).padStart(2,'0')} / 04</span>
                  <span>Built for {i===0?'high-volume frying':i===1?'pasta + boil cooking':i===2?'bowl building':'beverage service'}</span>
                </div>
                <div style={{fontFamily:'var(--rr-font-module)',fontWeight:900,fontSize:'clamp(64px,8vw,128px)',lineHeight:0.85,color:'#FFF'}}>
                  <span>{m.name}</span><span style={{color:m.color}}>{m.accent}</span>
                </div>
                <div style={{display:'flex',alignItems:'baseline',gap:14,marginTop:18,paddingTop:14,borderTop:'1px solid #2A2926'}}>
                  <span style={{fontSize:'clamp(28px,3vw,44px)',fontWeight:700,letterSpacing:'-0.03em',color:m.color,lineHeight:1}}>{m.speed}</span>
                  <span style={{fontSize:11,fontFamily:'var(--rr-font-mono)',letterSpacing:'0.2em',textTransform:'uppercase',color:'rgba(255,255,255,0.55)'}}>{m.speedL}</span>
                </div>
                <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'6px 32px',color:'rgba(255,255,255,0.78)',fontSize:13,marginTop:18,lineHeight:1.45}}>
                  {m.caps.map((c,j)=><span key={j}>— {c}</span>)}
                </div>
              </div>
            </div>
          ))}
          <span className="wf-anno" style={{top:14,right:20,color:'#E0BD63'}}>Food leads · 4 stacked bands</span>
        </div>
      </window.Variant>
    </React.Fragment>
  );
}
window.ModulesVariants = ModulesVariants;

/* ============================================================
 * 4. ROLO OS
 * ============================================================ */
const OS_CAPS = [
  { t:'AI Vision & Auto-Recovery',          d:'Vision-trained recovery for jams, mis-pours, and out-of-spec output.' },
  { t:'Real-Time Food Quality Sensing',     d:'Sensors flag temperature, moisture, and oil quality drift live.' },
  { t:'Customer Feedback Loops',            d:'Per-order ratings feed back into recipe tuning and inventory.' },
  { t:'Analytics & Inventory Intelligence', d:'FIFO inventory, demand forecasting, dynamic menu surfacing.' },
];

function OSVariants() {
  return (
    <React.Fragment>
      {/* A — Per brief */}
      <window.Variant
        letter="A"
        title="Capability rows + orbit"
        desc="Per brief. Headline + lede left, four capability rows with line icons; right side hosts the gold orbit graphic."
        notes={['4 capability rows', 'Line icons in gold', 'Animated orbit right']}
        dark
      >
        <div className="frame wide wf-reveal" style={{display:'grid',gridTemplateColumns:'1.2fr 1fr',gap:64,alignItems:'center'}}>
          <div>
            <span className="wf-eyebrow">Rolo OS</span>
            <h2 className="wf-h1" style={{color:'#FFF'}}>The brain behind every meal.</h2>
            <p className="wf-lede">
              An AI intelligence layer running across every module. 30 + sensors per cell, always on, always learning.
              Vision-driven recovery, food-quality sensing, and live customer feedback all feed one operating loop.
            </p>
            <ul style={{listStyle:'none',padding:0,margin:'36px 0 0',display:'flex',flexDirection:'column',gap:22}}>
              {OS_CAPS.map((c,i)=>(
                <li key={i} style={{display:'grid',gridTemplateColumns:'32px 1fr',gap:18,paddingBottom:18,borderBottom:'1px solid #2A2926'}}>
                  <span className="wf-icon" style={{color:'var(--rr-gold)',width:22,height:22}}></span>
                  <div>
                    <div style={{fontWeight:600,fontSize:19,color:'#FFF',letterSpacing:'-0.01em',lineHeight:1.25}}>{c.t}</div>
                    <div style={{fontSize:15,color:'#9A958A',marginTop:6,lineHeight:1.5}}>{c.d}</div>
                  </div>
                </li>
              ))}
            </ul>
          </div>
          <div className="wf-orbit spin">
            <span className="ring"></span>
            <span className="ring r2"></span>
            <span className="ring r3"></span>
            <span className="core"></span>
            <span className="sat a"></span>
            <span className="sat b"></span>
            <span className="sat c"></span>
            <span className="sat d"></span>
          </div>
          <span className="wf-anno" style={{top:14,right:20,color:'#E0BD63'}}>Gold orbit · slow rotation</span>
        </div>
      </window.Variant>

      {/* B — Centered orbit, radial caps */}
      <window.Variant
        letter="B"
        title="Radial · orbit at the centre"
        desc="The orbit graphic is the subject. Headline pinned above, four capability cards arranged around it like satellites."
        notes={['Orbit center stage', 'Caps as compact cards', '2 cards per side']}
        dark
      >
        <div className="frame wide wf-reveal" style={{textAlign:'center',padding:'48px clamp(28px, 4vw, 56px)',minHeight:600}}>
          <span className="wf-eyebrow" style={{justifyContent:'center'}}>Rolo OS</span>
          <h2 className="wf-h1" style={{color:'#FFF',maxWidth:'18ch',margin:'14px auto 0'}}>The brain behind every meal.</h2>
          <div style={{position:'relative',marginTop:36,minHeight:380,display:'grid',gridTemplateColumns:'1fr 280px 1fr',gap:24,alignItems:'center',textAlign:'left'}}>
            <div style={{display:'flex',flexDirection:'column',gap:18}}>
              {OS_CAPS.slice(0,2).map((c,i)=>(
                <div key={i} style={{border:'1px solid #2A2926',borderRadius:10,padding:'22px 24px',background:'#14140F'}}>
                  <div style={{display:'flex',alignItems:'center',gap:12}}>
                    <span className="wf-icon" style={{color:'var(--rr-gold)',width:22,height:22}}></span>
                    <span style={{color:'#FFF',fontWeight:600,fontSize:17,letterSpacing:'-0.01em'}}>{c.t}</span>
                  </div>
                  <div style={{fontSize:14,color:'#9A958A',marginTop:10,lineHeight:1.55}}>{c.d}</div>
                </div>
              ))}
            </div>
            <div className="wf-orbit spin" style={{maxWidth:280}}>
              <span className="ring"></span>
              <span className="ring r2"></span>
              <span className="ring r3"></span>
              <span className="core"></span>
              <span className="sat a"></span>
              <span className="sat b"></span>
              <span className="sat c"></span>
              <span className="sat d"></span>
            </div>
            <div style={{display:'flex',flexDirection:'column',gap:18}}>
              {OS_CAPS.slice(2).map((c,i)=>(
                <div key={i} style={{border:'1px solid #2A2926',borderRadius:10,padding:'22px 24px',background:'#14140F'}}>
                  <div style={{display:'flex',alignItems:'center',gap:12}}>
                    <span className="wf-icon" style={{color:'var(--rr-gold)',width:22,height:22}}></span>
                    <span style={{color:'#FFF',fontWeight:600,fontSize:17,letterSpacing:'-0.01em'}}>{c.t}</span>
                  </div>
                  <div style={{fontSize:14,color:'#9A958A',marginTop:10,lineHeight:1.55}}>{c.d}</div>
                </div>
              ))}
            </div>
          </div>
          <span className="wf-anno" style={{top:14,left:20,color:'#E0BD63'}}>Caps orbit the graphic · symmetrical</span>
        </div>
      </window.Variant>

      {/* C — Full-bleed dark + 2x2 + watermark */}
      <window.Variant
        letter="C"
        title="2×2 grid · orbit watermark behind"
        desc="A larger orbit lives behind the type as a watermark. Headline + lede left, 2×2 grid of capability tiles right, no icons — just numbers and big labels."
        notes={['Orbit as watermark only', 'Numbered caps 01–04', 'No icons — number do the job']}
        dark
      >
        <div className="frame wide wf-reveal" style={{minHeight:580,position:'relative'}}>
          <div style={{position:'absolute',right:-80,top:-80,width:520,height:520,opacity:0.18,pointerEvents:'none'}}>
            <div className="wf-orbit spin" style={{maxWidth:520}}>
              <span className="ring"></span>
              <span className="ring r2"></span>
              <span className="ring r3"></span>
              <span className="core"></span>
              <span className="sat a"></span>
              <span className="sat b"></span>
            </div>
          </div>
          <div style={{position:'relative',zIndex:1,display:'grid',gridTemplateColumns:'1fr 1fr',gap:64}}>
            <div>
              <span className="wf-eyebrow">Rolo OS</span>
              <h2 className="wf-h1" style={{color:'#FFF'}}>The brain behind every meal.</h2>
              <p className="wf-lede">30 + sensors per cell. Always on. Always learning. One operating loop running the floor.</p>
              <div style={{marginTop:32,display:'flex',gap:36}}>
                <div><div style={{fontSize:40,fontWeight:700,letterSpacing:'-0.03em',color:'var(--rr-gold)',lineHeight:1}}>30+</div><div className="wf-stat-lbl" style={{color:'#9A958A'}}>sensors / cell</div></div>
                <div><div style={{fontSize:40,fontWeight:700,letterSpacing:'-0.03em',color:'var(--rr-gold)',lineHeight:1}}>24/7</div><div className="wf-stat-lbl" style={{color:'#9A958A'}}>uptime</div></div>
              </div>
            </div>
            <div className="wf-os-caps" style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:18}}>
              {OS_CAPS.map((c,i)=>(
                <div key={i} className="wf-os-cap" style={{border:'1px solid #2A2926',borderRadius:10,padding:'26px',background:'rgba(20,20,15,0.7)',backdropFilter:'blur(6px)',display:'flex',flexDirection:'column',gap:12,minHeight:170}}>
                  <span className="mono" style={{color:'var(--rr-gold)',fontSize:13,letterSpacing:'0.24em'}}>0{i+1}</span>
                  <div style={{color:'#FFF',fontWeight:700,fontSize:20,letterSpacing:'-0.01em',lineHeight:1.2}}>{c.t}</div>
                  <div style={{fontSize:14,color:'#9A958A',lineHeight:1.55}}>{c.d}</div>
                </div>
              ))}
            </div>
          </div>
          <span className="wf-anno" style={{top:14,left:20,color:'#E0BD63'}}>Orbit as watermark · numbered caps</span>
        </div>
      </window.Variant>
    </React.Fragment>
  );
}
window.OSVariants = OSVariants;

/* ============================================================
 * 5. DEPLOYMENT
 * ============================================================ */
const DEPLOYMENTS_LIVE = [
  { name:'Singapore University of Technology and Design', short:'SUTD',  city:'Singapore', context:'University' },
  { name:'Nanyang Technological University',              short:'NTU',   city:'Singapore', context:'University' },
  { name:'Gedong Army Camp',                              short:'Gedong',city:'Singapore', context:'Defence' },
];
const DEPLOYMENTS_UPCOMING_SG = [
  { name:'Airport',        short:'Airport',  city:'Singapore', context:'Transit hub' },
  { name:'Office Canteen', short:'Canteen',  city:'Singapore', context:'Workplace'   },
  { name:'Hospital',       short:'Hospital', city:'Singapore', context:'Healthcare'  },
];
const DEPLOYMENTS_UPCOMING_INTL = [
  { name:'Amsterdam',     short:'Amsterdam', city:'Netherlands',  context:'Transit hub' },
  { name:'United States', short:'USA',       city:'North America',context:'Retail / Campus' },
];
const DEPLOYMENTS_UPCOMING = [...DEPLOYMENTS_UPCOMING_SG, ...DEPLOYMENTS_UPCOMING_INTL];
const ENVIRONMENTS = [
  'Universities','Hospitals','Airports','Train Stations','Retail & Malls','Cafes & Canteens','Defence'
];

/* Built for · environment strip — matches the Compliance gold-checkmark
   pill style (.wf-compliance-strip + .wf-compliance-pill): eyebrow on its
   own row, then cream pills with a gold ✓ icon wrapping below. */
function EnvStrip({ compact }) {
  return (
    <div className="wf-compliance-strip" style={{display:'flex',flexWrap:'wrap',alignItems:'center',gap:'12px 10px',padding: compact ? '14px 0' : '18px 0'}}>
      <span className="wf-eyebrow" style={{flex:'none',marginRight:14}}>Built for</span>
      {ENVIRONMENTS.map(e=>(
        <span key={e} className="wf-compliance-pill">
          <span className="check" aria-hidden="true">✓</span>{e}
        </span>
      ))}
    </div>
  );
}

/* D3-powered rotating globe (orthographic projection).
   Loads world-atlas TopoJSON once and caches the GeoJSON FeatureCollection. */
let __ROLO_WORLD_CACHE = null;
let __ROLO_WORLD_PROMISE = null;
function loadWorldAtlas() {
  if (__ROLO_WORLD_CACHE) return Promise.resolve(__ROLO_WORLD_CACHE);
  if (__ROLO_WORLD_PROMISE) return __ROLO_WORLD_PROMISE;
  __ROLO_WORLD_PROMISE = fetch(window.A('worldAtlas'))
    .then(r => r.json())
    .then(topo => {
      const land = topojson.feature(topo, topo.objects.land);
      __ROLO_WORLD_CACHE = land;
      return land;
    });
  return __ROLO_WORLD_PROMISE;
}

function WorldMap() {
  const wrapRef = useRef(null);
  const svgRef  = useRef(null);
  const [ready, setReady] = useState(false);

  useEffect(() => {
    let raf = 0;
    let cancelled = false;
    const size = 520; // viewBox is square

    loadWorldAtlas().then(land => {
      if (cancelled || !svgRef.current) return;
      setReady(true);

      const svg = window.d3.select(svgRef.current);
      svg.selectAll('*').remove();

      const cx = size/2, cy = size/2, r = size/2 - 24;
      const projection = window.d3.geoOrthographic()
        .scale(r)
        .translate([cx, cy])
        .clipAngle(90)
        .rotate([-100, -10, 0]); // start centred near Singapore
      const path = window.d3.geoPath(projection);

      // Defs — glow + gradient
      const defs = svg.append('defs');
      defs.append('radialGradient')
        .attr('id','rolo-globe-shade')
        .attr('cx','45%').attr('cy','40%').attr('r','60%')
        .selectAll('stop')
        .data([
          {o:'0%',  c:'#1A1A17'},
          {o:'60%', c:'#0F0F0D'},
          {o:'100%',c:'#070706'},
        ])
        .enter().append('stop')
        .attr('offset', d=>d.o).attr('stop-color', d=>d.c);
      // Outer atmosphere glow
      const glow = defs.append('radialGradient')
        .attr('id','rolo-globe-glow')
        .attr('cx','50%').attr('cy','50%').attr('r','50%');
      glow.append('stop').attr('offset','85%').attr('stop-color','rgba(255,255,255,0)');
      glow.append('stop').attr('offset','100%').attr('stop-color','rgba(255,255,255,0.10)');

      // Atmosphere ring
      svg.append('circle').attr('cx',cx).attr('cy',cy).attr('r',r+8)
        .attr('fill','url(#rolo-globe-glow)');
      // Globe sphere
      svg.append('circle').attr('cx',cx).attr('cy',cy).attr('r',r)
        .attr('fill','url(#rolo-globe-shade)')
        .attr('stroke','rgba(255,255,255,0.18)')
        .attr('stroke-width',1);

      // Graticule
      const graticule = window.d3.geoGraticule10();
      const graticulePath = svg.append('path')
        .datum(graticule)
        .attr('d', path)
        .attr('fill','none')
        .attr('stroke','rgba(255,255,255,0.07)')
        .attr('stroke-width',0.6);

      // Land
      const landPath = svg.append('path')
        .datum(land)
        .attr('d', path)
        .attr('fill','rgba(238,231,213,0.18)')
        .attr('stroke','rgba(238,231,213,0.5)')
        .attr('stroke-width',0.45);

      // Pins
      const pins = [
        { lng: 103.85, lat: 1.35,  status:'live',     label:'Singapore',     sub:'3 sites · live', color:'#2BB673' },
        { lng:   4.90, lat: 52.37, status:'upcoming', label:'Amsterdam',     sub:'Upcoming',       color:'#D4A23E' },
        { lng: -98.0,  lat: 39.0,  status:'upcoming', label:'United States', sub:'Upcoming',       color:'#D4A23E' },
      ];
      const pinG = svg.append('g').attr('class','pins');

      const drawPins = () => {
        pinG.selectAll('*').remove();
        const center = projection.invert([cx, cy]);
        pins.forEach((p, i) => {
          // visibility via geo distance
          const d = window.d3.geoDistance([p.lng, p.lat], center);
          const visible = d < Math.PI/2 - 0.02;
          if (!visible) return;
          const [px, py] = projection([p.lng, p.lat]);
          const g = pinG.append('g').attr('transform', `translate(${px},${py})`);
          // pulse for upcoming
          if (p.status === 'upcoming') {
            const pulse = g.append('circle')
              .attr('r', 6).attr('fill', p.color).attr('opacity', 0.45);
            pulse.append('animate').attr('attributeName','r').attr('values','6;22;6').attr('dur','3.2s').attr('repeatCount','indefinite').attr('begin', i===1 ? '0s' : '1.2s');
            pulse.append('animate').attr('attributeName','opacity').attr('values','0.55;0;0.55').attr('dur','3.2s').attr('repeatCount','indefinite').attr('begin', i===1 ? '0s' : '1.2s');
          } else {
            g.append('circle').attr('r',12).attr('fill', p.color).attr('opacity',0.22);
          }
          // core dot
          g.append('circle').attr('r',5).attr('fill', p.color).attr('stroke','rgba(255,255,255,0.7)').attr('stroke-width',1);
          // label
          const labelDx = px < cx ? 12 : -12;
          const anchor  = px < cx ? 'start' : 'end';
          const tg = g.append('g').attr('transform', `translate(${labelDx},-2)`);
          tg.append('text')
            .attr('x',0).attr('y',-6)
            .attr('text-anchor', anchor)
            .attr('font-family', 'var(--rr-font-mono)')
            .attr('font-size', 11)
            .attr('letter-spacing', '0.22em')
            .attr('fill', '#FFF')
            .style('text-transform','uppercase')
            .text(p.label);
          tg.append('text')
            .attr('x',0).attr('y',8)
            .attr('text-anchor', anchor)
            .attr('font-family', 'var(--rr-font-mono)')
            .attr('font-size', 9)
            .attr('letter-spacing', '0.18em')
            .attr('fill', p.color)
            .style('text-transform','uppercase')
            .text(p.sub);
        });
      };
      drawPins();

      // Rotation loop
      let lng = -100, lat = -10;
      let last = performance.now();
      const tick = (now) => {
        const dt = Math.min(40, now - last); last = now;
        lng += dt * 0.012; // ~7°/sec rotation
        projection.rotate([lng, lat, 0]);
        graticulePath.attr('d', path(graticule));
        landPath.attr('d', path(land));
        drawPins();
        raf = requestAnimationFrame(tick);
      };
      raf = requestAnimationFrame(tick);
    }).catch(err => {
      console.warn('[WorldMap] failed to load world atlas', err);
    });

    return () => { cancelled = true; if (raf) cancelAnimationFrame(raf); };
  }, []);

  return (
    <div ref={wrapRef} style={{position:'relative',background:'#0D0D0C',color:'#FAF5E9',borderRadius:10,overflow:'hidden',border:'1px solid #1F1E1A',minHeight:380}}>
      <div style={{position:'absolute',top:0,left:0,right:0,padding:'14px 18px',display:'flex',justifyContent:'space-between',alignItems:'center',zIndex:5,fontFamily:'var(--rr-font-mono)',fontSize:10,letterSpacing:'0.22em',textTransform:'uppercase',color:'rgba(255,255,255,0.5)',pointerEvents:'none'}}>
        <span>Deployment globe · 2025–26</span>
        <span style={{display:'flex',gap:18}}>
          <span style={{display:'inline-flex',alignItems:'center',gap:6,color:'rgba(255,255,255,0.85)'}}><span style={{width:8,height:8,borderRadius:999,background:'#2BB673'}}></span>Live · 3</span>
          <span style={{display:'inline-flex',alignItems:'center',gap:6,color:'var(--rr-gold)'}}><span style={{width:8,height:8,borderRadius:999,background:'var(--rr-gold)'}}></span>Upcoming · 5</span>
        </span>
      </div>
      <svg ref={svgRef} viewBox="0 0 520 520" preserveAspectRatio="xMidYMid meet" style={{display:'block',width:'100%',height:'auto'}} />
      {!ready && (
        <div style={{position:'absolute',inset:0,display:'flex',alignItems:'center',justifyContent:'center',color:'rgba(255,255,255,0.4)',fontFamily:'var(--rr-font-mono)',fontSize:11,letterSpacing:'0.22em',textTransform:'uppercase'}}>Loading globe…</div>
      )}
    </div>
  );
}

function DeployCard({ name, city, context, status, invite, big }) {
  const isUpcoming = status === 'upcoming';
  const isLive = status === 'live';
  return (
    <div style={{
      background: invite ? '#FFF' : '#F0F0F0',
      border: invite ? '1px solid var(--rr-gold)' : '1px solid #E2DED2',
      borderRadius:8,
      padding: big ? '28px 22px' : '20px 18px',
      minHeight: big ? 160 : 130,
      display:'flex',
      flexDirection:'column',
      justifyContent:'space-between',
      gap:14,
      cursor:'pointer',
      color: invite ? 'var(--rr-gold)' : 'var(--wf-ink)',
      transition:'border-color .2s'
    }}>
      <div style={{display:'flex',alignItems:'center',gap:8}}>
        {isLive && (
          <span style={{display:'inline-flex',alignItems:'center',gap:6,fontFamily:'var(--rr-font-mono)',fontSize:10,letterSpacing:'0.18em',textTransform:'uppercase',color:'#1F8A5B'}}>
            <span style={{width:7,height:7,borderRadius:999,background:'#1F8A5B',boxShadow:'0 0 0 3px rgba(31,138,91,0.18)'}}></span>
            Live
          </span>
        )}
        {isUpcoming && (
          <span style={{display:'inline-flex',alignItems:'center',gap:6,fontFamily:'var(--rr-font-mono)',fontSize:10,letterSpacing:'0.18em',textTransform:'uppercase',color:'var(--rr-gold)'}}>
            <span style={{width:7,height:7,borderRadius:999,background:'var(--rr-gold)'}}></span>
            Upcoming
          </span>
        )}
        {context && !invite && (
          <span style={{marginLeft:'auto',fontFamily:'var(--rr-font-mono)',fontSize:10,letterSpacing:'0.16em',textTransform:'uppercase',color:'#8B8779'}}>{context}</span>
        )}
        {invite && (
          <span className="wf-icon" style={{color:'var(--rr-gold)', width:16, height:16, marginLeft:'auto'}}></span>
        )}
      </div>
      <div>
        <div style={{fontSize:big?20:15,fontWeight:600,letterSpacing:'-0.01em',lineHeight:1.25}}>{name}</div>
        {city && <div className="mono" style={{fontSize:11,letterSpacing:'0.18em',textTransform:'uppercase',color: invite ? 'rgba(196,154,60,0.7)' : '#8B8779',marginTop:8}}>{city}</div>}
      </div>
    </div>
  );
}

function DeployVariants() {
  const liveCount = DEPLOYMENTS_LIVE.length;
  const upcomingSGCount = DEPLOYMENTS_UPCOMING_SG.length;
  const upcomingIntlCount = DEPLOYMENTS_UPCOMING_INTL.length;
  const upcomingCount = upcomingSGCount + upcomingIntlCount;

  return (
    <React.Fragment>
      {/* A — Live + Upcoming card grid */}
      <window.Variant
        letter="A"
        title="Live & upcoming · card grid"
        desc="Built-for strip up top reminds you which environments Rolo runs in. Three clearly-labelled groups of cards below: live Singapore sites, upcoming Singapore sites, then upcoming international pilots."
        notes={[`${liveCount} live · ${upcomingCount} upcoming`, 'Singapore upcoming sites (Airport · Office Canteen · Hospital)', 'Status pill per card', 'Invite tile closes upcoming row']}
      >
        <div className="frame wf-reveal">
          <span className="wf-eyebrow">Deployment</span>
          <h2 className="wf-h2" style={{marginBottom:8}}>Live in Singapore.<br/>Coming up worldwide.</h2>
          <p className="wf-lede" style={{maxWidth:'52ch',marginTop:14,fontSize:15}}>
            Built for the places that never close — campuses, hospitals, transit hubs, defence sites, retail floors. Three sites already running in Singapore. Three more queued locally; pilots in Amsterdam and the United States queued for next.
          </p>

          <div style={{marginTop:28,paddingTop:18,paddingBottom:6,borderTop:'1px solid var(--wf-line)',borderBottom:'1px solid var(--wf-line)'}}>
            <EnvStrip />
          </div>

          {/* Live SG */}
          <div style={{marginTop:36,display:'flex',alignItems:'baseline',justifyContent:'space-between',marginBottom:14}}>
            <span className="wf-eyebrow" style={{color:'#1F8A5B'}}><span style={{display:'inline-block',width:8,height:8,borderRadius:999,background:'#1F8A5B',marginRight:8,boxShadow:'0 0 0 3px rgba(31,138,91,0.18)'}}></span>Live · Singapore</span>
            <span className="mono" style={{fontSize:11,letterSpacing:'0.18em',textTransform:'uppercase',color:'var(--wf-muted)'}}>0{liveCount} sites</span>
          </div>
          <div style={{display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:14}}>
            {DEPLOYMENTS_LIVE.map(d => <DeployCard key={d.name} {...d} status="live" />)}
          </div>

          {/* Upcoming SG */}
          <div style={{marginTop:36,display:'flex',alignItems:'baseline',justifyContent:'space-between',marginBottom:14}}>
            <span className="wf-eyebrow" style={{color:'var(--rr-gold)'}}><span style={{display:'inline-block',width:8,height:8,borderRadius:999,background:'var(--rr-gold)',marginRight:8}}></span>Upcoming · Singapore</span>
            <span className="mono" style={{fontSize:11,letterSpacing:'0.18em',textTransform:'uppercase',color:'var(--wf-muted)'}}>0{upcomingSGCount} sites · location TBD</span>
          </div>
          <div style={{display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:14}}>
            {DEPLOYMENTS_UPCOMING_SG.map(d => <DeployCard key={d.name} {...d} status="upcoming" />)}
          </div>

          {/* Upcoming International */}
          <div style={{marginTop:36,display:'flex',alignItems:'baseline',justifyContent:'space-between',marginBottom:14}}>
            <span className="wf-eyebrow" style={{color:'var(--rr-gold)'}}><span style={{display:'inline-block',width:8,height:8,borderRadius:999,background:'var(--rr-gold)',marginRight:8}}></span>Upcoming · International</span>
            <span className="mono" style={{fontSize:11,letterSpacing:'0.18em',textTransform:'uppercase',color:'var(--wf-muted)'}}>0{upcomingIntlCount} sites + invite</span>
          </div>
          <div style={{display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:14}}>
            {DEPLOYMENTS_UPCOMING_INTL.map(d => <DeployCard key={d.name} {...d} status="upcoming" />)}
            <DeployCard name="Your site next?" city="Tell us where" invite />
          </div>

          <span className="wf-anno" style={{top:14,right:20}}>Env strip · 3 site groups · invite</span>
        </div>
      </window.Variant>

      {/* B — Map locator + environments */}
      <window.Variant
        letter="B"
        title="Locator · world map + site list"
        desc="A stylised world map with continent silhouettes anchors the section. Singapore glows live (3 sites in one pin); Amsterdam and the USA pulse for upcoming, with dashed gold arcs from the home base. Built-for strip frames the environments."
        notes={['Stylised world map', 'SG cluster as single pin · 3 sites', 'Live pins glow · upcoming pulse', '"Built for" strip beneath']}
      >
        <div className="frame wide wf-reveal">
          <span className="wf-eyebrow">Deployment</span>
          <h2 className="wf-h2" style={{marginBottom:8}}>Live in Singapore.<br/>Coming up worldwide.</h2>
          <div style={{display:'grid',gridTemplateColumns:'1.55fr 1fr',gap:32,marginTop:28,alignItems:'stretch'}}>
            <WorldMap />
            <div style={{display:'flex',flexDirection:'column',gap:18}}>
              <div>
                <span className="wf-eyebrow" style={{color:'#1F8A5B'}}>Live · Singapore</span>
                <ul style={{listStyle:'none',padding:0,margin:'12px 0 0',display:'flex',flexDirection:'column',gap:10}}>
                  {DEPLOYMENTS_LIVE.map(d=>(
                    <li key={d.name} style={{display:'flex',alignItems:'center',gap:10,fontSize:14}}>
                      <span style={{width:8,height:8,borderRadius:999,background:'#1F8A5B',flex:'none'}}></span>
                      <span style={{fontWeight:600}}>{d.name}</span>
                      <span className="mono" style={{fontSize:10,letterSpacing:'0.16em',textTransform:'uppercase',color:'var(--wf-muted)',marginLeft:'auto'}}>{d.context}</span>
                    </li>
                  ))}
                </ul>
              </div>
              <div style={{paddingTop:16,borderTop:'1px solid var(--wf-line)'}}>
                <span className="wf-eyebrow" style={{color:'var(--rr-gold)'}}>Upcoming · Singapore</span>
                <ul style={{listStyle:'none',padding:0,margin:'12px 0 0',display:'flex',flexDirection:'column',gap:10}}>
                  {DEPLOYMENTS_UPCOMING_SG.map(d=>(
                    <li key={d.name} style={{display:'flex',alignItems:'center',gap:10,fontSize:14}}>
                      <span style={{width:8,height:8,borderRadius:999,background:'var(--rr-gold)',flex:'none'}}></span>
                      <span style={{fontWeight:600}}>{d.name}</span>
                      <span className="mono" style={{fontSize:10,letterSpacing:'0.16em',textTransform:'uppercase',color:'var(--wf-muted)',marginLeft:'auto'}}>TBD</span>
                    </li>
                  ))}
                </ul>
              </div>
              <div style={{paddingTop:16,borderTop:'1px solid var(--wf-line)'}}>
                <span className="wf-eyebrow" style={{color:'var(--rr-gold)'}}>Upcoming · International</span>
                <ul style={{listStyle:'none',padding:0,margin:'12px 0 0',display:'flex',flexDirection:'column',gap:10}}>
                  {DEPLOYMENTS_UPCOMING_INTL.map(d=>(
                    <li key={d.name} style={{display:'flex',alignItems:'center',gap:10,fontSize:14}}>
                      <span style={{width:8,height:8,borderRadius:999,background:'var(--rr-gold)',flex:'none'}}></span>
                      <span style={{fontWeight:600}}>{d.name}</span>
                      <span className="mono" style={{fontSize:10,letterSpacing:'0.16em',textTransform:'uppercase',color:'var(--wf-muted)',marginLeft:'auto'}}>{d.city}</span>
                    </li>
                  ))}
                </ul>
              </div>
              <a href="#sec-cta" style={{marginTop:'auto',border:'1px solid var(--rr-gold)',color:'var(--rr-gold)',padding:'14px 18px',borderRadius:8,fontSize:13,fontWeight:600,textDecoration:'none',display:'flex',justifyContent:'space-between',alignItems:'center'}}>
                <span>Want a site next? Tell us where.</span><span>→</span>
              </a>
            </div>
          </div>

          {/* Built-for strip below the map */}
          <div style={{marginTop:32,paddingTop:18,paddingBottom:6,borderTop:'1px solid var(--wf-line)'}}>
            <EnvStrip />
          </div>

          <span className="wf-anno" style={{top:14,right:20}}>World map · SG live · gold pulses</span>
        </div>
      </window.Variant>

      {/* C — Horizontal scroll w/ photos */}
      <window.Variant
        letter="C"
        title="Horizontal scroll · with photography"
        desc="Each deployment becomes a wider portrait card with a site photo + name + status pill. Built-for strip lives between headline and cards."
        notes={['Photographed site tiles', 'Status pill per card', '"Built for" strip up top']}
      >
        <div className="frame wf-reveal">
          <span className="wf-eyebrow">Deployment</span>
          <h2 className="wf-h2" style={{marginBottom:8}}>Live in Singapore.<br/>Coming up worldwide.</h2>
          <div style={{marginTop:24,paddingTop:18,paddingBottom:6,borderTop:'1px solid var(--wf-line)',borderBottom:'1px solid var(--wf-line)'}}>
            <EnvStrip />
          </div>
          <div style={{display:'flex',gap:14,overflowX:'auto',padding:'24px 0 16px',scrollbarWidth:'thin'}}>
            {[...DEPLOYMENTS_LIVE.map(d=>({...d,status:'live'})), ...DEPLOYMENTS_UPCOMING.map(d=>({...d,status:'upcoming'}))].map((d,i)=>(
              <div key={d.name} style={{flex:'0 0 240px'}}>
                <div className="wf-photo" style={{aspectRatio:'3 / 4',marginBottom:10,position:'relative'}}>
                  <span style={{position:'absolute',top:10,left:10,fontFamily:'var(--rr-font-mono)',fontSize:10,letterSpacing:'0.18em',textTransform:'uppercase',padding:'4px 8px',borderRadius:999,background: d.status==='live' ? 'rgba(31,138,91,0.16)' : 'rgba(196,154,60,0.20)',color: d.status==='live' ? '#1F8A5B' : 'var(--rr-gold)'}}>
                    {d.status==='live' ? '● Live' : '○ Upcoming'}
                  </span>
                  <span style={{position:'absolute',top:10,right:10,fontFamily:'var(--rr-font-mono)',fontSize:10,letterSpacing:'0.16em',textTransform:'uppercase',color:'#6F6B5F'}}>{d.context}</span>
                  <span style={{position:'absolute',bottom:10,left:10,right:10,fontSize:12,fontFamily:'var(--rr-font-mono)',letterSpacing:'0.12em',textTransform:'uppercase',color:'#8B8779'}}>{d.short}</span>
                </div>
                <div style={{fontSize:14,fontWeight:600,color:'var(--wf-ink)',lineHeight:1.25}}>{d.name}</div>
                <div className="mono" style={{fontSize:10,letterSpacing:'0.18em',textTransform:'uppercase',color:'var(--wf-muted)',marginTop:4}}>{d.city}</div>
              </div>
            ))}
            <div style={{flex:'0 0 240px'}}>
              <div style={{aspectRatio:'3 / 4',marginBottom:10,border:'1px solid var(--rr-gold)',borderRadius:8,display:'flex',flexDirection:'column',justifyContent:'space-between',padding:18,color:'var(--rr-gold)'}}>
                <span className="wf-icon" style={{color:'var(--rr-gold)',width:18,height:18}}></span>
                <div style={{fontSize:18,fontWeight:600,letterSpacing:'-0.01em',lineHeight:1.2}}>Your site next? Tell us where.</div>
              </div>
              <div style={{fontSize:14,fontWeight:600,color:'var(--rr-gold)'}}>Open to pilots</div>
            </div>
          </div>
          <span className="wf-anno" style={{top:14,right:20}}>Photographed sites · status pill</span>
        </div>
      </window.Variant>
    </React.Fragment>
  );
}
window.DeployVariants = DeployVariants;
