// NoMind — landing page sections (evaluation + governance positioning)
const { useState, useEffect: useEffectSections, useRef: useRefSections } = React;

function Eyebrow({ num, children }) {
  return (
    <div className="eyebrow">
      {num && <span className="eyebrow-num">{num}</span>}
      <span className="eyebrow-line" />
      <span className="eyebrow-text">{children}</span>
    </div>
  );
}

function MathBlock({ children }) {
  return <div className="math-block">{children}</div>;
}

function DiagramPlate({ eyebrow, title, src, alt }) {
  return (
    <figure className="nm-diagram-plate">
      <figcaption>
        <span className="mono-label">{eyebrow}</span>
        <strong>{title}</strong>
      </figcaption>
      <img src={src} alt={alt || title} />
    </figure>
  );
}

function getAnalyticsContext() {
  const params = new URLSearchParams(window.location.search);
  const utm = {};
  ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'].forEach(key => {
    const value = params.get(key);
    if (value) utm[key] = value;
  });

  const posthog = window.posthog;
  let distinctId = '';
  let sessionId = '';
  let deviceId = '';
  try { distinctId = posthog?.get_distinct_id?.() || ''; } catch (_) {}
  try { sessionId = posthog?.get_session_id?.() || posthog?.get_property?.('$session_id') || ''; } catch (_) {}
  try { deviceId = posthog?.get_property?.('$device_id') || ''; } catch (_) {}

  return {
    provider: 'posthog',
    distinctId,
    sessionId,
    deviceId,
    currentUrl: window.location.href,
    pathname: window.location.pathname,
    referrer: document.referrer || '',
    title: document.title,
    utm,
    viewport: {
      width: window.innerWidth,
      height: window.innerHeight,
    },
  };
}

