// How It Works — long-scroll explainer

const { useState: useStateHIW, useEffect: useEffectHIW, useRef: useRefHIW } = React;

const PageHero = () => (
  <section className="page-hero" data-screen-label="01 Quote">
    <ParticleField density={60} color="125, 255, 196" baseAlpha={0.35} speed={0.04}/>
    <div className="container">
      <div className="page-eyebrow"><span className="bar"></span>HOW IT WORKS · CHAPTER 0</div>
      <h1 className="t-h1" style={{ maxWidth: 1100, marginBottom: 32 }}>
        Embodied cognition<br/>is not a metaphor.
      </h1>
      <p className="lede">
        Forty years of cognitive science says the same thing: <b style={{ color: 'var(--ink-0)' }}>you remember what you can stand inside.</b> Until recently, building a place was prohibitively expensive. Then Marble arrived. The rest of this page explains, in five short chapters, exactly how a sentence from a teacher becomes an accredited grade for a student.
      </p>
    </div>
  </section>
);

// Chapter I — Splat vs Mesh diagram
const SplatVsMesh = () => {
  const meshTris = [];
  const seed = (n) => { let s = n; return () => { s = (s * 9301 + 49297) % 233280; return s / 233280; }; };
  const r1 = seed(7);
  for (let i = 0; i < 40; i++) {
    const a = r1() * Math.PI * 2, b = r1() * Math.PI * 2, c = r1() * Math.PI * 2;
    const cx = 50, cy = 50, R = 32;
    meshTris.push([
      [cx + Math.cos(a) * R, cy + Math.sin(a) * R],
      [cx + Math.cos(b) * R * 0.7, cy + Math.sin(b) * R * 0.7],
      [cx + Math.cos(c) * R * 0.55, cy + Math.sin(c) * R * 0.55],
    ]);
  }
  const r2 = seed(31);
  const splatPts = [];
  for (let i = 0; i < 280; i++) {
    const t = r2() * Math.PI * 2, rr = r2() * 32 + 4;
    splatPts.push({
      x: 50 + Math.cos(t) * rr + (r2() - 0.5) * 8,
      y: 50 + Math.sin(t) * rr + (r2() - 0.5) * 8,
      r: r2() * 1.3 + 0.3,
      o: r2() * 0.7 + 0.3,
      c: r2() > 0.85 ? '#7DFFC4' : '#E5E5EA',
    });
  }
  return (
    <div className="splat-vs-mesh">
      <div className="svm-cell">
        <div className="svm-label">LEGACY · POLYGON MESH</div>
        <h4 className="svm-title">Triangles.</h4>
        <p className="svm-desc">A 3D scene built from triangulated surfaces. Edges are sharp. Lighting must be baked or simulated. Built by humans. Slowly.</p>
        <div className="svm-diag">
          <svg viewBox="0 0 100 100" style={{ width: '100%', height: '100%' }}>
            {meshTris.map((t, i) => (
              <polygon key={i} points={t.map(p => p.join(',')).join(' ')} fill="none" stroke="rgba(255,255,255,0.18)" strokeWidth="0.2"/>
            ))}
          </svg>
        </div>
        <div className="svm-stat">
          <span><b>120K</b> POLYGONS</span>
          <span><b>~3 WEEKS</b> TO BUILD</span>
          <span>UNREAL · MAYA</span>
        </div>
      </div>
      <div className="svm-cell">
        <div className="svm-label">MARBLE · GAUSSIAN SPLATTING</div>
        <h4 className="svm-title">Point cloud.</h4>
        <p className="svm-desc">Millions of 3D Gaussians — fuzzy ellipsoids with color, opacity, and view-dependent shading. Lit by the world they were sampled from. Generated, not built.</p>
        <div className="svm-diag">
          <svg viewBox="0 0 100 100" style={{ width: '100%', height: '100%' }}>
            {splatPts.map((p, i) => (
              <circle key={i} cx={p.x} cy={p.y} r={p.r * 0.4} fill={p.c} opacity={p.o}/>
            ))}
          </svg>
        </div>
        <div className="svm-stat">
          <span><b>4.2M</b> SPLATS</span>
          <span><b>~5 MIN</b> TO GENERATE</span>
          <span>SPARK.JS RUNTIME</span>
        </div>
      </div>
    </div>
  );
};

