/* ===========================================================================
   Article.jsx — Individual AI Before Institutional AI
   All article-specific components in one file. The article TEXT is verbatim
   from uploads/linkedin-article-institutional-ai.md; only formatting is added.
   ===========================================================================*/

/* ---------- shared atoms ---------------------------------------------------*/

const Eyebrow = ({children, color = 'var(--accent-fg)'}) => (
  <div style={{
    fontFamily: 'var(--font-mono)', fontSize: 11,
    textTransform: 'uppercase', letterSpacing: '.12em',
    color, fontWeight: 500
  }}>{children}</div>
);

const ArrowRight = ({size = 14}) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
    <line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/>
  </svg>
);

/* small hook: in-view trigger — scroll-listener fallback (IntersectionObserver
   doesn't fire in some embedded preview iframes) */
const useInView = (opts = {threshold: .2}) => {
  const ref = React.useRef(null);
  const [seen, setSeen] = React.useState(false);
  React.useEffect(() => {
    if (seen) return;
    const check = () => {
      const el = ref.current;
      if (!el) return;
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight;
      // visible if any part is in viewport, with a small bottom margin so
      // animations kick off as it scrolls in
      if (r.top < vh - 40 && r.bottom > 0) {
        setSeen(true);
      }
    };
    check();
    window.addEventListener('scroll', check, {passive: true});
    window.addEventListener('resize', check);
    // also try IO as a bonus
    let io;
    try {
      io = new IntersectionObserver((entries) => {
        entries.forEach(e => { if (e.isIntersecting) setSeen(true); });
      }, opts);
      if (ref.current) io.observe(ref.current);
    } catch (_) {}
    return () => {
      window.removeEventListener('scroll', check);
      window.removeEventListener('resize', check);
      if (io) io.disconnect();
    };
  }, [seen]);
  return [ref, seen];
};

/* count-up hook — interval-based (rAF doesn't fire in some preview iframes) */
const useCountUp = (target, ms = 1400, run = true, start = 0) => {
  const [n, setN] = React.useState(start);
  React.useEffect(() => {
    if (!run) return;
    const t0 = Date.now();
    const id = setInterval(() => {
      const k = Math.min(1, (Date.now() - t0) / ms);
      const eased = 1 - Math.pow(1 - k, 3);
      setN(start + (target - start) * eased);
      if (k >= 1) clearInterval(id);
    }, 16);
    return () => clearInterval(id);
  }, [run, target]);
  return n;
};

/* ===========================================================================
   ReadProgress — thin top bar
   ===========================================================================*/

const ReadProgress = () => {
  const [w, setW] = React.useState(0);
  React.useEffect(() => {
    const h = () => {
      const doc = document.documentElement;
      const max = doc.scrollHeight - doc.clientHeight;
      setW(max > 0 ? (window.scrollY / max) * 100 : 0);
    };
    h();
    window.addEventListener('scroll', h, {passive: true});
    window.addEventListener('resize', h);
    return () => {
      window.removeEventListener('scroll', h);
      window.removeEventListener('resize', h);
    };
  }, []);
  return <div className="read-progress" style={{width: `${w}%`}}/>;
};
window.ReadProgress = ReadProgress;

/* ===========================================================================
   ArticleNav — minimal sticky nav
   ===========================================================================*/

