// Concept E — "Context-Revealing Merge-Down"
// A single loop clock drives a camera that pulls back through three scales.
// Nothing stacks. The camera widens. What was the whole frame in beat 1 becomes
// a node in beat 2 becomes a module in beat 3.
//
// Loop: 16,000ms  (slowed from 11s — each beat gets more breathing room,
// transitions stay snappy)
//   B1   0    – 4000   "AI Agent doing work"     — camera tight on one agent
//   T12  4000 – 4700   camera-pulls-back
//   B2   4700 – 9000   "Workflow"                — agent + humans + other agents
//   T23  9000 – 9700   camera-pulls-back
//   B3   9700 – 14500  "Custom Software"         — chrome assembles around workflow
//   END  14500 – 16000 hold + loop crossfade
// (crossfade back to start on loop)

const CE = {
  DUR: 16000,
  B1:  [0, 4000],
  T12: [4000, 4700],
  B2:  [4700, 9000],
  T23: [9000, 9700],
  B3:  [9700, 14500],
  END: [14500, 16000],
};

// ---------- helpers ----------
const clamp01 = v => Math.max(0, Math.min(1, v));
const easeOut = t => 1 - Math.pow(1 - t, 3);
const easeInOut = t => t < 0.5 ? 2*t*t : 1 - Math.pow(-2*t + 2, 2)/2;
const localP = (t, [s,e]) => clamp01((t - s) / (e - s));
const localE = (t, r, ease=easeInOut) => ease(localP(t, r));
const lerp = (a,b,p) => a + (b - a) * p;

