/* eslint-disable */
// MS BRIDGE — Timeline v2 (restyle) — J+0 → J+90, 3 variants + colored bg break
//  · vertical : ColdIQ-style vertical timeline (rail + nodes + content)
//  · stepper  : horizontal milestone bar + active step detail
//  · phases   : 5 connected phase cards

;(function () {
const { useState, useRef, useEffect } = React;
const T = window.MSB.tokens;

const INK   = "#16150F";
const INK60 = "#6B6A64";
const INK40 = "#9A9994";
const LINE  = "rgba(0,0,0,0.10)";
const SOFT  = "rgba(0,0,0,0.07)";

const ACCENTS = {
  "#E8291C": { base: "#E8291C", soft: "rgba(232,41,28,0.11)", on: "#fff" },
  "#FF6200": { base: "#FF6200", soft: "rgba(255,98,0,0.12)", on: "#fff" },
};

const STEPS = [
  { day: "J+0", dur: "10 min", tag: "Connexion", title: "Vous branchez votre outil de transcription.",
    body: "Fireflies, Modjo, Gong, Zoom, Teams, Meet — une clé API, c'est tout. MS Bridge ingère vos appels automatiquement, sans rien changer à votre stack.", mock: "connect" },
  { day: "J+1", dur: "Automatique", tag: "Ingestion", title: "Vos appels se structurent tout seuls.",
    body: "Les premiers transcripts sont importés. L'IA segmente, taggue et cartographie pain points, objections et personas — sans intervention humaine.", mock: "ingest" },
  { day: "J+7", dur: "Premiers insights", tag: "Détection", title: "Votre équipe accède aux données terrain.",
    body: "Pain points classés par fréquence, objections documentées, vocabulaire prospect prêt à l'emploi. Vous interrogez votre base via Chat RAG.", mock: "insights" },
  { day: "J+30", dur: "Activation", tag: "Production", title: "Le marketing produit, briefé sur le terrain.",
    body: "Le Studio Contenu génère posts, séquences email et scripts ads à partir d'objections réelles. Les premières Rencontres Sales s'organisent.",
    bullets: ["Studio Contenu — posts, emails, ads", "Rencontres Sales pilotées par la donnée", "Premier lead magnet applicatif lancé"], mock: "produce" },
  { day: "J+90", dur: "Système autonome", tag: "Scale", title: "MS Bridge devient votre cerveau quotidien.",
    body: "Pain points, ICP, objections et besoins s'interconnectent dans une base vivante. Le système s'auto-enrichit à chaque appel, interrogeable à tout moment.",
    bullets: ["Base de connaissance vivante", "Auto-enrichissement à chaque appel", "Interrogeable depuis Claude (MCP)"], mock: "scale" },
];

function Mono({ children, color = INK40, style }) {
  return <span style={{ fontFamily: "'Geist Mono', monospace", fontSize: 11.5, letterSpacing: "0.12em", textTransform: "uppercase", color, ...style }}>{children}</span>;
}

function Header({ accent, ghost }) {
  return (
    <div className="tl-head">
      <div className="tl-mk-center">
        <span className="tl-mk">
          <span style={{ width: 7, height: 7, borderRadius: 999, background: accent.base, boxShadow: `0 0 0 3px ${accent.soft}` }} />
          <Mono>(06)</Mono>
          <span style={{ width: 18, height: 1, background: INK40 }} />
          <Mono>votre déploiement</Mono>
        </span>
      </div>
      <h2 className="tl-h2">
        <span>De </span><span style={{ color: accent.base }}>J+0</span><span> à </span><span style={{ color: accent.base }}>J+90</span>
        <span className={ghost ? "tl-ghost" : undefined}>. Voici ce qui se passe.</span>
      </h2>
      <p className="tl-sub">Aucune migration, aucune saisie. Vous branchez vos outils MS Bridge fait le reste, et s'enrichit à chaque appel.</p>
    </div>
  );
}

function Bullets({ items, accent }) {
  return (
    <ul className="tl-bullets">
      {items.map((b, i) => (<li key={i}><span className="tl-bdot" style={{ background: accent.base }} aria-hidden />{b}</li>))}
    </ul>
  );
}

/* per-step mocks (ported) */
function MockShell({ chip, title, children, height }) {
  return (
    <div style={{
      background: T.surface,
      border: `1px solid ${T.border}`,
      borderRadius: 22,
      padding: "24px 24px 26px",
      fontFamily: T.fontSans,
      boxShadow: "0 28px 80px -40px rgba(0,0,0,0.30), 0 1px 0 rgba(0,0,0,0.02)",
      display: "flex", flexDirection: "column", gap: 16,
      height: height || "auto",
      boxSizing: "border-box",
      animation: "msbTLFade 380ms ease",
    }}>
      <div style={{
        display: "flex", alignItems: "center", justifyContent: "space-between",
      }}>
        <div style={{
          display: "inline-flex", alignItems: "center", gap: 8,
          fontSize: 10.5, letterSpacing: "0.12em", textTransform: "uppercase",
          color: T.ink60, fontWeight: 500,
          fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
        }}>
          <span aria-hidden style={{
            width: 6, height: 6, borderRadius: 999, background: T.red,
          }} />
          {chip}
        </div>
        <div style={{
          fontSize: 10.5, color: T.ink40, letterSpacing: "0.08em",
          textTransform: "uppercase",
          fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
        }}>
          aperçu produit
        </div>
      </div>
      <div style={{
        fontSize: 20, fontWeight: 500, color: T.ink,
        letterSpacing: "-0.015em", lineHeight: 1.2,
      }}>
        {title}
      </div>
      {children}
    </div>
  );
}

/* --- Mock 1: Connection ---------------------------------------------------- */
const TOOLS = [
  { name: "Fireflies", color: "#F4502A", letter: "F", sub: "Transcripts auto" },
  { name: "Modjo",     color: "#7E2BFF", letter: "M", sub: "Conversational AI" },
  { name: "Gong",      color: "#5C28D2", letter: "G", sub: "Revenue intelligence" },
  { name: "Zoom",      color: "#0B5CFF", letter: "Z", sub: "Visioconférence" },
  { name: "Teams",     color: "#5059C9", letter: "T", sub: "Appels d'équipe" },
  { name: "Meet",      color: "#34A853", letter: "G", sub: "Google Meet" },
];

function MockConnect() {
  return (
    <MockShell chip="Étape 1 · Connexion" title="Choisissez votre source d'appels.">
      <div className="tlm-tools" style={{ display: "grid", gap: 10 }}>
        {TOOLS.map((t, i) => (
          <div key={t.name} style={{
            display: "flex", alignItems: "center", gap: 12,
            background: i === 0 ? T.redSoft : T.surface2,
            border: `1px solid ${i === 0 ? "rgba(232,41,28,0.25)" : T.borderSoft}`,
            borderRadius: 12, padding: "10px 12px",
          }}>
            <span aria-hidden style={{
              width: 30, height: 30, borderRadius: 8,
              background: t.color, color: "#fff",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              fontSize: 14, fontWeight: 700,
            }}>{t.letter}</span>
            <div style={{ minWidth: 0, flex: 1 }}>
              <div style={{
                fontSize: 13, fontWeight: 500, color: T.ink,
                fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
              }}>{t.name}</div>
              <div style={{ fontSize: 11, color: T.ink60, marginTop: 1 }}>{t.sub}</div>
            </div>
            {i === 0 && (
              <span style={{
                fontSize: 10, padding: "3px 8px", borderRadius: 999,
                background: T.red, color: "#fff", fontWeight: 500,
                letterSpacing: "0.06em", textTransform: "uppercase",
                fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
              }}>connecté</span>
            )}
          </div>
        ))}
      </div>

      <div style={{
        background: T.ink, color: "#fff", borderRadius: 12,
        padding: "14px 16px", display: "flex", alignItems: "center", gap: 12,
      }}>
        <span aria-hidden style={{
          width: 28, height: 28, borderRadius: 8, background: "rgba(255,255,255,0.10)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden>
            <path d="M12 1l3 7h7l-5.5 4.5L18 20l-6-4-6 4 1.5-7.5L2 8h7l3-7z" stroke="#fff" strokeWidth="1.5" strokeLinejoin="round" />
          </svg>
        </span>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 10.5, color: "rgba(255,255,255,0.55)", letterSpacing: "0.12em", textTransform: "uppercase",
            fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace' }}>Clé API</div>
          <div style={{
            fontSize: 13, marginTop: 3, fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
            color: "rgba(255,255,255,0.85)",
          }}>
            ff_sk_•••• •••• •••• 7f3a
          </div>
        </div>
        <span style={{
          background: "#3B6D11", color: "#fff",
          fontSize: 10.5, padding: "5px 10px", borderRadius: 999,
          fontWeight: 500, letterSpacing: "0.08em", textTransform: "uppercase",
          fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
        }}>✓ valide</span>
      </div>
    </MockShell>
  );
}

/* --- Mock 2: Ingestion ---------------------------------------------------- */
function MockIngest() {
  return (
    <MockShell chip="Étape 2 · Ingestion" title="Vos appels se structurent automatiquement.">
      {/* Top stat row */}
      <div className="tlm-stats" style={{ display: "grid", gap: 10 }}>
        {[
          { val: "47", lab: "Appels analysés", c: T.ink },
          { val: "312", lab: "Pain points détectés", c: T.red },
          { val: "8", lab: "Personas affinés", c: "#3B6D11" },
        ].map((s) => (
          <div key={s.lab} style={{
            background: T.surface2, border: `1px solid ${T.borderSoft}`,
            borderRadius: 12, padding: "12px 14px",
          }}>
            <div style={{
              fontSize: 24, fontWeight: 500, color: s.c, letterSpacing: "-0.025em",
              fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
            }}>{s.val}</div>
            <div style={{ fontSize: 11.5, color: T.ink60, marginTop: 3, letterSpacing: "-0.005em" }}>
              {s.lab}
            </div>
          </div>
        ))}
      </div>

      {/* Live feed */}
      <div style={{
        background: T.surface2, borderRadius: 12, padding: "12px 14px",
        border: `1px solid ${T.borderSoft}`,
        display: "flex", flexDirection: "column", gap: 8,
      }}>
        <div style={{
          fontSize: 10.5, letterSpacing: "0.12em", textTransform: "uppercase",
          color: T.ink60, fontWeight: 500,
          fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
          display: "flex", alignItems: "center", gap: 8,
        }}>
          <span aria-hidden style={{
            width: 8, height: 8, borderRadius: 999, background: "#3B6D11",
            animation: "msbTLPulse 1.4s ease-in-out infinite",
          }} />
          Live feed
        </div>
        {[
          { time: "il y a 12s", txt: "Appel — Acme SaaS — objection « prix perçu » détectée" },
          { time: "il y a 1m",  txt: "Persona « CTO Scale » enrichi (+2 verbatim)" },
          { time: "il y a 3m",  txt: "Pain point « intégration » — 34 mentions cumulées" },
        ].map((row, i) => (
          <div key={i} style={{
            display: "flex", alignItems: "flex-start", gap: 10,
            fontSize: 12.5, color: T.ink80, lineHeight: 1.4,
          }}>
            <span style={{
              flexShrink: 0,
              fontSize: 10, color: T.ink40, fontVariantNumeric: "tabular-nums",
              fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
              minWidth: 64,
            }}>{row.time}</span>
            <span style={{ letterSpacing: "-0.005em" }}>{row.txt}</span>
          </div>
        ))}
      </div>
    </MockShell>
  );
}

/* --- Mock 3: First insights ----------------------------------------------- */
function MockInsights() {
  const TOPS = [
    { lab: "Prix perçu",        n: 87, c: "#FCEBEB" },
    { lab: "ROI flou",          n: 64, c: "#FFF7E0" },
    { lab: "Intégration",       n: 52, c: "#EAF0FB" },
    { lab: "Concurrent X",      n: 38, c: "#F2EAFB" },
    { lab: "Délai contractuel", n: 27, c: "#EAF3DE" },
  ];
  const max = TOPS[0].n;

  return (
    <MockShell chip="Étape 3 · Premiers insights" title="Top objections classées par fréquence.">
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        {TOPS.map((row) => (
          <div key={row.lab} className="tlm-bars" style={{
            display: "grid",
            alignItems: "center", gap: 12,
            fontFamily: T.fontSans,
          }}>
            <span style={{
              fontSize: 12.5, color: T.ink, letterSpacing: "-0.005em",
            }}>{row.lab}</span>
            <span style={{
              position: "relative", height: 22,
              background: T.surface2, borderRadius: 6, overflow: "hidden",
            }}>
              <span style={{
                position: "absolute", inset: 0, right: "auto",
                width: `${(row.n / max) * 100}%`,
                background: row.c, borderRadius: 6,
                borderRight: `2px solid ${T.red}`,
              }} />
            </span>
            <span style={{
              fontSize: 11.5, color: T.ink60, textAlign: "right",
              fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
            }}>{row.n}</span>
          </div>
        ))}
      </div>

      {/* Chat RAG preview */}
      <div style={{
        background: T.ink, color: "#fff", borderRadius: 12,
        padding: "14px 16px", display: "flex", flexDirection: "column", gap: 8,
      }}>
        <div style={{
          fontSize: 10.5, color: "rgba(255,255,255,0.55)", letterSpacing: "0.12em",
          textTransform: "uppercase",
          fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
        }}>Chat RAG</div>
        <div style={{ fontSize: 13, color: "rgba(255,255,255,0.92)", lineHeight: 1.4 }}>
          « Quels sont les verbatim sur l'objection prix perçu sur le segment CTO Scale ? »
        </div>
        <div style={{ fontSize: 11.5, color: "rgba(255,255,255,0.55)" }}>
          → 14 verbatim · 9 deals concernés · 2,3 M€ pipeline impacté
        </div>
      </div>
    </MockShell>
  );
}

/* --- Mock 4: Production --------------------------------------------------- */
function MockProduce() {
  return (
    <MockShell chip="Étape 4 · Production" title="Studio Contenu — premières sorties.">
      <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
        {[
          { tag: "LinkedIn",  title: "Comment le prix perçu détruit vos deals avant la démo.", st: "Publié",      sc: "#3B6D11" },
          { tag: "Email × 3", title: "Séquence nurture — objection ROI non démontré.",         st: "En cours",    sc: "#F4B400" },
          { tag: "Ad META",   title: "Hook « Intégration trop complexe » → CTO Scale.",         st: "Idée",        sc: T.ink40 },
        ].map((c) => (
          <div key={c.title} style={{
            background: T.surface, border: `1px solid ${T.borderSoft}`,
            borderRadius: 12, padding: "12px 14px",
            display: "flex", alignItems: "center", gap: 14,
          }}>
            <span style={{
              fontSize: 10, padding: "4px 10px", borderRadius: 999,
              background: T.surface2, color: T.ink80,
              fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
              letterSpacing: "0.04em", whiteSpace: "nowrap",
            }}>{c.tag}</span>
            <span style={{
              flex: 1, fontSize: 13, color: T.ink, letterSpacing: "-0.005em",
              lineHeight: 1.35,
            }}>{c.title}</span>
            <span style={{
              fontSize: 10, padding: "4px 10px", borderRadius: 999,
              background: "transparent", color: c.sc,
              border: `1px solid ${c.sc}`,
              letterSpacing: "0.06em", textTransform: "uppercase", fontWeight: 500,
              fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
              whiteSpace: "nowrap",
            }}>{c.st}</span>
          </div>
        ))}
      </div>

      {/* Rencontre Sales prompt */}
      <div style={{
        background: T.redSoft, border: "1px solid rgba(232,41,28,0.25)",
        borderRadius: 12, padding: "12px 14px",
        display: "flex", alignItems: "center", gap: 12,
      }}>
        <span aria-hidden style={{
          width: 28, height: 28, borderRadius: 8,
          background: T.red, color: "#fff",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          fontSize: 14, flexShrink: 0,
        }}>↗</span>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={{
            fontSize: 10.5, letterSpacing: "0.12em", textTransform: "uppercase",
            color: T.redDark, fontWeight: 500,
            fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
          }}>
            Rencontre Sales · suggérée
          </div>
          <div style={{ fontSize: 13, color: T.ink, marginTop: 3, letterSpacing: "-0.005em" }}>
            Karim B. (CTO Scale) — 34 mentions « intégration complexe »
          </div>
        </div>
      </div>
    </MockShell>
  );
}

/* --- Mock 5: Scale (Obsidian-style brain graph) --------------------------- */

const GRAPH_VB = { w: 400, h: 320 };

const GRAPH_HUBS = [
  { id: "pain",  x: 112, y: 100, label: "Pain Points", color: "#E8291C" },
  { id: "icp",   x: 290, y:  80, label: "ICP",         color: "#F4B400" },
  { id: "obj",   x:  90, y: 230, label: "Objections",  color: "#E8291C" },
  { id: "need",  x: 310, y: 238, label: "Besoins",     color: "#3B6D11" },
];

const GRAPH_NODES = (() => {
  let seed = 11;
  const rand = () => { seed = (seed * 9301 + 49297) % 233280; return seed / 233280; };
  const arr = [];
  GRAPH_HUBS.forEach((h, hi) => {
    const count = 11;
    for (let i = 0; i < count; i++) {
      const angle = rand() * Math.PI * 2;
      const dist  = 28 + rand() * 56;
      arr.push({
        x: h.x + Math.cos(angle) * dist,
        y: h.y + Math.sin(angle) * dist,
        r: 2 + rand() * 1.6,
        delay: rand() * 4,
        dx: (rand() - 0.5) * 4,
        dy: (rand() - 0.5) * 4,
        hub: hi,
      });
    }
  });
  // floaters between hubs
  for (let i = 0; i < 14; i++) {
    arr.push({
      x: 130 + rand() * 150,
      y: 130 + rand() * 90,
      r: 1.8 + rand() * 1.3,
      delay: rand() * 4,
      dx: (rand() - 0.5) * 4,
      dy: (rand() - 0.5) * 4,
      hub: -1,
    });
  }
  return arr;
})();

const GRAPH_HUB_LINKS = [
  ["pain", "icp"],
  ["pain", "obj"],
  ["icp",  "need"],
  ["obj",  "need"],
  ["pain", "need"],
];

function GraphAnimStyles() {
  return (
    <style>{`
      @keyframes msbGraphPulse {
        0%, 100% { transform: scale(1);   opacity: 0.55; }
        50%      { transform: scale(1.7); opacity: 0; }
      }
      @keyframes msbGraphFlow {
        to { stroke-dashoffset: -120; }
      }
      @keyframes msbGraphTwinkle {
        0%, 100% { opacity: 0.55; }
        50%      { opacity: 1; }
      }
    `}</style>
  );
}

function MockScale() {
  const hubById = Object.fromEntries(GRAPH_HUBS.map(h => [h.id, h]));

  return (
    <MockShell chip="Étape 5 · Scale" title="Votre base de connaissance vivante.">
      <GraphAnimStyles />

      <div style={{
        position: "relative",
        background: "#0E0E0E",
        backgroundImage: "radial-gradient(circle at 30% 30%, rgba(232,41,28,0.10), transparent 60%), radial-gradient(circle at 75% 75%, rgba(59,109,17,0.08), transparent 60%)",
        borderRadius: 16,
        overflow: "hidden",
        padding: 0,
      }}>
        {/* Subtle grid overlay */}
        <div aria-hidden style={{
          position: "absolute", inset: 0,
          backgroundImage:
            "linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px)",
          backgroundSize: "32px 32px",
          maskImage: "radial-gradient(ellipse at center, #000 50%, transparent 100%)",
          WebkitMaskImage: "radial-gradient(ellipse at center, #000 50%, transparent 100%)",
        }} />

        <svg
          viewBox={`0 0 ${GRAPH_VB.w} ${GRAPH_VB.h}`}
          preserveAspectRatio="xMidYMid meet"
          style={{ position: "relative", display: "block", width: "100%", height: "auto" }}
          aria-hidden
        >
          {/* Cluster links — hub to its small nodes */}
          {GRAPH_NODES.filter(n => n.hub >= 0).map((n, i) => {
            const h = GRAPH_HUBS[n.hub];
            return (
              <line
                key={`cl-${i}`}
                x1={h.x} y1={h.y} x2={n.x} y2={n.y}
                stroke={h.color}
                strokeOpacity={0.18}
                strokeWidth={0.8}
              />
            );
          })}

          {/* Inter-hub animated links */}
          {GRAPH_HUB_LINKS.map(([a, b], i) => {
            const A = hubById[a], B = hubById[b];
            return (
              <line
                key={`hl-${i}`}
                x1={A.x} y1={A.y} x2={B.x} y2={B.y}
                stroke="rgba(255,255,255,0.35)"
                strokeWidth={1}
                strokeDasharray="2 6"
                style={{ animation: `msbGraphFlow ${5 + i * 0.6}s linear infinite` }}
              />
            );
          })}

          {/* Small nodes */}
          {GRAPH_NODES.map((n, i) => (
            <circle
              key={`n-${i}`}
              cx={n.x} cy={n.y} r={n.r}
              fill={n.hub >= 0 ? "rgba(255,255,255,0.7)" : "rgba(255,255,255,0.45)"}
              style={{
                animation: `msbGraphTwinkle ${4 + (i % 5) * 0.7}s ease-in-out ${n.delay}s infinite`,
                transformOrigin: `${n.x}px ${n.y}px`,
              }}
            />
          ))}

          {/* Hub bubbles */}
          {GRAPH_HUBS.map((h) => (
            <g key={h.id}>
              {/* Pulse ring */}
              <circle
                cx={h.x} cy={h.y} r={14}
                fill="none" stroke={h.color} strokeWidth={1.4}
                style={{
                  animation: "msbGraphPulse 2.6s ease-out infinite",
                  transformOrigin: `${h.x}px ${h.y}px`,
                }}
              />
              {/* Solid hub */}
              <circle cx={h.x} cy={h.y} r={10} fill={h.color} />
              <circle cx={h.x} cy={h.y} r={5}  fill="rgba(255,255,255,0.85)" />
            </g>
          ))}

          {/* Hub labels */}
          {GRAPH_HUBS.map((h) => {
            const above = h.y > GRAPH_VB.h / 2;
            const labelY = above ? h.y - 22 : h.y + 22;
            const textY  = labelY + 4.5;
            const w = h.label.length * 5.5 + 16;
            return (
              <g key={`lbl-${h.id}`}>
                <rect
                  x={h.x - w / 2} y={labelY - 9}
                  width={w} height={18} rx={9}
                  fill="rgba(255,255,255,0.95)"
                />
                <text
                  x={h.x} y={textY}
                  fontFamily="ui-monospace, SF Mono, Menlo, Consolas, monospace"
                  fontSize="9.2" fontWeight="500"
                  fill="#1A1A1A" textAnchor="middle"
                  letterSpacing="0.06em" textTransform="uppercase"
                >
                  {h.label.toUpperCase()}
                </text>
              </g>
            );
          })}
        </svg>

        {/* Top-left status badge */}
        <div style={{
          position: "absolute", top: 14, left: 14,
          display: "inline-flex", alignItems: "center", gap: 8,
          background: "rgba(255,255,255,0.08)",
          backdropFilter: "blur(8px)",
          border: "1px solid rgba(255,255,255,0.12)",
          padding: "6px 10px", borderRadius: 999,
          fontSize: 10, letterSpacing: "0.12em", textTransform: "uppercase",
          color: "rgba(255,255,255,0.85)", fontWeight: 500,
          fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
        }}>
          <span aria-hidden style={{
            width: 7, height: 7, borderRadius: 999, background: "#3B6D11",
            boxShadow: "0 0 0 3px rgba(59,109,17,0.30)",
            animation: "msbTLPulse 1.4s ease-in-out infinite",
          }} />
          Base vivante
        </div>

        {/* Bottom-right counter */}
        <div style={{
          position: "absolute", bottom: 14, right: 14,
          display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 2,
          fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
          color: "rgba(255,255,255,0.85)",
        }}>
          <div style={{ fontSize: 18, fontWeight: 500, letterSpacing: "-0.02em" }}>
            1 248
          </div>
          <div style={{
            fontSize: 9.5, letterSpacing: "0.12em", textTransform: "uppercase",
            color: "rgba(255,255,255,0.55)",
          }}>
            nœuds connectés
          </div>
        </div>
      </div>

      {/* Caption row */}
      <div style={{
        display: "flex", alignItems: "center", gap: 10,
        fontSize: 12.5, color: T.ink60, lineHeight: 1.4,
        letterSpacing: "-0.005em",
      }}>
        <span aria-hidden style={{
          width: 6, height: 6, borderRadius: 999, background: T.red, flexShrink: 0,
        }} />
        <span>
          Chaque appel enrichit le graphe — pain points, ICP, objections et besoins
          s'interconnectent en continu.
        </span>
      </div>
    </MockShell>
  );
}

function MockFor({ step }) {
  switch (step.mock) {
    case "connect":  return <MockConnect  key="connect" />;
    case "ingest":   return <MockIngest   key="ingest" />;
    case "insights": return <MockInsights key="insights" />;
    case "produce":  return <MockProduce  key="produce" />;
    case "scale":    return <MockScale    key="scale" />;
    default:         return null;
  }
}

/* ===========================================================================
 *  FRAME + HOOK
 * ======================================================================= */

function FadeStyles() {
  return (
    <style>{`
      @keyframes msbTLFade {
        from { opacity: 0; transform: translateY(6px); }
        to   { opacity: 1; transform: translateY(0); }
      }
      @keyframes msbTLPulse {
        0%, 100% { opacity: 1; }
        50%      { opacity: 0.35; }
      }
      @keyframes msbBounceClick {
        0%, 100% { transform: translate(-50%, 0); }
        50%      { transform: translate(-50%, 4px); }
      }
    `}</style>
  );
}

function Timeline({ accentKey, ghost = true, layout = "vertical", bg = "#F1ECE3" }) {
  const accent = ACCENTS[accentKey] || ACCENTS["#E8291C"];
  const [active, setActive] = useState(0);
  const MockForC = MockFor;
  const isDark = bg === "#0B0B0C";
  const faint = isDark ? "rgba(255,255,255,0.18)" : LINE;

  let body;

  if (layout === "stepper") {
    const s = STEPS[active];
    body = (
      <>
        <div className="tl-bar">
          {STEPS.map((st, i) => (
            <React.Fragment key={st.day}>
              {i > 0 && <span className="tl-conn" style={{ background: i <= active ? accent.base : faint }} aria-hidden />}
              <button className={"tl-snode" + (i === active ? " active" : "")} onClick={() => setActive(i)} style={{ position: "relative" }}>
                {i === active + 1 && (
                  <div style={{
                    position: "absolute", bottom: "100%", left: "50%",
                    transform: "translateX(-50%)", marginBottom: 6,
                    color: accent.base, pointerEvents: "none",
                    animation: "msbBounceClick 1.5s ease-in-out infinite",
                    display: "flex", flexDirection: "column", alignItems: "center",
                    gap: 2,
                  }}>
                    <span style={{
                      fontSize: 9, letterSpacing: "0.08em", textTransform: "uppercase",
                      fontWeight: 600, whiteSpace: "nowrap", opacity: 0.9,
                      fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
                    }}>Suivant</span>
                    <svg width="12" height="12" viewBox="0 0 24 24" fill="none">
                      <path d="M12 4v14M7 13l5 5 5-5" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
                    </svg>
                  </div>
                )}
                <span className="tl-snode-dot" style={i <= active ? { background: accent.base, borderColor: accent.base } : { borderColor: faint, background: isDark ? "#0B0B0C" : "#fff" }} />
                <span className="tl-snode-day" style={{ color: i === active ? (isDark ? "#F6F5F3" : INK) : INK40 }}>{st.day}</span>
              </button>
            </React.Fragment>
          ))}
        </div>
        <div className="tl-bento">
          <div className="tl-bento-left">
            <div className="tl-detail-meta" style={{ justifyContent: "flex-start" }}><span className="tl-tag" style={{ background: accent.soft, color: accent.base }}>{s.tag}</span><Mono color={INK40}>{s.day} · {s.dur}</Mono></div>
            <h3 className="tl-bento-title">{s.title}</h3>
            <p className="tl-bento-body">{s.body}</p>
            {s.bullets && <Bullets items={s.bullets} accent={accent} />}
          </div>
          <div className="tl-bento-right">
            {MockForC && <MockForC step={s} />}
          </div>
        </div>
      </>
    );
  } else if (layout === "phases") {
    body = (
      <div className="tl-phases">
        {STEPS.map((s, i) => (
          <div key={s.day} className="tl-pcard">
            <div className="tl-pcard-day" style={{ color: accent.base }}>{s.day}</div>
            <span className="tl-tag" style={{ background: accent.soft, color: accent.base, alignSelf: "flex-start" }}>{s.tag}</span>
            <h3 className="tl-pcard-title">{s.title}</h3>
            <p className="tl-pcard-body">{s.body}</p>
          </div>
        ))}
      </div>
    );
  } else {
    // vertical (default)
    body = (
      <div className="tl-vert">
        {STEPS.map((s, i) => (
          <div key={s.day} className="tl-item">
            <div className="tl-item-left">
              <span className="tl-item-day" style={{ color: accent.base }}>{s.day}</span>
              <Mono color={INK40} style={{ fontSize: 10 }}>{s.dur}</Mono>
            </div>
            <div className="tl-item-line" style={{ background: i === STEPS.length - 1 ? "transparent" : LINE }}>
              <span className="tl-item-dot" style={{ background: accent.base, boxShadow: `0 0 0 4px ${accent.soft}` }} aria-hidden />
            </div>
            <div className="tl-item-content">
              <span className="tl-tag" style={{ background: accent.soft, color: accent.base }}>{s.tag}</span>
              <h3 className="tl-item-title">{s.title}</h3>
              <p className="tl-item-body">{s.body}</p>
              {s.bullets && <Bullets items={s.bullets} accent={accent} />}
            </div>
          </div>
        ))}
      </div>
    );
  }

  return (
    <div className={"tl" + (isDark ? " tl-dark" : "")} style={{ background: bg, color: isDark ? "#F6F5F3" : INK, position: "relative", overflow: "hidden" }}>
      {isDark && <div className="tl-grid" aria-hidden />}
      {isDark && <div className="tl-glow" style={{ background: `radial-gradient(900px 380px at 50% 0%, ${accent.soft} 0%, transparent 60%)` }} aria-hidden />}
      <div className="tl-inner" style={{ position: "relative", zIndex: 1 }}>
        <Header accent={accent} ghost={ghost} />
        <div className="tl-body">{body}</div>
      </div>
    </div>
  );
}

Object.assign(window, { TimelineV2: Timeline });

})();