const ArticleNav = () => {
  const [scrolled, setScrolled] = React.useState(false);
  React.useEffect(() => {
    const h = () => setScrolled(window.scrollY > 12);
    window.addEventListener('scroll', h, {passive: true});
    return () => window.removeEventListener('scroll', h);
  }, []);
  return (
    <nav style={{
      position: 'sticky', top: 0, zIndex: 50,
      background: scrolled ? 'rgba(12,15,26,0.78)' : 'transparent',
      backdropFilter: scrolled ? 'blur(16px) saturate(180%)' : 'none',
      WebkitBackdropFilter: scrolled ? 'blur(16px) saturate(180%)' : 'none',
      borderBottom: scrolled ? '1px solid rgba(42,46,66,.6)' : '1px solid transparent',
      transition: 'background .2s ease, border-color .2s ease'
    }}>
      <div className="article-nav-inner" style={{maxWidth: 1240, margin: '0 auto', padding: '14px 28px', display: 'flex', alignItems: 'center', gap: 24, flexWrap: 'wrap'}}>
        <a href="/" style={{display: 'flex', alignItems: 'center', gap: 10, textDecoration: 'none'}}>
          <img src="/assets/yambr-glyph.svg" width="26" height="26" alt=""/>
          <span style={{fontFamily: 'var(--font-mono)', fontWeight: 600, fontSize: 16, color: 'var(--fg-primary)'}}>
            yambr<span style={{color: 'var(--brand-green)'}}>.</span>
          </span>
        </a>
        <span style={{
          fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-muted)',
          padding: '3px 8px', border: '1px solid var(--border-default)',
          borderRadius: 4, textTransform: 'uppercase', letterSpacing: '.08em'
        }}>writing</span>
        <span style={{fontSize: 13, color: 'var(--fg-secondary)', display: 'flex', alignItems: 'center', gap: 8}}>
          <a href="/" style={{color: 'var(--fg-muted)', textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 4}}>
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>
            Back to yambr
          </a>
        </span>
        <div className="article-nav-meta" style={{marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 14, fontSize: 12.5, color: 'var(--fg-muted)', fontFamily: 'var(--font-mono)'}}>
          <span>Apr 2026</span>
          <span style={{color: 'var(--border-default)'}}>·</span>
          <span>~14 min read</span>
          <span style={{color: 'var(--border-default)'}}>·</span>
          <a
            href="https://www.linkedin.com/in/nikolai-iambroskin-493a38247/"
            target="_blank"
            rel="noopener noreferrer"
            style={{
              display: 'inline-flex', alignItems: 'center', gap: 6,
              color: 'var(--fg-secondary)', textDecoration: 'none',
              padding: '4px 10px',
              border: '1px solid var(--border-default)',
              borderRadius: 4,
              transition: 'border-color .15s, color .15s'
            }}
            onMouseEnter={e => { e.currentTarget.style.borderColor = 'var(--brand-green)'; e.currentTarget.style.color = 'var(--fg-primary)'; }}
            onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border-default)'; e.currentTarget.style.color = 'var(--fg-secondary)'; }}
          >
            <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14zM8.5 18.5v-9H6v9h2.5zm-1.25-10.2a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM18.5 18.5v-5.1c0-2.4-1.3-3.5-3-3.5-1.4 0-2 .8-2.4 1.4v-1.2H10.6c0 .7 0 9 0 9h2.5v-5c0-.2 0-.4.1-.6.2-.5.6-1 1.4-1 1 0 1.4.8 1.4 1.9v4.7h2.5z"/></svg>
            Follow
          </a>
        </div>
      </div>
    </nav>
  );
};
window.ArticleNav = ArticleNav;

/* ===========================================================================
   ArticleHero — title + interactive "path" diagram
   ===========================================================================*/

