/* global React, SIGNALS, TOPICS, POSTS, PERSONAS, TRENDS, BRIEF_BLOCKS, WORKSPACE,
   COMPETITORS, MOVES, PRICE_LADDER, CAMPAIGNS, INGREDIENTS,
   Sparkline, Agent, StatGrid, ModuleHead, TabBar, PuigMark */
const { useState, useMemo } = React;

// ═══════════════════════════════════════════════════════════════
// HOME
// ═══════════════════════════════════════════════════════════════
function Home({ setRoute }) {
  return (
    <div className="page">
      <div>
        <div className="mono-eyebrow">Tuesday · 21 April 2026 · CH Good Girl · EU5</div>
        <h1 className="title" style={{ marginTop: 8 }}>Today in your brand.</h1>
        <div className="subtitle">Canvas composed this overnight from 2.4K social posts, 6 simulated interviews, Spate's lifecycle model, and five competitor moves.</div>
      </div>
      <Agent
        eyebrow="Canvas · Morning brief"
        text="Two quiet weeks just ended. Sentiment for Good Girl in Spain <em>rose overnight</em> on refill news — the driver is recycled glass, not longevity. Meanwhile <em>Dior Sauvage launched its Italy refill yesterday</em> (€42 refill, €98 full) and Spate shows <em>olfactive layering</em> entering growth stage. One creator brief is waiting for your approval."
        actions={[
          { label: "Open today's brief", variant: "primary", onClick: () => setRoute("briefs") },
          { label: "Hear it differently", onClick: () => {} },
          { label: "Dismiss", variant: "ghost", onClick: () => {} },
        ]}
      />
      <div>
        <div className="row sb" style={{ marginBottom: 12 }}>
          <div className="mono-eyebrow">Four signals · one from each room</div>
          <div className="mono-eyebrow">Ranked by novelty</div>
        </div>
        <div>
          {[
            { room: "Analyst · Pulse", headline: "Refillable packaging becomes the dominant positive driver", meta: "TIKTOK · INSTAGRAM · +41% VOL · SENT +0.5", verb: "Investigate", route: "analyst", tab: "pulse", spark: [2,3,2,4,5,4,6,7,9,8,10,12] },
            { room: "Analyst · Looking Glass", headline: "Dior shipped Italy refill yesterday — <em>you are now second to market</em>", meta: "DIOR SAUVAGE · €42 REFILL · ROME + MILAN", verb: "Compare", route: "analyst", tab: "lookingglass", spark: [1,1,1,2,2,3,3,4,5,7,10,14] },
            { room: "Strategist · Chorus", headline: "Eco-Mara would pay €95 with recycled glass — 4 of 6 synthetic personas agree", meta: "SIMULATED APR 18 · AUDIENCE 4.2M", verb: "Simulate again", route: "strategist", tab: "chorus", spark: [4,4,4,5,5,6,5,6,7,7,8,8] },
            { room: "Predictor · Spate", headline: "Olfactive layering enters growth stage in EU5 fragrance", meta: "SPATE · +38% YoY · LIKELY TO CONTINUE", verb: "Forecast", route: "predictor", tab: "spate", spark: [1,1,2,2,3,3,4,5,7,9,11,13] },
          ].map((s, i) => (
            <div key={i} className="signal-row">
              <div className="room">{s.room}</div>
              <div>
                <div className="headline" dangerouslySetInnerHTML={{ __html: s.headline }} />
                <div className="meta">{s.meta}</div>
                <div style={{ height: 24, marginTop: 12, maxWidth: 240 }}>
                  <Sparkline data={s.spark} />
                </div>
              </div>
              <div className="cta">
                <button className="btn" onClick={() => setRoute(s.route)}>{s.verb} →</button>
              </div>
            </div>
          ))}
        </div>
      </div>
      <div className="grid-2">
        <div className="card">
          <div className="ch"><div className="t">Your briefs</div><div className="k">3 in flight</div></div>
          <div className="cb" style={{ padding: 0 }}>
            {[
              ["CH Good Girl Refill · launch narrative", "Canvas drafted 4 blocks"],
              ["JPG Scandal · Q2 creator shortlist", "Awaiting Chorus"],
              ["Rabanne Fame Refill · pricing deep-dive", "Ledger flagged 2 skus"],
            ].map(([t, sub], i) => (
              <div key={i} style={{ padding: "14px 20px", borderTop: i === 0 ? 0 : "1px solid var(--rule)", display: "flex", justifyContent: "space-between", fontFamily: "var(--font-mono)", fontSize: 13 }}>
                <span>{t}</span><span style={{ color: "var(--ink-50)" }}>{sub}</span>
              </div>
            ))}
          </div>
        </div>
        <div className="card">
          <div className="ch"><div className="t">Weak signals</div><div className="k">Detected by Canvas</div></div>
          <div className="cb" style={{ padding: 0 }}>
            {[
              ["Biotech vetiver", "Materia · +78% · early stage"],
              ["Waterless formulations", "Spate · +34% · early stage"],
              ["Galaxolide phase-out risk", "Materia · EU scrutiny"],
            ].map(([t, sub], i) => (
              <div key={i} style={{ padding: "14px 20px", borderTop: i === 0 ? 0 : "1px solid var(--rule)", display: "flex", justifyContent: "space-between", fontSize: 14 }}>
                <span>{t}</span><span style={{ color: "var(--accent-ink)", fontFamily: "var(--font-mono)", fontSize: 11 }}>{sub}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════
// ANALYST  (Pulse · Looking Glass · Ledger · Postscript)
// ═══════════════════════════════════════════════════════════════
function Analyst({ setRoute, initialTab = "pulse" }) {
  const [tab, setTab] = useState(initialTab);
  const tabs = [
    { id: "pulse",        label: "Pulse",         sub: "Social listener" },
    { id: "lookingglass", label: "Looking Glass", sub: "Competitive benchmark" },
    { id: "ledger",       label: "Ledger",        sub: "Pricing intelligence" },
    { id: "postscript",   label: "Postscript",    sub: "Campaign debrief" },
  ];
  return (
    <div className="page">
      <div>
        <div className="mono-eyebrow">Analyst</div>
        <h1 className="title" style={{ marginTop: 8 }}>Read the market, then <em style={{fontStyle:"italic",color:"var(--accent-ink)"}}>explain</em> it.</h1>
        <div className="subtitle">Four modules share one workspace. Pulse listens, Looking Glass compares, Ledger watches price, Postscript debriefs.</div>
      </div>
      <TabBar tabs={tabs} active={tab} setActive={setTab} />
      {tab === "pulse" && <Pulse />}
      {tab === "lookingglass" && <LookingGlass />}
      {tab === "ledger" && <Ledger />}
      {tab === "postscript" && <Postscript />}
    </div>
  );
}

// ── Pulse (Social Listener) ──────────────────────────────────
function Pulse() {
  const [active, setActive] = useState("Refillable packaging");
  return (
    <>
      <ModuleHead code="MODULE 01" name="Pulse" tagline="The social listener." />
      <Agent
        eyebrow="Canvas · This week in Pulse"
        text="Refill packaging became the <em>dominant positive driver</em> (+41% volume, +0.5 sentiment). Two mid-tier creators on TikTok Spain have outsized engagement — worth briefing. Crisis risk remains low."
        actions={[
          { label: "Draft creator brief", variant: "primary" },
          { label: "Compare to last week" },
        ]}
      />
      <StatGrid items={[
        { k: "Mentions · 7d", n: "2,438", d: "↑ 18% vs last week", spark: [12,13,11,14,16,19,22] },
        { k: "Sentiment", n: "+7.2", d: "↑ 0.5", spark: [6.4,6.5,6.6,6.8,7.0,7.1,7.2] },
        { k: "Crisis risk", n: "Low", d: "Stable 14d", tone: "flat" },
        { k: "Trending topics", n: "8", d: "2 new this week" },
      ]} />
      <div className="grid-2">
        <div className="card">
          <div className="ch"><div className="t">Trending conversations</div><div className="k">Ranked by momentum</div></div>
          <div className="topics">
            {TOPICS.map((t, i) => (
              <div key={i} className={`topic ${active === t.n ? "on" : ""}`} onClick={() => setActive(t.n)}>
                <div className="idx">{String(i + 1).padStart(2, "0")}</div>
                <div className="name">{t.n}<span className="sub">{t.sub}</span></div>
                <div className="num">{t.mentions.toLocaleString()}</div>
                <div className={`num ${t.delta > 0 ? "up" : t.delta < 0 ? "down" : "flat"}`}>{t.delta > 0 ? "+" : ""}{t.delta}%</div>
                <div className="bar"><span style={{ width: `${t.momentum}%` }} /></div>
              </div>
            ))}
          </div>
        </div>
        <div className="card">
          <div className="ch"><div className="t">{active}</div><div className="k">Top posts</div></div>
          <div>
            {(POSTS[active] || []).map((p, i) => (
              <div key={i} className="post">
                <div className="chan">{p.ch}</div>
                <div className="text"><span className="au">{p.au}</span>{p.t}</div>
                <div className={`senti ${p.s < 0 ? "neg" : ""}`}>{p.s > 0 ? "+" : ""}{p.s.toFixed(1)}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </>
  );
}

// ── Looking Glass (Competitive Benchmark) ──────────────────────
function LookingGlass() {
  return (
    <>
      <ModuleHead code="MODULE 02" name="Looking Glass" tagline="The competitive benchmark hub." />
      <Agent
        eyebrow="Canvas · Competitive read"
        text="<em>Dior shipped Italy refill yesterday.</em> You are now second to market there. YSL cut Spain price by 8%, undercutting CH by €3. Chanel's patent filing last week is not yet shipping — a 6-week window likely remains."
        actions={[{ label: "Draft counter-move brief", variant: "primary" }, { label: "Ask Canvas to scenario-plan" }]}
      />
      <div className="grid-2">
        <div className="card" style={{ gridColumn: "1 / -1" }}>
          <div className="ch"><div className="t">Benchmark table</div><div className="k">Share × SoV × Sentiment · EU5 · 30d</div></div>
          <div style={{ padding: 0 }}>
            <div style={{ display: "grid", gridTemplateColumns: "1.6fr 1fr 70px 60px 60px 60px 110px", padding: "12px 20px", borderBottom: "1px solid var(--ink-100)", fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--ink-50)" }}>
              <span>Brand</span><span>House</span><span style={{textAlign:"right"}}>Price</span><span style={{textAlign:"right"}}>Share</span><span style={{textAlign:"right"}}>SoV</span><span style={{textAlign:"right"}}>Sent.</span><span>Momentum</span>
            </div>
            {COMPETITORS.map((c, i) => (
              <div key={i} style={{
                display: "grid",
                gridTemplateColumns: "1.6fr 1fr 70px 60px 60px 60px 110px",
                padding: "14px 20px",
                borderBottom: "1px solid var(--rule)",
                alignItems: "center",
                background: c.self ? "var(--accent-tint)" : "transparent",
              }}>
                <span style={{ fontFamily: "var(--font-display)", fontSize: 17, fontStyle: c.self ? "italic" : "normal", color: c.self ? "var(--accent-ink)" : "var(--ink-100)" }}>
                  {c.self && "▲ "}{c.brand}
                </span>
                <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "0.1em", color: "var(--ink-50)", textTransform: "uppercase" }}>{c.house}</span>
                <span style={{ fontFamily: "var(--font-mono)", fontSize: 13, textAlign: "right" }}>€{c.price}</span>
                <span style={{ fontFamily: "var(--font-mono)", fontSize: 13, textAlign: "right" }}>{c.share}%</span>
                <span style={{ fontFamily: "var(--font-mono)", fontSize: 13, textAlign: "right" }}>{c.sov}%</span>
                <span style={{ fontFamily: "var(--font-mono)", fontSize: 13, textAlign: "right", color: "var(--accent-ink)" }}>+{c.sent}</span>
                <span style={{ height: 6, background: "var(--paper-10)", position: "relative" }}>
                  <span style={{ position: "absolute", inset: "0 auto 0 0", width: `${c.momentum}%`, background: c.self ? "var(--accent)" : "var(--ink-70)" }} />
                </span>
              </div>
            ))}
          </div>
        </div>
      </div>
      <div className="card">
        <div className="ch"><div className="t">Recent competitive moves</div><div className="k">Canvas watchlist · 30d</div></div>
        <div style={{ padding: 0 }}>
          {MOVES.map((m, i) => (
            <div key={i} style={{ display: "grid", gridTemplateColumns: "80px 160px 1fr 80px", gap: 16, padding: "18px 20px", borderTop: i === 0 ? 0 : "1px solid var(--rule)", alignItems: "start" }}>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "0.14em", color: "var(--ink-50)" }}>{m.date}</span>
              <span style={{ fontFamily: "var(--font-display)", fontSize: 16, fontStyle: "italic" }}>{m.brand}</span>
              <span style={{ fontFamily: "var(--font-display)", fontSize: 16, lineHeight: 1.4, color: "var(--ink-90)", textWrap: "pretty" }}>{m.move}</span>
              <span style={{
                fontFamily: "var(--font-mono)",
                fontSize: 9,
                letterSpacing: "0.16em",
                padding: "3px 8px",
                background: m.impact === "high" ? "var(--accent)" : m.impact === "med" ? "var(--accent-tint)" : "var(--paper-10)",
                color: m.impact === "high" ? "white" : m.impact === "med" ? "var(--accent-ink)" : "var(--ink-70)",
                alignSelf: "start",
                justifySelf: "end",
                textTransform: "uppercase",
              }}>{m.verb}</span>
            </div>
          ))}
        </div>
      </div>
    </>
  );
}

// ── Ledger (Pricing Intelligence) ──────────────────────────────
function Ledger() {
  return (
    <>
      <ModuleHead code="MODULE 03" name="Ledger" tagline="Pricing intelligence." />
      <Agent
        eyebrow="Canvas · Pricing watch"
        text="Two SKUs are trading below MAP: <em>50ml EDP on Amazon ES (−2%)</em> and <em>50ml Refill on Sephora FR (−8%)</em>. The 30ml Refill at €38 is working — margin holds at 54% and volume up 22% WoW. Recommend enforcement notice on Amazon ES this week."
        actions={[{ label: "Draft enforcement brief", variant: "primary" }, { label: "Open with Finance" }]}
      />
      <div className="card">
        <div className="ch"><div className="t">Price ladder · CH Good Girl</div><div className="k">MSRP / MAP / Street · margin held</div></div>
        <div style={{ padding: 0 }}>
          <div style={{ display: "grid", gridTemplateColumns: "2fr 70px 70px 70px 70px 70px 1fr", padding: "12px 20px", borderBottom: "1px solid var(--ink-100)", fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--ink-50)" }}>
            <span>SKU</span><span style={{textAlign:"right"}}>MSRP</span><span style={{textAlign:"right"}}>MAP</span><span style={{textAlign:"right"}}>Street</span><span style={{textAlign:"right"}}>Margin</span><span style={{textAlign:"right"}}>Δ</span><span>Flag</span>
          </div>
          {PRICE_LADDER.map((r, i) => (
            <div key={i} style={{ display: "grid", gridTemplateColumns: "2fr 70px 70px 70px 70px 70px 1fr", padding: "14px 20px", borderBottom: "1px solid var(--rule)", alignItems: "center" }}>
              <span style={{ fontFamily: "var(--font-display)", fontSize: 15 }}>{r.sku}</span>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, textAlign: "right" }}>€{r.price}</span>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, textAlign: "right", color: "var(--ink-50)" }}>€{r.map}</span>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, textAlign: "right", color: r.street < r.map ? "oklch(50% 0.16 25)" : "var(--ink-70)" }}>€{r.street}</span>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, textAlign: "right" }}>{r.margin}%</span>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, textAlign: "right", color: r.delta < 0 ? "oklch(50% 0.16 25)" : "var(--ink-50)" }}>{r.delta > 0 ? "+" : ""}{r.delta}%</span>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.1em", color: r.flag ? "oklch(45% 0.16 25)" : "var(--ink-30)", textTransform: "uppercase" }}>{r.flag || "—"}</span>
            </div>
          ))}
        </div>
      </div>
      <div className="grid-2">
        <div className="card">
          <div className="ch"><div className="t">Vs competitors · 50ml EDP</div><div className="k">EU5 MSRP</div></div>
          <div className="cb">
            {COMPETITORS.slice(0, 5).map((c, i) => (
              <div key={i} style={{ display: "grid", gridTemplateColumns: "180px 1fr 60px", gap: 12, alignItems: "center", padding: "10px 0", borderTop: i === 0 ? 0 : "1px solid var(--rule)" }}>
                <span style={{ fontFamily: "var(--font-display)", fontSize: 15, fontStyle: c.self ? "italic" : "normal", color: c.self ? "var(--accent-ink)" : "var(--ink-90)" }}>{c.self && "▲ "}{c.brand}</span>
                <span style={{ height: 6, background: "var(--paper-10)", position: "relative" }}>
                  <span style={{ position: "absolute", inset: "0 auto 0 0", width: `${(c.price / 110) * 100}%`, background: c.self ? "var(--accent)" : "var(--ink-70)" }} />
                </span>
                <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, textAlign: "right" }}>€{c.price}</span>
              </div>
            ))}
          </div>
        </div>
        <div className="card">
          <div className="ch"><div className="t">Refill ratio</div><div className="k">Refill / Full-bottle revenue · Q1</div></div>
          <div className="cb" style={{ height: 240 }}>
            <svg viewBox="0 0 400 200" style={{ width: "100%", height: "100%" }} preserveAspectRatio="none">
              {[0,1,2,3].map(i => <line key={i} x1="0" x2="400" y1={i*50+10} y2={i*50+10} stroke="var(--rule-soft)" strokeWidth="1"/>)}
              {[12,18,28,34,41,48,52,58].map((v, i, a) => {
                const x1 = (i/(a.length-1))*400, x2 = ((i+1)/(a.length-1))*400;
                const y1 = 190 - (v*3), y2 = i+1 < a.length ? 190 - (a[i+1]*3) : y1;
                return i+1 < a.length ? <line key={i} x1={x1} x2={x2} y1={y1} y2={y2} stroke="var(--accent)" strokeWidth="2"/> : null;
              })}
              <text x="12" y="30" fontFamily="var(--font-display)" fontSize="28" fill="var(--accent-ink)" fontStyle="italic">58%</text>
              <text x="12" y="48" fontFamily="var(--font-mono)" fontSize="9" letterSpacing="0.12em" fill="var(--ink-50)">REFILL SHARE · APR</text>
            </svg>
          </div>
        </div>
      </div>
    </>
  );
}