function ParticleDissolve({ active }) {
  const canvasRef = useRefSections(null);

  useEffectSections(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    let frame;

    const resize = () => {
      const rect = canvas.getBoundingClientRect();
      const dpr = Math.min(window.devicePixelRatio || 1, 2);
      canvas.width = Math.max(1, Math.floor(rect.width * dpr));
      canvas.height = Math.max(1, Math.floor(rect.height * dpr));
      return { rect, dpr };
    };

    const { rect, dpr } = resize();
    if (!active) return;

    const sampleFormulaPixels = () => {
      const card = canvas.closest('.math-card');
      const stage = canvas.closest('.math-card-stage');
      const svg = card?.querySelector('.math-face-formula svg');
      if (!stage || !svg) return null;
      try {
        const stageRect = stage.getBoundingClientRect();
        const svgRect = svg.getBoundingClientRect();
        const xml = new XMLSerializer().serializeToString(svg);
        const img = new Image();
        const url = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(xml);
        return new Promise((resolve) => {
          img.onload = () => {
            const off = document.createElement('canvas');
            off.width = Math.max(1, Math.ceil(svgRect.width * dpr));
            off.height = Math.max(1, Math.ceil(svgRect.height * dpr));
            const octx = off.getContext('2d');
            octx.drawImage(img, 0, 0, off.width, off.height);
            URL.revokeObjectURL(url);
            const image = octx.getImageData(0, 0, off.width, off.height).data;
            const points = [];
            const step = Math.max(2, Math.floor(3 * dpr));
            for (let y = 0; y < off.height; y += step) {
              for (let x = 0; x < off.width; x += step) {
                const a = image[(y * off.width + x) * 4 + 3];
                if (a > 24 && Math.random() > 0.08) {
                  points.push({
                    x: (svgRect.left - stageRect.left) + x / dpr,
                    y: (svgRect.top - stageRect.top) + y / dpr,
                    a: a / 255,
                  });
                }
              }
            }
            resolve(points.length ? points : null);
          };
          img.onerror = () => resolve(null);
          img.src = url;
        });
      } catch (_) {
        return null;
      }
    };

    const hexToRgb = (value, fallback) => {
      const hex = value.trim().match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
      if (!hex) return fallback;
      return [parseInt(hex[1], 16) / 255, parseInt(hex[2], 16) / 255, parseInt(hex[3], 16) / 255];
    };

    const styles = getComputedStyle(document.documentElement);
    const colors = [
      hexToRgb(styles.getPropertyValue('--accent') || '#8aa38f', [0.54, 0.64, 0.56]),
      hexToRgb(styles.getPropertyValue('--ink') || '#151515', [0.08, 0.08, 0.08]),
      hexToRgb(styles.getPropertyValue('--accent-ink') || '#005a3b', [0, 0.35, 0.23]),
    ];

    let cancelled = false;
    let cleanup = () => {};

    Promise.resolve(sampleFormulaPixels()).then((sourcePoints) => {
      if (cancelled) return;

      const makeSource = (i, count) => sourcePoints?.[i % sourcePoints.length] || {
        x: rect.width * (0.08 + Math.random() * 0.26),
        y: rect.height * (0.2 + Math.random() * 0.5),
        a: 1,
      };

      if (window.THREE) {
        const THREE = window.THREE;
        const renderer = new THREE.WebGLRenderer({ canvas, alpha: true, antialias: true, premultipliedAlpha: false });
        renderer.setPixelRatio(dpr);
        renderer.setSize(rect.width, rect.height, false);
        renderer.setClearColor(0x000000, 0);

        const scene = new THREE.Scene();
        const camera = new THREE.OrthographicCamera(0, rect.width, rect.height, 0, -1, 1);
        const count = sourcePoints ? Math.min(Math.max(sourcePoints.length, 420), 1600) : 640;
        const positions = new Float32Array(count * 3);
        const velocities = new Float32Array(count * 2);
        const life = new Float32Array(count);
        const size = new Float32Array(count);
        const colorIndex = new Float32Array(count);
        const seed = new Float32Array(count);
        for (let i = 0; i < count; i++) {
          const s = makeSource(i, count);
          positions[i * 3 + 0] = s.x;
          positions[i * 3 + 1] = s.y;
          positions[i * 3 + 2] = 0;
          velocities[i * 2 + 0] = rect.width * (0.08 + Math.random() * 0.24) * (Math.random() > 0.5 ? 1 : 0.65);
          velocities[i * 2 + 1] = (Math.random() - 0.5) * 128;
          life[i] = 0.82 + Math.random() * 0.28;
          size[i] = (1.1 + Math.random() * 3.2) * dpr * (0.8 + s.a * 0.5);
          colorIndex[i] = i % 3;
          seed[i] = Math.random();
        }

        const geometry = new THREE.BufferGeometry();
        geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
        geometry.setAttribute('a_velocity', new THREE.BufferAttribute(velocities, 2));
        geometry.setAttribute('a_life', new THREE.BufferAttribute(life, 1));
        geometry.setAttribute('a_size', new THREE.BufferAttribute(size, 1));
        geometry.setAttribute('a_color', new THREE.BufferAttribute(colorIndex, 1));
        geometry.setAttribute('a_seed', new THREE.BufferAttribute(seed, 1));

        const material = new THREE.ShaderMaterial({
          transparent: true,
          depthTest: false,
          uniforms: {
            u_time: { value: 0 },
            u_color0: { value: new THREE.Color(colors[0][0], colors[0][1], colors[0][2]) },
            u_color1: { value: new THREE.Color(colors[1][0], colors[1][1], colors[1][2]) },
            u_color2: { value: new THREE.Color(colors[2][0], colors[2][1], colors[2][2]) },
          },
          vertexShader: `
            attribute vec2 a_velocity;
            attribute float a_life;
            attribute float a_size;
            attribute float a_color;
            attribute float a_seed;
            uniform float u_time;
            varying float v_alpha;
            varying float v_color;
            float easeOutCubic(float x) { return 1.0 - pow(1.0 - x, 3.0); }
            void main() {
              float u = clamp(u_time / a_life, 0.0, 1.0);
              float ease = easeOutCubic(u);
              vec2 swirl = vec2(sin(u * 18.0 + a_seed * 6.283), cos(u * 15.0 + a_seed * 4.1)) * 13.0 * ease;
              vec3 displaced = position + vec3(a_velocity * u_time * ease + swirl + vec2(0.0, -22.0 * ease), 0.0);
              gl_Position = projectionMatrix * modelViewMatrix * vec4(displaced, 1.0);
              gl_PointSize = a_size * (1.0 - 0.58 * u);
              v_alpha = pow(1.0 - u, 1.32);
              v_color = a_color;
            }
          `,
          fragmentShader: `
            precision mediump float;
            uniform vec3 u_color0;
            uniform vec3 u_color1;
            uniform vec3 u_color2;
            varying float v_alpha;
            varying float v_color;
            void main() {
              vec2 p = gl_PointCoord - vec2(0.5);
              float d = length(p);
              float soft = smoothstep(0.5, 0.18, d);
              vec3 color = mix(u_color0, u_color1, step(0.5, v_color));
              color = mix(color, u_color2, step(1.5, v_color));
              gl_FragColor = vec4(color, soft * v_alpha * 0.86);
            }
          `,
        });
        const points = new THREE.Points(geometry, material);
        scene.add(points);
        const start = performance.now();
        const drawThree = (now) => {
          const t = Math.min((now - start) / 1000, 1.15);
          material.uniforms.u_time.value = t;
          renderer.render(scene, camera);
          if (t < 1.15) frame = requestAnimationFrame(drawThree);
        };
        frame = requestAnimationFrame(drawThree);
        cleanup = () => {
          cancelAnimationFrame(frame);
          geometry.dispose();
          material.dispose();
          renderer.dispose();
        };
        return;
      }

      const gl = canvas.getContext('webgl', { alpha: true, antialias: true, premultipliedAlpha: false });

      // Fallback for older browsers: same true glyph-source dissolve when sampling works.
      if (!gl) {
        const ctx = canvas.getContext('2d');
        ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
        const particles = Array.from({ length: sourcePoints ? Math.min(sourcePoints.length, 520) : 180 }, (_, i) => {
          const s = makeSource(i, sourcePoints ? sourcePoints.length : 180);
          return ({
        x: s.x,
        y: s.y,
        vx: rect.width * (0.004 + Math.random() * 0.011),
        vy: (Math.random() - 0.5) * 1.8,
        r: 0.8 + Math.random() * 2.2,
        delay: (i / (sourcePoints?.length || 180)) * 220 + Math.random() * 120,
        life: 520 + Math.random() * 360,
        color: ['#8aa38f', '#151515', '#005a3b'][i % 3],
          });
        });
      const start = performance.now();
      const draw2d = (now) => {
        const t = now - start;
        ctx.clearRect(0, 0, rect.width, rect.height);
        for (const p of particles) {
          const local = t - p.delay;
          if (local <= 0 || local >= p.life) continue;
          const u = local / p.life;
          ctx.globalAlpha = Math.sin(Math.PI * u) * 0.72;
          ctx.fillStyle = p.color;
          ctx.beginPath();
          ctx.arc(p.x + p.vx * local, p.y + p.vy * local - u * 18, p.r, 0, Math.PI * 2);
          ctx.fill();
        }
        ctx.globalAlpha = 1;
        if (t < 1050) frame = requestAnimationFrame(draw2d);
      };
      frame = requestAnimationFrame(draw2d);
        cleanup = () => { cancelAnimationFrame(frame); ctx.clearRect(0, 0, rect.width, rect.height); };
        return;
      }

    const vertex = `
      attribute vec2 a_origin;
      attribute vec2 a_velocity;
        attribute float a_life;
        attribute float a_size;
        attribute float a_color;
        attribute float a_seed;
        uniform float u_time;
        uniform vec2 u_resolution;
        varying float v_alpha;
        varying float v_color;
        float easeOutCubic(float x) { return 1.0 - pow(1.0 - x, 3.0); }
        void main() {
        float u = clamp(u_time / a_life, 0.0, 1.0);
        float ease = easeOutCubic(u);
        vec2 swirl = vec2(sin(u * 18.0 + a_seed * 6.283), cos(u * 15.0 + a_seed * 4.1)) * 12.0 * ease;
        vec2 pos = a_origin + a_velocity * u_time * ease + swirl + vec2(0.0, -22.0 * ease);
        vec2 clip = (pos / u_resolution) * 2.0 - 1.0;
        gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0);
        gl_PointSize = a_size * (1.0 - 0.55 * u);
        v_alpha = pow(1.0 - u, 1.35);
        v_color = a_color;
      }
    `;
    const fragment = `
      precision mediump float;
      uniform vec3 u_color0;
      uniform vec3 u_color1;
      uniform vec3 u_color2;
      varying float v_alpha;
      varying float v_color;
      void main() {
        vec2 p = gl_PointCoord - vec2(0.5);
        float d = length(p);
        float soft = smoothstep(0.5, 0.18, d);
        vec3 color = mix(u_color0, u_color1, step(0.5, v_color));
        color = mix(color, u_color2, step(1.5, v_color));
        gl_FragColor = vec4(color, soft * v_alpha * 0.82);
      }
    `;

    const compile = (type, source) => {
      const shader = gl.createShader(type);
      gl.shaderSource(shader, source);
      gl.compileShader(shader);
      return shader;
    };
    const program = gl.createProgram();
    gl.attachShader(program, compile(gl.VERTEX_SHADER, vertex));
    gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fragment));
    gl.linkProgram(program);
    gl.useProgram(program);

    const count = sourcePoints ? Math.min(Math.max(sourcePoints.length, 360), 1400) : 520;
    const stride = 8;
    const data = new Float32Array(count * stride);
    for (let i = 0; i < count; i++) {
      const base = i * stride;
      const band = i / count;
      const source = makeSource(i, count);
      data[base + 0] = source.x;
      data[base + 1] = source.y;
      data[base + 2] = rect.width * (0.08 + Math.random() * 0.24) * (0.75 + band * 0.5);
      data[base + 3] = (Math.random() - 0.5) * 120;
      data[base + 4] = 820 + Math.random() * 260;
      data[base + 5] = (1.05 + Math.random() * 2.8) * dpr * (0.8 + source.a * 0.5);
      data[base + 6] = i % 3;
      data[base + 7] = Math.random();
    }

    const buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
    const attrs = [
      ['a_origin', 2, 0], ['a_velocity', 2, 2], ['a_life', 1, 4],
      ['a_size', 1, 5], ['a_color', 1, 6], ['a_seed', 1, 7],
    ];
    attrs.forEach(([name, size, offset]) => {
      const loc = gl.getAttribLocation(program, name);
      gl.enableVertexAttribArray(loc);
      gl.vertexAttribPointer(loc, size, gl.FLOAT, false, stride * 4, offset * 4);
    });

    gl.uniform2f(gl.getUniformLocation(program, 'u_resolution'), canvas.width, canvas.height);
    gl.uniform3fv(gl.getUniformLocation(program, 'u_color0'), colors[0]);
    gl.uniform3fv(gl.getUniformLocation(program, 'u_color1'), colors[1]);
    gl.uniform3fv(gl.getUniformLocation(program, 'u_color2'), colors[2]);
    const timeLoc = gl.getUniformLocation(program, 'u_time');
    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.clearColor(0, 0, 0, 0);
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

    const start = performance.now();
    const draw = (now) => {
      const t = now - start;
      gl.clear(gl.COLOR_BUFFER_BIT);
      gl.uniform1f(timeLoc, t);
      gl.drawArrays(gl.POINTS, 0, count);
      if (t < 1050) frame = requestAnimationFrame(draw);
    };
    frame = requestAnimationFrame(draw);
      cleanup = () => {
      cancelAnimationFrame(frame);
      gl.clear(gl.COLOR_BUFFER_BIT);
      gl.deleteBuffer(buffer);
      gl.deleteProgram(program);
      };
    });

    return () => {
      cancelled = true;
      cleanup();
    };
  }, [active]);

  return <canvas className="particle-canvas" ref={canvasRef} aria-hidden="true" />;
}

