/* ===========================================================================
   Principles45.jsx — Principles 4 & 5 + remaining sections
   ===========================================================================*/

/* ---------- Principle 4: Adoption is pull, not push. ----------------------*/

const PrincipleFour = () => {
  return (
    <section style={{padding: '24px 0'}}>
      <Prose>
        <div style={{display: 'flex', alignItems: 'baseline', gap: 14, marginBottom: 18}}>
          <span className="principle-num">PRINCIPLE 04</span>
          <span style={{flex: 1, height: 1, background: 'var(--border-subtle)'}}/>
        </div>
        <h2>Adoption is pull, not push.</h2>
        <p>The old workflow: someone has a problem, they find a person who can solve it, they wait, the person solves it.</p>
        <p>The new workflow: someone has a problem, they poke AI in whatever interface they already use. Even an accountant on our platform can ask AI to read source code from one of our internal systems and extract data they need. They don't write the code. They don't know what a repository is. They describe the problem and the AI does the work. The accountant didn't have to wait three weeks for a developer.</p>
      </Prose>

      <PullVsPush/>

      <Prose>
        <p>That's the pull. People come to your platform because their pain gets reduced. When they discover it works, they come back. They don't need to be told.</p>
        <p>I'll be transparent about one thing: we did run an active internal program of showcasing wins, both the modest "this saved me an hour today" stories and the spectacular ones. Not to force adoption, but to remove the friction of not knowing what was possible.</p>
        <p>And honestly, we were often surprised ourselves. People found uses we hadn't predicted, hadn't designed for, hadn't even imagined. At one point someone built a working desktop application directly out of our chat interface. That kind of thing happens when you keep the barrier low and resist prescribing what the tool is for.</p>
        <p>The real lever was always pull. Once a user got value from it, they couldn't afford not to use it again. That's the adoption flywheel: demonstrated value, repeated by people who look like the rest of your company. Not training programs, not mandates.</p>
        <hr/>
      </Prose>
    </section>
  );
};
window.PrincipleFour = PrincipleFour;