function useLoopClock(duration) {
  const [t, setT] = React.useState(0);
  React.useEffect(() => {
    let raf, start = performance.now();
    const tick = (now) => {
      setT((now - start) % duration);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [duration]);
  return t;
}

// ==============================================================
// CAMERA MODEL
// The SVG viewBox is 0 0 1000 1000. We transform the inner <g> with
// a scale+translate to produce a "camera pull-back" effect.
//
// In Beat 1 the camera is tight on the agent scene (zoom ~2.2x, centered on agent).
// In Beat 2 the camera pulls back (zoom ~1x) to show the whole workflow.
// In Beat 3 the camera pulls back further (zoom ~0.7x translated) so the platform
// chrome fits around the workflow.
// The pull-back is a continuous curve, not a cut, during transitions.
// ==============================================================
// ==============================================================
// VIEWBOX FRAMES — each beat has its OWN viewBox that fills the SVG canvas.
// The SVG is set to width:100% and the viewBox aspect determines height.
// We animate the viewBox (x, y, w, h) between frames during transitions, so
// content always fills the visible canvas — no letterboxing.
//
// Content world (where all SVG elements live) — same as before:
//   Agent scene:   x ~250..650,  y ~370..600
//   Workflow chain: x ~270..1080, y ~370..600
//   Platform chrome: x 60..1160, y 130..890
// ==============================================================
function viewBoxForT(t) {
  // All viewBoxes share the same 1.45:1 aspect ratio (matching the platform's
  // natural shape), so the SVG canvas is one stable rectangle and content fills
  // it edge-to-edge in every beat. Empty vertical space in B1/B2 is OK — the
  // dashed background pattern shows through and gives breathing room.
  // [x, y, w, h]
  const B1_BOX = [220, 380, 440, 304];   // agent + input doc + output card
  const B2_BOX = [240, 211, 880, 607];   // full chain Extract→Approve, vertically centered
  const B3_BOX = [ 30, 110, 1160, 800];  // full platform chrome with margin

  if (t < CE.T12[0]) return B1_BOX;
  if (t < CE.T12[1]) {
    const p = localE(t, CE.T12, easeInOut);
    return B1_BOX.map((v, i) => lerp(v, B2_BOX[i], p));
  }
  if (t < CE.T23[0]) return B2_BOX;
  if (t < CE.T23[1]) {
    const p = localE(t, CE.T23, easeInOut);
    return B2_BOX.map((v, i) => lerp(v, B3_BOX[i], p));
  }
  return B3_BOX;
}

// ==============================================================
// MAIN VISUAL
// ==============================================================
function ConceptE_Visual() {
  const t = useLoopClock(CE.DUR);
  const vb = viewBoxForT(t);

  // Current phase for pill label
  const phase =
    t < CE.T12[0] ? "one" :
    t < CE.T23[0] ? "two" :
    t < CE.END[0] ? "three" :
                    "end";

  const pill = {
    one:   { label: "AI Agent",           color: "#397ae7", bg: "#dfeaff" },
    two:   { label: "Automated Workflow", color: "#6d49e0", bg: "#e6dfff" },
    three: { label: "Custom Software",    color: "#3d7827", bg: "#d9ecce" },
    end:   { label: "Custom Software",    color: "#3d7827", bg: "#d9ecce" },
  }[phase];

  // Pill is visible during beats and end card; compresses slightly during transitions to morph
  const inTransition = (t >= CE.T12[0] && t < CE.T12[1]) || (t >= CE.T23[0] && t < CE.T23[1]);
  const pillScaleY = inTransition
    ? 1 - 0.4 * Math.sin(((t - (t < CE.T23[0] ? CE.T12[0] : CE.T23[0])) / 500) * Math.PI)
    : 1;

  return (
    <div style={{
      position: "relative",
      width: "100%",
      maxWidth: 1240,
      display: "flex",
      flexDirection: "column",
      gap: 16,
    }}>
      <div style={{
        width: "100%",
        aspectRatio: "1160 / 800",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
      }}>
        <svg
          viewBox={vb.join(" ")}
          width="100%"
          height="100%"
          preserveAspectRatio="xMidYMid meet"
          style={{ display: "block" }}
        >
        {/* Content — no camera transform; viewBox does the framing */}
        <PlatformChrome t={t}/>
        <WorkflowGraph t={t}/>
        <AgentScene t={t}/>
        <EndTags t={t}/>
      </svg>
      </div>

      {/* Caption stack — sits below the visual */}
      <div style={{
        padding: "0 4px",
        pointerEvents: "none",
      }}>
        <div style={{
          display: "flex", alignItems: "stretch", gap: 8,
          fontFamily: "var(--sb-font-sans)",
        }}>
          {[
            { key: "one",   label: "AI Agent",           color: "#397ae7", bg: "#dfeaff" },
            { key: "two",   label: "Automated Workflow", color: "#6d49e0", bg: "#e6dfff" },
            { key: "three", label: "Custom Software",    color: "#3d7827", bg: "#d9ecce" },
          ].map((p, i) => {
            const active = (phase === p.key) || (phase === "end" && p.key === "three");
            return (
              <div key={p.key} style={{
                flex: 1,
                padding: "8px 16px",
                borderRadius: 12,
                border: "1.5px solid #000",
                background: active ? p.bg : "#fff",
                opacity: active ? 1 : 0.55,
                transform: active ? "translateY(-2px)" : "translateY(0)",
                transition: "all .5s var(--sb-ease)",
                display: "flex", alignItems: "center", gap: 10,
                whiteSpace: "nowrap",
              }}>
                <span style={{
                  flexShrink: 0,
                  width: 10, height: 10, borderRadius: 999,
                  background: p.color,
                  boxShadow: active ? `0 0 0 3px ${p.bg}` : "none",
                  transition: "box-shadow .4s var(--sb-ease)",
                }}/>
                <span style={{
                  fontSize: 13, fontWeight: 500, letterSpacing: "-0.01em",
                  color: active ? p.color : "#4e5769",
                  lineHeight: 1.1,
                }}>
                  {i + 1}. {p.label}
                </span>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { ConceptE_Visual, CE, localP, localE, easeOut, easeInOut, clamp01, lerp });
