/* maglab.jsx — MagLab research toolchain card + case-study page.

   "AI for Science as a lab instrument, not a demo prompt."
   github.com/TaewoooPark/MagLab

   MagLab is a harness platform for magnetism / spintronics research.
   The LLM layer plans, routes, explains, and drafts; deterministic
   domain modules do the actual scientific work (physics formulae,
   unit conversion, material lookup, simulation pipelines, fitters,
   figure renderers, literature connectors, SCPI safety checks, data
   lineage, review workflows).

   On the site this lives at two surfaces:
   1. MagLabCard — a wide bento on /research, between papers and tooling
   2. MagLabPage — /research/maglab, an interactive datasheet that:
      - lists the 5 manifesto principles with cross-links to features
      - renders the 8-layer pipeline as an isometric multilayer stack
        (hover lifts; ↑↓ buttons reorder; click expands)
      - walks the 10-stage research lifecycle by pointer X
      - plays 5 example research-loop CLI sequences
      - shows 15+ effect models as a 4×4 schematic catalog
      - prints the verifiable-orchestrator architecture as ASCII art
      - closes with 5 pillars and a one-line install strip

   No comparison table, no §01–§03 prose blocks. The page IS the
   instrument's datasheet. */

const { useState: useStateML, useEffect: useEffectML, useMemo: useMemoML, useRef: useRefML } = React;

const MAGLAB_REPO = "https://github.com/TaewoooPark/MagLab";

/* ---- Data ------------------------------------------------------ */

const ML_MANIFESTO = [
  { id: "tools",
    title: "LLM reasons, tools compute",
    feature: "physics oracle · honesty gate · DataPoint",
    layerIds: ["physics", "fitting", "sim"] },
  { id: "numbers",
    title: "Every number is verifiable",
    feature: "formula module · unit conversion · physics-range checks",
    layerIds: ["physics", "fitting"] },
  { id: "citations",
    title: "Every citation is real",
    feature: "OpenAlex · Semantic Scholar · arXiv · Crossref",
    layerIds: ["lit"] },
  { id: "figures",
    title: "Every figure is reproducible",
    feature: "FigureSpec JSON · vector · journal styles · data lineage",
    layerIds: ["figures"] },
  { id: "results",
    title: "Every result has provenance",
    feature: "W3C PROV ledger · ELN entries · append-only artifacts",
    layerIds: ["fitting", "authoring"] },
];

/* 8 pipeline layers, top-down on the page = closest-to-paper (Comms) at
   the top, closest-to-keyboard (Terminal UX) at the bottom. The stack
   reads like a magnetic multilayer schematic: each layer is a stripe. */
const ML_LAYERS_SEED = [
  { id: "comms",     name: "Communications", brief: "slides · posters · emails — always marked for review",       tools: ["LaTeX", "PowerPoint", "Word", "smolagents"], principles: ["citations", "figures"] },
  { id: "authoring", name: "Authoring",      brief: "manuscripts · cover letters · revisions · rebuttals",        tools: ["LaTeX", "Word", "LiteLLM"],                  principles: ["citations", "results"] },
  { id: "figures",   name: "Figures",        brief: "FigureSpec JSON · vector · journal styles · primitives",     tools: ["Matplotlib", "SciencePlots", "PyVista", "CairoSVG"], principles: ["figures"] },
  { id: "fitting",   name: "Analysis & Fit", brief: "effect registry · lmfit · symmetry · ELN hook",              tools: ["lmfit", "SciPy", "pandas", "Pydantic"],      principles: ["numbers", "results"] },
  { id: "sim",       name: "Simulation",     brief: "DFT → atomistic → micromagnetic → device handoff",            tools: ["Ubermag", "OOMMF", "magnum.np", "Paramiko"], principles: ["numbers", "results"] },
  { id: "physics",   name: "Physics & Mat",  brief: "formulae · units · oracle · materials registry",              tools: ["NumPy", "SciPy", "Pydantic", "PROV"],        principles: ["tools", "numbers"] },
  { id: "lit",       name: "Literature",     brief: "OpenAlex · Semantic Scholar · arXiv · Crossref",              tools: ["KeyBERT", "LanceDB", "scikit-learn"],        principles: ["citations"] },
  { id: "term",      name: "Terminal UX",    brief: "Typer · Rich · prompt_toolkit",                               tools: ["Python", "Typer", "Rich", "pyfiglet"],       principles: ["tools"] },
];

/* 10 lifecycle stages, ordered left → right like the cycle on the
   MagLab hero poster (image1). */
const ML_LIFECYCLE = [
  { id: "lit",        name: "Literature",     hint: "Search/audit across OpenAlex, Semantic Scholar, arXiv, Crossref. Build an evidence matrix." },
  { id: "materials",  name: "Materials",      hint: "Query magnetic materials, build multilayer stacks, exchange-length / FMR / DW formulae." },
  { id: "physics",    name: "Physics",        hint: "Formula evaluation, unit conversion, physics oracle before downstream work." },
  { id: "sim",        name: "Simulation",     hint: "DFT → atomistic → micromagnetic → device-scale handoff with validated specs." },
  { id: "fit",        name: "Fitting",        hint: "AMR · AHE · ST-FMR · FMR/Kittel · damping · spin pumping · DMI · DW · skyrmion · hysteresis · Curie-T." },
  { id: "analysis",   name: "Analysis",       hint: "Effect model registry · symmetry · consistency · DataPoint lineage." },
  { id: "instr",      name: "Instruments",    hint: "PyVISA scaffolds · SCPI safety check · manual RAG ingest · script generation." },
  { id: "figures",    name: "Figures",        hint: "FigureSpec JSON · vector · journal-aware styles · schematic primitives." },
  { id: "authoring",  name: "Authoring",      hint: "Manuscripts · cover letters · revision letters · rebuttals · grants — marked for review." },
  { id: "comms",      name: "Communications", hint: "Slides · posters · emails · abstracts — always marked for human review." },
];

const ML_LOOPS = [
  { id: "lit-to-plan",  title: "Literature → experiment plan", cmds: [
    "maglab lit search papers/pt_cofeb_mgo --top-n 40",
    "maglab lit authors \"spin orbit torque CoFeB MgO\"",
    "maglab lab plan \"SOT efficiency in Pt/CoFeB/MgO\" --n-doe 16 --output sot_plan.yaml",
  ] },
  { id: "meas-fit-fig", title: "Measurement → fit → figure",   cmds: [
    "maglab analyze load data/stfmr.csv --columns frequency,field,voltage",
    "maglab fit --effect stfmr data/stfmr.csv --method least_squares",
    "maglab sim plot data/stfmr.csv --journal aps --format pdf --output figures/stfmr.pdf",
  ] },
  { id: "multiscale",   title: "Multiscale handoff",            cmds: [
    "maglab sim dft --structure bcc_fe --engine qe --calc-type jij",
    "maglab sim atomistic --engine vampire --j-ij-k 398 --t-max-k 1300",
    "maglab sim pipeline --structure bcc_fe --scales dft,atomistic,micro,device --backend mock",
  ] },
  { id: "instr",        title: "Instrument workflow",           cmds: [
    "maglab instr ingest \"Keithley 2400\" --manual-path manuals/k2400.pdf",
    "maglab instr skillgen \"Keithley 2400\" --safety-model keithley-2400",
    "maglab instr script \"Keithley 2400\" --description \"field sweep Hall voltage\"",
    "maglab instr check hall_sweep.py",
  ] },
  { id: "authoring",    title: "Verified result → manuscript",  cmds: [
    "maglab write \"ST-FMR fit gives xi_DL=0.12 with provenance IDs ...\" --journal prl --dry-run",
    "maglab comms cover-letter --journal \"Physical Review Letters\" --title \"SOT in Pt/CoFeB/MgO\"",
    "maglab present slides \"Key results from the SOT study\" --template aps-12min --format beamer --n-slides 10",
  ] },
];

