const { useState, useRef, useEffect, Reveal, Icon } = window;

const PACK_BADGE = {
  starter: { label: 'Starter', color: '#8b8b8b', bg: 'rgba(139,139,139,0.12)', border: 'rgba(139,139,139,0.25)' },
  pro:     { label: 'Pro',     color: '#3b82f6', bg: 'rgba(59,130,246,0.12)',  border: 'rgba(59,130,246,0.3)'  },
  premium: { label: 'Premium', color: '#f97316', bg: 'rgba(249,115,22,0.12)',  border: 'rgba(249,115,22,0.3)'  },
};

const TOOLS = [
  {
    id: 'web',
    name: 'VIZION WEB',
    pack: 'starter',
    title: 'Ta page de vente, en ligne en 10 minutes.',
    desc: 'Pages de vente et link-in-bio intégrés. Pas de code, pas de plugin — juste l\'éditeur, ta charte, ton offre.',
    bullets: ['Link-in-bio', 'Landing page', 'Templates prêts à vendre'],
  },
  {
    id: 'flow',
    name: 'VIZION FLOW',
    pack: 'pro',
    title: 'Le focus, quand tu en as besoin.',
    desc: 'Lance une session, coupe le bruit, avance sur ce qui compte. Un pomodoro pensé pour les créateurs qui veulent livrer.',
    bullets: ['Sessions chronométrées', 'Objectif de session', 'Historique & streaks'],
  },
  {
    id: 'planner',
    name: 'VIZION PLANNER',
    pack: 'pro',
    title: 'Une semaine claire, zéro bazar.',
    desc: 'Pose tes priorités, répartis tes tâches, coche au fur et à mesure. Une vue calendrier simple, synchronisée avec Flow.',
    bullets: ['Vue semaine', 'Priorités automatiques', 'Sync avec Flow'],
  },
  {
    id: 'tracker',
    name: 'VIZION TRACKER',
    pack: 'pro',
    title: 'Tes habitudes, en vue claire.',
    desc: 'Coche tes routines quotidiennes, visualise tes streaks, repère ce qui fait réellement avancer ton business. Pas un simple to-do.',
    bullets: ['Tracking par habitude', 'Streaks & statistiques', 'Moods quotidiens'],
  },
  {
    id: 'ai',
    name: 'VIZION IA',
    pack: 'premium',
    title: 'Ton copywriter, toujours prêt.',
    desc: 'Scripts, hooks, légendes, analyses vidéo. Entraîné sur les formats qui fonctionnent en 2026 sur TikTok, Instagram et YouTube.',
    bullets: ['Scripts courts / longs', 'Hooks testés', 'Analyse vidéo IA'],
  },
  {
    id: 'trend',
    name: 'VIZION TREND',
    pack: 'premium',
    title: 'Tu gagnes 2 heures par jour.',
    desc: 'Fini la veille TikTok chronophage. VIZION Trend affiche directement les meilleures vidéos MRR du moment. Tu vois ce qui marche, tu t\'en inspires, tu passes à l\'action.',
    bullets: ['Trending par niche', 'Mise à jour quotidienne', 'Exports one-click'],
  },
];

// Durées approximatives d'un cycle complet par outil (pour l'auto-play)
const TOOL_CYCLE_MS = {
  web:     7200,
  flow:    13000,
  planner: 24000, // le plus long : drops + édition + drag
  tracker: 9500,
  ai:      11000,
  trend:   10500,
};

function PackBadge({ pack }) {
  const b = PACK_BADGE[pack];
  if (!b) return null;
  return (
    <span style={{
      fontSize: 10, fontWeight: 600, letterSpacing: '0.06em',
      padding: '3px 8px', borderRadius: 999,
      color: b.color, background: b.bg,
      border: '1px solid ' + b.border,
      textTransform: 'uppercase',
      fontFamily: "'Geist', sans-serif",
      whiteSpace: 'nowrap',
    }}>Pack {b.label}</span>
  );
}

function Demo() {
  const [active, setActive] = useState('web');
  const tool = TOOLS.find(t => t.id === active);

  const handleTabClick = (id) => {
    setActive(id);
  };

  return (
    <section id="fonctionnalites" className="section" style={{ paddingTop: 'calc(var(--pad-section-y) * 0.5)' }}>
      <div className="container">
        <Reveal className="section-header" style={{ textAlign: 'center', alignItems: 'center', marginLeft: 'auto', marginRight: 'auto' }}>
          <h2 className="h2" style={{ textTransform: 'none' }}>
            Des fonctionnalités pour<br />
            <span className="serif-i" style={{ color: 'var(--accent)', fontWeight: 400 }}>performer dans le digital.</span>
          </h2>
          <p style={{ color: 'var(--ink-dim)', fontSize: 18, maxWidth: 540 }}>
            Tout ce dont tu as besoin pour créer, publier et convertir. Intégré, cohérent, sans friction.
          </p>
        </Reveal>

        {/* Tabs pleine largeur */}
        <div className="demo-tabs" style={{
          display: 'grid',
          gridTemplateColumns: `repeat(${TOOLS.length}, 1fr)`,
          borderBottom: '1px solid var(--line)',
          marginBottom: 40,
          position: 'relative',
        }}>
          {TOOLS.map(t => {
            const isActive = active === t.id;
            return (
              <button key={t.id} onClick={() => handleTabClick(t.id)} data-cursor="hover"
                style={{
                  position: 'relative', padding: '18px 8px',
                  background: 'transparent', border: 'none',
                  color: isActive ? 'var(--ink)' : 'var(--ink-mute)',
                  fontFamily: 'Geist, sans-serif',
                  fontSize: 12,
                  fontWeight: isActive ? 600 : 500,
                  letterSpacing: '0.08em',
                  textTransform: 'uppercase',
                  cursor: 'pointer',
                  transition: 'color 0.25s ease',
                  display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
                }}>
                {isActive && (
                  <span style={{
                    width: 6, height: 6, borderRadius: '50%',
                    background: 'var(--accent)',
                    boxShadow: '0 0 10px var(--accent-glow)',
                  }} />
                )}
                {t.name}
                {isActive && (
                  <span style={{
                    position: 'absolute', bottom: -1, left: '8%', right: '8%', height: 1.5,
                    background: 'var(--accent)',
                    boxShadow: '0 0 8px var(--accent-glow)',
                  }} />
                )}
              </button>
            );
          })}
        </div>

        {/* Card outil — style pillar minimaliste */}
        <Reveal key={active}>
          <div className="card demo-card" style={{
            display: 'grid',
            gridTemplateColumns: '1fr 1.05fr',
            gap: 48,
            padding: '44px 48px',
            minHeight: 360,
            alignItems: 'center',
          }}>
            <div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 20 }}>
                <span className="mono" style={{ fontSize: 11, color: 'var(--accent)', letterSpacing: '0.14em' }}>{tool.name}</span>
                <span style={{ height: 1, flex: 1, maxWidth: 40, background: 'var(--line-strong)' }} />
                {tool.pack && <PackBadge pack={tool.pack} />}
              </div>
              <h3 className="h3" style={{
                textTransform: 'none',
                fontSize: 'clamp(34px, 3.6vw, 48px)',
                lineHeight: 1.08,
                marginBottom: 20,
                maxWidth: 480,
              }}>
                {tool.title}
              </h3>
              <p style={{ color: 'var(--ink-dim)', fontSize: 15, lineHeight: 1.55, marginBottom: 26, maxWidth: 460 }}>
                {tool.desc}
              </p>
              <div className="demo-bullets" style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                {tool.bullets.map((b, i) => (
                  <span key={i} className="chip" style={{
                    background: 'var(--bg-elev)',
                    color: 'var(--ink)',
                    textTransform: 'none',
                    letterSpacing: 0,
                    fontSize: 12,
                    fontFamily: 'Geist, sans-serif',
                    padding: '7px 13px',
                  }}>
                    <Icon.Check size={11} />{b}
                  </span>
                ))}
              </div>
            </div>
            <div style={{ position: 'relative', minHeight: 300, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              {active === 'web'     && <WebVisual />}
              {active === 'flow'    && <FlowVisual />}
              {active === 'planner' && <PlannerVisual />}
              {active === 'ai'      && <AIVisual />}
              {active === 'trend'   && <TrendVisual />}
              {active === 'tracker' && <TrackerVisual />}
            </div>
          </div>
        </Reveal>
      </div>
    </section>
  );
}