// Chapter II — Prompt input that "generates" a world
const PromptToWorld = () => {
  const [value, setValue] = useStateHIW('');
  const [state, setState] = useStateHIW('idle');
  const [progress, setProgress] = useStateHIW(0);
  const [scheme, setScheme] = useStateHIW(null);

  const suggestions = [
    { p: 'Walk through the Roman Forum, 79 AD', s: 'ancient' },
    { p: 'Stand inside a mitochondrion at scale', s: 'cell' },
    { p: 'Visit a Mars colony at sunrise', s: 'space' },
    { p: 'Library of Alexandria, before the fire', s: 'story' },
  ];

  const generate = (p, s) => {
    setValue(p);
    setState('generating');
    setProgress(0);
    setScheme(null);
    const dur = 3200;
    const start = performance.now();
    const tick = () => {
      const t = (performance.now() - start) / dur;
      if (t >= 1) {
        setProgress(100);
        setScheme(s || 'ancient');
        setState('done');
      } else {
        setProgress(Math.round(t * 100));
        requestAnimationFrame(tick);
      }
    };
    requestAnimationFrame(tick);
  };

  const onSubmit = (e) => {
    e.preventDefault();
    if (!value.trim() || state === 'generating') return;
    const match = suggestions.find(s => s.p.toLowerCase() === value.trim().toLowerCase());
    generate(value, match ? match.s : 'space');
  };

  return (
    <div className="prompt-stage">
      <form className="prompt-input" onSubmit={onSubmit}>
        <span style={{ color: 'var(--accent)' }}>{'>'}</span>
        <input
          type="text"
          placeholder="Describe a place. e.g. 'A coral reef at 30m depth, dawn.'"
          value={value}
          onChange={(e) => setValue(e.target.value)}
          disabled={state === 'generating'}
        />
        <button type="submit" disabled={!value.trim() || state === 'generating'}>
          {state === 'generating' ? 'GENERATING…' : 'GENERATE'}
        </button>
      </form>
      <div className="prompt-suggestions">
        {suggestions.map((s, i) => (
          <button key={i} onClick={() => generate(s.p, s.s)} disabled={state === 'generating'}>{s.p}</button>
        ))}
      </div>
      <div className="prompt-output">
        {state === 'generating' && (
          <div className="prompt-progress" style={{ width: `${progress}%` }} />
        )}
        {state === 'idle' && (
          <div className="prompt-empty">// world will render here</div>
        )}
        {state !== 'idle' && (
          <div style={{ position: 'absolute', inset: 0, opacity: state === 'done' ? 1 : 0.4, transition: 'opacity .5s ease' }}>
            <SplatThumb scheme={scheme || 'space'} density={120}/>
          </div>
        )}
        {state === 'generating' && (
          <div className="prompt-status">
            <span>RENDERING · {progress}%</span>
            <span>{Math.round(progress * 42000)} splats</span>
          </div>
        )}
        {state === 'done' && (
          <div className="prompt-status">
            <span><span style={{ display: 'inline-block', width: 6, height: 6, borderRadius: '50%', background: 'var(--accent)', marginRight: 6, boxShadow: '0 0 8px var(--accent)' }}></span>WORLD READY · 4.2M SPLATS · 3.1s</span>
            <span>marble://world.gen.{Math.floor(Math.random()*9000+1000)}</span>
          </div>
        )}
      </div>
    </div>
  );
};

