/* ===========================================================================
   ArticlePrinciples.jsx — Principles 1-5 with their interactive artifacts
   ===========================================================================*/

/* ---------- Principle 1: Don't go deep. Stay simple. -----------------------*/

const PrincipleOne = () => {
  return (
    <section style={{padding: '24px 0'}}>
      <Prose>
        <div style={{display: 'flex', alignItems: 'baseline', gap: 14, marginBottom: 18}}>
          <span className="principle-num">PRINCIPLE 01</span>
          <span style={{flex: 1, height: 1, background: 'var(--border-subtle)'}}/>
        </div>
        <h2>Don't go deep. Stay simple.</h2>
        <p>Yesterday Qwen3.5. Today Qwen3.6. Tomorrow something else. The temptation is to go deep: pick a model, fine-tune it, build complex orchestration around its quirks. That's how you get stuck.</p>
        <p>This isn't only about models. It applies to every layer of your stack: framework, vector DB, orchestration, agent runtime. None of these are durable choices in 2026. The half-life of "best-in-class" is about three months.</p>
      </Prose>

      <StackHalfLife/>

      <Prose>
        <p>So build with tools that are <strong>understandable, manageable, and fault-tolerant</strong>. Two simple tests for whether you've gone too far: a new teammate can't reason about a component on their first day, or something breaks at 11 PM and you can't debug it without paging a senior engineer.</p>
        <p>"Simple" doesn't mean stripped-down. It means the right capability, with predictable failure modes and operational headroom. We knew on day one we'd need to support 2,000 people, so the portal had to scale cleanly to that load, not cleverly. It needed proven deployments at 10x our user count so we'd know where the cliff was before we hit it. And it had to support MCP out of the box, because <strong>AI without access to your internal systems is just a chat</strong>.</p>
        <p>We picked OpenWebUI. Johannes Gutenberg University Mainz was already running it for 30,000+ students and 5,000+ employees. That validation mattered more than feature lists. At the time of the decision it was the best option for our requirements. As far as I can tell, it still is.</p>
        <p>When something better comes along, we swap. The skills, the data, the user habits stay.</p>
        <hr/>
      </Prose>
    </section>
  );
};
window.PrincipleOne = PrincipleOne;