function MathCard({ metric }) {
  const [active, setActive] = useState(false);
  return (
    <div
      className={`math-card ${active ? 'is-dissolving' : ''}`}
      onMouseEnter={() => setActive(true)}
      onMouseLeave={() => setActive(false)}
      onFocus={() => setActive(true)}
      onBlur={() => setActive(false)}
      tabIndex="0"
    >
      <div className="math-card-label">{metric.k}</div>
      <div className="math-card-stage">
        <div className="math-face math-face-formula"><MathBlock>{metric.v}</MathBlock></div>
        <div className="math-face math-face-solution">{metric.solution}</div>
        <ParticleDissolve active={active} />
      </div>
    </div>
  );
}

function Nav({ onContact }) {
  return (
    <nav className="nm-nav">
      <div className="nm-wordmark">
        <img className="nm-logo-img nm-logo-wordmark" src="assets/logo-wordmark.png?v=2" alt="NoMind" />
      </div>
      <div className="nm-navlinks">
        <a href="#thesis">Thesis</a>
        <a href="#pilot-theater">Pilot failure</a>
        <a href="#systems">Systems economics</a>
        <a href="#offer">How we help</a>
        <a href="#who">Why NoMind</a>
      </div>
      <button className="nm-navcta" onClick={onContact}>
        <span>Start a conversation</span>
        <span className="nm-navcta-arrow">↗</span>
      </button>
    </nav>
  );
}