// Chapter III — Student device mockup
const StudentDevice = () => (
  <div className="device-mock">
    <div className="device-bezel">
      <div className="device-screen">
        <SplatThumb scheme="cell" density={150} label="WORLD · INSIDE THE CELL"/>
      </div>
      <div className="device-ui">
        <div className="device-topbar">
          <div className="device-tag">
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
              <span style={{ width: 6, height: 6, borderRadius: '50%', background: '#7DFFC4', boxShadow: '0 0 6px #7DFFC4' }}></span>
              MIA · GRADE 10
            </span>
            <span>BIO · UNIT 4 · DAY 2</span>
          </div>
          <div className="device-tag">14:08</div>
        </div>
        <div className="device-actionbar">
          <div className="sofai-dock">
            <div className="sofai-avatar"></div>
            <div className="sofai-dock-text">
              <div className="who">SofAI · in-world</div>
              See that double membrane? That's where ATP is made. Touch it.
            </div>
          </div>
          <div className="device-controls">
            <div className="ctrl"><Icon name="sliders" size={14}/></div>
            <div className="ctrl"><Icon name="book" size={14}/></div>
            <div className="ctrl"><Icon name="enter" size={14}/></div>
          </div>
        </div>
      </div>
    </div>
  </div>
);

// Chapter IV — SofAI modes
const SofAIModes = () => (
  <div className="modes-grid">
    <div className="mode-card">
      <span className="badge">STUDENT</span>
      <h4>In the world.</h4>
      <ul>
        <li><span className="b">→</span>In-world hints tied to viewport</li>
        <li><span className="b">→</span>Pacing nudges, not push notifications</li>
        <li><span className="b">→</span>"Ask me harder" mode for stretch</li>
        <li><span className="b">→</span>Knows what your teacher just said</li>
      </ul>
    </div>
    <div className="mode-card">
      <span className="badge">PARENT</span>
      <h4>Outside it, watching.</h4>
      <ul>
        <li><span className="b">→</span>End-of-day recap, in plain language</li>
        <li><span className="b">→</span>Next two weeks of standards</li>
        <li><span className="b">→</span>Three things to ask at dinner</li>
        <li><span className="b">→</span>Aid + tuition status, on request</li>
      </ul>
    </div>
    <div className="mode-card">
      <span className="badge">TEACHER</span>
      <h4>Building it.</h4>
      <ul>
        <li><span className="b">→</span>Cohort heatmap, by objective</li>
        <li><span className="b">→</span>Prompt suggestions for next world</li>
        <li><span className="b">→</span>Transcript drafts, you sign</li>
        <li><span className="b">→</span>Office hours, scheduled by signal</li>
      </ul>
    </div>
  </div>
);

// Chapter V — Accreditation diagram
const AccredFlow = () => (
  <div className="accred-flow">
    <div className="accred-row">
      <div className="accred-node">
        <div className="mono">SESSION ARTIFACT</div>
        <h5>A 50-min world session</h5>
        <p>Quiz responses, in-world choices, written reflections, peer reviews — all stamped to a learning objective.</p>
      </div>
      <div className="accred-arrow"><Icon name="arrowRight" size={20}/></div>
      <div className="accred-node">
        <div className="mono">COURSE TRANSCRIPT</div>
        <h5>UC A–G transcript</h5>
        <p>Sessions aggregate into course grades on the same scale a brick-and-mortar UC school uses. Letter grade. Credit hours.</p>
      </div>
      <div className="accred-arrow"><Icon name="arrowRight" size={20}/></div>
      <div className="accred-node stamp">
        <div className="mono">WASC · UC · COLLEGE</div>
        <h5>Diploma the system reads</h5>
        <p>WASC reviews the school annually. UC reads the transcript as it would any A–G high school. CVC opens dual-enrollment.</p>
      </div>
    </div>
    <div className="stamp-row">
      <span className="stamp">ACS WASC · 43 46070 999</span>
      <span className="stamp">UC A–G · 7 OF 7 AREAS</span>
      <span className="stamp">CVC DUAL ENROLLMENT</span>
      <span className="stamp">40 UC HONORS COURSES</span>
    </div>
  </div>
);

// Chapter shell
const Chapter = ({ roman, title, lede, children, vis, label }) => (
  <section className="chapter" data-screen-label={label}>
    <div className="container chapter-grid">
      <div className="chapter-roman">{roman}</div>
      <div className="chapter-body">
        <h2>{title}</h2>
        {lede && <p className="lede">{lede}</p>}
        {children}
        <div className="chapter-vis">{vis}</div>
      </div>
    </div>
  </section>
);