const ArticleHero = () => {
  // Animated scroll-along path — Sivulka drew the map; here is the PATH
  const [t, setT] = React.useState(0);
  React.useEffect(() => {
    const t0 = Date.now();
    const id = setInterval(() => {
      setT(((Date.now() - t0) / 8000) % 1);
    }, 33);
    return () => clearInterval(id);
  }, []);

  // path: irregular, 1890 → 2030, with five waypoints (the principles)
  const W = 1100, H = 200;
  const pts = [
    {x: 60,  y: 150, label: '1890', sub: 'electric motors'},
    {x: 280, y: 110, label: '1920', sub: 'assembly line'},
    {x: 540, y: 130, label: '2025', sub: 'individual AI'},
    {x: 760, y: 70,  label: '2027', sub: 'ecosystems'},
    {x: 1040,y: 40,  label: '2030', sub: 'institutional AI'},
  ];
  const d = `M ${pts[0].x},${pts[0].y} ` + pts.slice(1).map((p, i) => {
    const prev = pts[i];
    const cx = (prev.x + p.x) / 2;
    return `C ${cx},${prev.y} ${cx},${p.y} ${p.x},${p.y}`;
  }).join(' ');

  return (
    <section className="article-hero" style={{position: 'relative', padding: '84px 28px 32px', overflow: 'hidden'}}>
      <div aria-hidden style={{
        position: 'absolute', inset: '-200px 0 auto 0', height: 700, zIndex: 0, pointerEvents: 'none',
        background: 'radial-gradient(ellipse 900px 460px at 50% 0%, rgba(74,222,128,.10), transparent 68%)'
      }}/>
      <div aria-hidden style={{
        position: 'absolute', inset: 0, zIndex: 0, pointerEvents: 'none', opacity: .35,
        backgroundImage: 'linear-gradient(rgba(42,46,66,.35) 1px, transparent 1px), linear-gradient(90deg, rgba(42,46,66,.35) 1px, transparent 1px)',
        backgroundSize: '56px 56px',
        maskImage: 'radial-gradient(ellipse 900px 500px at 50% 0%, #000 20%, transparent 72%)',
        WebkitMaskImage: 'radial-gradient(ellipse 900px 500px at 50% 0%, #000 20%, transparent 72%)'
      }}/>

      <div style={{maxWidth: 1100, margin: '0 auto', position: 'relative', zIndex: 1}}>
        <div style={{display: 'inline-flex', alignItems: 'center', gap: 10, marginBottom: 28, fontFamily: 'var(--font-mono)', fontSize: 11.5}}>
          <span style={{color: 'var(--accent-fg)', textTransform: 'uppercase', letterSpacing: '.14em'}}>Essay · Apr 2026</span>
          <span style={{color: 'var(--border-default)'}}>/</span>
          <span style={{color: 'var(--fg-muted)'}}>practitioner notes</span>
        </div>

        <h1 style={{
          fontSize: 'clamp(40px, 5.6vw, 76px)',
          fontWeight: 600, letterSpacing: '-0.035em', lineHeight: 1.02,
          margin: 0, maxWidth: 1000
        }}>
          Individual AI<br/>
          before <span style={{
            background: 'linear-gradient(90deg, #B8E936, #4ADE80 55%, #16A34A)',
            WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent',
            backgroundClip: 'text'
          }}>Institutional AI.</span>
        </h1>
        <p style={{
          fontSize: 19, color: 'var(--fg-secondary)', lineHeight: 1.55,
          maxWidth: 720, marginTop: 22
        }}>
          Five principles from building enterprise AI for 1,100 users.
          A practitioner's response to a16z's <a href="https://www.a16z.news/p/institutional-ai-vs-individual-ai" target="_blank" rel="noopener noreferrer" style={{color: 'var(--fg-primary)', fontStyle: 'italic', textDecoration: 'underline', textDecorationColor: 'var(--brand-green)', textUnderlineOffset: 3}}>Institutional AI vs Individual AI</a>.
        </p>

        {/* author card */}
        <div className="article-author-card" style={{
          marginTop: 36,
          display: 'flex', alignItems: 'flex-start', gap: 18,
          padding: '20px 22px',
          background: 'var(--bg-secondary)',
          border: '1px solid var(--border-default)',
          borderRadius: 12
        }}>
          <div style={{
            width: 44, height: 44, borderRadius: 10, flexShrink: 0,
            background: 'linear-gradient(135deg, var(--brand-lime), var(--brand-green-deep))',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            fontFamily: 'var(--font-mono)', fontSize: 14, color: 'var(--brand-ink)', fontWeight: 700,
            letterSpacing: '-.02em'
          }}>YA</div>
          <div style={{flex: 1, minWidth: 0}}>
            <div style={{display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap'}}>
              <span style={{fontSize: 15, fontWeight: 600, color: 'var(--fg-primary)', letterSpacing: '-.01em'}}>
                AI Platform Lead at a financial-services company (~2,000 people)
              </span>
              <span style={{
                fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--accent-fg)',
                textTransform: 'uppercase', letterSpacing: '.12em',
                padding: '2px 7px',
                background: 'var(--accent-subtle)',
                border: '1px solid rgba(34,197,94,.25)',
                borderRadius: 4
              }}>practitioner</span>
            </div>
            <p style={{
              fontSize: 13.5, color: 'var(--fg-secondary)', lineHeight: 1.6,
              margin: '8px 0 0 0', maxWidth: 720
            }}>
              Everything below is what I learned building Individual AI inside the company over the last ten months.
              The numbers, the principles, and the decisions are from production, not theory.
            </p>
            <a
              href="https://www.linkedin.com/in/nikolai-iambroskin-493a38247/"
              target="_blank"
              rel="noopener noreferrer"
              style={{
                display: 'inline-flex', alignItems: 'center', gap: 8,
                marginTop: 14,
                padding: '8px 14px',
                fontFamily: 'var(--font-mono)', fontSize: 12,
                color: 'var(--brand-ink)', textDecoration: 'none',
                background: 'var(--brand-lime)',
                border: '1px solid var(--brand-lime)',
                borderRadius: 6,
                fontWeight: 600,
                letterSpacing: '.02em',
                transition: 'transform .12s ease, box-shadow .12s ease'
              }}
              onMouseEnter={e => { e.currentTarget.style.transform = 'translateY(-1px)'; e.currentTarget.style.boxShadow = '0 4px 14px rgba(184,233,54,.25)'; }}
              onMouseLeave={e => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = 'none'; }}
            >
              <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14zM8.5 18.5v-9H6v9h2.5zm-1.25-10.2a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM18.5 18.5v-5.1c0-2.4-1.3-3.5-3-3.5-1.4 0-2 .8-2.4 1.4v-1.2H10.6c0 .7 0 9 0 9h2.5v-5c0-.2 0-.4.1-.6.2-.5.6-1 1.4-1 1 0 1.4.8 1.4 1.9v4.7h2.5z"/></svg>
              Follow on LinkedIn
              <span style={{opacity: .55, fontWeight: 400}}>· Nikolai Iambroskin</span>
            </a>
          </div>
        </div>

        {/* byline strip */}
        <div className="article-byline-strip" style={{
          marginTop: 40, display: 'flex', alignItems: 'center', gap: 16,
          paddingTop: 20, borderTop: '1px solid var(--border-subtle)',
          fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-muted)'
        }}>
          <span>5 months in production</span>
          <span style={{color: 'var(--border-default)'}}>·</span>
          <span>1,100 monthly users</span>
          <span style={{color: 'var(--border-default)'}}>·</span>
          <span>50B+ tokens / month</span>
        </div>

        {/* the PATH artifact */}
        <div style={{
          marginTop: 56,
          background: 'var(--bg-secondary)',
          border: '1px solid var(--border-default)',
          borderRadius: 14,
          padding: '26px 28px',
          position: 'relative', overflow: 'hidden'
        }}>
          <div style={{display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 14, gap: 24, flexWrap: 'wrap'}}>
            <div>
              <Eyebrow>the path</Eyebrow>
              <div style={{fontSize: 17, fontWeight: 600, color: 'var(--fg-primary)', marginTop: 6, letterSpacing: '-.01em'}}>
                Sivulka drew the map. Here is the path.
              </div>
            </div>
            <div style={{fontFamily: 'var(--font-mono)', fontSize: 11.5, color: 'var(--fg-muted)'}}>
              ▸ live · the dot is moving along the irregular line because the line itself is being drawn
            </div>
          </div>
          <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none" style={{width: '100%', height: 200, display: 'block'}}>
            <defs>
              <linearGradient id="path-grad" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop offset="0%" stopColor="rgba(184,233,54,.0)"/>
                <stop offset="20%" stopColor="rgba(184,233,54,.6)"/>
                <stop offset="60%" stopColor="rgba(74,222,128,.9)"/>
                <stop offset="100%" stopColor="rgba(22,163,74,.9)"/>
              </linearGradient>
              <linearGradient id="map-grad" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop offset="0%" stopColor="rgba(156,163,175,.18)"/>
                <stop offset="100%" stopColor="rgba(156,163,175,.06)"/>
              </linearGradient>
            </defs>

            {/* Sivulka's "map" = a straight idealized line */}
            <line x1={pts[0].x} y1={pts[0].y} x2={pts[pts.length - 1].x} y2={pts[pts.length - 1].y}
                  stroke="url(#map-grad)" strokeWidth="2" strokeDasharray="4 6"/>

            {/* The actual path */}
            <path d={d} stroke="url(#path-grad)" strokeWidth="2.5" fill="none" strokeLinecap="round"/>

            {/* waypoints */}
            {pts.map((p, i) => (
              <g key={p.label}>
                <circle cx={p.x} cy={p.y} r="5" fill="var(--brand-ink)" stroke="var(--brand-green)" strokeWidth="2"/>
                <text x={p.x} y={p.y - 14} fontFamily="var(--font-mono)" fontSize="10" fill="var(--fg-secondary)" textAnchor="middle">{p.label}</text>
                <text x={p.x} y={p.y + 22} fontFamily="var(--font-mono)" fontSize="9.5" fill="var(--fg-muted)" textAnchor="middle">{p.sub}</text>
              </g>
            ))}

            {/* Moving dot */}
            <PathTraveler d={d} t={t}/>
          </svg>

          <div style={{display: 'flex', gap: 24, marginTop: 8, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-muted)'}}>
            <span style={{display: 'inline-flex', alignItems: 'center', gap: 8}}>
              <span style={{width: 18, height: 0, borderTop: '2px dashed rgba(156,163,175,.6)'}}/>
              the map
            </span>
            <span style={{display: 'inline-flex', alignItems: 'center', gap: 8}}>
              <span style={{width: 18, height: 2, background: 'linear-gradient(90deg, var(--brand-lime), var(--brand-green-deep))', borderRadius: 2}}/>
              the path
            </span>
          </div>
        </div>
      </div>
    </section>
  );
};
window.ArticleHero = ArticleHero;