/* Pull vs Push: little particle physics */
const PullVsPush = () => {
  const [mode, setMode] = React.useState('pull'); // 'pull' | 'push'
  const canvasRef = React.useRef(null);
  const stateRef = React.useRef(null);
  const modeRef = React.useRef(mode);
  React.useEffect(() => { modeRef.current = mode; }, [mode]);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const resize = () => {
      const r = canvas.getBoundingClientRect();
      canvas.width = r.width * devicePixelRatio;
      canvas.height = r.height * devicePixelRatio;
      ctx.scale(devicePixelRatio, devicePixelRatio);
    };
    resize();

    const W = () => canvas.getBoundingClientRect().width;
    const H = () => canvas.getBoundingClientRect().height;

    // init particles once
    if (!stateRef.current) {
      const N = 70;
      const ps = [];
      for (let i = 0; i < N; i++) {
        ps.push({
          x: Math.random() * W(),
          y: Math.random() * H(),
          vx: (Math.random() - .5) * .5,
          vy: (Math.random() - .5) * .5,
          r: 1.5 + Math.random() * 1.5,
        });
      }
      stateRef.current = {ps};
    }

    let intervalId;
    const tick = () => {
      const ww = W(), hh = H();
      ctx.clearRect(0, 0, ww, hh);
      const cx = ww / 2, cy = hh / 2;

      // hub
      const grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, 90);
      grad.addColorStop(0, 'rgba(74,222,128,.18)');
      grad.addColorStop(1, 'rgba(74,222,128,0)');
      ctx.fillStyle = grad;
      ctx.beginPath(); ctx.arc(cx, cy, 90, 0, Math.PI * 2); ctx.fill();

      ctx.strokeStyle = 'rgba(74,222,128,.5)';
      ctx.lineWidth = 1.2;
      ctx.beginPath(); ctx.arc(cx, cy, 18, 0, Math.PI * 2); ctx.stroke();
      ctx.fillStyle = '#0C0F1A';
      ctx.beginPath(); ctx.arc(cx, cy, 18, 0, Math.PI * 2); ctx.fill();
      ctx.fillStyle = '#4ADE80';
      ctx.font = '600 10px Geist Mono, monospace';
      ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
      ctx.fillText('yambr', cx, cy);

      const m = modeRef.current;
      const {ps} = stateRef.current;
      ps.forEach(p => {
        const dx = cx - p.x, dy = cy - p.y;
        const d = Math.hypot(dx, dy) + 0.001;
        const ux = dx / d, uy = dy / d;
        const force = m === 'pull' ? 0.06 : -0.05;
        // pull: stronger when closer (saturates)
        const mag = m === 'pull' ? Math.min(0.6, 35 / d) : Math.max(0.2, 25 / d);
        p.vx += ux * force * mag;
        p.vy += uy * force * mag;
        // damping
        p.vx *= .985; p.vy *= .985;
        p.x += p.vx; p.y += p.vy;
        // wrap edges
        if (p.x < -10) p.x = ww + 10;
        if (p.x > ww + 10) p.x = -10;
        if (p.y < -10) p.y = hh + 10;
        if (p.y > hh + 10) p.y = -10;

        const close = d < 90;
        ctx.fillStyle = close && m === 'pull' ? 'rgba(184,233,54,.95)' :
                        m === 'push' ? 'rgba(248,113,113,.85)' : 'rgba(156,163,175,.7)';
        ctx.beginPath();
        ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
        ctx.fill();
      });
    };
    intervalId = setInterval(tick, 33);
    tick();
    window.addEventListener('resize', resize);
    return () => {
      clearInterval(intervalId);
      window.removeEventListener('resize', resize);
    };
  }, []);

  return (
    <div className="artifact-frame">
      <div className="artifact-card">
        <div className="artifact-head">
          <span>adoption · particle simulation</span>
          <span style={{textTransform: 'none', letterSpacing: 0, color: 'var(--fg-secondary)'}}>toggle the mode →</span>
          <span className="live">RUNNING</span>
        </div>
        <div style={{display: 'grid', gridTemplateColumns: '1fr 280px', minHeight: 360}}>
          <div style={{position: 'relative', background: 'var(--bg-primary)', borderRight: '1px solid var(--border-subtle)'}}>
            <canvas ref={canvasRef} style={{width: '100%', height: 360, display: 'block'}}/>
          </div>
          <div style={{padding: '24px 22px', background: 'var(--bg-secondary)', display: 'flex', flexDirection: 'column'}}>
            <Eyebrow>mode</Eyebrow>
            <div style={{display: 'flex', gap: 6, marginTop: 10}}>
              {[
                {k: 'pull', label: 'PULL', sub: 'demonstrated value'},
                {k: 'push', label: 'PUSH', sub: 'mandate · training'},
              ].map(o => (
                <button key={o.k} onClick={() => setMode(o.k)} style={{
                  flex: 1, textAlign: 'left',
                  padding: '12px 14px',
                  background: mode === o.k ? 'var(--bg-elevated)' : 'transparent',
                  border: `1px solid ${mode === o.k ? (o.k === 'pull' ? 'rgba(74,222,128,.5)' : 'rgba(248,113,113,.5)') : 'var(--border-subtle)'}`,
                  borderRadius: 8, cursor: 'pointer',
                  fontFamily: 'var(--font-mono)'
                }}>
                  <div style={{fontSize: 13, color: mode === o.k ? (o.k === 'pull' ? 'var(--brand-green)' : 'var(--danger-fg)') : 'var(--fg-secondary)', fontWeight: 600}}>{o.label}</div>
                  <div style={{fontSize: 11, color: 'var(--fg-muted)', marginTop: 4}}>{o.sub}</div>
                </button>
              ))}
            </div>

            <div style={{marginTop: 24, padding: 14, background: 'var(--bg-tertiary)', borderRadius: 8, border: '1px solid var(--border-subtle)'}}>
              {mode === 'pull' ? (
                <div style={{fontSize: 12.5, color: 'var(--fg-secondary)', lineHeight: 1.65}}>
                  <span style={{color: 'var(--brand-green)', fontFamily: 'var(--font-mono)'}}>▸ pull</span> &nbsp;Users gravitate to the platform because their pain gets reduced. Once they get value from it, they can't afford not to use it again.
                </div>
              ) : (
                <div style={{fontSize: 12.5, color: 'var(--fg-secondary)', lineHeight: 1.65}}>
                  <span style={{color: 'var(--danger-fg)', fontFamily: 'var(--font-mono)'}}>▸ push</span> &nbsp;Mandates and training programs scatter users away. They show up under duress, leave at the first chance, and never return.
                </div>
              )}
            </div>

            <div style={{marginTop: 'auto', paddingTop: 16, fontFamily: 'var(--font-mono)', fontSize: 10.5, color: 'var(--fg-muted)', lineHeight: 1.65}}>
              ▸ flywheel: value once → return → tell a colleague → return again
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};
window.PullVsPush = PullVsPush;