function Hero() {
  return (
    <header className="nm-hero" data-screen-label="01 Hero">
      <div className="nm-hero-meta">
        <Eyebrow num="00">Index</Eyebrow>
        <div className="nm-hero-coord">
          <span>High-stakes workflows</span><span>·</span><span>Agent evaluation</span><span>·</span><span>Rev. 05 — 2026</span>
        </div>
      </div>

      <h1 className="nm-display">
        <span className="nm-display-line">AI pilots are easy.</span>
        <span className="nm-display-line nm-display-kicker">Production systems are hard.</span>
      </h1>

      <div className="nm-hero-foot">
        <p className="nm-lead">
          NoMind helps teams design and evaluate AI agent systems for high-stakes expert workflows — because trust is not a model property, it is a workflow property.
        </p>
        <div className="nm-hero-ctas">
          <a href="#contact" className="btn btn-primary">
            <span>Start a conversation</span>
            <span className="btn-arrow">→</span>
          </a>
        </div>
      </div>

      <div className="nm-hero-ledger">
        <div><span className="mono-label">Focus</span><span>Evaluation · Systems design · Governance</span></div>
        <div><span className="mono-label">Domains</span><span>Healthcare · Legal · Compliance · Enterprise operations</span></div>
        <div><span className="mono-label">Model</span><span>Assessment · Evaluation design · Fractional AI/CTO leadership</span></div>
      </div>
    </header>
  );
}