/* ══════════════════════════════════════════════════════════════════════
   VISUELS MINIMALISTES par outil — avec animations humaines (cursor, drag, typing)
   ══════════════════════════════════════════════════════════════════════ */

// Curseur SVG animé réutilisable — z-index 30 pour passer au-dessus des popups
// Prop `instant` désactive la transition CSS (pour les animations RAF lerp fluides)
const Cursor = ({ style, clicking = false, instant = false }) => (
  <div style={{
    position: 'absolute',
    width: 20, height: 22,
    pointerEvents: 'none',
    zIndex: 30,
    filter: 'drop-shadow(0 3px 6px rgba(0,0,0,0.4))',
    transition: instant ? 'none' : 'all 0.55s cubic-bezier(.4,.2,.2,1)',
    ...style,
  }}>
    <svg width="20" height="22" viewBox="0 0 20 22">
      <path d="M2 2 L9 17 L11.5 11 L18 9 Z" fill="#ffffff" stroke="#0a0a0b" strokeWidth="1.2" strokeLinejoin="round" />
    </svg>
    {clicking && (
      <div style={{
        position: 'absolute',
        /* Ring centré sur le tip (2,2) du SVG, pas sur le coin du wrapper */
        top: -18, left: -18,
        width: 40, height: 40,
        borderRadius: '50%',
        border: '2px solid var(--accent)',
        opacity: 0,
        animation: 'clickRing 0.5s ease-out',
      }} />
    )}
  </div>
);

/**
 * Helper universel : positionne le wrapper du Cursor pour que le TIP du SVG (pt 2,2)
 * tombe pile au centre de l'élément cible. Compatible avec tout conteneur local.
 */
function cursorTipFor(targetEl, rootEl, ox = 0, oy = 0) {
  if (!targetEl || !rootEl) return { x: 0, y: 0 };
  const a = targetEl.getBoundingClientRect();
  const b = rootEl.getBoundingClientRect();
  return {
    x: (a.left - b.left) + a.width / 2 - 2 + ox,
    y: (a.top  - b.top)  + a.height / 2 - 2 + oy,
  };
}

/**
 * Chrome macOS — barre titre avec 3 dots (fermer/réduire/agrandir) + URL centrée.
 * Accepte `rootRef` pour que le parent puisse utiliser `containerRef` et positionner
 * correctement le Cursor via `cursorTipFor`.
 */
function MacChrome({ title, children, maxWidth = 460, contentStyle = {}, rootRef, compact = false, contentRef }) {
  return (
    <div ref={rootRef} style={{
      position: 'relative',
      background: 'var(--bg-elev)',
      borderRadius: 14,
      border: '1px solid var(--line)',
      width: '100%',
      maxWidth,
      overflow: 'hidden',
      boxShadow: '0 24px 60px -28px rgba(0,0,0,0.55), 0 2px 10px -4px rgba(0,0,0,0.3)',
    }}>
      {/* Barre chrome façon macOS */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 8,
        padding: compact ? '8px 12px' : '10px 14px',
        borderBottom: '1px solid var(--line)',
        background: 'linear-gradient(to bottom, color-mix(in oklab, var(--bg-elev) 20%, var(--bg)), var(--bg-elev))',
      }}>
        <div className="mac-dots">
          <button className="mac-dot mac-dot--close" tabIndex={-1} aria-label="close">
            <svg width="6" height="6" viewBox="0 0 6 6" fill="none"><path d="M1 1L5 5M5 1L1 5" stroke="rgba(0,0,0,0.55)" strokeWidth="1" strokeLinecap="round"/></svg>
          </button>
          <button className="mac-dot mac-dot--minimize" tabIndex={-1} aria-label="minimize">
            <svg width="6" height="6" viewBox="0 0 6 6" fill="none"><path d="M1 3H5" stroke="rgba(0,0,0,0.55)" strokeWidth="1" strokeLinecap="round"/></svg>
          </button>
          <button className="mac-dot mac-dot--maximize" tabIndex={-1} aria-label="maximize">
            <svg width="6" height="6" viewBox="0 0 6 6" fill="none"><path d="M1 3H5M3 1V5" stroke="rgba(0,0,0,0.55)" strokeWidth="1" strokeLinecap="round"/></svg>
          </button>
        </div>
        <div className="mono" style={{
          flex: 1, textAlign: 'center',
          fontSize: 10, color: 'var(--ink-mute)',
          letterSpacing: '0.04em',
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
        }}>
          {title}
        </div>
        {/* Spacer symétrique aux 3 dots pour centrer le titre */}
        <div style={{ width: 46 }} aria-hidden="true" />
      </div>
      {/* Contenu */}
      <div ref={contentRef} style={contentStyle}>
        {children}
      </div>
    </div>
  );
}