/* ---------- Principle 5 — pyramid bottom-up ------------------------------*/

const PrincipleFive = () => {
  return (
    <section style={{padding: '24px 0'}}>
      <Prose>
        <div style={{display: 'flex', alignItems: 'baseline', gap: 14, marginBottom: 18}}>
          <span className="principle-num">PRINCIPLE 05</span>
          <span style={{flex: 1, height: 1, background: 'var(--border-subtle)'}}/>
        </div>
        <h2>Individual before institutional. There is no other path.</h2>
        <p>Here's what Sivulka's framing leaves implicit. To build Institutional AI, you need people who can <strong>create value with AI</strong>, not just consume it.</p>
        <p>Where are those people going to come from?</p>
        <p>Only from Individual AI. From the mass of users who first felt the shift on their own work, who learned what AI is good at, what it's bad at, what they can offload, what they can't. That experience can't be lectured. It has to be lived.</p>
      </Prose>

      <PyramidBottomUp/>

      <Prose>
        <p>Without that bottom-up critical mass, your Institutional AI is empty architecture. You can't have agents that find signal in slop if no one in the company has ever drowned in slop themselves. You can't build deterministic, auditable institutional agents if your people haven't internalized what non-deterministic feels like and why it matters.</p>
        <p>This is also where the 60+ user-created skills in our system come from. Power users who started as everyday users. They built something for themselves, then realized it could scale. That's the seed of institutional intelligence, and you can't manufacture it. You can only create the conditions for it.</p>
        <p>The path to Institutional AI runs through Individual AI. There is no shortcut.</p>
        <hr/>
      </Prose>
    </section>
  );
};
window.PrincipleFive = PrincipleFive;