function What() {
  return (
    <section id="thesis" className="nm-section" data-screen-label="02 Thesis">
      <div className="nm-section-head">
        <Eyebrow num="01">The thesis</Eyebrow>
        <h2 className="nm-h2">
          Enterprise AI adoption will be limited less by model capability<br/>
          <span className="dim">than by an organization’s ability to specify, evaluate, and govern the workflows around them.</span>
        </h2>
      </div>

      <div className="nm-thesis-grid">
        <div className="nm-thesis-col">
          <div className="nm-tc-label"><span className="mono-label">A.</span><span>The gap</span></div>
          <p className="nm-body">
            Most teams can produce an impressive agent demo. Far fewer can show that the system follows domain rules, respects review boundaries, exposes uncertainty, and behaves consistently when the easy cases disappear.
          </p>
        </div>

        <div className="nm-thesis-col">
          <div className="nm-tc-label"><span className="mono-label">B.</span><span>The failure mode</span></div>
          <p className="nm-body">
            Pilots stall when real operations appear: incomplete context, stale knowledge, permission boundaries, long-tail user behavior, audit needs, unclear ownership when the system is wrong, and inference paths whose latency and cost multiply under load.
          </p>
        </div>

        <div className="nm-thesis-col">
          <div className="nm-tc-label"><span className="mono-label">C.</span><span>Our role</span></div>
          <p className="nm-body">
            We help teams turn expert judgment into testable system behavior: evaluation harnesses, guardrail architecture, risk models, human review policies, and operating economics that can survive real use.
          </p>
        </div>
      </div>

      <DiagramPlate
        eyebrow="Failure map"
        title="What must be true before demos scale"
        src="assets/diagrams/pilot-production-failure-map.png"
        alt="Minimal diagram showing demo readiness through feasibility test, workflow map, risk review, governance check, and scale decision."
      />
    </section>
  );
}

function Transformation() {
  const rows = [
    { k: 'Curated examples', v: 'Demos often run on clean examples with implicit human babysitting. Production receives ambiguous inputs, missing context, and adversarial edge cases.' },
    { k: 'Hidden unit economics', v: 'The pilot budget usually ignores retries, validation passes, tool latency, cache misses, review queues, and the cost of recovering from bad outputs.' },
    { k: 'Compute fanout', v: 'Planning, retrieval, tool use, validation, retries, and repair loops can turn one user request into dozens of inference calls.' },
    { k: 'Review burden', v: 'When confidence, escalation, and audit boundaries are vague, humans become the hidden infrastructure keeping the pilot alive.' },
  ];
  return (
    <section id="pilot-theater" className="nm-section nm-section-inset" data-screen-label="03 Pilot Theater">
      <div className="nm-section-head">
        <Eyebrow num="02">Pilot failure</Eyebrow>
        <h2 className="nm-h2">
          The pilot worked because it was small, curated, and babysat.
        </h2>
      </div>
      <div className="nm-table">
        {rows.map((r, i) => (
          <div className="nm-row" key={r.k}>
            <div className="nm-row-num">0{i+1}</div>
            <div className="nm-row-k">{r.k}</div>
            <div className="nm-row-v">{r.v}</div>
          </div>
        ))}
      </div>

      <DiagramPlate
        eyebrow="Risk gates"
        title="Readiness gates before agent action"
        src="assets/diagrams/workflow-risk-gates.png"
        alt="Minimal diagram showing a use case passing through context requirements, access requirements, reliability threshold, review design, and auditability requirements."
      />
    </section>
  );
}