/* The half-life slider: drag a "month" cursor; deep-bet rows decay, simple rows survive */
const StackHalfLife = () => {
  const [m, setM] = React.useState(0); // months elapsed 0..12
  const layers = [
    {name: 'Model',       deep: 'fine-tuned Qwen3.5 with custom RLHF',  simple: 'any tool-calling model · pluggable', life: 2},
    {name: 'Framework',   deep: 'LangGraph + custom orchestrator',      simple: 'plain functions · plain MCP',         life: 4},
    {name: 'Vector DB',   deep: 'sharded Weaviate cluster',             simple: 'pgvector in our existing Postgres',   life: 5},
    {name: 'Agent runtime', deep: 'Autogen + bespoke memory layer',     simple: 'one Docker container per chat',       life: 3},
    {name: 'Portal',      deep: 'home-rolled chat UI',                  simple: 'OpenWebUI (proven at 30k+)',          life: 12},
  ];
  return (
    <div className="artifact-frame">
      <div className="artifact-card">
        <div className="artifact-head">
          <span>stack half-life simulator</span>
          <span style={{textTransform: 'none', letterSpacing: 0, color: 'var(--fg-secondary)'}}>drag the month cursor →</span>
          <span className="live">SIMULATING</span>
        </div>

        <div style={{padding: '20px 24px 16px', background: 'var(--bg-primary)'}}>
          <div style={{display: 'flex', alignItems: 'center', gap: 14, marginBottom: 6, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-muted)'}}>
            <span>month {m === 0 ? '0 (today)' : `+${m}`}</span>
            <input
              type="range" min={0} max={12} step={1} value={m}
              onChange={(e) => setM(+e.target.value)}
              className="range"
              style={{flex: 1, maxWidth: 380}}
            />
            <span>{m === 12 ? 'a year later' : ''}</span>
          </div>
          <div style={{display: 'flex', justifyContent: 'space-between', fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--fg-muted)', maxWidth: 380, marginLeft: 'calc(0px + 80px)'}}>
            <span>0</span><span>3</span><span>6</span><span>9</span><span>12</span>
          </div>
        </div>

        <div style={{padding: 0}}>
          <div style={{
            display: 'grid', gridTemplateColumns: '180px 1fr 1fr',
            padding: '12px 24px', borderTop: '1px solid var(--border-subtle)', borderBottom: '1px solid var(--border-subtle)',
            background: 'var(--bg-tertiary)',
            fontFamily: 'var(--font-mono)', fontSize: 10.5, textTransform: 'uppercase', letterSpacing: '.1em', color: 'var(--fg-muted)'
          }}>
            <div>layer</div>
            <div style={{color: 'var(--danger-fg)'}}>deep bet · custom</div>
            <div style={{color: 'var(--brand-green)'}}>simple · understandable</div>
          </div>
          {layers.map((L, i) => {
            const decay = Math.max(0, 1 - m / Math.max(L.life, 1));
            const dead = m > L.life;
            return (
              <div key={L.name} style={{
                display: 'grid', gridTemplateColumns: '180px 1fr 1fr',
                padding: '14px 24px',
                borderBottom: i < layers.length - 1 ? '1px solid var(--border-subtle)' : 'none',
                alignItems: 'center'
              }}>
                <div style={{fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-secondary)'}}>{L.name}</div>
                <div style={{
                  display: 'flex', alignItems: 'center', gap: 10,
                  padding: '8px 12px', marginRight: 14,
                  background: dead ? 'rgba(248,113,113,.05)' : 'var(--bg-secondary)',
                  border: `1px solid ${dead ? 'rgba(248,113,113,.35)' : 'var(--border-subtle)'}`,
                  borderRadius: 6,
                  opacity: dead ? .55 : decay * .5 + .5,
                  textDecoration: dead ? 'line-through' : 'none',
                  transition: 'opacity .25s, border-color .25s, background .25s'
                }}>
                  <span style={{
                    width: 8, height: 8, borderRadius: 2,
                    background: dead ? 'var(--danger-fg)' : `rgba(248,113,113,${.4 + .6 * (1 - decay)})`
                  }}/>
                  <span style={{fontFamily: 'var(--font-mono)', fontSize: 12, color: dead ? 'var(--fg-muted)' : 'var(--fg-secondary)'}}>{L.deep}</span>
                  {dead && <span style={{marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--danger-fg)'}}>obsolete</span>}
                </div>
                <div style={{
                  display: 'flex', alignItems: 'center', gap: 10,
                  padding: '8px 12px',
                  background: 'rgba(74,222,128,.06)',
                  border: '1px solid rgba(74,222,128,.25)',
                  borderRadius: 6
                }}>
                  <span style={{width: 8, height: 8, borderRadius: 2, background: 'var(--brand-green)', boxShadow: '0 0 6px rgba(74,222,128,.5)'}}/>
                  <span style={{fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-primary)'}}>{L.simple}</span>
                  <span style={{marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--brand-green)'}}>still here</span>
                </div>
              </div>
            );
          })}
        </div>
        <div style={{padding: '12px 24px', borderTop: '1px solid var(--border-subtle)', background: 'var(--bg-tertiary)', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-muted)'}}>
          ▸ when a deep bet dies, you rewrite. when a simple layer is replaced, the skills, data, and user habits stay.
        </div>
      </div>
    </div>
  );
};
window.StackHalfLife = StackHalfLife;

/* ---------- Principle 2: Build the ecosystem, not the product. ------------*/

const PrincipleTwo = () => {
  return (
    <section style={{padding: '24px 0'}}>
      <Prose>
        <div style={{display: 'flex', alignItems: 'baseline', gap: 14, marginBottom: 18}}>
          <span className="principle-num">PRINCIPLE 02</span>
          <span style={{flex: 1, height: 1, background: 'var(--border-subtle)'}}/>
        </div>
        <h2>Build the ecosystem, not the product.</h2>
        <p>Your user touches your AI in many places: the portal, the team chat, the IDE, the cloud workspace, the bot in a messenger. Each of those is a surface. Most companies build them as separate products, and that's the mistake.</p>
        <p>The skills they build, the MCP connectors they configure, the memory they accumulate, their context. <strong>All of it should follow them across every surface.</strong> A skill made in the portal should run in the chat bot. A connection set up in the cloud workspace should work for the autonomous agent at night. Memory of one conversation should inform the next, regardless of where it happens.</p>
      </Prose>

      <EcosystemMap/>

      <Prose>
        <p>This compounds. Each new surface multiplies the value of every existing skill, and each new skill makes every surface more useful. Without that, you end up with a portfolio of disconnected products and you wonder why nobody uses them.</p>
        <p>There's also a simple math problem here. If I went and built a great IDP pipeline myself, I might save the company $250K a year. That's a real number. But I'm one engineer. I cannot personally build the thousand small workflows that 1,100 people need every day. Nobody can.</p>
        <p>The ecosystem can. Each user automates the friction that's specific to their job, the kind no centralized team would ever bother to solve. As those workflows accumulate, you get the foundation for the next layer: coordination across teams, signal for leaders, focused management of what people are doing with AI.</p>
        <p>That's how Coordination, Sivulka's first pillar, actually emerges in practice. Not imposed from the top, but grown from an ecosystem with enough usage to coordinate.</p>
        <p>The unit of work is no longer "the chatbot" or "the IDE plugin." It's the user's accumulated capability, and your job is to make sure they carry it everywhere.</p>
        <hr/>
      </Prose>
    </section>
  );
};
window.PrincipleTwo = PrincipleTwo;

/* Compounding-leverage inventory: a real skill (counterparty check) accrues
   invocations across surfaces and users; the math compounds in real time. */
const EcosystemMap = () => {
  const SURFACES = ['Portal', 'Slack bot', 'IDE', 'Cloud workspace', 'Night agent', 'Web embed'];
  const USERS    = ['j.miller · risk',   'd.cohen · sales',     'm.parker · legal',
                    'e.johnson · ops',   'k.reed · finance',    'a.walker · audit',
                    'l.foster · ops',    's.nelson · sales',    'r.bailey · legal',
                    'n.greene · finance'];
  const ACTIONS  = [
    'pulled INN from invoice',
    'fetched company card · gov registry',
    'crossed with internal blacklist',
    'checked litigation history',
    'pulled bank statement summary',
    'flagged sanctions overlap',
    'wrote 1-page risk memo',
    'attached supporting docs',
    'queued for night re-check',
    'exported PDF report',
  ];

  const [events, setEvents] = React.useState([]);  // newest first
  const [tick, setTick] = React.useState(0);

  React.useEffect(() => {
    // seed a couple so the panel isn't empty
    const seed = Array.from({length: 4}, (_, i) => ({
      id: -i - 1,
      t: '—',
      surface: SURFACES[i % SURFACES.length],
      user: USERS[i % USERS.length],
      action: ACTIONS[i % ACTIONS.length],
    }));
    setEvents(seed);

    let n = 0;
    const id = setInterval(() => {
      n++;
      const now = new Date();
      const t = `${String(now.getHours()).padStart(2,'0')}:${String(now.getMinutes()).padStart(2,'0')}:${String(now.getSeconds()).padStart(2,'0')}`;
      const ev = {
        id: n,
        t,
        surface: SURFACES[Math.floor(Math.random() * SURFACES.length)],
        user:    USERS[Math.floor(Math.random() * USERS.length)],
        action:  ACTIONS[Math.floor(Math.random() * ACTIONS.length)],
      };
      setEvents(prev => [ev, ...prev].slice(0, 14));
      setTick(n);
    }, 1100);
    return () => clearInterval(id);
  }, []);

  // compounding math (animated)
  const skills    = 1;
  const surfaces  = 6;
  const users     = Math.min(1100, 40 + tick * 28);
  const perDay    = Math.min(18, 4 + tick * 0.35);
  const leverage  = Math.round(skills * surfaces * users * perDay);

  return (
    <div className="artifact-frame">
      <div className="artifact-card">
        <div className="artifact-head">
          <span>skill.counterparty_check · live invocation log</span>
          <span style={{textTransform: 'none', letterSpacing: 0, color: 'var(--fg-secondary)'}}>
            one skill · accruing across surfaces & users
          </span>
          <span className="live">RECORDING</span>
        </div>

        <div style={{display: 'grid', gridTemplateColumns: 'minmax(0,1.25fr) minmax(0,1fr)', gap: 0, minHeight: 460}}>

          {/* LEFT — inventory log */}
          <div style={{background: 'var(--bg-primary)', borderRight: '1px solid var(--border-subtle)', display: 'flex', flexDirection: 'column', minWidth: 0}}>
            <div style={{
              display: 'grid', gridTemplateColumns: '76px 130px 150px minmax(0,1fr)',
              padding: '12px 22px',
              background: 'var(--bg-tertiary)',
              borderBottom: '1px solid var(--border-subtle)',
              fontFamily: 'var(--font-mono)', fontSize: 10.5, textTransform: 'uppercase', letterSpacing: '.1em', color: 'var(--fg-muted)'
            }}>
              <div>time</div>
              <div>surface</div>
              <div>user · role</div>
              <div>what the skill did</div>
            </div>
            <div style={{flex: 1, overflow: 'hidden', position: 'relative'}}>
              {events.map((e, i) => (
                <div key={e.id} style={{
                  display: 'grid', gridTemplateColumns: '76px 130px 150px minmax(0,1fr)',
                  alignItems: 'center', gap: 0,
                  padding: '11px 22px',
                  borderBottom: '1px solid var(--border-subtle)',
                  background: i === 0 ? 'rgba(74,222,128,.06)' : 'transparent',
                  fontFamily: 'var(--font-mono)', fontSize: 12,
                  animation: i === 0 ? 'slideIn .35s ease' : 'none',
                  opacity: Math.max(.35, 1 - i * 0.06),
                  transition: 'opacity .3s'
                }}>
                  <div style={{color: 'var(--fg-muted)', fontSize: 11}}>{e.t}</div>
                  <div style={{
                    color: 'var(--fg-secondary)',
                    display: 'inline-flex', alignItems: 'center', gap: 6, minWidth: 0
                  }}>
                    <span style={{
                      width: 6, height: 6, borderRadius: 2,
                      background: i === 0 ? 'var(--brand-green)' : 'var(--brand-green-deep)',
                      flexShrink: 0,
                      boxShadow: i === 0 ? '0 0 6px rgba(74,222,128,.6)' : 'none'
                    }}/>
                    <span style={{overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}}>{e.surface}</span>
                  </div>
                  <div style={{color: 'var(--fg-secondary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}}>{e.user}</div>
                  <div style={{color: 'var(--fg-primary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}}>{e.action}</div>
                </div>
              ))}
            </div>
          </div>

          {/* RIGHT — compounding math */}
          <div style={{padding: '24px 26px', background: 'var(--bg-secondary)', display: 'flex', flexDirection: 'column', minWidth: 0}}>
            <Eyebrow>compounding leverage</Eyebrow>

            <div style={{
              marginTop: 16,
              fontFamily: 'var(--font-mono)', fontSize: 13,
              color: 'var(--fg-secondary)',
              display: 'flex', flexDirection: 'column', gap: 10
            }}>
              <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12}}>
                <span style={{color: 'var(--fg-muted)', flex: 1, minWidth: 0}}>skills</span>
                <span style={{color: 'var(--fg-primary)', flexShrink: 0}}>{skills}</span>
              </div>
              <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12}}>
                <span style={{color: 'var(--fg-muted)', flex: 1, minWidth: 0}}>× surfaces</span>
                <span style={{color: 'var(--fg-primary)', flexShrink: 0}}>{surfaces}</span>
              </div>
              <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12}}>
                <span style={{color: 'var(--fg-muted)', flex: 1, minWidth: 0}}>× users reached</span>
                <span style={{color: 'var(--fg-primary)', flexShrink: 0}}>{users.toLocaleString()}</span>
              </div>
              <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12}}>
                <span style={{color: 'var(--fg-muted)', flex: 1, minWidth: 0, fontSize: 12}}>× invocations / user / day</span>
                <span style={{color: 'var(--fg-primary)', flexShrink: 0}}>{perDay.toFixed(1)}</span>
              </div>
              <div style={{height: 1, background: 'var(--border-subtle)', margin: '4px 0'}}/>
              <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12}}>
                <span style={{color: 'var(--fg-muted)', flex: 1, minWidth: 0}}>= work / day</span>
                <span style={{
                  color: 'var(--brand-green)', flexShrink: 0,
                  fontSize: 26, fontWeight: 600, letterSpacing: '-.02em', lineHeight: 1
                }}>{leverage.toLocaleString()}</span>
              </div>
            </div>

            <div style={{
              marginTop: 22, padding: '14px 16px',
              background: 'var(--bg-elevated)',
              border: '1px solid var(--border-subtle)',
              borderRadius: 8,
              fontFamily: 'var(--font-mono)', fontSize: 11.5, color: 'var(--fg-secondary)', lineHeight: 1.7
            }}>
              <span style={{color: 'var(--brand-green)'}}>▸ </span>
              one engineer building the same workflow as a one-off:<br/>
              <span style={{color: 'var(--fg-primary)'}}>~$250K / yr saved</span>, ceiling.
              <div style={{height: 8}}/>
              <span style={{color: 'var(--brand-green)'}}>▸ </span>
              same workflow shipped as a skill on the ecosystem:<br/>
              <span style={{color: 'var(--fg-primary)'}}>{leverage.toLocaleString()} runs / day · no ceiling.</span>
            </div>

            <div style={{marginTop: 'auto', paddingTop: 18, fontFamily: 'var(--font-mono)', fontSize: 10.5, color: 'var(--fg-muted)', lineHeight: 1.65}}>
              ▸ a skill made in the portal runs in the chat bot. a connection set up in the cloud workspace works for the night agent. each new surface multiplies every existing skill.
            </div>
          </div>
        </div>

        <div style={{
          padding: '10px 22px',
          borderTop: '1px solid var(--border-subtle)',
          background: 'var(--bg-tertiary)',
          fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--fg-muted)',
          textTransform: 'uppercase', letterSpacing: '.12em',
          display: 'flex', alignItems: 'center', gap: 8
        }}>
          <span style={{color: 'var(--brand-green)'}}>◇</span>
          <span>illustrative · synthetic data · the math is real, the log is generated for this article</span>
        </div>
      </div>
    </div>
  );
};
window.EcosystemMap = EcosystemMap;

/* ---------- Principle 3: Make logging in the hardest step. -----------------*/

const PrincipleThree = () => {
  return (
    <section style={{padding: '24px 0'}}>
      <Prose>
        <div style={{display: 'flex', alignItems: 'baseline', gap: 14, marginBottom: 18}}>
          <span className="principle-num">PRINCIPLE 03</span>
          <span style={{flex: 1, height: 1, background: 'var(--border-subtle)'}}/>
        </div>
        <h2>Make logging in the hardest step.</h2>
        <p>Be honest with yourself about your users. They struggle with passwords. They file helpdesk tickets when their VPN reconnects. Most of them have never opened a terminal in their life.</p>
        <p>Now imagine telling them to install Claude Code. Install Node.js first. Set up an MCP server. Configure their API keys. Edit a JSON file. Restart, get the path wrong, debug.</p>
        <p>You've already lost.</p>
      </Prose>

      <FloorCeiling/>

      <Prose>
        <p>The barrier to entry isn't a feature on your roadmap. It <strong>is</strong> the feature. If a user can log in and immediately do something useful (read a document, draft an email, generate a report, ask their data a question), you've won. Everything else is power-user territory.</p>
        <p>For power users, give them a ceiling: a cloud workspace with Claude Code pre-installed, MCPs auto-mounted, skills available, no setup. They go deep on their own terms. They don't need to drag everyone else through their toolchain.</p>
        <p>Low floor. High ceiling. <strong>No middle for people to get stuck in.</strong></p>
        <hr/>
      </Prose>
    </section>
  );
};
window.PrincipleThree = PrincipleThree;

/* The two-path interactive: DIY install vs Coder + custom template */
const FloorCeiling = () => {
  const [path, setPath] = React.useState('template'); // 'diy' | 'template'
  const [step, setStep] = React.useState(0);
  const [ok, setOk] = React.useState(false);

  const diy = [
    {t: 'Install Node.js · Python · uv',     ok: true},
    {t: 'Install Claude Code',               ok: true},
    {t: 'Get an API key, set env vars',      ok: true},
    {t: 'Edit ~/.claude/config.json',        fail: 'JSON syntax error'},
    {t: 'Stand up your own MCP servers',     fail: 'connection refused · port 7777'},
    {t: 'Wire up secrets, SSO, gateway',     fail: 'expired token · contact IT'},
    {t: 'Hope it restarts cleanly tomorrow', fail: ''},
  ];
  const template = [
    {t: 'Open Coder · pick custom template', ok: true},
    {t: 'Workspace boots · Claude Code ready', ok: true},
    {t: 'LiteLLM gateway · already wired',     ok: true},
    {t: 'Internal MCP servers · auto-mounted', ok: true},
    {t: 'Skills library · already mounted',    ok: true},
    {t: '✓ consuming in ~60 sec',              ok: true, done: true},
  ];
  const list = path === 'diy' ? diy : template;

  React.useEffect(() => {
    setStep(0); setOk(false);
    let i = 0;
    const id = setInterval(() => {
      i++;
      if (i >= list.length) {
        clearInterval(id);
        setOk(path === 'template');
        return;
      }
      setStep(i);
    }, 750);
    return () => clearInterval(id);
  }, [path]);

  return (
    <div className="artifact-frame">
      <div className="artifact-card">
        <div className="artifact-head">
          <span>same user · two onboarding paths</span>
          <span style={{textTransform: 'none', letterSpacing: 0, color: 'var(--fg-secondary)'}}>what we shipped vs. what we avoided</span>
          <span className="live">RUNNING</span>
        </div>

        {/* path selector */}
        <div style={{display: 'flex', gap: 0, padding: '14px 24px', background: 'var(--bg-tertiary)', borderBottom: '1px solid var(--border-subtle)'}}>
          {[
            {k: 'diy',      label: 'DIY install · Claude Code + your own MCPs'},
            {k: 'template', label: 'Coder · custom template (skills · LiteLLM · MCPs pre-wired)'}
          ].map(o => (
            <button key={o.k} onClick={() => setPath(o.k)} style={{
              padding: '8px 14px', marginRight: 8,
              background: path === o.k ? 'var(--bg-elevated)' : 'transparent',
              border: `1px solid ${path === o.k ? 'var(--border-default)' : 'transparent'}`,
              borderRadius: 6, fontFamily: 'var(--font-mono)', fontSize: 12,
              color: path === o.k ? 'var(--fg-primary)' : 'var(--fg-muted)',
              cursor: 'pointer'
            }}>{o.label}</button>
          ))}
        </div>

        <div style={{display: 'grid', gridTemplateColumns: '1.2fr 1fr', minHeight: 360}}>
          {/* staircase */}
          <div style={{padding: '24px 28px', background: 'var(--bg-primary)', borderRight: '1px solid var(--border-subtle)'}}>
            <Eyebrow>steps to first useful action</Eyebrow>
            <div style={{marginTop: 16, display: 'flex', flexDirection: 'column', gap: 8}}>
              {list.map((s, i) => {
                const active = i === step;
                const reached = i < step || (i === step && (s.ok || s.done));
                const failed = active && s.fail !== undefined;
                return (
                  <div key={i} style={{
                    display: 'flex', alignItems: 'center', gap: 12,
                    padding: '10px 12px', borderRadius: 6,
                    background: failed ? 'rgba(248,113,113,.08)' :
                                active ? 'rgba(74,222,128,.08)' :
                                reached ? 'transparent' : 'transparent',
                    border: `1px solid ${failed ? 'rgba(248,113,113,.4)' :
                                          active ? 'rgba(74,222,128,.35)' :
                                          'var(--border-subtle)'}`,
                    opacity: i > step ? .35 : 1,
                    transition: 'all .3s ease'
                  }}>
                    <span style={{
                      width: 22, height: 22, borderRadius: 4,
                      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                      background: failed ? 'var(--danger-fg)' :
                                  reached ? 'var(--brand-green)' :
                                  'var(--bg-tertiary)',
                      color: failed || reached ? '#0C0F1A' : 'var(--fg-muted)',
                      fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 600
                    }}>
                      {failed ? '!' : reached ? '✓' : i + 1}
                    </span>
                    <span style={{flex: 1, fontFamily: 'var(--font-mono)', fontSize: 13, color: failed ? 'var(--danger-fg)' : reached ? 'var(--fg-primary)' : 'var(--fg-secondary)'}}>
                      {s.t}
                    </span>
                    {failed && <span style={{fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--danger-fg)'}}>{s.fail || 'stuck'}</span>}
                  </div>
                );
              })}
            </div>
          </div>

          {/* outcome */}
          <div style={{padding: '24px 28px', background: 'var(--bg-secondary)', display: 'flex', flexDirection: 'column'}}>
            <Eyebrow>outcome</Eyebrow>
            {path === 'diy' ? (
              <div style={{marginTop: 16, padding: '20px 22px', background: 'rgba(248,113,113,.08)', border: '1px solid rgba(248,113,113,.35)', borderRadius: 10}}>
                <div style={{fontSize: 16, fontWeight: 600, color: 'var(--danger-fg)', letterSpacing: '-.01em'}}>Stuck assembling a setup.</div>
                <div style={{fontSize: 13.5, color: 'var(--fg-secondary)', marginTop: 8, lineHeight: 1.55}}>
                  Hours spent on plumbing before the first useful prompt. Most users won't make it past step 4. The ones who do still own a fragile config.
                </div>
                <div style={{marginTop: 16, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-muted)', lineHeight: 1.7}}>
                  → time spent on plumbing: <span style={{color: 'var(--danger-fg)'}}>hours</span><br/>
                  → time consuming AI: <span style={{color: 'var(--danger-fg)'}}>~0</span><br/>
                  → drift across users: <span style={{color: 'var(--danger-fg)'}}>high</span>
                </div>
              </div>
            ) : (
              <div style={{marginTop: 16, padding: '20px 22px', background: 'rgba(74,222,128,.08)', border: '1px solid rgba(74,222,128,.4)', borderRadius: 10, opacity: ok ? 1 : .7, transition: 'opacity .3s'}}>
                <div style={{fontSize: 16, fontWeight: 600, color: 'var(--brand-green)', letterSpacing: '-.01em'}}>Consuming in ~60 seconds.</div>
                <div style={{fontSize: 13.5, color: 'var(--fg-secondary)', marginTop: 8, lineHeight: 1.55}}>
                  Pick a template. The workspace boots with the gateway, MCPs and skills already wired. They start using AI instead of installing it.
                </div>
                <div style={{marginTop: 16, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-muted)', lineHeight: 1.7}}>
                  → time spent on plumbing: <span style={{color: 'var(--brand-green)'}}>~0</span><br/>
                  → time to first useful prompt: <span style={{color: 'var(--brand-green)'}}>~60 sec</span><br/>
                  → drift across users: <span style={{color: 'var(--brand-green)'}}>none — same template</span>
                </div>
              </div>
            )}

            <div style={{marginTop: 'auto', paddingTop: 18, fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-muted)', lineHeight: 1.65}}>
              <div><span style={{color: 'var(--brand-green)'}}>low floor</span> · open template → consuming</div>
              <div><span style={{color: 'var(--brand-green)'}}>high ceiling</span> · Claude Code, full toolchain in the same workspace</div>
              <div><span style={{color: 'var(--brand-lime)'}}>no middle</span> · nothing to assemble by hand</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};
window.FloorCeiling = FloorCeiling;