// ── Postscript (Campaign Debrief Engine) ──────────────────────
function Postscript() {
  const [sel, setSel] = useState("gg-refill-es");
  const c = CAMPAIGNS.find(x => x.id === sel);
  return (
    <>
      <ModuleHead code="MODULE 04" name="Postscript" tagline="Campaign debrief engine." />
      <Agent
        eyebrow="Canvas · Postscript"
        text="<em>Spain refill launch</em> outperformed on sentiment (+7.4 vs 6.5 target) and lift (+18% vs 12% target). The creator tier you nearly cut drove 42% of positive mentions. <em>Recommend applying the same creator mix to Italy.</em>"
        actions={[{ label: "Replicate mix in Italy brief", variant: "primary" }, { label: "Send lessons to Library" }]}
      />
      <div className="grid-2">
        <div className="card">
          <div className="ch"><div className="t">Campaigns</div><div className="k">Past 120 days</div></div>
          <div style={{ padding: 0 }}>
            {CAMPAIGNS.map((x, i) => (
              <div key={x.id} onClick={() => setSel(x.id)} style={{
                padding: "18px 20px",
                borderTop: i === 0 ? 0 : "1px solid var(--rule)",
                cursor: "pointer",
                background: sel === x.id ? "var(--accent-tint)" : "transparent",
                display: "flex", flexDirection: "column", gap: 4,
              }}>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                  <span style={{ fontFamily: "var(--font-display)", fontSize: 17, fontStyle: "italic", color: sel === x.id ? "var(--accent-ink)" : "var(--ink-100)" }}>{x.name}</span>
                  <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.14em", color: x.status === "Live" ? "var(--accent-ink)" : "var(--ink-50)" }}>{x.status.toUpperCase()}</span>
                </div>
                <div style={{ display: "flex", gap: 16, fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--ink-50)", letterSpacing: "0.04em" }}>
                  <span>{x.window}</span>
                  <span>€{x.spend}M</span>
                  <span>{x.reach}M reach</span>
                  <span style={{ color: "var(--accent-ink)" }}>Verdict: {x.verdict}</span>
                </div>
              </div>
            ))}
          </div>
        </div>
        <div className="card">
          <div className="ch"><div className="t">{c.name}</div><div className="k">Debrief · 6 dimensions</div></div>
          <div className="cb" style={{ display: "flex", flexDirection: "column", gap: 14 }}>
            {[
              ["Reach", `${c.reach}M`, "↑ 18% vs target"],
              ["Sentiment lift", `+${c.lift}%`, "↑ 6pt vs target"],
              ["Final sentiment", `+${c.sent}`, "Top quartile for house"],
              ["Spend", `€${c.spend}M`, "On budget"],
              ["CPM", "€84", "↓ 12% vs H2 '25"],
              ["Carry-over sentiment", "+0.3 / wk", "Persists 3 weeks post"],
            ].map(([k, v, n], i) => (
              <div key={i} style={{ display: "grid", gridTemplateColumns: "140px 100px 1fr", gap: 12, padding: "10px 0", borderTop: i === 0 ? 0 : "1px solid var(--rule)", alignItems: "baseline" }}>
                <span className="mono-eyebrow">{k}</span>
                <span style={{ fontFamily: "var(--font-display)", fontSize: 24, letterSpacing: "-0.02em" }}>{v}</span>
                <span style={{ fontFamily: "var(--font-display)", fontStyle: "italic", fontSize: 14, color: "var(--ink-70)" }}>{n}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════
// STRATEGIST  (Chorus · Briefs)
// ═══════════════════════════════════════════════════════════════
function Strategist({ setRoute, initialTab = "chorus" }) {
  const [tab, setTab] = useState(initialTab);
  const tabs = [
    { id: "chorus",    label: "Chorus",  sub: "Persona lab" },
    { id: "briefs",    label: "Briefs",  sub: "Living documents" },
  ];
  return (
    <div className="page">
      <div>
        <div className="mono-eyebrow">Strategist</div>
        <h1 className="title" style={{ marginTop: 8 }}>Turn signals into <em style={{fontStyle:"italic",color:"var(--accent-ink)"}}>decisions</em>.</h1>
        <div className="subtitle">Interview synthetic audiences, then compose briefs that carry the evidence with them.</div>
      </div>
      <TabBar tabs={tabs} active={tab} setActive={setTab} />
      {tab === "chorus" && <Chorus />}
      {tab === "briefs" && <BriefsInline />}
    </div>
  );
}

// ── Chorus (Persona Lab) ──────────────────────────────────────
function Chorus() {
  const [selected, setSelected] = useState(["mara", "zoe", "ines"]);
  const toggle = (id) => setSelected(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);
  const chosen = PERSONAS.filter(p => selected.includes(p.id));
  return (
    <>
      <ModuleHead code="MODULE 05" name="Chorus" tagline="The persona lab." />
      <Agent
        eyebrow="Canvas · Audience definition"
        text="Showing 6 personas for <em>fragrance buyers, EU5, ages 23–52</em>. Canvas adjusted the mix to over-represent refill-receptive profiles since that's what you're testing."
        actions={[
          { label: "Re-generate personas", variant: "primary" },
          { label: "Adjust audience" },
          { label: "Ask all 6 a question" },
        ]}
      />
      <div>
        <div className="mono-eyebrow" style={{ marginBottom: 12 }}>6 personas · select to simulate</div>
        <div className="persona-grid">
          {PERSONAS.map(p => (
            <div key={p.id} className={`persona ${selected.includes(p.id) ? "on" : ""}`} onClick={() => toggle(p.id)}>
              <div className="portrait" data-name={p.name.split(" ").slice(-1)[0]} />
              <div className="meta">
                <div className="name">{p.name}</div>
                <div className="bio">{p.bio}</div>
                <div className="tags">{p.tags.map(t => <span key={t} className="chip">{t}</span>)}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
      <div className="card">
        <div className="ch">
          <div className="t">Simulation Room <span className="chip accent" style={{ marginLeft: 12, verticalAlign: "middle" }}>Live</span></div>
          <div className="k">Asking {chosen.length} of 6</div>
        </div>
        <div className="sim">
          <div className="bubble system">SYSTEM · Simulating responses to: <b>"Would you pay €95 for CH Good Girl with recycled-glass packaging?"</b></div>
          {chosen.map(p => (
            <div key={p.id} className="bubble persona">
              <div className="eb">▲ {p.name}</div>
              <div className="text">"{p.answer}"</div>
            </div>
          ))}
          <div className="bubble system" style={{ background: "var(--accent-tint)", color: "var(--accent-ink)" }}>
            ▲ CANVAS SYNTHESIS · <b>{Math.round(chosen.length * 0.66)} of {chosen.length} would buy at €95.</b> Common objection: sustainability proof beyond packaging. Recommended next prompt: "What would change your mind?"
          </div>
        </div>
      </div>
    </>
  );
}

// ── Briefs (inline tab) ──────────────────────────────────────
function BriefsInline() {
  return (
    <>
      <ModuleHead code="MODULE 06" name="Briefs" tagline="Living documents." />
      <div className="row" style={{ justifyContent: "space-between" }}>
        <div style={{ display: "flex", gap: 8 }}>
          <span className="chip">Brand · CH</span>
          <span className="chip">Market · EU5</span>
          <span className="chip accent">Status · Draft</span>
          <span className="chip">Authors · Canvas + 2</span>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          <button className="btn">Export to Keynote</button>
          <button className="btn">Share</button>
          <button className="btn primary">Approve</button>
        </div>
      </div>
      <div className="brief-blocks">
        {BRIEF_BLOCKS.map((b, i) => (
          <div key={i} className={`brief-block ${b.ai ? "ai" : ""}`}>
            <div className="k">{b.k}</div>
            <div className="v" dangerouslySetInnerHTML={{ __html: b.v }} />
          </div>
        ))}
      </div>
      <div className="empty">
        <div className="t">Add the next block.</div>
        <div className="d">Drag a signal from Pulse, a Chorus response, a Spate forecast or a Materia ingredient.</div>
        <div style={{ marginTop: 20, display: "flex", gap: 10, justifyContent: "center" }}>
          <button className="btn primary">▲ Ask Canvas to draft</button>
          <button className="btn">Add empty block</button>
        </div>
      </div>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════
// PREDICTOR  (Spate · Materia)
// ═══════════════════════════════════════════════════════════════
function Predictor({ setRoute, initialTab = "spate" }) {
  const [tab, setTab] = useState(initialTab);
  const tabs = [
    { id: "spate",    label: "Spate",    sub: "Trend forecasting" },
    { id: "materia",  label: "Materia",  sub: "Ingredients radar" },
  ];
  return (
    <div className="page">
      <div>
        <div className="mono-eyebrow">Predictor</div>
        <h1 className="title" style={{ marginTop: 8 }}>What's <em style={{fontStyle:"italic",color:"var(--accent-ink)"}}>coming next</em>.</h1>
        <div className="subtitle">Trend lifecycle via Spate, ingredient movements via Materia — queried in plain language.</div>
      </div>
      <TabBar tabs={tabs} active={tab} setActive={setTab} />
      {tab === "spate" && <SpateModule />}
      {tab === "materia" && <Materia />}
    </div>
  );
}

// ── Spate (Trend Forecasting) ─────────────────────────────────
function SpateModule() {
  const [mode, setMode] = useState("console");
  return (
    <>
      <ModuleHead code="MODULE 07" name="Spate" tagline="Trend lifecycle forecasting." />
      <div className="row sb" style={{ alignItems: "flex-end" }}>
        <div style={{ fontFamily: "var(--font-display)", fontStyle: "italic", fontSize: 18, color: "var(--ink-70)", maxWidth: "60ch" }}>
          Powered by Spate's 20B searches and 60M TikTok videos — filtered to your workspace.
        </div>
        <div className="mode-switch">
          <button className={mode === "console" ? "on" : ""} onClick={() => setMode("console")}>Console</button>
          <button className={mode === "radar" ? "on" : ""} onClick={() => setMode("radar")}>Radar</button>
          <button className={mode === "sandbox" ? "on" : ""} onClick={() => setMode("sandbox")}>Sandbox</button>
          <span className="sp">● SPATE</span>
        </div>
      </div>
      {mode === "console" && <ConsoleMode />}
      {mode === "radar" && <RadarMode />}
      {mode === "sandbox" && <SandboxMode />}
    </>
  );
}

function ConsoleMode() {
  return (
    <>
      <div className="card" style={{ borderColor: "var(--ink-100)" }}>
        <div style={{ padding: "24px 28px" }}>
          <div className="mono-eyebrow" style={{ color: "var(--accent-ink)" }}>Ask Predictor</div>
          <div style={{ fontFamily: "var(--font-display)", fontSize: 32, lineHeight: 1.25, marginTop: 8, fontStyle: "italic" }}>
            "How mature is the <em style={{ color: "var(--accent-ink)" }}>refillable luxury</em> trend in fragrance, EU5?"
          </div>
        </div>
      </div>
      <Agent
        eyebrow="Canvas · Verdict"
        text="<b>Growth stage, likely to continue.</b> Momentum is +38% YoY. Two competitor filings since December (Chanel, Dior). Strongest in Spain, slower in Italy — where the window to own the narrative closes in Q2."
        actions={[
          { label: "Send to Brief", variant: "primary" },
          { label: "Simulate on Chorus" },
          { label: "Open in Spate" },
        ]}
      />
      <div className="grid-2">
        <div className="card">
          <div className="ch"><div className="t">12-month forecast</div><div className="k">Spate lifecycle curve</div></div>
          <div className="cb" style={{ padding: 24, height: 280 }}>
            <svg viewBox="0 0 400 200" style={{ width: "100%", height: "100%" }} preserveAspectRatio="none">
              {[0,1,2,3,4].map(i => <line key={i} x1="0" x2="400" y1={i*50} y2={i*50} stroke="var(--rule-soft)" strokeWidth="1"/>)}
              <line x1="200" x2="200" y1="0" y2="200" stroke="var(--ink-100)" strokeWidth="1" strokeDasharray="2 4"/>
              <text x="204" y="14" fontFamily="var(--font-mono)" fontSize="10" fill="var(--ink-50)">TODAY</text>
              <path d="M0,180 Q80,170 120,150 T200,100 Q260,70 320,45 L400,30" fill="none" stroke="var(--accent)" strokeWidth="2"/>
              <path d="M0,180 Q80,170 120,150 T200,100" fill="none" stroke="var(--ink-100)" strokeWidth="2"/>
              <text x="30" y="190" fontFamily="var(--font-mono)" fontSize="10" fill="var(--ink-50)">EARLY</text>
              <text x="160" y="190" fontFamily="var(--font-mono)" fontSize="10" fill="var(--ink-50)">GROWTH</text>
              <text x="320" y="190" fontFamily="var(--font-mono)" fontSize="10" fill="var(--ink-50)">MATURE</text>
            </svg>
          </div>
        </div>
        <div className="card">
          <div className="ch"><div className="t">Similar trends</div><div className="k">Spate adjacency</div></div>
          <div className="cb">
            {[
              ["Refillable luxury", 92, "+38%"],
              ["Olfactive layering", 74, "+22%"],
              ["Gender-fluid EDP", 58, "+14%"],
              ["Niche-to-mass", 44, "+9%"],
              ["Solid perfume", 18, "−3%"],
            ].map(([n, w, d], i) => (
              <div key={i} style={{ display: "grid", gridTemplateColumns: "180px 1fr 50px", gap: 12, alignItems: "center", padding: "10px 0", borderTop: i === 0 ? 0 : "1px solid var(--rule)" }}>
                <div style={{ fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--ink-70)" }}>{n}</div>
                <div style={{ height: 6, background: "var(--paper-10)", position: "relative" }}>
                  <span style={{ position: "absolute", inset: "0 auto 0 0", width: `${w}%`, background: "var(--accent)" }} />
                </div>
                <div style={{ fontFamily: "var(--font-mono)", fontSize: 12, textAlign: "right", color: d.startsWith("−") ? "oklch(50% 0.12 25)" : "var(--accent-ink)" }}>{d}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </>
  );
}

function RadarMode() {
  return (
    <>
      <Agent
        eyebrow="Canvas · Reading the radar"
        text="Three trends are in the <em>sweet spot</em> — growth stage, high momentum, relevant to fragrance: <b>Refillable luxury, Olfactive layering, Neurocosmetics</b>. Two are cooling: solid perfume and oud."
      />
      <div className="card">
        <div className="ch"><div className="t">Trend lifecycle radar</div><div className="k">Maturity × Momentum · Fragrance EU5</div></div>
        <div className="cb">
          <div className="radar">
            <div className="ax" style={{ left: 16, top: 12 }}>↑ HIGH MOMENTUM</div>
            <div className="ax" style={{ right: 16, bottom: 12 }}>MATURE →</div>
            <div className="ax" style={{ left: 16, bottom: 12 }}>← EARLY</div>
            {TRENDS.map((t, i) => (
              <div
                key={i}
                className={`bubble ${t.accent ? "accent" : t.state === "mature" ? "muted" : ""}`}
                style={{
                  left: `${t.x * 100}%`,
                  top: `${(1 - t.y) * 100}%`,
                  width: t.size, height: t.size,
                }}
                title={`${t.n} · ${t.delta}`}
              >
                {t.size > 32 ? t.n : ""}
              </div>
            ))}
          </div>
        </div>
      </div>
    </>
  );
}

function SandboxMode() {
  return (
    <>
      <Agent
        eyebrow="Canvas · Scenario"
        text="Stack signals to simulate a trajectory. You've combined <em>refillable luxury</em> + <em>Gen-Z audience</em> + <em>Spain</em>. Canvas is running 12-month projections against three comparable historical trends."
        actions={[{ label: "Save scenario", variant: "primary" }]}
      />
      <div className="grid-2">
        <div className="card">
          <div className="ch"><div className="t">Stack signals</div><div className="k">Drag or click to add</div></div>
          <div className="cb" style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            {[
              ["Ingredient", "—"],
              ["Claim", "Refillable luxury ×"],
              ["Demographic", "Gen-Z ×"],
              ["Market", "Spain ×"],
              ["Season", "SS '26"],
            ].map(([k, v], i) => (
              <div key={i} style={{ display: "grid", gridTemplateColumns: "140px 1fr", padding: "10px 0", borderTop: i === 0 ? 0 : "1px solid var(--rule)", gap: 16, alignItems: "center" }}>
                <div className="mono-eyebrow">{k}</div>
                <div style={{ fontFamily: "var(--font-display)", fontSize: 18, color: v === "—" ? "var(--ink-30)" : "var(--ink-100)" }}>{v}</div>
              </div>
            ))}
            <button className="btn" style={{ marginTop: 12, alignSelf: "flex-start" }}>+ Add signal</button>
          </div>
        </div>
        <div className="card">
          <div className="ch"><div className="t">Projected trajectory</div><div className="k">Spate comparable model · 12mo</div></div>
          <div className="cb" style={{ height: 300 }}>
            <svg viewBox="0 0 400 240" style={{ width: "100%", height: "100%" }} preserveAspectRatio="none">
              {[0,1,2,3,4].map(i => <line key={i} x1="0" x2="400" y1={i*60} y2={i*60} stroke="var(--rule-soft)" strokeWidth="1"/>)}
              <path d="M0,200 Q100,180 200,140 T400,60" fill="none" stroke="var(--accent)" strokeWidth="2"/>
              <path d="M0,200 Q100,190 200,170 T400,120" fill="none" stroke="var(--ink-30)" strokeWidth="1" strokeDasharray="3 3"/>
              <path d="M0,200 Q100,170 200,110 T400,30" fill="none" stroke="var(--ink-30)" strokeWidth="1" strokeDasharray="3 3"/>
              <text x="340" y="55" fontFamily="var(--font-mono)" fontSize="10" fill="var(--accent-ink)">SCENARIO</text>
              <text x="340" y="115" fontFamily="var(--font-mono)" fontSize="10" fill="var(--ink-50)">LOW</text>
              <text x="340" y="30" fontFamily="var(--font-mono)" fontSize="10" fill="var(--ink-50)">HIGH</text>
            </svg>
          </div>
        </div>
      </div>
    </>
  );
}

// ── Materia (Ingredients Radar) ───────────────────────────────
function Materia() {
  const stateColor = (s) => s === "growth" ? "var(--accent)" : s === "early" ? "#2E6B53" : s === "mature" ? "var(--ink-70)" : s === "plateau" ? "#8A5A2C" : "oklch(50% 0.16 25)";
  return (
    <>
      <ModuleHead code="MODULE 08" name="Materia" tagline="The ingredients radar." />
      <Agent
        eyebrow="Canvas · Ingredient watch"
        text="Three molecules are worth a perfumer conversation: <em>ambrocenide</em> (growth, +88 momentum), <em>biotech vetiver</em> (early, +78) and <em>ambrette seed</em> (early, +68). <em>Galaxolide</em> is under EU phase-out scrutiny — inventory audit recommended."
        actions={[{ label: "Draft perfumer brief", variant: "primary" }, { label: "Audit portfolio exposure" }]}
      />
      <div className="card">
        <div className="ch"><div className="t">Ingredient lifecycle</div><div className="k">Fragrance, 60 molecules tracked · 8 highlighted</div></div>
        <div style={{ padding: 0 }}>
          <div style={{ display: "grid", gridTemplateColumns: "1.6fr 1.2fr 100px 90px 70px 90px 120px", padding: "12px 20px", borderBottom: "1px solid var(--ink-100)", fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--ink-50)" }}>
            <span>Molecule</span><span>Family</span><span>Stage</span><span style={{textAlign:"right"}}>Momentum</span><span style={{textAlign:"right"}}>Price Δ</span><span>Supply</span><span>Flag</span>
          </div>
          {INGREDIENTS.map((r, i) => (
            <div key={i} style={{ display: "grid", gridTemplateColumns: "1.6fr 1.2fr 100px 90px 70px 90px 120px", padding: "14px 20px", borderBottom: "1px solid var(--rule)", alignItems: "center" }}>
              <span style={{ display: "flex", alignItems: "baseline", gap: 8, fontFamily: "var(--font-display)", fontSize: 17, fontStyle: "italic" }}>
                {r.n}
                {r.novel && <span className="chip accent" style={{ fontStyle: "normal" }}>NOVEL</span>}
              </span>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "0.08em", color: "var(--ink-70)", textTransform: "uppercase" }}>{r.family}</span>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: stateColor(r.trend) }}>● {r.trend}</span>
              <span style={{ display: "flex", alignItems: "center", gap: 6, justifyContent: "flex-end" }}>
                <span style={{ width: 40, height: 4, background: "var(--paper-10)", position: "relative" }}>
                  <span style={{ position: "absolute", inset: "0 auto 0 0", width: `${r.momentum}%`, background: stateColor(r.trend) }} />
                </span>
                <span style={{ fontFamily: "var(--font-mono)", fontSize: 12 }}>{r.momentum}</span>
              </span>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, textAlign: "right", color: r.price.startsWith("−") ? "oklch(50% 0.16 25)" : r.price.startsWith("+") ? "var(--accent-ink)" : "var(--ink-50)" }}>{r.price}</span>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "0.06em", color: "var(--ink-70)", textTransform: "uppercase" }}>{r.supply}</span>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.1em", color: r.flag ? "oklch(45% 0.16 25)" : "var(--ink-30)", textTransform: "uppercase" }}>{r.flag || "—"}</span>
            </div>
          ))}
        </div>
      </div>
      <div className="grid-2">
        <div className="card">
          <div className="ch"><div className="t">Your portfolio exposure</div><div className="k">Across Puig fragrance houses</div></div>
          <div className="cb">
            {[
              ["Galaxolide", 12, "12 SKUs across 3 houses", "risk"],
              ["Oud (natural)", 8, "JPG + Rabanne · tight supply", "risk"],
              ["Ambrocenide", 3, "Under evaluation for 2 NPDs", "opportunity"],
              ["Biotech vetiver", 1, "Pilot — JPG Scandal reformulation", "opportunity"],
            ].map(([n, c, note, kind], i) => (
              <div key={i} style={{ display: "grid", gridTemplateColumns: "180px 60px 1fr 90px", gap: 12, padding: "14px 0", borderTop: i === 0 ? 0 : "1px solid var(--rule)", alignItems: "baseline" }}>
                <span style={{ fontFamily: "var(--font-display)", fontSize: 17, fontStyle: "italic" }}>{n}</span>
                <span style={{ fontFamily: "var(--font-display)", fontSize: 22, color: kind === "risk" ? "oklch(45% 0.16 25)" : "var(--accent-ink)" }}>{c}</span>
                <span style={{ fontFamily: "var(--font-display)", fontStyle: "italic", fontSize: 14, color: "var(--ink-70)" }}>{note}</span>
                <span className="chip" style={{
                  background: kind === "risk" ? "oklch(92% 0.05 25)" : "var(--accent-tint)",
                  color: kind === "risk" ? "oklch(40% 0.16 25)" : "var(--accent-ink)",
                  borderColor: "transparent",
                  justifySelf: "end",
                }}>{kind === "risk" ? "Risk" : "Opportunity"}</span>
              </div>
            ))}
          </div>
        </div>
        <div className="card">
          <div className="ch"><div className="t">Adjacencies</div><div className="k">Molecules often listed together · Spate x IFF index</div></div>
          <div className="cb" style={{ height: 320, position: "relative", overflow: "hidden" }}>
            <svg viewBox="0 0 400 280" style={{ width: "100%", height: "100%" }}>
              {/* A tiny node-link graph */}
              {[
                [200,140,"Ambrocenide",20,true],
                [100,80,"Iso E Super",16,false],
                [120,220,"Hedione",14,false],
                [300,100,"Cashmeran",14,false],
                [320,200,"Ambrette",16,true],
                [60,160,"Galaxolide",12,false],
                [260,50,"Oud",14,false],
                [240,240,"Biotech vetiver",18,true],
              ].map(([x,y,n,r,a], i) => (
                <g key={i}>
                  <line x1={200} y1={140} x2={x} y2={y} stroke={a ? "var(--accent)" : "var(--rule)"} strokeWidth={a ? 1.4 : 1}/>
                </g>
              ))}
              {[
                [200,140,"Ambrocenide",20,true],
                [100,80,"Iso E Super",16,false],
                [120,220,"Hedione",14,false],
                [300,100,"Cashmeran",14,false],
                [320,200,"Ambrette",16,true],
                [60,160,"Galaxolide",12,false],
                [260,50,"Oud",14,false],
                [240,240,"Biotech vetiver",18,true],
              ].map(([x,y,n,r,a], i) => (
                <g key={i}>
                  <circle cx={x} cy={y} r={r} fill={a ? "var(--accent)" : "#FBF8F2"} stroke={a ? "var(--accent)" : "var(--ink-70)"} strokeWidth="1"/>
                  <text x={x} y={y + r + 12} fontFamily="var(--font-mono)" fontSize="9" letterSpacing="0.06em" fill="var(--ink-70)" textAnchor="middle">{n}</text>
                </g>
              ))}
            </svg>
          </div>
        </div>
      </div>
    </>
  );
}

// ═══════════════════════════════════════════════════════════════
// BRIEFS (full page · kept as standalone room too)
// ═══════════════════════════════════════════════════════════════
function Briefs() {
  return (
    <div className="page">
      <div>
        <div className="mono-eyebrow">Briefs · Active</div>
        <h1 className="title" style={{ marginTop: 8 }}>CH Good Girl — the refill story.</h1>
        <div className="subtitle">A living document composed from Pulse, Chorus, Spate and Materia. Canvas drafted 4 of 6 blocks overnight.</div>
      </div>
      <div className="row" style={{ justifyContent: "space-between" }}>
        <div style={{ display: "flex", gap: 8 }}>
          <span className="chip">Brand · CH</span>
          <span className="chip">Market · EU5</span>
          <span className="chip accent">Status · Draft</span>
          <span className="chip">Authors · Canvas + 2</span>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          <button className="btn">Export to Keynote</button>
          <button className="btn">Share</button>
          <button className="btn primary">Approve</button>
        </div>
      </div>
      <div className="brief-blocks">
        {BRIEF_BLOCKS.map((b, i) => (
          <div key={i} className={`brief-block ${b.ai ? "ai" : ""}`}>
            <div className="k">{b.k}</div>
            <div className="v" dangerouslySetInnerHTML={{ __html: b.v }} />
          </div>
        ))}
      </div>
      <div className="empty">
        <div className="t">Add the next block.</div>
        <div className="d">Drag a signal from Pulse, a Chorus response, a Spate forecast or a Materia ingredient.</div>
        <div style={{ marginTop: 20, display: "flex", gap: 10, justifyContent: "center" }}>
          <button className="btn primary">▲ Ask Canvas to draft</button>
          <button className="btn">Add empty block</button>
        </div>
      </div>
    </div>
  );
}

function Library() {
  return (
    <div className="page">
      <div>
        <div className="mono-eyebrow">Library</div>
        <h1 className="title" style={{ marginTop: 8 }}>Everything you've shipped.</h1>
        <div className="subtitle">Briefs, persona sets, forecasts and creator lists — versioned and searchable.</div>
      </div>
      <div className="empty">
        <div className="t">Library preview — not part of this proposal.</div>
        <div className="d">Will mirror the Briefs block model, with brand &amp; market filters.</div>
      </div>
    </div>
  );
}

Object.assign(window, { Home, Analyst, Strategist, Predictor, Briefs, Library });