function Systems() {
  const metrics = [
    {
      k: 'Amortized context cost',
      v: '\\[C_{req} = (1-h_{cache})C_{prefill}(T_{ctx}) + C_{decode}(T_{out}) + C_{tools}\\]',
      solution: 'Design context like a cache hierarchy: keep stable policy and workflow memory reusable, retrieve only what changes, and avoid paying the prefill tax on every request.'
    },
    {
      k: 'Latency budget',
      v: '\\[L_{e2e} \\approx L_{queue}(B) + L_{prefill}(T_{ctx}) + T_{out}/r_{decode} + L_{tools} + L_{retry}\\]',
      solution: 'Set latency budgets before architecture decisions: batch where throughput matters, stream where users wait, and move validation off the critical path when safe.'
    },
    {
      k: 'API bill at scale',
      v: '\\[Bill = N_{workflows} \\sum_j n_j(p^{in}_jT^{in}_j + p^{out}_jT^{out}_j)(1+r_j)\\]',
      solution: 'Model the bill per completed workflow, not per prompt. Retries, validators, tool loops, and long outputs are where demo economics quietly explode.'
    },
  ];
  return (
    <section id="systems" className="nm-section" data-screen-label="04 Systems Economics">
      <div className="nm-section-head">
        <Eyebrow num="03">Systems economics</Eyebrow>
        <h2 className="nm-h2">
          Batch size, latency, cache hit rate, and token pricing become product decisions.
        </h2>
      </div>
      <div className="nm-thesis-grid nm-systems-grid">
        <div className="nm-thesis-col">
          <div className="nm-tc-label"><span className="mono-label">Memory</span><span>Context is not free</span></div>
          <p className="nm-body">
            Long-context models reduce retrieval friction, but they do not eliminate systems design. Context has to be selected, compressed, cached, permissioned, and invalidated — otherwise every request silently drags a growing prefill tax.
          </p>
        </div>
        <div className="nm-thesis-col">
          <div className="nm-tc-label"><span className="mono-label">Compute</span><span>Inference multiplies</span></div>
          <p className="nm-body">
            Agent systems fan out across planners, retrievers, tools, verifiers, and repair loops. Batching helps throughput, caching amortizes repeated context, and long-context expands the retrieval surface — but each changes latency, freshness, and unit economics.
          </p>
        </div>
        <div className="nm-thesis-col">
          <div className="nm-tc-label"><span className="mono-label">Economics</span><span>The API bill is a systems property</span></div>
          <DiagramPlate
            eyebrow="Cost fanout"
            title="Where agent workflows multiply cost"
            src="assets/diagrams/agent-cost-fanout.png"
            alt="Minimal diagram showing where agent workflows multiply cost through planning, retrieval load, tool-use risk, validation, failure handling, and review burden."
          />
          <div className="math-stack">
            {metrics.map((m) => <MathCard metric={m} key={m.k} />)}
          </div>
        </div>
      </div>
    </section>
  );
}

function Offer() {
  const deliverables = [
    'Workflow risk assessment: where agents should act, assist, escalate, or stay out',
    'Domain-specific evaluation design for expert rules, edge cases, and failure modes',
    'Benchmark and regression plan for pilot-to-production decisions',
    'Guardrail, memory, permission, review, and audit design',
    'Technical diligence for AI adoption, vendor claims, and internal build strategy',
  ];
  return (
    <section id="offer" className="nm-section nm-section-inset" data-screen-label="05 Offer">
      <div className="nm-section-head">
        <Eyebrow num="04">How we help</Eyebrow>
        <h2 className="nm-h2">
          Turn promising pilots into testable operating plans.<br/>
          <span className="dim">Before cost, latency, and risk harden into the architecture.</span>
        </h2>
      </div>
      <div className="nm-thesis-grid">
        <div className="nm-thesis-col">
          <div className="nm-tc-label"><span className="mono-label">Assessment</span><span>Workflow risk</span></div>
          <p className="nm-body">
            We identify where an agent can safely help, where it needs supervision, and where the workflow needs evaluation infrastructure before deployment.
          </p>
        </div>
        <div className="nm-thesis-col">
          <div className="nm-tc-label"><span className="mono-label">Outputs</span><span>What the assessment clarifies</span></div>
          <ul className="nm-list">
            {deliverables.map((d) => <li key={d}><span>{d}</span></li>)}
          </ul>
        </div>
        <div className="nm-thesis-col">
          <div className="nm-tc-label"><span className="mono-label">Execution</span><span>From assessment to build</span></div>
          <p className="nm-body">
            Engagements can stay advisory or continue into fractional technical leadership for evaluation design, agent architecture review, and governed pilot planning.
          </p>
        </div>
      </div>

      <DiagramPlate
        eyebrow="Trust boundary"
        title="Trust lives around the model"
        src="assets/diagrams/trust-boundary-layers.png"
        alt="Minimal layered diagram showing model, tools, memory and context, permissions, human review, and audit trail."
      />
    </section>
  );
}