const HowItWorksPage = () => (
  <>
    <Nav current="how"/>
    <PageHero/>
    <Chapter
      roman="I"
      label="02 What Marble is"
      title="What World Labs Marble is."
      lede="Marble is a generative model for 3D worlds, by World Labs. It does not render polygons. It renders splats."
      vis={<SplatVsMesh/>}
    >
      <p>For thirty years, every 3D world a student stepped into was made of triangles, painstakingly placed by humans. Gaussian Splatting changes the input: instead of geometry, you give it light. Instead of weeks, you get five minutes.</p>
      <p>The catch: splats are heavy. Spark.js — the WebGL runtime World Labs ships — streams them at 60fps on a five-year-old MacBook. That's the only reason a school like this is possible.</p>
    </Chapter>
    <Chapter
      roman="II"
      label="03 Teacher workflow"
      title="The teacher workflow."
      lede="Teachers do not build worlds. They describe them. Try it."
      vis={<PromptToWorld/>}
    >
      <p>The interactive above is a faithful mock of the Marble Teacher Console: a single text input, a few suggested prompts, a progress bar. Behind the bar, on the real platform, World Labs is solving for several million splats and packaging them for Spark.js delivery. The teacher's job is to know what's worth standing inside.</p>
    </Chapter>
    <Chapter
      roman="III"
      label="04 Student experience"
      title="The student experience."
      lede="A browser tab. A world. A guide. That is the whole stack."
      vis={<StudentDevice/>}
    >
      <p>Mia is in tenth grade. It's 14:08 her time. She is standing inside a mitochondrion. There is no headset, no app, no install. The bar at the bottom of her screen is SofAI, who knows what she is looking at and what her cohort is supposed to learn this hour.</p>
      <p>Sessions are 30–50 minutes. Five live cohorts per week per subject. The rest is async — open the world whenever, SofAI continues where you left off.</p>
    </Chapter>
    <Chapter
      roman="IV"
      label="05 SofAI's role"
      title="SofAI's role."
      lede="One identity. Three lenses on the same student."
      vis={<SofAIModes/>}
    >
      <p>SofAI is the only AI a family interacts with across the entire experience. The model is the same — the context, the permissions, and the tone shift by role. A teacher asking "how is Mia doing?" sees objective coverage. A parent asking the same question gets dinner-table answers. Mia asking the same question gets a nudge.</p>
    </Chapter>
    <Chapter
      roman="V"
      label="06 Accreditation & diploma"
      title="Accreditation, and the diploma."
      lede="Everything else is novel. This part is boring on purpose."
      vis={<AccredFlow/>}
    >
      <p>The pedagogy is unusual. The credential cannot be. We hold ACS WASC accreditation under code 43 46070 999. All seven UC A–G subject areas are approved. Forty courses carry UC Honors weighting. California Community Colleges open for dual enrollment after grade 9.</p>
      <blockquote style={{ fontSize: 22, color: 'var(--ink-0)', borderLeft: '2px solid var(--warm)', paddingLeft: 24, margin: '32px 0' }}>
        Accreditation is the floor. Not the ceiling.
      </blockquote>
    </Chapter>
    <section style={{ padding: '96px 0 128px', borderTop: '1px solid var(--line-soft)', textAlign: 'center', background: 'var(--bg-0)' }}>
      <div className="container">
        <h2 className="t-h2" style={{ marginBottom: 16 }}>That's the whole stack.</h2>
        <p className="ink-2" style={{ fontSize: 18, marginBottom: 32 }}>If you want to see what a course looks like, the catalog is one click away. If you want a diploma, enrollment is two.</p>
        <div style={{ display: 'flex', gap: 12, justifyContent: 'center', flexWrap: 'wrap' }}>
          <a className="btn btn-primary btn-lg" href="enroll.html">Begin enrollment <Icon name="arrowRight" size={16}/></a>
          <a className="btn btn-secondary btn-lg" href="courses.html">Browse courses</a>
        </div>
      </div>
    </section>
    <Footer/>
  </>
);

ReactDOM.createRoot(document.getElementById('root')).render(<HowItWorksPage/>);