function WebVisual() {
  const [activeLink, setActiveLink] = useState(-1);
  const [cursorPos, setCursorPos] = useState({ x: 200, y: 30 });
  const [clicking, setClicking] = useState(false);
  const [activeTheme, setActiveTheme] = useState(0);
  const [panelOpen, setPanelOpen] = useState(false);
  const containerRef = useRef(null);
  const linkRefs = useRef([]);
  const themeCardRefs = useRef([]);
  const themeBtnRef = useRef(null);

  const THEMES = [
    { name: 'Émeraude',  emoji: '🟢', primary: '#2DCD93', bg: '#0a1410', card: '#0f2018', text: '#e8faf3', muted: '#5a9c7a', line: '#1e3828' },
    { name: 'Minuit',    emoji: '🔵', primary: '#3b82f6', bg: '#090f1a', card: '#0d1628', text: '#e0eeff', muted: '#4a72b0', line: '#162240' },
    { name: 'Aurora',    emoji: '🩷', primary: '#ec4899', bg: '#1a0910', card: '#280f1c', text: '#ffe0ee', muted: '#a0406e', line: '#3a1428' },
    { name: 'Lumière ☀️', emoji: '⬜', primary: '#2DCD93', bg: '#f5f7f5', card: '#ffffff', text: '#111a14', muted: '#6b8878', line: '#d8e8dd' },
  ];

  const LINKS = [
    { title: 'Formation MRR 2.0',  sub: '12 h de vidéos · accès à vie',  icon: '🎓' },
    { title: 'Pack de ressources', sub: 'Templates, scripts, prompts IA', icon: '📦' },
    { title: 'Réserver un call',   sub: '30 min · 1-to-1 · offert',       icon: '📅' },
  ];

  const theme = THEMES[activeTheme];
  const isLight = activeTheme === 3;

  useEffect(() => {
    let cancelled = false;
    const sleep = (ms) => new Promise(r => setTimeout(r, ms));
    const run = async () => {
      while (!cancelled) {
        // Phase 1 : clic sur le bouton "Changer de thème"
        if (themeBtnRef.current && containerRef.current) {
          setCursorPos(cursorTipFor(themeBtnRef.current, containerRef.current));
        }
        await sleep(800);
        setClicking(true);
        await sleep(150);
        setClicking(false);
        setPanelOpen(true);
        await sleep(500);

        // Phase 2 : souris parcourt les cartes de thème dans le panel
        for (let t = 0; t < THEMES.length; t++) {
          if (cancelled) return;
          if (themeCardRefs.current[t] && containerRef.current) {
            setCursorPos(cursorTipFor(themeCardRefs.current[t], containerRef.current));
          }
          await sleep(600);
          setClicking(true);
          setActiveTheme(t);
          await sleep(150);
          setClicking(false);
          await sleep(800);
        }

        // Phase 3 : ferme le panel
        setPanelOpen(false);
        await sleep(600);

        // Phase 4 : souris clique sur les liens
        for (let i = 0; i < LINKS.length; i++) {
          if (cancelled) return;
          if (linkRefs.current[i] && containerRef.current) {
            setCursorPos(cursorTipFor(linkRefs.current[i], containerRef.current));
          }
          await sleep(800);
          setClicking(true);
          setActiveLink(i);
          await sleep(150);
          setClicking(false);
          await sleep(900);
        }
        setActiveLink(-1);
        await sleep(600);
      }
    };
    run();
    return () => { cancelled = true; };
  }, []);

  return (
    <MacChrome title="vizionmrr.fr/remy-digit" rootRef={containerRef}>
      {/* ── Fond global du thème ── */}
      <div style={{ background: theme.bg, transition: 'background 0.5s ease', position: 'relative' }}>

        {/* ── Barre outils en haut ── */}
        <div style={{
          padding: '8px 12px',
          borderBottom: `1px solid ${theme.line}`,
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          transition: 'border-color 0.4s ease',
        }}>
          {/* Indicateur thème actif */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
            <div style={{ width: 8, height: 8, borderRadius: '50%', background: theme.primary, transition: 'background 0.4s ease' }} />
            <span style={{ fontSize: 9, fontFamily: 'Geist Mono, monospace', color: theme.muted, letterSpacing: '0.06em', transition: 'color 0.4s ease' }}>
              {theme.name}
            </span>
          </div>
          {/* Bouton Changer de thème */}
          <button
            ref={themeBtnRef}
            onClick={() => setPanelOpen(o => !o)}
            style={{
              display: 'flex', alignItems: 'center', gap: 5,
              padding: '4px 9px',
              borderRadius: 7,
              background: isLight ? `${theme.primary}18` : `${theme.primary}25`,
              border: `1px solid ${theme.primary}55`,
              color: theme.primary,
              fontSize: 9, fontWeight: 700, letterSpacing: '0.05em',
              fontFamily: 'Geist Mono, monospace',
              cursor: 'pointer',
              transition: 'all 0.3s ease',
            }}
          >
            <svg width="10" height="10" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2">
              <circle cx="8" cy="8" r="3"/><path d="M8 1v2M8 13v2M1 8h2M13 8h2M3.22 3.22l1.42 1.42M11.36 11.36l1.42 1.42M3.22 12.78l1.42-1.42M11.36 4.64l1.42-1.42"/>
            </svg>
            Changer de thème
          </button>
        </div>

        {/* ── Panel de sélection de thème (popup) ── */}
        <div style={{
          position: 'absolute',
          top: 36, right: 8,
          width: 220,
          background: isLight ? '#fff' : '#131313',
          border: `1px solid ${isLight ? '#d0d0d0' : '#2a2a2a'}`,
          borderRadius: 12,
          boxShadow: isLight
            ? '0 12px 40px -8px rgba(0,0,0,0.15), 0 2px 8px rgba(0,0,0,0.06)'
            : '0 20px 50px -12px rgba(0,0,0,0.7), 0 0 0 1px rgba(255,255,255,0.04)',
          opacity: panelOpen ? 1 : 0,
          transform: panelOpen ? 'translateY(0) scale(1)' : 'translateY(-6px) scale(0.97)',
          pointerEvents: panelOpen ? 'auto' : 'none',
          transition: 'all 0.3s cubic-bezier(.2,.7,.2,1)',
          zIndex: 30,
          padding: 10,
        }}>
          <div style={{ fontSize: 8, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase', color: isLight ? '#888' : '#555', fontFamily: 'Geist Mono, monospace', marginBottom: 8 }}>
            Sélectionner un thème
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6 }}>
            {THEMES.map((t, i) => (
              <div
                key={i}
                ref={el => themeCardRefs.current[i] = el}
                onClick={() => setActiveTheme(i)}
                style={{
                  borderRadius: 8,
                  overflow: 'hidden',
                  border: `2px solid ${activeTheme === i ? t.primary : (isLight ? '#e0e0e0' : '#222')}`,
                  cursor: 'pointer',
                  transform: activeTheme === i ? 'scale(1.04)' : 'scale(1)',
                  boxShadow: activeTheme === i ? `0 0 0 2px ${t.primary}44` : 'none',
                  transition: 'all 0.25s cubic-bezier(.2,.7,.2,1)',
                }}
              >
                {/* Mini preview du thème */}
                <div style={{ background: t.bg, padding: '6px 7px', display: 'flex', flexDirection: 'column', gap: 3 }}>
                  {/* Avatar mini */}
                  <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                    <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#2DCD93', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 7, fontWeight: 800, color: '#fff', flexShrink: 0 }}>R</div>
                    <div style={{ height: 4, borderRadius: 2, background: t.text, opacity: 0.7, flex: 1 }} />
                  </div>
                  {/* Lignes simulées */}
                  {[0.9, 0.6, 0.4].map((op, j) => (
                    <div key={j} style={{ height: 3, borderRadius: 2, background: t.primary, opacity: op, width: j === 0 ? '100%' : j === 1 ? '80%' : '65%' }} />
                  ))}
                </div>
                {/* Nom du thème */}
                <div style={{
                  background: isLight ? '#f8f8f8' : '#1a1a1a',
                  padding: '3px 6px',
                  display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                }}>
                  <span style={{ fontSize: 8, fontWeight: 600, color: isLight ? '#333' : '#aaa', fontFamily: 'Geist, sans-serif' }}>{t.name.replace(' ☀️','')}</span>
                  {activeTheme === i && (
                    <svg width="8" height="8" viewBox="0 0 10 10" fill="none">
                      <path d="M2 5L4 7L8 3" stroke={t.primary} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
                    </svg>
                  )}
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* ── Bio preview ── */}
        <div style={{ paddingBottom: 14 }}>
          {/* Avatar + profil */}
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', paddingTop: 16, paddingBottom: 6 }}>
            <div style={{
              width: 58, height: 58, borderRadius: '50%',
              background: '#2DCD93',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontFamily: "var(--display-font, 'Bricolage Grotesque'), sans-serif",
              fontWeight: 800, fontSize: 23, color: '#fff',
              boxShadow: `0 0 0 3px ${theme.card}, 0 0 0 4.5px #2DCD93`,
              transition: 'box-shadow 0.5s ease',
              flexShrink: 0,
            }}>R</div>

            <div style={{ display: 'flex', alignItems: 'center', gap: 5, marginTop: 8 }}>
              <span style={{ fontSize: 14, fontWeight: 700, color: theme.text, transition: 'color 0.5s ease', letterSpacing: '-0.01em' }}>Rémy Digit</span>
              <span style={{ width: 13, height: 13, borderRadius: '50%', background: theme.primary, flexShrink: 0, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', transition: 'background 0.4s ease' }}>
                <svg width="7" height="7" viewBox="0 0 10 10" fill="none"><path d="M2 5L4 7L8 3" stroke="#fff" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/></svg>
              </span>
            </div>

            {/* Bio description — plus grande, plus lisible */}
            <div style={{ fontSize: 11, color: theme.muted, marginTop: 4, textAlign: 'center', lineHeight: 1.45, maxWidth: 200, transition: 'color 0.5s ease' }}>
              Marketing digital · Business MRR<br />
              <span style={{ fontSize: 10, opacity: 0.8 }}>Créateur de contenu · 4.8K abonnés</span>
            </div>
          </div>

          {/* Liens */}
          <div style={{ padding: '0 12px', display: 'grid', gap: 7 }}>
            {LINKS.map((l, i) => {
              const isActive = activeLink === i;
              return (
                <div
                  key={i}
                  ref={el => linkRefs.current[i] = el}
                  style={{
                    display: 'grid', gridTemplateColumns: '30px 1fr 12px',
                    gap: 10, alignItems: 'center',
                    padding: '9px 11px',
                    borderRadius: 10,
                    background: isActive ? theme.card : 'transparent',
                    border: `1px solid ${isActive ? theme.primary : theme.line}`,
                    boxShadow: isActive ? `0 0 0 3px ${theme.primary}28, 0 8px 20px -8px ${theme.primary}` : 'none',
                    transform: isActive && clicking ? 'scale(0.98)' : 'scale(1)',
                    transition: 'all 0.28s cubic-bezier(.2,.7,.2,1)',
                  }}
                >
                  <div style={{ width: 30, height: 30, borderRadius: 8, background: `${theme.primary}22`, border: `1px solid ${isActive ? theme.primary : 'transparent'}`, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 14, transition: 'all 0.3s ease' }}>{l.icon}</div>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontSize: 11.5, fontWeight: 600, color: theme.text, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', transition: 'color 0.5s ease' }}>{l.title}</div>
                    <div style={{ fontSize: 9.5, color: theme.muted, marginTop: 1, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', transition: 'color 0.5s ease' }}>{l.sub}</div>
                  </div>
                  <svg width="10" height="10" viewBox="0 0 12 12" fill="none" stroke={theme.muted} strokeWidth="1.8"><path d="M2 6h8M6 2l4 4-4 4"/></svg>
                </div>
              );
            })}
          </div>
        </div>
      </div>

      <Cursor style={{ top: cursorPos.y, left: cursorPos.x }} clicking={clicking} />
      <style>{`@keyframes clickRing { 0% { opacity: 0.8; transform: scale(0.3); } 100% { opacity: 0; transform: scale(1.4); } }`}</style>
    </MacChrome>
  );
}

function FlowVisual() {
  const [secs, setSecs] = useState(25 * 60);
  const [running, setRunning] = useState(false);
  const [cursor, setCursor] = useState({ x: 80, y: 260 });
  const [clicking, setClicking] = useState(false);
  const containerRef = useRef(null);
  const bodyRef = useRef(null);
  const playBtnRef = useRef(null);

  // Positionne le curseur pile sur le bouton — ref = div interne (containing block réel du Cursor)
  const moveCursorToButton = () => {
    setCursor(cursorTipFor(playBtnRef.current, bodyRef.current));
  };

  // Scénario joué en boucle : clique play → décompte → clique pause → reset
  useEffect(() => {
    let cancelled = false;
    const sleep = (ms) => new Promise(r => setTimeout(r, ms));
    const run = async () => {
      while (!cancelled) {
        moveCursorToButton();
        await sleep(900);
        setClicking(true);
        await sleep(180);
        setRunning(true);
        setClicking(false);
        // Sort du cadre pour laisser voir le décompte
        setCursor({ x: 340, y: 220 });
        await sleep(5000);
        if (cancelled) return;
        moveCursorToButton();
        await sleep(900);
        setClicking(true);
        await sleep(180);
        setRunning(false);
        setClicking(false);
        await sleep(1400);
        setSecs(25 * 60);
        await sleep(400);
      }
    };
    run();
    return () => { cancelled = true; };
  }, []);

  useEffect(() => {
    if (!running) return;
    const t = setInterval(() => setSecs(s => (s > 0 ? s - 1 : 25 * 60)), 1000);
    return () => clearInterval(t);
  }, [running]);

  const m = String(Math.floor(secs / 60)).padStart(2, '0');
  const s = String(secs % 60).padStart(2, '0');
  const pct = 1 - secs / (25 * 60);
  const R = 118;
  const C = 2 * Math.PI * R;

  return (
    <MacChrome title="vizionmrr.fr/vizion-flow" rootRef={containerRef} maxWidth={360}>
      <div ref={bodyRef} style={{
        position: 'relative', width: '100%', height: 320,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
      {/* Halo pulsant quand actif */}
      <div style={{
        position: 'absolute', top: 20, left: 0, right: 0, marginLeft: 'auto', marginRight: 'auto',
        width: 280, height: 280,
        borderRadius: '50%',
        background: 'radial-gradient(circle at center, var(--accent-glow), transparent 70%)',
        opacity: running ? 0.7 : 0,
        transition: 'opacity 0.6s ease',
        animation: running ? 'flowPulse 2.4s ease-in-out infinite' : 'none',
        pointerEvents: 'none',
      }} />

      <svg width="280" height="280" viewBox="0 0 280 280" style={{ position: 'absolute', top: 20, left: '50%', transform: 'translateX(-50%)' }}>
        <circle cx="140" cy="140" r={R} stroke="var(--line)" strokeWidth="1.5" fill="none" />
        <circle cx="140" cy="140" r={R}
          stroke="var(--accent)" strokeWidth="2.5" fill="none"
          strokeDasharray={C} strokeDashoffset={C * (1 - pct)}
          strokeLinecap="round" transform="rotate(-90 140 140)"
          style={{
            transition: 'stroke-dashoffset 1s linear',
            filter: `drop-shadow(0 0 ${running ? 14 : 8}px var(--accent-glow))`,
          }} />
      </svg>

      {/* Timer + label (display bold) — remonté légèrement pour laisser place au bouton */}
      <div style={{
        position: 'absolute', top: 20, left: '50%', transform: 'translateX(-50%)',
        width: 280, height: 280,
        display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
        gap: 8, paddingBottom: 34,
      }}>
        <div className="mono" style={{ fontSize: 11, color: 'var(--ink-mute)', letterSpacing: '0.2em' }}>
          {running ? 'EN COURS' : 'FOCUS'}
        </div>
        <div style={{
          fontFamily: "var(--display-font, 'Bricolage Grotesque'), sans-serif",
          fontSize: 72,
          fontWeight: 800,
          lineHeight: 1,
          letterSpacing: '-0.04em',
          fontVariantNumeric: 'tabular-nums',
          color: running ? 'var(--ink)' : 'var(--ink-dim)',
          transition: 'color 0.3s ease',
        }}>{m}:{s}</div>
        <div className="mono" style={{ fontSize: 10, color: 'var(--accent)', letterSpacing: '0.14em' }}>SESSION 1/4</div>
      </div>

      {/* Bouton play/pause intégré en bas du cercle (overlap) */}
      <div style={{
        position: 'absolute',
        bottom: 40,
        left: '50%',
        transform: 'translateX(-50%)',
      }}>
        <button ref={playBtnRef} style={{
          width: 52, height: 52, borderRadius: '50%',
          background: running ? 'var(--accent)' : 'var(--ink)',
          color: running ? '#fff' : 'var(--bg)',
          border: 'none', display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          boxShadow: running
            ? '0 0 0 6px color-mix(in oklab, var(--accent) 22%, transparent), 0 0 30px var(--accent-glow)'
            : '0 10px 24px -8px rgba(0,0,0,0.4)',
          cursor: 'default',
          transition: 'all 0.3s cubic-bezier(.2,.7,.2,1)',
          transform: clicking ? 'scale(0.92)' : 'scale(1)',
        }}>
          {running ? <Icon.Pause size={15} /> : <Icon.Play size={15} />}
        </button>
      </div>

      <Cursor style={{ top: cursor.y, left: cursor.x }} clicking={clicking} />

      <style>{`
        @keyframes flowPulse {
          0%, 100% { transform: scale(0.98); opacity: 0.55; }
          50%      { transform: scale(1.04); opacity: 0.85; }
        }
      `}</style>
      </div>
    </MacChrome>
  );
}

function PlannerVisual() {
  // Semaine de travail : 5 jours → cases plus larges, texte lisible
  const DAYS = ['Lun', 'Mar', 'Mer', 'Jeu', 'Ven'];

  // Palette de couleurs pour simuler différentes catégories utilisateur
  const COLORS = {
    accent:  { bg: 'var(--accent)',                                           fg: '#fff' },
    blue:    { bg: '#3b82f6',                                                 fg: '#fff' },
    orange:  { bg: '#f59e0b',                                                 fg: '#0a0a0b' },
    violet:  { bg: '#8b5cf6',                                                 fg: '#fff' },
    soft:    { bg: 'color-mix(in oklab, var(--accent) 22%, transparent)',      fg: 'var(--accent)' },
  };
  // Tâches fixes validées (catégories variées)
  // IMPORTANT : Tournage (Jeu) sera DRAGGÉ vers Ven en fin de cycle
  const initialStatic = [
    { id: 's1', d: 0, row: 0, t: 'Script',   c: 'accent' },
    { id: 's2', d: 1, row: 1, t: 'Deep work', c: 'blue'   },
    { id: 's3', d: 3, row: 0, t: 'Tournage', c: 'orange' },
  ];

  // Tâches ajoutées par le curseur (avec typing)
  const DROP_SEQUENCE = [
    { id: 'd1', d: 2, row: 2, initial: 'Publi',  edited: 'Publication', c: 'violet', editable: true  },
    { id: 'd2', d: 4, row: 2, initial: 'Review', edited: 'Review',      c: 'accent', editable: false },
  ];

  // Tâche à drag & drop (existante) : Tournage passe Jeu → Ven
  const DRAG_MOVE = { id: 's3', fromD: 3, fromRow: 0, toD: 4, toRow: 0 };

  const [typed, setTyped] = useState('');
  const [phase, setPhase] = useState('idle'); // idle | typing | editing | dragging
  const [placed, setPlaced] = useState([]);
  const [staticTasks, setStaticTasks] = useState(initialStatic);
  const [editOpen, setEditOpen] = useState(false);
  const [editInput, setEditInput] = useState('');
  const [validHover, setValidHover] = useState(false);
  const [cursor, setCursor] = useState({ x: 440, y: 20 });
  const [clicking, setClicking] = useState(false);
  // Drag state : { ghostX, ghostY, task }
  const [dragGhost, setDragGhost] = useState(null);

  const containerRef = useRef(null);
  const bodyRef = useRef(null);
  const slotRefs = useRef({});
  const editInputRef = useRef(null);
  const validBtnRef = useRef(null);

  useEffect(() => {
    let cancelled = false;
    const sleep = (ms) => new Promise(r => setTimeout(r, ms));
    const run = async () => {
      while (!cancelled) {
        // Reset complet à chaque cycle
        setPlaced([]);
        setStaticTasks(initialStatic);
        setEditOpen(false);
        setValidHover(false);
        setDragGhost(null);
        setTyped('');
        setPhase('idle');
        setCursor({ x: 440, y: 20 });
        await sleep(600);

        // ══ PHASE 1 : drop + typing + (édition pour 1ère) ══
        for (let i = 0; i < DROP_SEQUENCE.length; i++) {
          if (cancelled) return;
          const task = DROP_SEQUENCE[i];
          const slot = slotRefs.current[`${task.row}-${task.d}`];

          setCursor(cursorTipFor(slot, bodyRef.current));
          await sleep(850);
          setClicking(true);
          await sleep(160);
          setClicking(false);

          setPhase('typing');
          setTyped('');
          const full = task.initial;
          for (let j = 0; j <= full.length; j++) {
            if (cancelled) return;
            setTyped(full.slice(0, j));
            await sleep(45);
          }

          setPlaced(prev => [...prev, { ...task, t: task.initial, valid: false }]);
          setTyped('');
          setPhase('idle');
          await sleep(380);

          if (task.editable) {
            setCursor(cursorTipFor(slot, bodyRef.current, 0, -4));
            await sleep(500);
            setClicking(true);
            await sleep(160);
            setClicking(false);
            setEditOpen(true);
            setEditInput(task.initial);
            setPhase('editing');

            await sleep(350);
            setCursor(cursorTipFor(editInputRef.current, bodyRef.current));
            await sleep(550);
            setClicking(true);
            await sleep(140);
            setClicking(false);

            for (let k = task.initial.length; k <= task.edited.length; k++) {
              if (cancelled) return;
              setEditInput(task.edited.slice(0, k));
              await sleep(55);
            }
            await sleep(350);

            setCursor(cursorTipFor(validBtnRef.current, bodyRef.current));
            await sleep(600);
            setValidHover(true);
            await sleep(160);
            setClicking(true);
            await sleep(160);
            setClicking(false);

            setPlaced(prev => prev.map((p, idx) =>
              idx === i ? { ...p, t: task.edited, valid: true } : p
            ));
            setEditOpen(false);
            setValidHover(false);
            setPhase('idle');
          } else {
            await sleep(260);
            setPlaced(prev => prev.map((p, idx) =>
              idx === i ? { ...p, valid: true } : p
            ));
          }

          setCursor({ x: 440, y: 20 });
          await sleep(700);
        }

        // ══ PHASE 2 : drag & drop d'une tâche existante (Tournage Jeu → Ven) ══
        await sleep(500);
        const fromSlot = slotRefs.current[`${DRAG_MOVE.fromRow}-${DRAG_MOVE.fromD}`];
        const toSlot = slotRefs.current[`${DRAG_MOVE.toRow}-${DRAG_MOVE.toD}`];
        if (fromSlot && toSlot) {
          // 1. Curseur arrive sur la tâche à déplacer
          setCursor(cursorTipFor(fromSlot, bodyRef.current));
          await sleep(750);

          // 2. Clic → effet de pression visible sur la tâche
          setClicking(true);
          // Le ghost apparaît déjà (avec scale-up pour simuler la "saisie")
          const draggedTask = staticTasks.find(t => t.id === DRAG_MOVE.id) || initialStatic.find(t => t.id === DRAG_MOVE.id);
          setPhase('dragging');
          setDragGhost({ task: draggedTask, grabbed: true });
          // La tâche disparaît de son emplacement source
          setStaticTasks(prev => prev.filter(t => t.id !== DRAG_MOVE.id));
          await sleep(220);
          setClicking(false);
          await sleep(220);

          // 3. Déplacement fluide via requestAnimationFrame (easing cubic ease-out)
          const fromPos = cursorTipFor(fromSlot, bodyRef.current);
          const toPos = cursorTipFor(toSlot, bodyRef.current);
          await new Promise((resolve) => {
            const duration = 1100;
            const start = performance.now();
            const tick = (now) => {
              if (cancelled) { resolve(); return; }
              const elapsed = now - start;
              const t = Math.min(1, elapsed / duration);
              // Ease out cubic : commence rapide, ralentit en fin
              const e = 1 - Math.pow(1 - t, 3);
              setCursor({
                x: fromPos.x + (toPos.x - fromPos.x) * e,
                y: fromPos.y + (toPos.y - fromPos.y) * e,
              });
              if (t < 1) requestAnimationFrame(tick);
              else resolve();
            };
            requestAnimationFrame(tick);
          });
          if (cancelled) return;

          // 4. Drop : petite pause sur la target, puis dépose la tâche
          await sleep(240);
          setStaticTasks(prev => [
            ...prev,
            { ...draggedTask, d: DRAG_MOVE.toD, row: DRAG_MOVE.toRow },
          ]);
          setDragGhost(null);
          setPhase('idle');
          await sleep(1400);
        }

        setCursor({ x: 440, y: 20 });
        await sleep(1800);
      }
    };
    run();
    return () => { cancelled = true; };
  }, []);

  const renderCell = (col, row) => {
    const ev = staticTasks.find(e => e.d === col && e.row === row);
    const dropped = placed.find(e => e.d === col && e.row === row);
    const beingDrawn = phase === 'typing'
      && placed.length < DROP_SEQUENCE.length
      && DROP_SEQUENCE[placed.length].d === col
      && DROP_SEQUENCE[placed.length].row === row;

    // Target du drop en cours de drag
    const isDropTarget = phase === 'dragging'
      && dragGhost
      && DRAG_MOVE.toD === col
      && DRAG_MOVE.toRow === row;

    let shown = null;
    let valid = true;
    if (ev) { shown = ev; valid = true; }
    else if (dropped) { shown = dropped; valid = dropped.valid; }
    else if (beingDrawn) {
      const t = DROP_SEQUENCE[placed.length];
      shown = { ...t, t: typed || '|' };
      valid = false;
    }

    const color = shown ? (COLORS[shown.c] || COLORS.accent) : null;
    const slotKey = `${row}-${col}`;

    return (
      <div
        key={slotKey}
        ref={el => { slotRefs.current[slotKey] = el; }}
        style={{
          height: 48, borderRadius: 8,
          border: (beingDrawn || isDropTarget)
            ? '1.5px dashed var(--accent)'
            : '1px solid var(--line)',
          background: (beingDrawn || isDropTarget)
            ? 'color-mix(in oklab, var(--accent) 6%, transparent)'
            : 'transparent',
          position: 'relative',
          transition: 'border-color 0.2s ease, background 0.2s ease',
        }}>
        {shown && (
          <div style={{
            position: 'absolute', inset: 3,
            background: !valid
              ? 'color-mix(in oklab, var(--ink-mute) 22%, transparent)'
              : color.bg,
            color: !valid ? 'var(--ink-dim)' : color.fg,
            borderRadius: 5, fontSize: 11, fontWeight: 600,
            display: 'flex', alignItems: 'center', padding: '0 8px',
            animation: beingDrawn ? 'none' : 'slideIn 0.4s ease-out both',
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
            letterSpacing: '-0.005em',
            transition: 'background 0.35s ease, color 0.35s ease',
          }}>{shown.t}</div>
        )}
      </div>
    );
  };

  return (
    <MacChrome title="vizionmrr.fr/vizion-planner" rootRef={containerRef} contentRef={bodyRef} maxWidth={480} contentStyle={{ padding: 22, position: 'relative' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16 }}>
        <span className="label">Semaine 16</span>
        <span className="mono" style={{ fontSize: 10, color: 'var(--accent)' }}>● {staticTasks.length + placed.length} tâches</span>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 6 }}>
        {DAYS.map((d, i) => (
          <div key={i} style={{
            textAlign: 'center',
            padding: '8px 0',
            fontSize: 11,
            fontFamily: 'Geist Mono',
            color: 'var(--ink-mute)',
            letterSpacing: '0.06em',
            textTransform: 'uppercase',
          }}>{d}</div>
        ))}
        {[0, 1, 2].map(row => DAYS.map((_, col) => renderCell(col, row)))}
      </div>

      {/* Popup d'édition de tâche */}
      <div style={{
        position: 'absolute',
        top: '50%', left: '50%',
        transform: `translate(-50%, -50%) scale(${editOpen ? 1 : 0.92})`,
        width: 260,
        padding: 16,
        background: 'var(--bg-card)',
        border: '1px solid var(--line-strong)',
        borderRadius: 14,
        boxShadow: '0 20px 50px -12px rgba(0,0,0,0.5), 0 0 0 6px color-mix(in oklab, var(--bg) 40%, transparent)',
        opacity: editOpen ? 1 : 0,
        pointerEvents: editOpen ? 'auto' : 'none',
        transition: 'opacity 0.3s ease, transform 0.3s cubic-bezier(.2,.7,.2,1)',
        zIndex: 20,
      }}>
        <div className="label" style={{ marginBottom: 10 }}>Éditer la tâche</div>
        <input ref={editInputRef} type="text" value={editInput} readOnly
          style={{
            width: '100%',
            padding: '8px 10px',
            background: 'var(--bg-elev)',
            border: '1px solid var(--accent)',
            borderRadius: 8,
            color: 'var(--ink)',
            fontSize: 13,
            fontFamily: 'Geist, sans-serif',
            outline: 'none',
            marginBottom: 12,
          }} />
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
          <button style={{
            padding: '7px 12px', fontSize: 11, fontWeight: 500,
            background: 'transparent', color: 'var(--ink-mute)',
            border: '1px solid var(--line)', borderRadius: 7, cursor: 'default',
          }}>Annuler</button>
          <button ref={validBtnRef} style={{
            padding: '7px 12px', fontSize: 11, fontWeight: 600,
            background: validHover ? 'var(--accent)' : 'color-mix(in oklab, var(--ink-mute) 18%, transparent)',
            color: validHover ? '#fff' : 'var(--ink-dim)',
            border: 'none', borderRadius: 7, cursor: 'default',
            boxShadow: validHover ? '0 0 0 4px color-mix(in oklab, var(--accent) 22%, transparent)' : 'none',
            transition: 'all 0.25s cubic-bezier(.2,.7,.2,1)',
            display: 'inline-flex', alignItems: 'center', gap: 5,
          }}>
            <Icon.Check size={11} /> Valider
          </button>
        </div>
      </div>

      {/* Ghost de la tâche pendant le drag — suit le curseur, pop on grab */}
      {dragGhost && (
        <div style={{
          position: 'absolute',
          top: cursor.y - 8,
          left: cursor.x + 14,
          pointerEvents: 'none',
          zIndex: 25,
          padding: '7px 14px',
          borderRadius: 7,
          background: (COLORS[dragGhost.task.c] || COLORS.accent).bg,
          color: (COLORS[dragGhost.task.c] || COLORS.accent).fg,
          fontSize: 12, fontWeight: 600,
          letterSpacing: '-0.005em',
          boxShadow: '0 18px 40px -10px rgba(0,0,0,0.55), 0 0 0 3px color-mix(in oklab, var(--accent) 30%, transparent)',
          whiteSpace: 'nowrap',
          transformOrigin: 'center',
          animation: 'ghostGrab 0.35s cubic-bezier(.2,.7,.2,1) forwards',
        }}>
          {dragGhost.task.t}
        </div>
      )}

      <Cursor style={{ top: cursor.y, left: cursor.x }} clicking={clicking} instant={phase === 'dragging'} />

      <style>{`
        @keyframes slideIn{from{opacity:0;transform:scale(0.9)}to{opacity:1;transform:scale(1)}}
        @keyframes ghostGrab {
          0%   { opacity: 0.6; transform: rotate(0deg)  scale(1); }
          45%  { opacity: 1;   transform: rotate(-5deg) scale(1.14); }
          100% { opacity: 1;   transform: rotate(-3deg) scale(1.08); }
        }
      `}</style>
    </MacChrome>
  );
}

function AIVisual() {
  const LINES = [
    '→ "J\'ai gagné 4 800€ ce mois…"',
    '→ "3 erreurs qui tuent ton MRR"',
    '→ "De 0 à 1 000€ en 30 jours"',
  ];
  const [shown, setShown] = useState([]);
  const [typing, setTyping] = useState('');
  useEffect(() => {
    let cancelled = false, li = 0, ci = 0;
    const tick = () => {
      if (cancelled) return;
      if (li >= LINES.length) {
        setTimeout(() => { if (!cancelled) { setShown([]); setTyping(''); li = 0; ci = 0; tick(); } }, 1800);
        return;
      }
      const cur = LINES[li];
      if (ci <= cur.length) {
        setTyping(cur.slice(0, ci));
        ci++;
        setTimeout(tick, 32);
      } else {
        setShown(s => [...s, cur]);
        setTyping('');
        li++; ci = 0;
        setTimeout(tick, 280);
      }
    };
    tick();
    return () => { cancelled = true; };
  }, []);
  return (
    <MacChrome title="vizionmrr.fr/vizion-ia" maxWidth={460} contentStyle={{ padding: 24 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16 }}>
        <span className="label">IA · Scripts</span>
        <span className="mono" style={{ fontSize: 10, color: 'var(--accent)', display: 'flex', alignItems: 'center', gap: 6 }}>
          <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--accent)', animation: 'breathe 1.4s infinite' }} />
          Génération
        </span>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, fontSize: 13, color: 'var(--ink-dim)' }}>
        {shown.map((l, i) => <div key={i} style={{ animation: 'fadein 0.3s both' }}>{l}</div>)}
        {typing && <div style={{ color: 'var(--ink)' }}>{typing}<span style={{ display: 'inline-block', width: 2, height: 13, background: 'var(--accent)', marginLeft: 2, verticalAlign: 'middle', animation: 'blink 1s infinite' }} /></div>}
      </div>
      <style>{`
        @keyframes fadein{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}
        @keyframes blink{50%{opacity:0}}
      `}</style>
    </MacChrome>
  );
}

function TrendVisual() {
  const POOL = [
    { hook: 'POV: t\'es en cours et tu fais 1 800 € 🫠',  views: '343k', tag: '#mrr'      },
    { hook: '3 erreurs qui tuent ton MRR en 2026',          views: '198k', tag: '#business' },
    { hook: 'De 0 à 1 000 € en 30 jours',                   views: '121k', tag: '#digital'  },
    { hook: 'Ce script IA a fait 340k vues',                views: '287k', tag: '#hook'     },
    { hook: 'Le setup qui convertit à 8 %',                 views: '156k', tag: '#setup'    },
    { hook: 'J\'ai testé VIZION pendant 30 jours',          views: '412k', tag: '#vizion'   },
  ];

  const [list, setList] = useState(POOL.slice(0, 3));
  const [flash, setFlash] = useState(false);

  useEffect(() => {
    let cancelled = false, i = 0;
    const sleep = (ms) => new Promise(r => setTimeout(r, ms));
    const run = async () => {
      while (!cancelled) {
        await sleep(3200);
        if (cancelled) return;
        // Nouveau trending pop au #1, les autres descendent
        const next = POOL[(i + 3) % POOL.length];
        i++;
        setList(prev => [next, ...prev.slice(0, 2)]);
        setFlash(true);
        await sleep(800);
        if (!cancelled) setFlash(false);
      }
    };
    run();
    return () => { cancelled = true; };
  }, []);

  return (
    <MacChrome title="vizionmrr.fr/vizion-trend" maxWidth={460} contentStyle={{ padding: 22, position: 'relative' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 12 }}>
        <span className="label">Trending · TikTok</span>
        <span className="mono" style={{ fontSize: 10, color: 'var(--accent)', display: 'flex', alignItems: 'center', gap: 6 }}>
          <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--accent)', animation: 'breathe 1.4s infinite' }} />
          24 h · #mrr
        </span>
      </div>

      {/* Badge "nouvelle tendance" qui flash */}
      <div style={{
        position: 'absolute', top: 34, right: 0, zIndex: 2,
        padding: '4px 10px', borderRadius: 999,
        background: 'var(--accent)', color: '#fff',
        fontSize: 9, fontFamily: 'Geist Mono', fontWeight: 600, letterSpacing: '0.1em',
        opacity: flash ? 1 : 0,
        transform: flash ? 'translateY(0)' : 'translateY(-6px)',
        transition: 'all 0.3s ease',
        pointerEvents: 'none',
        boxShadow: '0 0 20px var(--accent-glow)',
      }}>
        ✦ NOUVELLE TENDANCE
      </div>

      <div style={{ display: 'grid', gap: 8, position: 'relative' }}>
        {list.map((v, i) => (
          <div key={`${v.hook}-${i}`} style={{
            display: 'grid', gridTemplateColumns: '28px 1fr auto', gap: 14, alignItems: 'center',
            padding: '12px 14px',
            background: i === 0 && flash
              ? 'color-mix(in oklab, var(--accent) 12%, var(--bg-elev))'
              : 'var(--bg-elev)',
            borderRadius: 12,
            border: i === 0 && flash
              ? '1px solid var(--accent)'
              : '1px solid var(--line)',
            boxShadow: i === 0 && flash ? '0 0 24px -6px var(--accent-glow)' : 'none',
            transition: 'all 0.45s cubic-bezier(.2,.7,.2,1)',
            animation: i === 0 ? 'trendPop 0.6s cubic-bezier(.2,.7,.2,1) both' : undefined,
          }}>
            <span style={{
              width: 24, height: 24, borderRadius: 6,
              background: i === 0 ? 'var(--accent)' : 'var(--bg-card)',
              color: i === 0 ? '#fff' : 'var(--ink-dim)',
              fontFamily: 'Geist Mono', fontSize: 11, fontWeight: 600,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              transition: 'background 0.3s ease',
            }}>#{i + 1}</span>
            <div style={{ minWidth: 0 }}>
              <div style={{ fontSize: 12, color: 'var(--ink)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                {v.hook}
              </div>
              <div className="mono" style={{ fontSize: 10, color: 'var(--accent)', marginTop: 2 }}>{v.tag}</div>
            </div>
            <span className="mono" style={{ fontSize: 11, color: 'var(--ink)', fontWeight: 500, flexShrink: 0 }}>↗ {v.views}</span>
          </div>
        ))}
      </div>
      <style>{`
        @keyframes trendPop {
          0%   { opacity: 0; transform: translateY(-20px) scale(0.95); filter: blur(8px); }
          60%  { opacity: 1; transform: translateY(2px) scale(1.02); filter: blur(0); }
          100% { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
        }
      `}</style>
    </MacChrome>
  );
}

/* ══════════════════════════════════════════════════════════════════════
   TRACKER — curseur qui coche des habitudes du jour + stats
   ══════════════════════════════════════════════════════════════════════ */
function TrackerVisual() {
  const HABITS = [
    { id: 0, icon: '🏃', name: 'Sport',      streak: 12 },
    { id: 1, icon: '📚', name: 'Lecture',    streak: 8  },
    { id: 2, icon: '💧', name: 'Hydratation', streak: 23 },
    { id: 3, icon: '✍️', name: 'Contenu',    streak: 5  },
    { id: 4, icon: '🧘', name: 'Méditation', streak: 17 },
  ];

  const [checked, setChecked] = useState([false, false, false, false, false]);
  const [cursor, setCursor] = useState({ x: 380, y: 20 });
  const [clicking, setClicking] = useState(false);
  const containerRef = useRef(null);
  const bodyRef = useRef(null);
  const checkboxRefs = useRef([]);

  // Positionne le curseur pile sur la checkbox — bodyRef = containing block réel du Cursor
  const moveCursorToCheckbox = (i) => {
    setCursor(cursorTipFor(checkboxRefs.current[i], bodyRef.current));
  };

  useEffect(() => {
    let cancelled = false;
    const sleep = (ms) => new Promise(r => setTimeout(r, ms));
    const run = async () => {
      while (!cancelled) {
        setChecked([false, false, false, false, false]);
        await sleep(800);
        for (let i = 0; i < HABITS.length; i++) {
          if (cancelled) return;
          moveCursorToCheckbox(i);
          await sleep(700);
          setClicking(true);
          await sleep(140);
          setChecked(prev => {
            const next = [...prev];
            next[i] = true;
            return next;
          });
          setClicking(false);
          await sleep(320);
        }
        await sleep(2200);
      }
    };
    run();
    return () => { cancelled = true; };
  }, []);

  const completedCount = checked.filter(Boolean).length;

  return (
    <MacChrome title="vizionmrr.fr/vizion-tracker" rootRef={containerRef} contentRef={bodyRef} maxWidth={460} contentStyle={{ padding: 22, position: 'relative' }}>
      {/* Header : progression du jour */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }}>
        <div>
          <div className="label" style={{ marginBottom: 4 }}>Mardi · aujourd'hui</div>
          <div style={{
            fontFamily: "var(--display-font, 'Bricolage Grotesque'), sans-serif",
            fontSize: 22, fontWeight: 700, letterSpacing: '-0.02em',
            color: 'var(--ink)',
          }}>
            <span style={{ color: 'var(--accent)', fontVariantNumeric: 'tabular-nums' }}>{completedCount}</span>
            <span style={{ color: 'var(--ink-mute)' }}> / {HABITS.length}</span>
          </div>
        </div>
        {/* Mini progress ring */}
        <div style={{ position: 'relative', width: 40, height: 40 }}>
          <svg width="40" height="40" viewBox="0 0 40 40">
            <circle cx="20" cy="20" r="16" stroke="var(--line)" strokeWidth="2.5" fill="none" />
            <circle cx="20" cy="20" r="16"
              stroke="var(--accent)" strokeWidth="2.5" fill="none" strokeLinecap="round"
              strokeDasharray={2 * Math.PI * 16}
              strokeDashoffset={(2 * Math.PI * 16) * (1 - completedCount / HABITS.length)}
              transform="rotate(-90 20 20)"
              style={{ transition: 'stroke-dashoffset 0.4s ease', filter: 'drop-shadow(0 0 6px var(--accent-glow))' }}
            />
          </svg>
          <div style={{
            position: 'absolute', inset: 0,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontSize: 10, fontFamily: 'Geist Mono', color: 'var(--accent)', fontWeight: 600,
          }}>
            {Math.round((completedCount / HABITS.length) * 100)}%
          </div>
        </div>
      </div>

      {/* Liste des habitudes */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {HABITS.map((h, i) => {
          const done = checked[i];
          return (
            <div key={h.id} style={{
              display: 'grid', gridTemplateColumns: '28px 1fr auto 28px', gap: 12, alignItems: 'center',
              padding: '10px 12px',
              background: done ? 'color-mix(in oklab, var(--accent) 8%, var(--bg-card))' : 'var(--bg-card)',
              border: done ? '1px solid color-mix(in oklab, var(--accent) 35%, transparent)' : '1px solid var(--line)',
              borderRadius: 10,
              transition: 'background 0.3s ease, border-color 0.3s ease',
            }}>
              <span style={{ fontSize: 18 }}>{h.icon}</span>
              <div>
                <div style={{
                  fontSize: 13, fontWeight: 500,
                  color: done ? 'var(--ink)' : 'var(--ink-dim)',
                  textDecorationLine: done ? 'line-through' : 'none',
                  textDecorationColor: done ? 'color-mix(in oklab, var(--accent) 60%, transparent)' : 'transparent',
                  transition: 'color 0.3s ease',
                }}>{h.name}</div>
              </div>
              <span className="mono" style={{ fontSize: 10, color: 'var(--accent)', display: 'flex', alignItems: 'center', gap: 4 }}>
                🔥 {h.streak}j
              </span>
              {/* Checkbox */}
              <span ref={el => checkboxRefs.current[i] = el} style={{
                width: 22, height: 22, borderRadius: 6,
                border: done ? 'none' : '1.5px solid var(--line-strong)',
                background: done ? 'var(--accent)' : 'transparent',
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                color: '#fff',
                boxShadow: done ? '0 0 0 3px color-mix(in oklab, var(--accent) 20%, transparent)' : 'none',
                transition: 'all 0.3s cubic-bezier(.2,.7,.2,1)',
                transform: done ? 'scale(1.05)' : 'scale(1)',
              }}>
                {done && (
                  <svg width="12" height="12" viewBox="0 0 12 12" fill="none" style={{ animation: 'checkIn 0.4s cubic-bezier(.2,.7,.2,1) both' }}>
                    <path d="M2 6 L5 9 L10 3" stroke="#fff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                )}
              </span>
            </div>
          );
        })}
      </div>

      <Cursor style={{ top: cursor.y, left: cursor.x }} clicking={clicking} />

      <style>{`
        @keyframes checkIn {
          0%   { stroke-dasharray: 0, 16; opacity: 0; }
          100% { stroke-dasharray: 16, 0; opacity: 1; }
        }
      `}</style>
    </MacChrome>
  );
}

Object.assign(window, { Demo });