function Who() {
  const bands = [
    {
      k: 'Teams in high-consequence domains',
      v: 'Healthcare, legal, compliance, financial services, and complex enterprise operations where mistakes carry institutional cost.',
      tag: 'Domains'
    },
    {
      k: 'Leaders stuck between demo and deployment',
      v: 'Organizations with promising prototypes that need evidence, boundaries, and economics before scaling to real workflows.',
      tag: 'Scale'
    },
    {
      k: 'Technical teams building agent systems',
      v: 'Product, engineering, and data leaders deciding what agents can touch, what memory they need, and how behavior is evaluated.',
      tag: 'Architecture'
    },
    {
      k: 'Executives evaluating AI claims',
      v: 'Teams buying or building AI systems who need senior technical judgment before committing budget, data access, or operational trust.',
      tag: 'Diligence'
    },
  ];
  return (
    <section id="who" className="nm-section" data-screen-label="06 Who">
      <div className="nm-section-head">
        <Eyebrow num="05">Why NoMind</Eyebrow>
        <h2 className="nm-h2">
          Deep ML expertise, CTO-level systems judgment, and experience with workflows where mistakes are expensive.
        </h2>
      </div>
      <div className="nm-bands">
        {bands.map((b, i) => (
          <article className="nm-band" key={b.k}>
            <div className="nm-band-tag"><span className="mono-label">{String(i+1).padStart(2,'0')} · {b.tag}</span></div>
            <h3 className="nm-band-k">{b.k}</h3>
            <p className="nm-band-v">{b.v}</p>
          </article>
        ))}
      </div>
    </section>
  );
}

function Manifesto() {
  return (
    <section id="manifesto" className="nm-section nm-manifesto" data-screen-label="07 Manifesto">
      <Eyebrow num="06">Operating principle</Eyebrow>
      <blockquote className="nm-quote">
        <p>
          Trust is not a model property.<br/>
          <em>It is a workflow property.</em>
        </p>
        <p className="nm-quote-body">
          Agent systems become useful when expert rules, context boundaries, review paths, and failure recovery are explicit enough to test. The goal is not to make intelligence appear once. It is to make useful behavior repeatable under institutional constraints.
        </p>
        <footer className="nm-quote-foot">
          <span className="mono-label">NoMind · Operating Principle 01</span>
        </footer>
      </blockquote>
    </section>
  );
}