const ML_EFFECTS = [
  { id: "amr",   name: "AMR",          glyph: "hall-bar"        },
  { id: "ahe",   name: "AHE",          glyph: "hall-arrow"      },
  { id: "ohe",   name: "OHE",          glyph: "hall-linear"     },
  { id: "phe",   name: "PHE",          glyph: "hall-cross"      },
  { id: "smr",   name: "SMR",          glyph: "bilayer"         },
  { id: "usmr",  name: "USMR",         glyph: "bilayer-arrow"   },
  { id: "stfmr", name: "ST-FMR",       glyph: "lorentzian"      },
  { id: "fmr",   name: "FMR / Kittel", glyph: "kittel"          },
  { id: "alpha", name: "Damping",      glyph: "lorentzian-w"    },
  { id: "ishe",  name: "Spin pump · ISHE", glyph: "spin-pump"   },
  { id: "dmi",   name: "DMI",          glyph: "spiral"          },
  { id: "dw",    name: "Domain wall",  glyph: "domain-wall"     },
  { id: "sky",   name: "Skyrmion / Thiele", glyph: "skyrmion"   },
  { id: "hyst",  name: "Hysteresis",   glyph: "hyst-loop"       },
  { id: "tc",    name: "Curie-T",      glyph: "tc-curve"        },
];

const ML_PILLARS = [
  { id: "cli",  name: "CLI-first",      hint: "Reproducible. Every step is a command on disk." },
  { id: "ver",  name: "Verifiable",     hint: "Physics oracle + honesty gate gate every number." },
  { id: "prov", name: "Provenance",     hint: "W3C PROV ledger + DataPoint lineage." },
  { id: "int",  name: "Integrity",      hint: "No hallucinations. No fabrications." },
  { id: "os",   name: "Open science",   hint: "Open data, open code, open release." },
];

/* ---- Schematic primitives — 15+ tiny SVG glyphs ---------------- */

function MlGlyph({ kind, size = 36 }) {
  const sw = 1;
  const s = size;
  const c = "currentColor";
  const v = (x) => (x / 36) * s; // scale helper if we ever change size
  switch (kind) {
    case "hall-bar":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <rect x="6" y="9" width="24" height="6" fill="none" stroke={c} strokeWidth={sw} />
          <line x1="10" y1="5" x2="10" y2="9"   stroke={c} strokeWidth={sw} />
          <line x1="26" y1="5" x2="26" y2="9"   stroke={c} strokeWidth={sw} />
          <line x1="10" y1="15" x2="10" y2="19" stroke={c} strokeWidth={sw} />
          <line x1="26" y1="15" x2="26" y2="19" stroke={c} strokeWidth={sw} />
        </svg>
      );
    case "hall-arrow":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <rect x="6" y="9" width="24" height="6" fill="none" stroke={c} strokeWidth={sw} />
          <path d="M14 12 L24 12" fill="none" stroke={c} strokeWidth={sw} />
          <path d="M22 9 L24 12 L22 15" fill="none" stroke={c} strokeWidth={sw} />
        </svg>
      );
    case "hall-linear":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <line x1="5" y1="19" x2="31" y2="5" stroke={c} strokeWidth={sw} />
          <line x1="5" y1="19" x2="31" y2="19" stroke={c} strokeWidth={sw * 0.6} strokeDasharray="2 3" />
        </svg>
      );
    case "hall-cross":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <rect x="6" y="9" width="24" height="6" fill="none" stroke={c} strokeWidth={sw} />
          <line x1="10" y1="6" x2="14" y2="18" stroke={c} strokeWidth={sw} />
          <line x1="22" y1="6" x2="26" y2="18" stroke={c} strokeWidth={sw} />
        </svg>
      );
    case "bilayer":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <rect x="6" y="8"  width="24" height="3" fill="none" stroke={c} strokeWidth={sw} />
          <rect x="6" y="13" width="24" height="3" fill={c} stroke={c} strokeWidth={sw} />
        </svg>
      );
    case "bilayer-arrow":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <rect x="6" y="8"  width="24" height="3" fill="none" stroke={c} strokeWidth={sw} />
          <rect x="6" y="13" width="24" height="3" fill={c} stroke={c} strokeWidth={sw} />
          <line x1="18" y1="3"  x2="18" y2="7" stroke={c} strokeWidth={sw} />
          <path d="M16 3 L18 1 L20 3" fill="none" stroke={c} strokeWidth={sw} />
        </svg>
      );
    case "lorentzian":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <line x1="4" y1="20" x2="32" y2="20" stroke={c} strokeWidth={sw * 0.5} />
          <path d="M4 20 Q14 20 17 6 Q20 20 32 20" fill="none" stroke={c} strokeWidth={sw} />
        </svg>
      );
    case "kittel":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <line x1="4" y1="20" x2="32" y2="20" stroke={c} strokeWidth={sw * 0.5} />
          <path d="M5 18 Q14 14 18 11 Q26 8 31 6" fill="none" stroke={c} strokeWidth={sw} />
        </svg>
      );
    case "lorentzian-w":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <path d="M4 20 Q14 20 17 6 Q20 20 32 20" fill="none" stroke={c} strokeWidth={sw} />
          <line x1="11" y1="13" x2="23" y2="13" stroke={c} strokeWidth={sw} />
          <line x1="11" y1="11" x2="11" y2="15" stroke={c} strokeWidth={sw} />
          <line x1="23" y1="11" x2="23" y2="15" stroke={c} strokeWidth={sw} />
        </svg>
      );
    case "spin-pump":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <rect x="6" y="11" width="24" height="4" fill="none" stroke={c} strokeWidth={sw} />
          <line x1="12" y1="11" x2="12" y2="4" stroke={c} strokeWidth={sw} />
          <path d="M10 6 L12 4 L14 6" fill="none" stroke={c} strokeWidth={sw} />
          <line x1="20" y1="11" x2="28" y2="6" stroke={c} strokeWidth={sw} />
          <path d="M26 5 L28 6 L27 8" fill="none" stroke={c} strokeWidth={sw} />
        </svg>
      );
    case "spiral":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <path d="M4 12 Q8 4 12 12 Q16 20 20 12 Q24 4 28 12 Q32 20 32 12" fill="none" stroke={c} strokeWidth={sw} />
        </svg>
      );
    case "domain-wall":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <rect x="6" y="9" width="24" height="6" fill="none" stroke={c} strokeWidth={sw} />
          <line x1="18" y1="6" x2="18" y2="18" stroke={c} strokeWidth={sw * 1.4} />
          <path d="M10 12 L13 12" stroke={c} strokeWidth={sw} />
          <path d="M12 11 L13 12 L12 13" fill="none" stroke={c} strokeWidth={sw} />
          <path d="M26 12 L23 12" stroke={c} strokeWidth={sw} />
          <path d="M24 11 L23 12 L24 13" fill="none" stroke={c} strokeWidth={sw} />
        </svg>
      );
    case "skyrmion":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <circle cx="18" cy="12" r="7"   fill="none" stroke={c} strokeWidth={sw} />
          <circle cx="18" cy="12" r="4"   fill="none" stroke={c} strokeWidth={sw * 0.7} />
          <circle cx="18" cy="12" r="1.6" fill={c} />
        </svg>
      );
    case "hyst-loop":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <line x1="6" y1="12" x2="30" y2="12" stroke={c} strokeWidth={sw * 0.5} />
          <line x1="18" y1="3" x2="18" y2="21" stroke={c} strokeWidth={sw * 0.5} />
          <path d="M28 6 Q14 6 8 12 Q14 18 28 18 Q14 18 8 12 Q14 6 28 6 Z" fill="none" stroke={c} strokeWidth={sw} />
        </svg>
      );
    case "tc-curve":
      return (
        <svg width={s} height={s} viewBox="0 0 36 24" aria-hidden="true">
          <line x1="4" y1="20" x2="32" y2="20" stroke={c} strokeWidth={sw * 0.5} />
          <path d="M5 6 L5 6 Q12 6 18 8 Q24 12 28 20" fill="none" stroke={c} strokeWidth={sw} />
          <line x1="28" y1="17" x2="28" y2="20" stroke={c} strokeWidth={sw * 0.6} strokeDasharray="2 2" />
        </svg>
      );
    default:
      return null;
  }
}