const PyramidBottomUp = () => {
  const [fill, setFill] = React.useState(0); // 0..1
  const [auto, setAuto] = React.useState(true);
  const [ref, seen] = useInView();
  React.useEffect(() => {
    if (!seen || !auto) return;
    let v = 0;
    const id = setInterval(() => {
      v = Math.min(1, v + 0.012);
      setFill(v);
      if (v >= 1) clearInterval(id);
    }, 30);
    return () => clearInterval(id);
  }, [seen, auto]);

  // 4-tier pyramid bottom→top: Individual users, Power users, Skills factory, Institutional agents
  const tiers = [
    {label: 'Individual users',       sub: '1,100 MAU · 55% of company',  threshold: 0.0,  color: 'var(--brand-lime)',      need: ''},
    {label: 'Power users',            sub: 'climb out of mass usage',     threshold: 0.35, color: 'var(--brand-green)',     need: 'Need: a base of Individual AI users.'},
    {label: 'Skills factory',         sub: '60+ user-built skills',       threshold: 0.65, color: 'var(--brand-green-deep)',need: 'Need: power users who hit reusable patterns.'},
    {label: 'Institutional agents',   sub: 'auditable · deterministic',   threshold: 0.88, color: 'var(--accent-fg)',       need: 'Need: skills that scaled into processes.'},
  ];

  return (
    <div ref={ref} className="artifact-frame">
      <div className="artifact-card">
        <div className="artifact-head">
          <span>pyramid · bottom-up only</span>
          <span style={{textTransform: 'none', letterSpacing: 0, color: 'var(--fg-secondary)'}}>can the top exist without the bottom?</span>
          <span className="live">FILLING</span>
        </div>
        <div style={{display: 'grid', gridTemplateColumns: '1fr 280px', minHeight: 380}}>
          <div style={{padding: '32px 28px', background: 'var(--bg-primary)', borderRight: '1px solid var(--border-subtle)', display: 'flex', alignItems: 'center', justifyContent: 'center'}}>
            <svg viewBox="0 0 400 280" style={{width: '100%', maxWidth: 460, height: 280}}>
              <defs>
                <clipPath id="pyramid-clip">
                  <polygon points="200,20 380,260 20,260"/>
                </clipPath>
              </defs>
              {/* outline */}
              <polygon points="200,20 380,260 20,260" fill="none" stroke="var(--border-default)" strokeWidth="1.5"/>

              {/* tiers as horizontal stripes inside clip */}
              <g clipPath="url(#pyramid-clip)">
                {tiers.map((t, i) => {
                  const y0 = 260 - (i + 1) / tiers.length * 240;
                  const y1 = 260 - (i) / tiers.length * 240;
                  const filled = fill > t.threshold;
                  const partial = Math.max(0, Math.min(1, (fill - t.threshold) / (1 / tiers.length)));
                  return (
                    <g key={t.label}>
                      <rect x="0" y={y0} width="400" height={y1 - y0}
                        fill={filled || partial > 0 ? t.color : 'transparent'}
                        opacity={partial * .85}
                        style={{transition: 'opacity .4s ease'}}
                      />
                      <line x1="0" y1={y0} x2="400" y2={y0} stroke="var(--border-default)" strokeWidth=".5" strokeDasharray="2 4"/>
                    </g>
                  );
                })}
              </g>
              {/* labels outside */}
              {tiers.map((t, i) => {
                const yMid = 260 - (i + .5) / tiers.length * 240;
                return (
                  <g key={'l' + t.label}>
                    <line x1={20 + ((260 - yMid) / 240) * 180 - 5}
                          y1={yMid}
                          x2={5 + ((260 - yMid) / 240) * 180 - 5}
                          y2={yMid}
                          stroke="var(--fg-muted)" strokeWidth=".5"/>
                    <text x={2 + ((260 - yMid) / 240) * 180 - 8}
                          y={yMid + 3}
                          fontFamily="var(--font-mono)" fontSize="9.5"
                          fill="var(--fg-secondary)"
                          textAnchor="end">{t.label}</text>
                  </g>
                );
              })}
            </svg>
          </div>

          <div style={{padding: '24px 22px', background: 'var(--bg-secondary)', display: 'flex', flexDirection: 'column'}}>
            <Eyebrow>fill order</Eyebrow>
            <div style={{marginTop: 12, display: 'flex', flexDirection: 'column', gap: 8}}>
              {tiers.slice().reverse().map((t, idx) => {
                const i = tiers.length - 1 - idx;
                const filled = fill > t.threshold;
                return (
                  <div key={t.label} style={{
                    padding: '10px 12px',
                    border: `1px solid ${filled ? 'rgba(74,222,128,.4)' : 'var(--border-subtle)'}`,
                    background: filled ? 'rgba(74,222,128,.06)' : 'var(--bg-tertiary)',
                    borderRadius: 6,
                    transition: 'all .25s ease'
                  }}>
                    <div style={{display: 'flex', alignItems: 'center', gap: 8, fontFamily: 'var(--font-mono)', fontSize: 12, color: filled ? 'var(--fg-primary)' : 'var(--fg-muted)'}}>
                      <span style={{width: 6, height: 6, borderRadius: '50%', background: filled ? 'var(--brand-green)' : 'var(--border-default)'}}/>
                      <span style={{fontWeight: 500}}>{t.label}</span>
                      <span style={{marginLeft: 'auto', fontSize: 10, color: filled ? 'var(--brand-green)' : 'var(--fg-muted)'}}>{filled ? 'reached' : 'locked'}</span>
                    </div>
                    {t.need && (
                      <div style={{marginTop: 4, marginLeft: 14, fontFamily: 'var(--font-mono)', fontSize: 10.5, color: filled ? 'var(--fg-muted)' : 'var(--danger-fg)', lineHeight: 1.5}}>
                        {t.need}
                      </div>
                    )}
                  </div>
                );
              })}
            </div>
            <div style={{marginTop: 'auto', paddingTop: 14, display: 'flex', gap: 8, alignItems: 'center'}}>
              <button onClick={() => { setFill(0); setAuto(true); }} style={{
                padding: '7px 12px', background: 'var(--bg-tertiary)',
                border: '1px solid var(--border-default)', borderRadius: 6,
                color: 'var(--fg-secondary)', fontFamily: 'var(--font-mono)', fontSize: 11.5, cursor: 'pointer'
              }}>↺ refill</button>
              <button onClick={() => { setAuto(false); setFill(0.95); }} style={{
                padding: '7px 12px', background: 'var(--bg-tertiary)',
                border: '1px solid var(--border-default)', borderRadius: 6,
                color: 'var(--fg-secondary)', fontFamily: 'var(--font-mono)', fontSize: 11.5, cursor: 'pointer'
              }}>try top-down →</button>
            </div>
            {!auto && fill > .9 && (
              <div style={{marginTop: 10, padding: 10, background: 'rgba(248,113,113,.08)', border: '1px solid rgba(248,113,113,.35)', borderRadius: 6, fontFamily: 'var(--font-mono)', fontSize: 10.5, color: 'var(--danger-fg)', lineHeight: 1.5}}>
                error: cannot fill apex without supporting tiers — that's the point.
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};
window.PyramidBottomUp = PyramidBottomUp;