function Contact() {
  const CONTACT_EMAIL = 'hello@nomind.systems';
  const [status, setStatus] = useState('idle');
  const [error, setError] = useState('');
  const [form, setForm] = useState({
    projectType: [],
    stage: '',
    constraint: [],
    email: '',
    note: '',
  });

  const projectTypes = [
    'Agent workflow',
    'AI product / platform',
    'Evaluation / governance',
    'Technical diligence',
    'Not sure yet',
  ];
  const stages = [
    'Exploring',
    'Prototype / pilot',
    'In production',
    'Scaling across org',
  ];
  const constraints = [
    'Accuracy / evals',
    'Workflow integration',
    'Data / context / memory',
    'Compliance / risk',
    'Economics / ROI',
    'Org strategy',
  ];

  const update = (key, value) => {
    setStatus('idle');
    setError('');
    setForm(prev => ({ ...prev, [key]: value }));
  };

  const toggle = (field, option) => {
    setStatus('idle');
    setError('');
    setForm(prev => {
      const current = prev[field];
      const next = current.includes(option)
        ? current.filter(item => item !== option)
        : [...current, option];
      return { ...prev, [field]: next };
    });
  };

  const OptionGroup = ({ num, label, field, options, multiple = false }) => (
    <div className="field field-full option-field" role="group" aria-label={label}>
      <div className="option-heading">
        <span className="mono-label">{num} · {label}</span>
        {multiple && <span className="option-hint">Select all that apply</span>}
      </div>
      <div className="option-grid">
        {options.map(option => {
          const selected = multiple ? form[field].includes(option) : form[field] === option;
          return (
            <label key={option} className={`choice ${selected ? 'selected' : ''}`}>
              <input
                type={multiple ? 'checkbox' : 'radio'}
                name={field}
                value={option}
                checked={selected}
                onChange={() => multiple ? toggle(field, option) : update(field, option)}

              />
              <span>{option}</span>
            </label>
          );
        })}
      </div>
    </div>
  );

  const submit = async (e) => {
    e.preventDefault();
    setStatus('sending');
    setError('');

    const analytics = getAnalyticsContext();
    const payload = {
      ...form,
      source: 'nomind-site',
      submittedAt: new Date().toISOString(),
      analytics,
    };

    try {
      window.posthog?.capture?.('diagnostic_request_submitted', {
        source: 'nomind-site',
        project_type: form.projectType,
        stage: form.stage,
        constraint: form.constraint,
        has_note: Boolean(form.note.trim()),
        form_version: 'diagnostic-v1',
      });
    } catch (_) {}

    try {
      const response = await fetch('/api/contact', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
      if (!response.ok) throw new Error('request failed');
      setStatus('sent');
      setForm({ projectType: [], stage: '', constraint: [], email: '', note: '' });
    } catch (_) {
      setStatus('idle');
      setError(`This local preview is not connected yet. Email ${CONTACT_EMAIL} and include what you’re working on.`);
    }
  };

  return (
    <section id="contact" className="nm-section nm-contact" data-screen-label="08 Contact">
      <div className="nm-contact-head">
        <Eyebrow num="07">Start here</Eyebrow>
        <h2 className="nm-h2">
          Tell us what you’re trying to make work.
        </h2>
      </div>

      <form className="nm-form diagnostic-form" onSubmit={submit}>
        <OptionGroup num="01" label="What are you trying to ship?" field="projectType" options={projectTypes} multiple />
        <OptionGroup num="02" label="Where are you now?" field="stage" options={stages} />
        <OptionGroup num="03" label="What is the main constraint?" field="constraint" options={constraints} multiple />

        <label className="field">
          <span className="mono-label">04 · Email</span>
          <input
            type="email"
            required
            placeholder="you@company.com"
            value={form.email}
            onChange={(e) => update('email', e.target.value)}
          />
        </label>
        <label className="field">
          <span className="mono-label">05 · Optional context</span>
          <textarea
            rows="3"
            placeholder=""
            value={form.note}
            onChange={(e) => update('note', e.target.value)}
          />
        </label>

        <div className="nm-form-foot">
          <div className="nm-form-note">
            {(status === 'sent' || error) && <span className="dot" />}
            <span>
              {status === 'sent'
                ? `Received. We’ll reply from ${CONTACT_EMAIL}.`
                : error || ''}
            </span>
          </div>
          <button className="btn btn-primary" type="submit" disabled={status === 'sending'}>
            <span>{status === 'sending' ? 'Sending' : status === 'sent' ? 'Message received' : 'Start a conversation'}</span>
            <span className="btn-arrow">{status === 'sent' ? '✓' : '→'}</span>
          </button>
        </div>
      </form>
    </section>
  );
}

function Footer() {
  return (
    <footer className="nm-footer" data-screen-label="09 Footer">
      <div className="nm-footer-top">
        <div className="nm-footer-mark">
          <div>
            <img className="nm-logo-img nm-footer-wordmark" src="assets/logo-wordmark.png?v=2" alt="NoMind" />
            <div className="mono-label dim">Agent evaluation · Workflow governance</div>
          </div>
        </div>
        <div className="nm-footer-cols">
          <div>
            <div className="mono-label dim">Focus</div>
            <ul>
              <li>Evaluation design</li>
              <li>Workflow governance</li>
              <li>Agent architecture</li>
              <li>Technical diligence</li>
            </ul>
          </div>
          <div>
            <div className="mono-label dim">Themes</div>
            <ul>
              <li>Pilot-to-production</li>
              <li>Context and memory</li>
              <li>Human review boundaries</li>
              <li>Systems economics</li>
            </ul>
          </div>
          <div>
            <div className="mono-label dim">Contact</div>
            <ul>
              <li><a href="mailto:hello@nomind.systems">hello@nomind.systems</a></li>
              <li><a href="/privacy">Privacy</a></li>
              <li>Chicago · Remote</li>
              <li>Start a conversation</li>
            </ul>
          </div>
        </div>
      </div>
      <div className="nm-footer-bar">
        <span>© 2026 NoMind</span>
        <span className="nm-footer-tag">Trust is a workflow property</span>
        <span>Rev. 05</span>
      </div>
    </footer>
  );
}

Object.assign(window, { Nav, Hero, What, Transformation, Systems, Offer, Who, Manifesto, Contact, Footer, Eyebrow, MathBlock, MathCard, ParticleDissolve });