/* ---- Manifesto list (5 principles) ----------------------------- */

function ManifestoList({ hoverIdx, onHover, onLeave }) {
  return (
    <ol style={{ listStyle: "none", padding: 0, margin: 0 }}>
      {ML_MANIFESTO.map((p, i) => {
        const active = hoverIdx === i;
        return (
          <li key={p.id}
              onMouseEnter={() => onHover && onHover(i)}
              onMouseLeave={() => onLeave && onLeave()}
              style={{
                display: "grid",
                gridTemplateColumns: "20px 1fr",
                gap: 12,
                padding: "10px 0",
                borderTop: i === 0 ? "1px solid var(--line-soft)" : "0",
                borderBottom: "1px solid var(--line-soft)",
                color: active ? "var(--fg)" : "var(--fg)",
                background: active ? "var(--line-soft)" : "transparent",
                transition: "background 220ms var(--easing-default)",
              }}>
            <span className="micro" style={{ fontFamily: "var(--font-mono)", color: "var(--fg-muted)" }}>▶</span>
            <div>
              <div style={{
                fontFamily: "var(--font-mono)",
                fontSize: 13,
                letterSpacing: "0.04em",
                textTransform: "uppercase",
                fontWeight: 600,
              }}>{t(p.title)}</div>
              <div className="micro" style={{ color: "var(--fg-muted)", marginTop: 4, lineHeight: 1.4 }}>
                {p.feature}
              </div>
            </div>
          </li>
        );
      })}
    </ol>
  );
}

/* ---- Multilayer Stack — 8-layer isometric pipeline ------------- */