/* helper: dot travelling along an SVG path at parameter t (0..1) */
const PathTraveler = ({d, t}) => {
  const ref = React.useRef(null);
  const [pos, setPos] = React.useState({x: 0, y: 0});
  React.useEffect(() => {
    if (!ref.current) return;
    const len = ref.current.getTotalLength();
    const p = ref.current.getPointAtLength(len * t);
    setPos({x: p.x, y: p.y});
  }, [t, d]);
  return (
    <g>
      <path ref={ref} d={d} fill="none" stroke="none"/>
      <circle cx={pos.x} cy={pos.y} r="9" fill="rgba(74,222,128,.18)"/>
      <circle cx={pos.x} cy={pos.y} r="5" fill="var(--brand-green)" stroke="var(--brand-ink)" strokeWidth="1.5"/>
    </g>
  );
};

/* ===========================================================================
   Prose helper — lays out one or more paragraphs verbatim
   ===========================================================================*/

const Prose = ({children, style = {}}) => (
  <div className="prose" style={{padding: '0 28px', ...style}}>{children}</div>
);
window.Prose = Prose;

/* ===========================================================================
   ArticleIntro — first paragraphs + interactive MAU growth tile
   ===========================================================================*/

const ArticleIntro = () => {
  return (
    <section style={{padding: '40px 0 24px'}}>
      <Prose>
        <hr/>
        <p>A few weeks ago, a16z's George Sivulka published the clearest framing of enterprise AI I've read this year: <a href="https://www.a16z.news/p/institutional-ai-vs-individual-ai" target="_blank" rel="noopener noreferrer" style={{color: 'var(--fg-primary)', fontStyle: 'italic', textDecoration: 'underline', textDecorationColor: 'var(--brand-green)', textUnderlineOffset: 3}}>Individual AI vs Institutional AI</a>. He's right.</p>
        <p>For the last ten months I've been building Individual AI inside a 2,000-person company. 1,100 people use it every month now, about 55% of the company. We didn't get there by following any map. The map didn't exist, and as far as I can tell it still doesn't.</p>
        <p>Sivulka draws the destination well. Coordination, signal, edge, and outcomes are four of the seven pillars he names for where enterprise AI is going. What his essay leaves out is the path. Most companies will skip it.</p>
      </Prose>

      <MAUGrowth/>

      <Prose>
        <p>You can't prepare for Institutional AI directly. The 1890s textile mills took thirty years to figure out the assembly line, and this path will look obvious in hindsight too. By 2030 we'll all see it. Right now, we don't. New models ship weekly. The capability you built your platform around six months ago is a commodity now. The next layer of abstraction is being shipped while you're still deploying the last one.</p>
        <p>So you can't build a multi-year roadmap. You can only execute principles.</p>
        <p>Here are five I've been operating by. Not theory, just what got us from 0 to 1,100 monthly active users in five months without anyone being told to.</p>
        <hr/>
      </Prose>
    </section>
  );
};
window.ArticleIntro = ArticleIntro;