function MultilayerStack({ activeLayerIds, onLayerHover }) {
  const [layers, setLayers] = useStateML(ML_LAYERS_SEED);
  const [hoverIdx, setHoverIdx] = useStateML(null);
  const [openIdx, setOpenIdx] = useStateML(null);

  const move = (i, dir) => {
    setLayers((prev) => {
      const j = i + dir;
      if (j < 0 || j >= prev.length) return prev;
      const next = prev.slice();
      [next[i], next[j]] = [next[j], next[i]];
      return next;
    });
    // keep focus on the moved layer
    setOpenIdx((cur) => (cur === i ? i + dir : (cur === i + dir ? i : cur)));
  };

  const onEnter = (i) => {
    setHoverIdx(i);
    onLayerHover && onLayerHover(layers[i].id);
  };
  const onLeave = () => {
    setHoverIdx(null);
    onLayerHover && onLayerHover(null);
  };

  return (
    <div style={{ marginBottom: 80 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", flexWrap: "wrap", gap: 12, marginBottom: 14 }}>
        <div>
          <div className="micro" style={{ marginBottom: 6 }}>{t("Fig. 01 · Pipeline stack")}</div>
          <div className="display-md" style={{ fontSize: 26 }}>{t("Eight layers, top of stack = closest to paper.")}</div>
        </div>
        <div className="micro" style={{ color: "var(--fg-muted)" }}>
          {t("hover to lift · ↑↓ to reorder · click to expand")}
        </div>
      </div>

      <div className="ml-stack" style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        {layers.map((layer, i) => {
          const isHover = hoverIdx === i;
          const isOpen  = openIdx === i;
          const isLinked = activeLayerIds && activeLayerIds.has(layer.id);
          const lifted = isHover || isLinked || isOpen;
          return (
            <div key={layer.id}
                 className="ml-layer"
                 onMouseEnter={() => onEnter(i)}
                 onMouseLeave={onLeave}
                 onClick={() => setOpenIdx(isOpen ? null : i)}
                 data-cursor="link"
                 data-cursor-label={t(isOpen ? "Close" : "Expand")}
                 style={{
                   border: "1px solid var(--fg)",
                   background: lifted ? "var(--fg)" : "var(--bg)",
                   color: lifted ? "var(--bg)" : "var(--fg)",
                   marginLeft: `calc(${i} * 14px)`,
                   transform: lifted ? "translateY(-3px)" : "translateY(0)",
                   transition: "transform 240ms var(--easing-default), background 240ms var(--easing-default), color 240ms var(--easing-default)",
                   cursor: "pointer",
                   userSelect: "none",
                 }}>
              <div style={{
                display: "grid",
                gridTemplateColumns: "44px 200px 1fr auto",
                gap: 14,
                alignItems: "center",
                padding: "14px 18px",
              }} className="ml-layer-row">
                <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
                  <button type="button"
                          onClick={(e) => { e.stopPropagation(); move(i, -1); }}
                          aria-label={t("Move layer up")}
                          data-cursor="link" data-cursor-label={t("Up")}
                          disabled={i === 0}
                          style={{
                            background: "transparent",
                            border: 0,
                            color: i === 0 ? (lifted ? "rgba(255,255,255,0.35)" : "var(--fg-faint)") : "inherit",
                            cursor: i === 0 ? "default" : "pointer",
                            padding: 0,
                            fontFamily: "var(--font-mono)",
                            fontSize: 11,
                            lineHeight: 1,
                            opacity: i === 0 ? 0.5 : 1,
                          }}>↑</button>
                  <button type="button"
                          onClick={(e) => { e.stopPropagation(); move(i, +1); }}
                          aria-label={t("Move layer down")}
                          data-cursor="link" data-cursor-label={t("Down")}
                          disabled={i === layers.length - 1}
                          style={{
                            background: "transparent",
                            border: 0,
                            color: i === layers.length - 1 ? (lifted ? "rgba(255,255,255,0.35)" : "var(--fg-faint)") : "inherit",
                            cursor: i === layers.length - 1 ? "default" : "pointer",
                            padding: 0,
                            fontFamily: "var(--font-mono)",
                            fontSize: 11,
                            lineHeight: 1,
                            opacity: i === layers.length - 1 ? 0.5 : 1,
                          }}>↓</button>
                </div>
                <div className="display-md" style={{ fontSize: 18, letterSpacing: "-0.005em", color: "inherit" }}>{t(layer.name)}</div>
                <div className="body-sm" style={{
                  color: lifted ? "rgba(255,255,255,0.78)" : "var(--fg-muted)",
                  fontFamily: "var(--font-mono)",
                  fontSize: 12,
                  lineHeight: 1.5,
                }}>
                  {t(layer.brief)}
                </div>
                <div className="micro" style={{
                  fontFamily: "var(--font-mono)",
                  color: lifted ? "rgba(255,255,255,0.5)" : "var(--fg-muted)",
                  textAlign: "right",
                }}>
                  {`#${String(layers.length - i).padStart(2, "0")}`}
                </div>
              </div>
              {isOpen && (
                <div style={{
                  borderTop: `1px solid ${lifted ? "rgba(255,255,255,0.2)" : "var(--line-soft)"}`,
                  padding: "14px 18px 16px",
                  display: "grid",
                  gridTemplateColumns: "1fr 1fr",
                  gap: 18,
                }} className="ml-layer-detail">
                  <div>
                    <div className="micro" style={{ color: lifted ? "rgba(255,255,255,0.55)" : "var(--fg-muted)", marginBottom: 8 }}>
                      {t("Tool stack")}
                    </div>
                    <div style={{
                      display: "flex",
                      flexWrap: "wrap",
                      gap: 6,
                      fontFamily: "var(--font-mono)",
                      fontSize: 11,
                    }}>
                      {layer.tools.map((tool) => (
                        <span key={tool} style={{
                          padding: "3px 8px",
                          border: `1px solid ${lifted ? "rgba(255,255,255,0.55)" : "var(--line)"}`,
                          letterSpacing: "0.04em",
                        }}>{tool}</span>
                      ))}
                    </div>
                  </div>
                  <div>
                    <div className="micro" style={{ color: lifted ? "rgba(255,255,255,0.55)" : "var(--fg-muted)", marginBottom: 8 }}>
                      {t("Principles enforced here")}
                    </div>
                    <ul style={{ listStyle: "none", padding: 0, margin: 0 }}>
                      {layer.principles.map((pid) => {
                        const p = ML_MANIFESTO.find((mp) => mp.id === pid);
                        return p ? (
                          <li key={pid} style={{
                            fontFamily: "var(--font-mono)",
                            fontSize: 11,
                            letterSpacing: "0.04em",
                            lineHeight: 1.6,
                          }}>
                            <span style={{ color: lifted ? "rgba(255,255,255,0.55)" : "var(--fg-muted)" }}>▶ </span>{t(p.title)}
                          </li>
                        ) : null;
                      })}
                    </ul>
                  </div>
                </div>
              )}
            </div>
          );
        })}
      </div>

      <style>{`
        @media (max-width: 760px) {
          .ml-stack .ml-layer { margin-left: 0 !important; }
          .ml-layer-row { grid-template-columns: 36px 1fr auto !important; }
          .ml-layer-row > div:nth-child(3) { grid-column: 1 / -1; padding-top: 4px; }
          .ml-layer-detail { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </div>
  );
}

/* ---- Lifecycle Flow — 10 stages, mouse-X scrub ----------------- */

function LifecycleFlow() {
  const [stageIdx, setStageIdx] = useStateML(0);
  const wrapRef = useRefML(null);
  const stage = ML_LIFECYCLE[stageIdx];

  const onMove = (e) => {
    if (!window.__hasHover) return;
    const r = wrapRef.current.getBoundingClientRect();
    const f = Math.max(0, Math.min(1, (e.clientX - r.left) / r.width));
    const idx = Math.min(ML_LIFECYCLE.length - 1, Math.floor(f * ML_LIFECYCLE.length));
    setStageIdx(idx);
  };

  return (
    <div style={{ marginBottom: 80 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", flexWrap: "wrap", gap: 12, marginBottom: 14 }}>
        <div>
          <div className="micro" style={{ marginBottom: 6 }}>{t("Fig. 02 · Research lifecycle")}</div>
          <div className="display-md" style={{ fontSize: 26 }}>{t("Ten stages. Mouse along the row to scrub.")}</div>
        </div>
        <div className="micro" style={{ color: "var(--fg-muted)" }}>{t("hover or tap a stage")}</div>
      </div>

      <div ref={wrapRef}
           onMouseMove={onMove}
           className="ml-lifecycle"
           style={{
             display: "grid",
             gridTemplateColumns: `repeat(${ML_LIFECYCLE.length}, 1fr)`,
             border: "1px solid var(--line)",
           }}>
        {ML_LIFECYCLE.map((s, i) => {
          const active = i === stageIdx;
          return (
            <button key={s.id}
                    type="button"
                    onClick={() => setStageIdx(i)}
                    onMouseEnter={() => window.__hasHover && setStageIdx(i)}
                    data-cursor="link" data-cursor-label={t(s.name)}
                    style={{
                      background: active ? "var(--fg)" : "var(--bg)",
                      color:      active ? "var(--bg)" : "var(--fg)",
                      border: 0,
                      borderRight: i < ML_LIFECYCLE.length - 1 ? "1px solid var(--line-soft)" : "0",
                      padding: "16px 8px 14px",
                      display: "flex", flexDirection: "column", alignItems: "center", gap: 8,
                      cursor: "pointer",
                      transition: "background 200ms var(--easing-default), color 200ms var(--easing-default)",
                    }}>
              <span className="micro" style={{ color: "inherit", fontSize: 9, opacity: 0.7 }}>{String(i + 1).padStart(2, "0")}</span>
              <span className="micro" style={{ color: "inherit", fontSize: 10, letterSpacing: "0.06em" }}>{t(s.name)}</span>
            </button>
          );
        })}
      </div>

      <div style={{
        marginTop: 14,
        padding: "14px 18px",
        border: "1px solid var(--line-soft)",
        display: "grid",
        gridTemplateColumns: "160px 1fr",
        gap: 22,
        alignItems: "start",
      }} className="ml-lifecycle-detail">
        <div className="micro" style={{ fontFamily: "var(--font-mono)", letterSpacing: "0.08em" }}>
          {String(stageIdx + 1).padStart(2, "0")} · {t(stage.name)}
        </div>
        <div className="body-sm" style={{ color: "var(--fg-muted)", lineHeight: 1.55 }}>
          {t(stage.hint)}
        </div>
      </div>

      <style>{`
        @media (max-width: 760px) {
          .ml-lifecycle { grid-template-columns: repeat(5, 1fr) !important; }
          .ml-lifecycle button { border-bottom: 1px solid var(--line-soft); }
          .ml-lifecycle-detail { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </div>
  );
}

/* ---- Research Loop Strip — 5 vertical sequences ---------------- */

function ResearchLoopStrip() {
  const [openIdx, setOpenIdx] = useStateML(0);
  return (
    <div style={{ marginBottom: 80 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", flexWrap: "wrap", gap: 12, marginBottom: 14 }}>
        <div>
          <div className="micro" style={{ marginBottom: 6 }}>{t("Fig. 03 · Example research loops")}</div>
          <div className="display-md" style={{ fontSize: 26 }}>{t("Five sequences, all command-line.")}</div>
        </div>
        <div className="micro" style={{ color: "var(--fg-muted)" }}>{t("click a row to inspect the command sequence")}</div>
      </div>

      <div style={{ border: "1px solid var(--line)" }}>
        {ML_LOOPS.map((loop, i) => {
          const open = openIdx === i;
          return (
            <div key={loop.id} style={{ borderTop: i === 0 ? "0" : "1px solid var(--line-soft)" }}>
              <button type="button"
                      onClick={() => setOpenIdx(open ? null : i)}
                      data-cursor="link" data-cursor-label={t(open ? "Close" : "Open")}
                      style={{
                        width: "100%",
                        background: open ? "var(--fg)" : "var(--bg)",
                        color:      open ? "var(--bg)" : "var(--fg)",
                        border: 0,
                        padding: "16px 20px",
                        display: "grid",
                        gridTemplateColumns: "40px 1fr 40px",
                        gap: 18,
                        alignItems: "center",
                        textAlign: "left",
                        cursor: "pointer",
                        transition: "background 200ms var(--easing-default), color 200ms var(--easing-default)",
                      }}>
                <span className="micro" style={{ fontFamily: "var(--font-mono)", color: "inherit", opacity: 0.7 }}>
                  {String(i + 1).padStart(2, "0")}
                </span>
                <span className="display-md" style={{ fontSize: 17, color: "inherit", letterSpacing: "-0.005em" }}>
                  {t(loop.title)}
                </span>
                <span className="micro" style={{
                  fontFamily: "var(--font-mono)",
                  color: "inherit",
                  textAlign: "right",
                  transform: open ? "rotate(90deg)" : "rotate(0)",
                  transition: "transform 240ms var(--easing-default)",
                }}>→</span>
              </button>
              {open && (
                <div style={{ padding: "14px 20px 18px", background: "var(--bg)" }}>
                  {loop.cmds.map((c, ci) => (
                    <div key={ci} style={{
                      fontFamily: "var(--font-mono)",
                      fontSize: 12.5,
                      lineHeight: 1.65,
                      letterSpacing: "0.01em",
                      color: "var(--fg)",
                      paddingLeft: 16,
                      borderLeft: "1px solid var(--line-soft)",
                      marginBottom: ci < loop.cmds.length - 1 ? 4 : 0,
                    }}>
                      <span style={{ color: "var(--fg-muted)", marginRight: 6 }}>$</span>{c}
                    </div>
                  ))}
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ---- Effect Catalog Grid — 15 effects in a 4×4 specimen row ---- */

function EffectCatalogGrid() {
  const [active, setActive] = useStateML(0);
  const a = ML_EFFECTS[active];
  return (
    <div style={{ marginBottom: 80 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", flexWrap: "wrap", gap: 12, marginBottom: 14 }}>
        <div>
          <div className="micro" style={{ marginBottom: 6 }}>{t("Fig. 04 · Effect catalog")}</div>
          <div className="display-md" style={{ fontSize: 26 }}>{t("Fifteen spintronic effects, one fit registry.")}</div>
        </div>
        <div className="micro" style={{ color: "var(--fg-muted)" }}>{t("hover or tap a cell to inspect")}</div>
      </div>

      <div className="ml-effects" style={{
        display: "grid",
        gridTemplateColumns: "repeat(5, 1fr)",
        border: "1px solid var(--line)",
      }}>
        {ML_EFFECTS.map((eff, i) => {
          const isActive = i === active;
          return (
            <button key={eff.id}
                    type="button"
                    onMouseEnter={() => window.__hasHover && setActive(i)}
                    onClick={() => setActive(i)}
                    data-cursor="link" data-cursor-label={t(eff.name)}
                    style={{
                      background: isActive ? "var(--fg)" : "var(--bg)",
                      color:      isActive ? "var(--bg)" : "var(--fg)",
                      border: 0,
                      borderRight: ((i + 1) % 5 !== 0) ? "1px solid var(--line-soft)" : "0",
                      borderBottom: i < ML_EFFECTS.length - (ML_EFFECTS.length % 5 || 5) ? "1px solid var(--line-soft)" : "0",
                      padding: "18px 10px 14px",
                      display: "flex", flexDirection: "column", alignItems: "center", gap: 10,
                      cursor: "pointer",
                      transition: "background 200ms var(--easing-default), color 200ms var(--easing-default)",
                    }}>
              <span className="micro" style={{ color: "inherit", fontSize: 9, opacity: 0.7 }}>
                {String(i + 1).padStart(2, "0")}
              </span>
              <span style={{ display: "inline-flex", color: "inherit" }}>
                <MlGlyph kind={eff.glyph} size={40} />
              </span>
              <span className="micro" style={{ color: "inherit", fontSize: 10, letterSpacing: "0.06em", textAlign: "center" }}>
                {eff.name}
              </span>
            </button>
          );
        })}
      </div>

      <div style={{
        marginTop: 14,
        padding: "14px 18px",
        border: "1px solid var(--line-soft)",
        display: "grid",
        gridTemplateColumns: "180px 1fr",
        gap: 22,
        alignItems: "center",
      }} className="ml-effects-detail">
        <div>
          <div className="micro" style={{ color: "var(--fg-muted)", marginBottom: 6 }}>{t("Effect")}</div>
          <div className="body-sm" style={{ fontFamily: "var(--font-mono)" }}>{a.name}</div>
        </div>
        <div>
          <div className="micro" style={{ color: "var(--fg-muted)", marginBottom: 6 }}>{t("Fit command")}</div>
          <div style={{ fontFamily: "var(--font-mono)", fontSize: 12.5, color: "var(--fg)" }}>
            <span style={{ color: "var(--fg-muted)", marginRight: 6 }}>$</span>maglab fit --effect {a.id} DATA.csv
          </div>
        </div>
      </div>

      <style>{`
        @media (max-width: 760px) {
          .ml-effects { grid-template-columns: repeat(3, 1fr) !important; }
          .ml-effects-detail { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </div>
  );
}

/* ---- Orchestrator Diagram — ASCII-style verifiable harness ----- */

function OrchestratorDiagram() {
  const nodes = [
    { id: "intent",  label: "Researcher intent",        hint: "A question, a draft, a measurement, a hypothesis." },
    { id: "surface", label: "CLI · REPL · MCP · gateways", hint: "Terminal-first; the same surface works for chat, IDE, and bot front-ends." },
    { id: "orch",    label: "Orchestrator · subagents · skills · checkpoints", hint: "Plan, route, budget, persist. Where LLMs reason." },
    { id: "gate",    label: "Physics oracle · honesty gate · DataPoint · PROV", hint: "Verification layer. Nothing leaves without provenance." },
    { id: "engines", label: "Deterministic engines",   hint: "physics · materials · simulation · analysis · figures · instruments" },
    { id: "apps",    label: "Lifecycle applications",   hint: "literature · lab notebook · review · authoring · communications" },
    { id: "output",  label: "Human-reviewed scientific output", hint: "Always marked for review. Inspectable later." },
  ];
  const [activeId, setActiveId] = useStateML("gate");
  const active = nodes.find(n => n.id === activeId) || nodes[0];

  return (
    <div style={{ marginBottom: 80 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", flexWrap: "wrap", gap: 12, marginBottom: 14 }}>
        <div>
          <div className="micro" style={{ marginBottom: 6 }}>{t("Fig. 05 · Verifiable orchestrator")}</div>
          <div className="display-md" style={{ fontSize: 26 }}>{t("Where the LLM thinks vs. where the lab decides.")}</div>
        </div>
        <div className="micro" style={{ color: "var(--fg-muted)" }}>{t("hover a layer to read its responsibility")}</div>
      </div>

      <div style={{
        border: "1px solid var(--line)",
        padding: "22px 24px",
        background: "var(--bg)",
        display: "grid",
        gridTemplateColumns: "1.4fr 1fr",
        gap: 28,
      }} className="ml-orch">
        <div style={{
          fontFamily: "var(--font-mono)",
          fontSize: 12,
          lineHeight: 1.55,
          letterSpacing: "0.02em",
          color: "var(--fg)",
        }}>
          {nodes.map((n, i) => {
            const isActive = n.id === activeId;
            return (
              <div key={n.id}
                   onMouseEnter={() => setActiveId(n.id)}
                   data-cursor="link" data-cursor-label={t(n.label)}
                   style={{
                     padding: "10px 12px",
                     background: isActive ? "var(--fg)" : "transparent",
                     color: isActive ? "var(--bg)" : "var(--fg)",
                     border: isActive ? "1px solid var(--fg)" : "1px solid var(--line-soft)",
                     cursor: "pointer",
                     transition: "background 180ms var(--easing-default), color 180ms var(--easing-default)",
                   }}>
                <span style={{ color: isActive ? "rgba(255,255,255,0.55)" : "var(--fg-muted)", marginRight: 10 }}>
                  {String(i + 1).padStart(2, "0")}
                </span>
                {n.label}
              </div>
            );
          }).reduce((acc, el, i, arr) => {
            acc.push(el);
            if (i < arr.length - 1) {
              acc.push(
                <div key={`sep-${i}`} style={{
                  textAlign: "center",
                  color: "var(--fg-muted)",
                  lineHeight: 1,
                  padding: "2px 0",
                }}>↓</div>
              );
            }
            return acc;
          }, [])}
        </div>
        <div>
          <div className="micro" style={{ color: "var(--fg-muted)", marginBottom: 10, letterSpacing: "0.08em" }}>
            ※ {t("On this layer")}
          </div>
          <div className="display-md" style={{ fontSize: 17, marginBottom: 10, lineHeight: 1.3 }}>
            {t(active.label)}
          </div>
          <div className="body-sm" style={{ color: "var(--fg-muted)", lineHeight: 1.6 }}>
            {t(active.hint)}
          </div>
          <div className="micro" style={{ marginTop: 18, color: "var(--fg-muted)", fontFamily: "var(--font-mono)", letterSpacing: "0.04em" }}>
            {t("The verification layer is not the mission statement. It is the safety rail that lets MagLab be useful in scientific work.")}
          </div>
        </div>
      </div>

      <style>{`
        @media (max-width: 760px) {
          .ml-orch { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </div>
  );
}

/* ---- Five Pillars Strip --------------------------------------- */

function FivePillarsStrip() {
  return (
    <div className="ml-pillars" style={{
      display: "grid",
      gridTemplateColumns: `repeat(${ML_PILLARS.length}, 1fr)`,
      borderTop: "1px solid var(--line)",
      borderBottom: "1px solid var(--line)",
      marginBottom: 56,
    }}>
      {ML_PILLARS.map((p, i) => (
        <div key={p.id} style={{
          padding: "22px 20px",
          borderRight: i < ML_PILLARS.length - 1 ? "1px solid var(--line-soft)" : "0",
        }}>
          <div className="micro" style={{ color: "var(--fg-muted)", marginBottom: 8, letterSpacing: "0.08em" }}>
            {String(i + 1).padStart(2, "0")} · {t(p.name)}
          </div>
          <div className="body-sm" style={{ color: "var(--fg)", lineHeight: 1.5 }}>
            {t(p.hint)}
          </div>
        </div>
      ))}
      <style>{`
        @media (max-width: 760px) {
          .ml-pillars { grid-template-columns: 1fr !important; }
          .ml-pillars > div { border-right: 0 !important; border-bottom: 1px solid var(--line-soft); }
          .ml-pillars > div:last-child { border-bottom: 0 !important; }
        }
      `}</style>
    </div>
  );
}

/* ---- MagLabCard — research-page bento card -------------------- */

function MagLabCard({ onClick }) {
  const ref = useRefML(null);
  const [hover, setHover] = useStateML(false);
  const [phase, setPhase] = useStateML(0);

  // gentle idle tick — a top-down sweep highlights one layer at a time
  useEffectML(() => {
    let raf;
    const start = performance.now();
    const tick = (now) => {
      const elapsed = (now - start) / 1000;
      const cyc = 6;
      setPhase((elapsed % cyc) / cyc);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);

  const liveIdx = Math.floor(phase * ML_LAYERS_SEED.length);

  return (
    <div ref={ref}
         onClick={onClick}
         onMouseEnter={() => setHover(true)}
         onMouseLeave={() => setHover(false)}
         data-cursor="link" data-cursor-label={t("View Project")}
         className="ml-card"
         style={{
           border: "1px solid var(--line)",
           background: "var(--bg)",
           padding: 28,
           display: "grid",
           gridTemplateColumns: "1.1fr 1fr 1fr",
           gap: 28,
           cursor: "pointer",
           alignItems: "center",
           minHeight: 220,
         }}>
      {/* left — mini multilayer stack schematic */}
      <div style={{ position: "relative", height: 160 }}>
        <svg viewBox="0 0 220 160" preserveAspectRatio="xMidYMid meet"
             style={{ width: "100%", height: "100%", display: "block" }}
             aria-hidden="true">
          {ML_LAYERS_SEED.map((_, i) => {
            const live = i === liveIdx;
            const y = 20 + i * 16;
            const x = 30 + i * 4;
            const w = 150;
            return (
              <g key={i}>
                <rect x={x} y={y} width={w} height={12}
                      fill={live ? "var(--fg)" : "var(--bg)"}
                      stroke="var(--fg)"
                      strokeWidth="1"
                      style={{ transition: "fill 320ms var(--easing-default)" }} />
              </g>
            );
          })}
        </svg>
      </div>

      {/* middle — title + tagline */}
      <div>
        <div className="micro" style={{ marginBottom: 8 }}>{t("02b · Toolchain · Open source")}</div>
        <div className="display-lg" style={{ fontSize: "clamp(34px, 4vw, 52px)", letterSpacing: "-0.02em", marginBottom: 8 }}>
          MagLab
        </div>
        <div className="body" style={{ color: "var(--fg-muted)", maxWidth: 320 }}>
          {t("Magnetism and spintronics research lifecycle copilot.")}
        </div>
      </div>

      {/* right — tagline + stack + cycle pointer */}
      <div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", gap: 16, height: "100%" }}>
        <div>
          <div className="micro" style={{ color: "var(--fg-muted)", marginBottom: 6, letterSpacing: "0.08em" }}>
            ※ {t("Manifesto")}
          </div>
          <div className="body-sm" style={{ color: "var(--fg)", lineHeight: 1.5 }}>
            {t("LLM reasons. Tools compute. Every number, citation, figure, and result has provenance.")}
          </div>
        </div>
        <div>
          <div className="micro" style={{ color: "var(--fg-muted)", marginBottom: 4 }}>
            Python · Ubermag · OpenAlex · lmfit · LiteLLM · MCP
          </div>
          <div className="micro" style={{ fontFamily: "var(--font-mono)", color: "var(--fg-muted)" }}>
            {`▸ ${ML_LAYERS_SEED[liveIdx].name}`}
          </div>
        </div>
      </div>

      <style>{`
        @media (max-width: 760px) {
          .ml-card { grid-template-columns: 1fr !important; gap: 18px !important; padding: 22px !important; min-height: 0 !important; }
          .ml-card > div:first-child { height: 120px !important; }
        }
      `}</style>
    </div>
  );
}

/* ---- MagLabPage — the case-study page ------------------------ */

function MagLabPage() {
  useLang();
  const { go } = useRouter();
  const [hoverPrincipleIdx, setHoverPrincipleIdx] = useStateML(null);

  const activeLayerIds = useMemoML(() => {
    if (hoverPrincipleIdx == null) return null;
    return new Set(ML_MANIFESTO[hoverPrincipleIdx].layerIds);
  }, [hoverPrincipleIdx]);

  return (
    <div className="page" style={{ paddingTop: 140 }}>
      <div className="page-eyebrow">
        <button type="button" onClick={() => go("research")} data-cursor="link" data-cursor-label={t("Back")} className="micro" style={{ display: "flex", alignItems: "center", gap: 8 }}>
          {t("← Index 02 / Research")}
        </button>
        <span style={{ width: 24, height: 1, background: "var(--fg)" }} />
        <span className="micro micro-fg">{t("Case study · MagLab")}</span>
        <span style={{ width: 24, height: 1, background: "var(--fg)" }} />
        <a href={MAGLAB_REPO} target="_blank" rel="noopener noreferrer"
           data-cursor="link" data-cursor-label={t("Open on GitHub")}
           className="micro" style={{ color: "var(--fg)", textDecoration: "none", borderBottom: "1px solid var(--line)" }}>
          {t("GitHub ↗ TaewoooPark/MagLab")}
        </a>
      </div>

      {/* Hero — title left, AI-for-Science rationale right */}
      <div className="responsive-stack ml-hero" style={{
        display: "grid",
        gridTemplateColumns: "1fr 1fr",
        gap: 56,
        marginBottom: 72,
        alignItems: "start",
      }}>
        <div>
          <h1 className="display-xxl" style={{ fontFamily: "var(--font-kr)", fontWeight: 700, letterSpacing: "-0.04em", marginBottom: 16 }}>
            MAGLAB
          </h1>
          <div className="micro" style={{ marginBottom: 22, color: "var(--fg-muted)", letterSpacing: "0.08em" }}>
            {t("MAGNETISM AND SPINTRONICS RESEARCH LIFECYCLE COPILOT_")}
          </div>
          <p className="body-lg" style={{ color: "var(--fg-muted)", maxWidth: 560, marginBottom: 24 }}>
            {t("A harness platform for spintronics research. The LLM plans, routes, explains, and drafts. Domain modules — formulae, units, materials, simulations, fitters, figure renderers, literature connectors, SCPI safety checks, provenance ledgers — do the actual scientific work.")}
          </p>
          <p className="body" style={{ color: "var(--fg)", marginBottom: 0, fontWeight: 500 }}>
            <em>{t("\"AI for Science as a lab instrument, not a demo prompt.\"")}</em>
          </p>
        </div>
        <div className="ml-rationale" style={{
          border: "1px solid var(--line)",
          padding: "30px 30px 28px",
          background: "var(--bg)",
          position: "relative",
          isolation: "isolate",
        }}>
          <div aria-hidden style={{
            position: "absolute",
            inset: "-6px -12px -12px -6px",
            zIndex: -1,
            background: "repeating-linear-gradient(135deg, transparent 0 6px, var(--line-soft) 6px 7px)",
            pointerEvents: "none",
          }} />
          <div className="display-md" style={{
            fontSize: 28,
            fontWeight: 700,
            letterSpacing: "-0.015em",
            lineHeight: 1.2,
            color: "var(--fg)",
            marginBottom: 22,
            maxWidth: 520,
          }}>
            {t("Why does AI for Science need a harness?")}
          </div>
          <p className="body" style={{ color: "var(--fg)", marginBottom: 14, lineHeight: 1.7 }}>
            {t("Modern research is no longer limited only by ideas. It is limited by coordination overhead — too many papers to audit, too many file formats, too many unit conventions, too many simulation backends, too many figure revisions, and too much undocumented context living in lab notebooks, scripts, and memory.")}
          </p>
          <p className="body" style={{ color: "var(--fg)", marginBottom: 14, lineHeight: 1.7 }}>
            {t("A useful scientific AI system therefore cannot be a chatbot. It needs a controlled environment where language models ask for deterministic tools, receive structured results, preserve provenance, and expose enough of the process for a scientist to inspect it.")}
          </p>
          <p className="body" style={{ color: "var(--fg-muted)", marginBottom: 0, lineHeight: 1.7 }}>
            {t("MagLab treats the LLM as an orchestration layer, not the source of scientific truth. Numerical values come from formulae, fitters, simulations, datasets, literature records, or explicit user input. Figures are vector artifacts bound to data and provenance — not generated raster guesses.")}
          </p>
        </div>
      </div>

      {/* Fig.01 — Pipeline stack (left) + Manifesto principles (right) */}
      <div className="ml-stack-row" style={{
        display: "grid",
        gridTemplateColumns: "1.55fr 1fr",
        gap: 40,
        alignItems: "start",
        marginBottom: 32,
      }}>
        <MultilayerStack activeLayerIds={activeLayerIds}
                         onLayerHover={null} />
        <div style={{ position: "sticky", top: 100 }} className="ml-manifesto-col">
          <div className="micro" style={{ marginBottom: 6, color: "var(--fg-muted)", letterSpacing: "0.08em" }}>
            ※ {t("Five manifesto principles")}
          </div>
          <div className="display-md" style={{ fontSize: 18, marginBottom: 14, letterSpacing: "-0.005em" }}>
            {t("Rules the pipeline must obey.")}
          </div>
          <ManifestoList hoverIdx={hoverPrincipleIdx}
                         onHover={setHoverPrincipleIdx}
                         onLeave={() => setHoverPrincipleIdx(null)} />
          <div className="micro" style={{ marginTop: 14, color: "var(--fg-muted)", lineHeight: 1.6 }}>
            {t("hover a principle — the pipeline layers that enforce it lift on the left")}
          </div>
        </div>
      </div>

      {/* § 01 — Research bottlenecks the harness addresses */}
      <div className="ml-narrative" style={{
        display: "grid",
        gridTemplateColumns: "200px 1fr 1fr",
        gap: 32,
        padding: "44px 0 36px",
        marginTop: 80,
        marginBottom: 32,
        borderTop: "1px solid var(--line-soft)",
        alignItems: "start",
      }}>
        <div className="micro" style={{ color: "var(--fg-muted)", letterSpacing: "0.08em", paddingTop: 4 }}>
          § 01 — {t("What it helps with")}
        </div>
        <div>
          <div className="display-md" style={{ fontSize: 22, marginBottom: 14, letterSpacing: "-0.005em", maxWidth: 360 }}>
            {t("Ten bottlenecks of a real spintronics project.")}
          </div>
          <p className="body" style={{ color: "var(--fg-muted)", lineHeight: 1.7, marginBottom: 0, maxWidth: 460 }}>
            {t("MagLab does not chase a leaderboard score. It targets the slow parts of research that no benchmark captures — auditing literature, translating material stacks into parameters, checking units, handing off between simulation scales, fitting spintronic effects, producing reproducible figures, scripting instruments, keeping an electronic lab notebook, reviewing manuscripts, and turning verified results into communication artifacts.")}
          </p>
        </div>
        <div>
          <ul className="micro" style={{ listStyle: "none", padding: 0, margin: 0, color: "var(--fg)", fontFamily: "var(--font-mono)", lineHeight: 1.95, fontSize: 11.5, letterSpacing: "0.04em" }}>
            <li>· {t("Literature overload — OpenAlex / Semantic Scholar / arXiv / Crossref evidence matrix")}</li>
            <li>· {t("Material and unit friction — physics oracle, multilayer builder, CGS↔SI conversion")}</li>
            <li>· {t("Simulation handoff — DFT → atomistic → micromagnetic → device spec")}</li>
            <li>· {t("Fitting and interpretation — 15-effect registry, lmfit, bounds, residuals")}</li>
            <li>· {t("Figure reproducibility — FigureSpec, vector renderers, journal styles")}</li>
            <li>· {t("Instrument scripting — PyVISA scaffold, SCPI validation, safety checks")}</li>
            <li>· {t("Lab memory — ELN entries, measurement plans, DOE next steps")}</li>
            <li>· {t("Review and critique — persona review, anomaly explanation, disclosure")}</li>
            <li>· {t("Authoring — manuscript, cover letter, revision, rebuttal, abstract, grant")}</li>
            <li>· {t("Orchestration — REPL, Ralph loops, MCP, subagents, gateways, checkpoints")}</li>
          </ul>
        </div>
      </div>

      <LifecycleFlow />

      {/* § 02 — Loops, not one-shots */}
      <div className="ml-narrative" style={{
        display: "grid",
        gridTemplateColumns: "200px 1fr",
        gap: 48,
        padding: "36px 0",
        marginBottom: 32,
        borderTop: "1px solid var(--line-soft)",
        borderBottom: "1px solid var(--line-soft)",
        alignItems: "start",
      }}>
        <div className="micro" style={{ color: "var(--fg-muted)", letterSpacing: "0.08em", paddingTop: 4 }}>
          § 02 — {t("Loops, not one-shots")}
        </div>
        <div>
          <p className="body-lg" style={{ color: "var(--fg)", lineHeight: 1.65, marginBottom: 14, maxWidth: 820 }}>
            {t("Research is a loop, not a prompt. A paper folder becomes a plan. A plan becomes a measurement. A measurement becomes a fit. A fit becomes a figure. A figure becomes a manuscript. Each step calls deterministic tools, each output gets a DataPoint, and the orchestrator decides what runs next.")}
          </p>
          <p className="body" style={{ color: "var(--fg-muted)", lineHeight: 1.7, marginBottom: 0, maxWidth: 820 }}>
            {t("The Ralph loops, MCP server/client, subagents, skills, gateway bots, cost tracking, and checkpoints are not productivity polish. They are how a multi-step research process stays inspectable when an LLM is in the middle of it.")}
          </p>
        </div>
      </div>

      <ResearchLoopStrip />

      {/* § 03 — One fit registry */}
      <div className="ml-narrative" style={{
        display: "grid",
        gridTemplateColumns: "200px 1fr",
        gap: 48,
        padding: "36px 0",
        marginTop: 64,
        marginBottom: 32,
        borderTop: "1px solid var(--line-soft)",
        borderBottom: "1px solid var(--line-soft)",
        alignItems: "start",
      }}>
        <div className="micro" style={{ color: "var(--fg-muted)", letterSpacing: "0.08em", paddingTop: 4 }}>
          § 03 — {t("One fit registry")}
        </div>
        <div>
          <p className="body-lg" style={{ color: "var(--fg)", lineHeight: 1.65, marginBottom: 14, maxWidth: 820 }}>
            {t("AMR, AHE, OHE, PHE, SMR, USMR, ST-FMR, FMR/Kittel, damping, spin pumping/ISHE, DMI, domain-wall, skyrmion/Thiele, hysteresis, and Curie-temperature models are fit through the same registry. Same loader, same lmfit backend, same parameter-bounds machinery, same ELN/provenance hooks.")}
          </p>
          <p className="body" style={{ color: "var(--fg-muted)", lineHeight: 1.7, marginBottom: 0, maxWidth: 820 }}>
            {t("A user can run maglab analyze model <effect> to inspect the model, then maglab fit --effect <effect> data.csv. The output is a fitted parameter set, a residuals report, and a DataPoint — not a paragraph of LLM speculation.")}
          </p>
        </div>
      </div>

      <EffectCatalogGrid />

      {/* § 04 — Honesty gate */}
      <div className="ml-narrative" style={{
        display: "grid",
        gridTemplateColumns: "200px 1fr",
        gap: 48,
        padding: "36px 0",
        marginTop: 64,
        marginBottom: 32,
        borderTop: "1px solid var(--line-soft)",
        borderBottom: "1px solid var(--line-soft)",
        alignItems: "start",
      }}>
        <div className="micro" style={{ color: "var(--fg-muted)", letterSpacing: "0.08em", paddingTop: 4 }}>
          § 04 — {t("Honesty gate")}
        </div>
        <div>
          <p className="body-lg" style={{ color: "var(--fg)", lineHeight: 1.65, marginBottom: 14, maxWidth: 820 }}>
            {t("Before a number, a citation, or a figure leaves the harness, it passes through the physics oracle, the honesty gate, the DataPoint store, and a W3C PROV ledger. The verification layer is not the mission statement. It is the safety rail that lets MagLab be useful in scientific work.")}
          </p>
          <p className="body" style={{ color: "var(--fg-muted)", lineHeight: 1.7, marginBottom: 0, maxWidth: 820 }}>
            {t("Without this rail, a research-grade LLM agent is just a faster way to publish wrong things. With it, the loop becomes auditable — every value points back to a deterministic source, every citation resolves, every figure has a recipe.")}
          </p>
        </div>
      </div>

      <OrchestratorDiagram />

      <FivePillarsStrip />

      {/* § 05 — Open invitation */}
      <div className="ml-narrative" style={{
        display: "grid",
        gridTemplateColumns: "200px 1fr",
        gap: 48,
        padding: "40px 0 48px",
        marginTop: 56,
        marginBottom: 56,
        borderTop: "1px solid var(--line)",
        alignItems: "start",
      }}>
        <div className="micro" style={{ color: "var(--fg-muted)", letterSpacing: "0.08em", paddingTop: 4 }}>
          § 05 — {t("Open source, open invitation")}
        </div>
        <div>
          <p className="body-lg" style={{ color: "var(--fg)", lineHeight: 1.65, marginBottom: 14, maxWidth: 820 }}>
            {t("MagLab ships under a permissive license. The CLI runs without LLM credentials for any module that is itself offline — formula evaluation, unit conversion, material lookup, fitting, figure rendering, ELN, provenance inspection. LLM-driven planning, drafting, and review activate when keys are configured.")}
          </p>
          <p className="body" style={{ color: "var(--fg-muted)", lineHeight: 1.7, marginBottom: 0, maxWidth: 820 }}>
            {t("If you study magnetism, spin transport, multilayers, domain walls, skyrmions, or related device physics — and you want your AI tooling to be a lab instrument instead of a chat window — clone the repository, run maglab doctor, and start the loop.")}
          </p>
        </div>
      </div>

      {/* One-row install strip — no comparison table */}
      <div className="ml-cta" style={{
        display: "grid", gridTemplateColumns: "auto 1fr auto",
        gap: 24, alignItems: "center",
        borderTop: "1px solid var(--line)", borderBottom: "1px solid var(--line)",
        padding: "22px 0", marginBottom: 80,
      }}>
        <div>
          <div className="micro" style={{ color: "var(--fg-muted)", marginBottom: 6 }}>{t("Try it")}</div>
          <code style={{ fontFamily: "var(--font-mono)", fontSize: 13, color: "var(--fg)" }}>
            git clone …/MagLab && uv sync && .venv/bin/python -m maglab --help
          </code>
        </div>
        <div className="micro" style={{ color: "var(--fg-muted)", textAlign: "center" }}>
          {t("Python · MIT-style license · Ubermag · OpenAlex · LiteLLM")}
        </div>
        <a href={MAGLAB_REPO} target="_blank" rel="noopener noreferrer"
           data-cursor="link" data-cursor-label={t("Open on GitHub")}
           className="micro"
           style={{ color: "var(--fg)", textDecoration: "none", borderBottom: "1px solid var(--fg)", paddingBottom: 2 }}>
          {t("github.com/TaewoooPark/MagLab →")}
        </a>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 24, marginBottom: 80 }} className="ml-nav">
        <button type="button" onClick={() => go("research")} data-cursor="link" data-cursor-label={t("Back")}
                style={{ padding: "32px", border: "1px solid var(--line)", textAlign: "left" }}>
          <div className="micro" style={{ marginBottom: 8, color: "var(--fg-muted)" }}>{t("← Previous")}</div>
          <div className="display-md">{t("Back to research")}</div>
        </button>
        <button type="button" onClick={() => go("projects")} data-cursor="link" data-cursor-label={t("Next")}
                style={{ padding: "32px", border: "1px solid var(--line)", textAlign: "right", background: "var(--fg)", color: "var(--bg)" }}>
          <div className="micro" style={{ marginBottom: 8, color: "rgba(255,255,255,0.5)" }}>{t("Next →")}</div>
          <div className="display-md">{t("Projects")}</div>
        </button>
      </div>

      <style>{`
        @media (max-width: 900px) {
          .ml-stack-row { grid-template-columns: 1fr !important; gap: 40px !important; }
          .ml-manifesto-col { position: static !important; }
        }
        @media (max-width: 760px) {
          .ml-hero { grid-template-columns: 1fr !important; gap: 36px !important; }
          .ml-narrative { grid-template-columns: 1fr !important; gap: 16px !important; }
          .ml-cta { grid-template-columns: 1fr !important; text-align: left !important; }
          .ml-cta > div, .ml-cta > a { text-align: left !important; }
          .ml-nav { grid-template-columns: 1fr !important; }
          .ml-nav button { text-align: left !important; padding: 24px !important; }
        }
      `}</style>
    </div>
  );
}

Object.assign(window, {
  MagLabPage, MagLabCard,
  ML_MANIFESTO, ML_LAYERS_SEED, ML_LIFECYCLE, ML_LOOPS, ML_EFFECTS, ML_PILLARS,
  MlGlyph, ManifestoList, MultilayerStack, LifecycleFlow, ResearchLoopStrip,
  EffectCatalogGrid, OrchestratorDiagram, FivePillarsStrip,
});