/* the growth tile — animated counter and bars */
const MAUGrowth = () => {
  const [ref, seen] = useInView();
  const months = [
    {m: 'M1', mau: 80,   wau: 50,  dau: 18},
    {m: 'M2', mau: 240,  wau: 160, dau: 70},
    {m: 'M3', mau: 520,  wau: 360, dau: 180},
    {m: 'M4', mau: 820,  wau: 560, dau: 320},
    {m: 'M5', mau: 1100, wau: 745, dau: 450},
  ];
  const max = 1200;
  const mau = Math.round(useCountUp(1100, 1800, seen));
  const pct = Math.round(useCountUp(55, 1800, seen));

  return (
    <div ref={ref} className="artifact-frame">
      <div className="artifact-card">
        <div className="artifact-head">
          <span>adoption telemetry</span>
          <span style={{textTransform: 'none', letterSpacing: 0, color: 'var(--fg-secondary)'}}>5 months · gateway logs</span>
          <span className="live">RECORDING</span>
        </div>
        <div className="mau-growth-grid" style={{display: 'grid', gridTemplateColumns: '320px 1fr', gap: 0}}>
          {/* big number */}
          <div style={{padding: '32px 28px', borderRight: '1px solid var(--border-subtle)', background: 'var(--bg-primary)'}}>
            <Eyebrow>monthly active users</Eyebrow>
            <div style={{
              fontFamily: 'var(--font-mono)', fontSize: 64, fontWeight: 600,
              color: 'var(--fg-primary)', letterSpacing: '-.03em', lineHeight: 1, marginTop: 14
            }}>
              {mau.toLocaleString()}
            </div>
            <div style={{fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-muted)', marginTop: 8}}>
              <span style={{color: 'var(--brand-green)'}}>↑ {pct}%</span> of a 2,000-person company
            </div>
            <div style={{marginTop: 28, paddingTop: 18, borderTop: '1px solid var(--border-subtle)', display: 'flex', flexDirection: 'column', gap: 12, fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-secondary)'}}>
              <div style={{display: 'flex', justifyContent: 'space-between'}}>
                <span style={{color: 'var(--fg-muted)'}}>WAU</span>
                <span>745</span>
              </div>
              <div style={{display: 'flex', justifyContent: 'space-between'}}>
                <span style={{color: 'var(--fg-muted)'}}>peak DAU</span>
                <span>450</span>
              </div>
              <div style={{display: 'flex', justifyContent: 'space-between'}}>
                <span style={{color: 'var(--fg-muted)'}}>retention</span>
                <span>75–86%</span>
              </div>
            </div>
          </div>

          {/* chart */}
          <div style={{padding: '24px 28px', background: 'var(--bg-secondary)'}}>
            <div style={{display: 'flex', justifyContent: 'space-between', marginBottom: 14, alignItems: 'baseline'}}>
              <Eyebrow>MoM growth</Eyebrow>
              <div style={{fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-muted)'}}>
                <span style={{color: 'var(--brand-lime)'}}>■</span> MAU
                <span style={{marginLeft: 14, color: 'var(--brand-green)'}}>■</span> WAU
                <span style={{marginLeft: 14, color: 'var(--brand-green-deep)'}}>■</span> peak DAU
              </div>
            </div>
            <div style={{height: 220, display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 18, alignItems: 'end'}}>
              {months.map((row, i) => {
                const h = (v) => seen ? `${(v / max) * 100}%` : '0%';
                return (
                  <div key={row.m} style={{display: 'flex', flexDirection: 'column', alignItems: 'center', height: '100%'}}>
                    <div style={{flex: 1, width: '100%', display: 'flex', gap: 4, alignItems: 'flex-end'}}>
                      <div style={{flex: 1, background: 'var(--brand-lime)', height: h(row.mau), borderRadius: '3px 3px 0 0',
                        transition: `height .9s cubic-bezier(.2,.8,.2,1) ${i * 100}ms`,
                        boxShadow: '0 0 12px rgba(184,233,54,.18)'}}/>
                      <div style={{flex: 1, background: 'var(--brand-green)', height: h(row.wau), borderRadius: '3px 3px 0 0',
                        transition: `height .9s cubic-bezier(.2,.8,.2,1) ${i * 100 + 90}ms`}}/>
                      <div style={{flex: 1, background: 'var(--brand-green-deep)', height: h(row.dau), borderRadius: '3px 3px 0 0',
                        transition: `height .9s cubic-bezier(.2,.8,.2,1) ${i * 100 + 180}ms`}}/>
                    </div>
                    <div style={{marginTop: 8, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-muted)'}}>{row.m}</div>
                  </div>
                );
              })}
            </div>
            <div style={{marginTop: 10, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-muted)', display: 'flex', justifyContent: 'space-between'}}>
              <span>0 → 1,100 MAU · zero mandates</span>
              <span style={{color: 'var(--brand-green)'}}>+1,100 in 5 months</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

window.MAUGrowth = MAUGrowth;
