(function(){
/* FORGE · mittelstand tenant — Line readiness  /line/queue
   Wave A1 / Mittelstand / Agent #16 (line-flavor).
   Single screen: ScreenMittelstandLine. Babel-standalone. NO imports/exports.
   Globals expected: React, getActiveTenant(), useActiveTenant(), navigate(),
   registerMittelstandRoute() (agent #3), Pill, Btn, I, Icons.

   Spec anchors:
     · tenant-spec/mittelstand.md §12 entry 16  (line-flavor task)
     · pump/act4-screens.jsx:1186 ScreenLineReadiness (visual reference)
     · §10 cool palette: --mittel-* vars from agent #8 cross-cutting.jsx
     · §3 anchor parts (GMN 180d, Heidenhain 45d, Kessler 90d…)
     · §4 KPIs · "Line readiness 91% (−3 pt, granite cell)"

   Mittelstand visual flavor: anthracite ink, steel accent, graphite ruling,
   units everywhere (µm, °C, mm/s, d, €). Mono privileged for every number.
*/

const { useState: uSML, useEffect: uEML, useMemo: uMML } = React;

/* ────────────────────────────────────────────────────────────────────
   Local style atoms — fall back to pump tokens until cross-cutting.jsx
   (agent #8) sets the --mittel-* vars on :root.
   ──────────────────────────────────────────────────────────────────── */

const ML_BG       = "var(--mittel-bg, var(--bg-1))";
const ML_BG_2     = "var(--mittel-bg-2, var(--bg-2))";
const ML_BG_3     = "var(--mittel-bg-3, var(--bg-3))";
const ML_INK      = "var(--mittel-ink, var(--ink))";
const ML_INK_2    = "var(--mittel-ink-2, var(--ink-2))";
const ML_INK_3    = "var(--mittel-ink-3, var(--ink-3))";
const ML_INK_4    = "var(--mittel-ink-4, var(--ink-4))";
const ML_LINE     = "var(--mittel-line, var(--line))";
const ML_LINE_S   = "var(--mittel-line-soft, var(--line-soft))";
const ML_ACCENT   = "var(--mittel-accent, var(--accent))";
const ML_WARN     = "var(--mittel-accent-warn, var(--warn))";
const ML_BAD      = "var(--mittel-accent-bad, var(--err))";
const ML_OK       = "var(--ok)";
const ML_INFO     = "var(--info)";
const ML_FONT_MN  = "var(--font-mono)";

/* Extracted styles (react-doctor: no-inline-exhaustive-style). */
const _ML_TOOLBAR_STYLE = {
  display: "flex",
  alignItems: "center",
  justifyContent: "space-between",
  gap: 8,
  padding: "6px 10px",
  background: ML_BG,
  borderBottom: "1px solid " + ML_LINE,
  height: 38,
  flexShrink: 0,
};
function _mlAvatarStyle(size, tone) {
  return {
    display: "inline-flex", alignItems: "center", justifyContent: "center",
    width: size, height: size, borderRadius: "50%",
    background: "color-mix(in oklch, " + tone + " 16%, " + ML_BG_2 + ")",
    color: tone,
    border: "1px solid color-mix(in oklch, " + tone + " 30%, " + ML_LINE + ")",
    fontFamily: ML_FONT_MN, fontSize: 12, letterSpacing: "0.04em", fontWeight: 600,
  };
}
const _ML_NEED_GRID_STYLE = {
  display: "grid",
  gridTemplateColumns: "repeat(3, 1fr)",
  gap: 6, marginTop: 8,
  border: "1px solid " + ML_LINE_S,
  borderRadius: 3,
  background: ML_BG_2,
  padding: 6,
};
const _ML_RECO_BOX_STYLE = {
  marginTop: 8, padding: 10,
  background: ML_BG_2,
  border: "1px dashed " + ML_LINE,
  borderRadius: 3,
  fontSize: 12, color: ML_INK_2, lineHeight: 1.5,
};

/* Toolbar — chassis-grey strip with chip + buttons */
function _MLToolbar({ children, right }) {
  return (
    <div style={_ML_TOOLBAR_STYLE}>
      <div style={{ display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }}>{children}</div>
      <div style={{ display: "flex", alignItems: "center", gap: 6 }}>{right}</div>
    </div>
  );
}

/* Modal · paper-overlay confirmer with Esc/backdrop dismiss */
function _MLModal({ title, body, onCancel, onConfirm, confirmLabel }) {
  uEML(() => {
    const onKey = (e) => { if (e.key === "Escape" && typeof onCancel === "function") onCancel(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onCancel]);
  return (
    <div
      role="button"
      tabIndex={0}
      onClick={() => { if (typeof onCancel === "function") onCancel(); }}
      onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); if (typeof onCancel === "function") onCancel(); } }}
      style={{
        position: "fixed", inset: 0,
        background: "color-mix(in oklch, " + ML_INK + " 38%, transparent)",
        display: "flex", alignItems: "center", justifyContent: "center", zIndex: 50,
      }}
    >
      <div
        role="dialog"
        aria-label={title}
        tabIndex={-1}
        onClick={e => e.stopPropagation()}
        onKeyDown={e => e.stopPropagation()}
        style={{
          background: "var(--bg-0)",
          border: "1px solid " + ML_LINE,
          borderRadius: 4,
          boxShadow: "0 18px 48px rgba(0,0,0,0.18)",
          width: 480,
          padding: 16,
        }}
      >
        <div className="label" style={{ color: ML_INK_3, marginBottom: 6 }}>{title}</div>
        <div style={{ fontSize: 13, color: ML_INK, lineHeight: 1.45, marginBottom: 14 }}>{body}</div>
        <div style={{ display: "flex", justifyContent: "flex-end", gap: 6 }}>
          <Btn onClick={onCancel}>Cancel</Btn>
          <Btn variant="primary" onClick={onConfirm}>{confirmLabel || "Confirm"}</Btn>
        </div>
      </div>
    </div>
  );
}

/* Skill bar · 0..1 ratio with steel/amber/bad tones */
function _MLSkillBar({ v }) {
  const tone = v >= 0.9 ? ML_OK : v >= 0.6 ? ML_INFO : v >= 0.3 ? ML_WARN : ML_INK_4;
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 4 }}>
      <div style={{ height: 5, flex: 1, background: ML_BG_3, borderRadius: 2, overflow: "hidden" }}>
        <div style={{ width: (v * 100) + "%", height: "100%", background: tone }} />
      </div>
      <span className="mono" style={{ fontSize: 12, color: ML_INK_3, minWidth: 22, textAlign: "right" }}>
        {Math.round(v * 100)}
      </span>
    </div>
  );
}

/* Initials avatar · steel-on-graphite circle */
function _MLAvatar({ name, size = 24 }) {
  const parts = String(name || "—").replace(/[^A-Za-z. ]/g, "").split(/\s+/).filter(Boolean);
  const a = parts[0] ? parts[0][0] : "?";
  const b = parts[1] ? parts[1][0] : (parts[0] && parts[0][1] ? parts[0][1] : "");
  const tone = ML_ACCENT;
  return (
    <span style={_mlAvatarStyle(size, tone)}>{(a + b).toUpperCase()}</span>
  );
}

/* Severity → Pill tone (matches pump convention) */
function _ml_sev(s) {
  if (s === "critical") return "err";
  if (s === "high")     return "warn";
  if (s === "med")      return "info";
  return "mute";
}

/* ════════════════════════════════════════════════════════════════════
   ScreenMittelstandLine · /line/queue
   Tomorrow's run readiness for the 24-mill MAHLE batch.
   ──────────────────────────────────────────────────────────────────── */

function ScreenMittelstandLine() {
  /* ── Long-lead inventory · the three named items per spec ─────── */
  const longLead = [
    {
      pn: "10.01-LAP",
      name: "Granite lap stones · ø450 grit-1200",
      supplier: "in-house · stones from Naturstein Hofmann",
      need: 6, on_hand: 2, eta_days: 14, eta_date: "2026-05-23",
      severity: "high",
      note: "Re-grind op for ECO-MS-0017 needs 6 stones / batch · reorder PO-LSC-0341 pending vendor acknowledgement",
      blocks: "Granite cell · routing op 04-LAP-RG (lap re-grind)",
    },
    {
      pn: "50.01",
      name: "Main spindle · HSK-A63 24k rpm",
      supplier: "GMN, Nürnberg",
      need: 24, on_hand: 6, eta_days: 180, eta_date: "2026-11-04",
      severity: "critical",
      note: "Long-lead 180 d · PO-GMN-2401..2418 released 2026-01-11 · 12 / 18 confirmed in production · no real dual-source",
      blocks: "Subassy station 3 · spindle alignment to A/C head",
    },
    {
      pn: "70.00",
      name: "Control cabinet · Heidenhain TNC 640",
      supplier: "Heidenhain, Traunreut",
      need: 24, on_hand: 8, eta_days: 45, eta_date: "2026-06-23",
      severity: "med",
      note: "PO-HDN-2401..2424 released 2026-01-11 · cabinet wiring batched in lots of 6 · LC 415 encoders shipping in parallel",
      blocks: "Final wiring op 06-CTRL · pre-FAT software load",
    },
  ];

  /* ── Tomorrow's WO progression · 24-mill batch readiness ──────── */
  const tomorrow = {
    date: "2026-05-10",
    shift: "Frühschicht (06:00–14:30)",
    target: "Mill 06 · Station 2 (machine shop) → Mill 04 · Station 3 (subassy) → Mill 02 · Station 4 (FAI rehearsal)",
    units_active: 6,
    units_done: 1,
    units_total: 24,
  };

  const progression = [
    { wo: "WO-MTL-2401", unit: "MTL-220 · S/N 0001", station: "S4 · FAI",        progress: 0.96, status: "FAI rehearsal · MAHLE witness 2026-08-14", tone: "info"    },
    { wo: "WO-MTL-2402", unit: "MTL-220 · S/N 0002", station: "S4 · FAI",        progress: 0.84, status: "ballbar pass · contouring vibe pending",     tone: "info"    },
    { wo: "WO-MTL-2403", unit: "MTL-220 · S/N 0003", station: "S3 · subassy",    progress: 0.71, status: "spindle aligned · awaiting Faro check",      tone: "ok"      },
    { wo: "WO-MTL-2404", unit: "MTL-220 · S/N 0004", station: "S3 · subassy",    progress: 0.62, status: "C-axis rotary mating in progress",            tone: "ok"      },
    { wo: "WO-MTL-2405", unit: "MTL-220 · S/N 0005", station: "S2 · machine",    progress: 0.48, status: "Z-axis ram bores, op 03-Z-FIN running",      tone: "ok"      },
    { wo: "WO-MTL-2406", unit: "MTL-220 · S/N 0006", station: "S2 · machine",    progress: 0.34, status: "granite cross-beam at lap re-grind · short on stones", tone: "warn" },
    { wo: "WO-MTL-2407", unit: "MTL-220 · S/N 0007", station: "S1 · receiving",  progress: 0.18, status: "granite blank on surface plate (3 µm target)", tone: "ok"      },
    { wo: "WO-MTL-2408", unit: "MTL-220 · S/N 0008", station: "S1 · receiving",  progress: 0.10, status: "blank scheduled · COC arrived 2026-05-08",    tone: "mute"    },
  ];

  /* ── Operators on shift · skills matrix ───────────────────────── */
  const operators = [
    { name: "M. Schreiber", role: "Granite cell lead · Stations 1–2",        shift: "Frühschicht", skills: { receiving: 1.0, granite: 1.0, machining: 0.8, subassy: 0.4, fai: 0.3, metrology: 0.7 } },
    { name: "T. Ostermann", role: "CNC machinist · X/Y/Z bores · Station 2", shift: "Frühschicht", skills: { receiving: 0.4, granite: 0.5, machining: 1.0, subassy: 0.5, fai: 0.3, metrology: 0.6 } },
    { name: "K. Vogt",      role: "Spindle subassy · Station 3",             shift: "Frühschicht", skills: { receiving: 0.3, granite: 0.2, machining: 0.5, subassy: 1.0, fai: 0.7, metrology: 0.8 } },
    { name: "D. Hüber",     role: "FAI / acceptance · Station 4",            shift: "Frühschicht", skills: { receiving: 0.4, granite: 0.3, machining: 0.6, subassy: 0.7, fai: 1.0, metrology: 1.0 } },
    { name: "S. Klein",     role: "Quality lead · floating · CMM operator",  shift: "Frühschicht", skills: { receiving: 0.6, granite: 0.6, machining: 0.7, subassy: 0.7, fai: 0.9, metrology: 1.0 } },
  ];

  /* ── Machines & uptime ────────────────────────────────────────── */
  const machines = [
    { id: "GRD-01",  name: "Granite lapping bed · 2.4 m × 1.2 m",   uptime: 0.97, status: "ok",   note: "lap stones short · 2 of 6 on hand"          },
    { id: "GRD-02",  name: "Granite re-grind station (ECO-MS-0017)",uptime: 0.92, status: "warn", note: "re-grind op qualified 2026-03 · waiting stones" },
    { id: "CNC-DMU", name: "DMU 75 monoBLOCK · X/Y/Z carriage cuts", uptime: 0.94, status: "ok",   note: "Heidenhain TNC 640 control · scheduled 14:30 cal" },
    { id: "CNC-DMC", name: "DMC 1450 V · ram bores",                 uptime: 0.91, status: "ok",   note: "tooling magazine refreshed · 24 HSK-A63 holders ready" },
    { id: "ASM-01",  name: "Subassy bench · spindle / A-C head",     uptime: 0.99, status: "ok",   note: "Faro Vantage tracker last cal 2026-04-22"   },
    { id: "FAI-01",  name: "Acceptance cell · ISO 230-2 / ballbar",  uptime: 0.95, status: "ok",   note: "Renishaw QC20-W ballbar cal 2026-04-30"     },
  ];
  const uptimeAvg = machines.reduce((s, m) => s + m.uptime, 0) / machines.length;

  /* ── Takt time computation · §3 program window ────────────────── */
  const taktDays = uMML(() => {
    // 24 units · production window 2026-06 first article → 2026-12 ship
    // ~ 26 weeks · 5 working days = 130 days available, 24 units → 5.4 d / unit
    const window_days = 130;
    const units = 24;
    return (window_days / units);
  }, []);

  /* ── State ────────────────────────────────────────────────────── */
  const [showRiskPanel, setShowRiskPanel] = uSML(false);
  const [showLockModal, setShowLockModal] = uSML(false);
  const [picked, setPicked] = uSML(null);
  // W14B — toast for modal-confirm mutate results.
  const [toast, setToast] = uSML(null);
  uEML(() => {
    if (!toast) return undefined;
    const t = setTimeout(() => setToast(null), 3000);
    return () => clearTimeout(t);
  }, [toast]);

  /* ── W14B · modal-confirm mutate handlers ─────────────────────── */
  function _mlActor() {
    const u = (typeof window !== "undefined") ? window.__forgeCurrentUser : null;
    return (u && u.name) || "—";
  }
  function _mlQueuedOk(err) {
    // server 404 = unknown resource for this tenant; 400 = invalid patch path.
    // Either way the demo treats the action as queued so the flow continues.
    return err && (err.status === 404 || err.status === 400);
  }
  function _mlLockAndPublish() {
    const actor = _mlActor();
    if (window.forgeApi && typeof window.forgeApi.mutate === "function") {
      window.forgeApi.mutate("line_locks", {
        op: "add", path: "/-",
        value: { shift: tomorrow.shift, date: tomorrow.date, locked_by: actor, ts: Date.now() },
      }).then(function () {
        setToast({ kind: "ok", msg: "Line locked · LINE_LOCKED emitted" });
      }).catch(function (err) {
        if (_mlQueuedOk(err)) {
          setToast({ kind: "ok", msg: "LINE_LOCKED queued · " + tomorrow.date });
        } else {
          setToast({ kind: "err", msg: "Lock failed · " + (err && err.message || "unknown") });
        }
      });
    } else {
      setToast({ kind: "ok", msg: "LINE_LOCKED queued · " + tomorrow.date });
    }
    setShowLockModal(false);
  }
  function _mlScheduleAudit() {
    // Risk-panel confirm: "Acknowledge" when nothing picked, otherwise
    // "Schedule audit · <supplier>" which writes to supplier_audits.
    if (!picked) {
      setShowRiskPanel(false);
      return;
    }
    const supplier = picked;
    const actor = _mlActor();
    if (window.forgeApi && typeof window.forgeApi.mutate === "function") {
      window.forgeApi.mutate("supplier_audits", {
        op: "add", path: "/-",
        value: { supplier: supplier, scheduled_by: actor, scheduled_at: Date.now(), kind: "Q3-envelope" },
      }).then(function () {
        setToast({ kind: "ok", msg: "Audit scheduled · " + supplier });
      }).catch(function (err) {
        if (_mlQueuedOk(err)) {
          setToast({ kind: "ok", msg: "Audit queued · " + supplier });
        } else {
          setToast({ kind: "err", msg: "Schedule failed · " + (err && err.message || "unknown") });
        }
      });
    } else {
      setToast({ kind: "ok", msg: "Audit queued · " + supplier });
    }
    setShowRiskPanel(false);
    setPicked(null);
  }

  uEML(() => {
    const onTenant = () => { setShowRiskPanel(false); setShowLockModal(false); setPicked(null); };
    window.addEventListener("forge:tenant-change", onTenant);
    return () => window.removeEventListener("forge:tenant-change", onTenant);
  }, []);

  /* ── Render ───────────────────────────────────────────────────── */
  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", minHeight: 0, background: ML_BG_3 }}>

      <_MLToolbar
        right={
          <>
            <Btn icon="Calendar" onClick={() => window.forgeToast && window.forgeToast("Shift schedule queued — wired in v2")}>Shift schedule</Btn>
            <Btn icon="File" onClick={() => window.forgeToast && window.forgeToast("Export readiness PDF queued — wired in v2")}>Export readiness PDF</Btn>
            <Btn variant="primary" icon="Check" onClick={() => setShowLockModal(true)}>
              Lock line for tomorrow
            </Btn>
          </>
        }
      >
        <span style={{ fontSize: 12, color: ML_INK_3 }}>
          Tomorrow ·{" "}
          <b className="mono" style={{ color: ML_INK_2 }}>{tomorrow.date} / {tomorrow.shift}</b>
          &nbsp;·&nbsp; target&nbsp;
          <span className="mono" style={{ color: ML_INK_2 }}>{tomorrow.units_active} units active</span>
          &nbsp;·&nbsp;
          <span style={{ color: ML_WARN }}>1 long-lead short · 1 calculated risk · granite cell −3 pt</span>
        </span>
      </_MLToolbar>

      {/* ── Header strip · KPI tiles ─────────────────────────────── */}
      <div style={{
        display: "grid",
        gridTemplateColumns: "repeat(6, 1fr)",
        borderBottom: "1px solid " + ML_LINE,
        background: ML_BG,
      }}>
        {[
          { k: "Line readiness",    v: "91%",                   t: "−3 pt (granite cell)",        tone: "warn" },
          { k: "Units in flight",   v: tomorrow.units_active + " / " + tomorrow.units_total, t: "MAHLE 24-mill batch", tone: "info" },
          { k: "Takt time",         v: taktDays.toFixed(1) + " d/unit", t: "26-wk window",         tone: "ok"   },
          { k: "Machine uptime",    v: (uptimeAvg * 100).toFixed(1) + " %", t: "6 cells · trailing 30 d", tone: "ok" },
          { k: "Operators on shift",v: operators.length + " / 5",t: tomorrow.shift.split(" ")[0],   tone: "ok"   },
          { k: "Open ECOs",         v: "1 critical",             t: "ECO-MS-0017 granite re-grind",tone: "warn" },
        ].map((tile, i) => (
          <div key={tile.k} style={{
            padding: "10px 12px",
            borderRight: i < 5 ? "1px solid " + ML_LINE_S : "none",
          }}>
            <div className="label" style={{ color: ML_INK_3, fontSize: 12, letterSpacing: "0.04em" }}>{tile.k}</div>
            <div className="mono tnum" style={{
              fontSize: 18, color: ML_INK, marginTop: 4, letterSpacing: "-0.01em",
            }}>{tile.v}</div>
            <div className="mono" style={{ fontSize: 12, color: tile.tone === "warn" ? ML_WARN : tile.tone === "ok" ? ML_OK : ML_INK_3, marginTop: 2 }}>
              {tile.t}
            </div>
          </div>
        ))}
      </div>

      <div style={{ flex: 1, display: "grid", gridTemplateColumns: "1.3fr 1.1fr 1fr 0.95fr", minHeight: 0 }}>

        {/* ── Column 1 · Long-lead & shortages ────────────────── */}
        <div style={{ borderRight: "1px solid " + ML_LINE, display: "flex", flexDirection: "column", minHeight: 0 }}>
          <div className="label" style={{
            padding: "8px 12px",
            borderBottom: "1px solid " + ML_LINE,
            background: ML_BG,
            display: "flex", justifyContent: "space-between", alignItems: "center",
          }}>
            <span>LONG-LEAD &amp; SHORTAGE</span>
            <span style={{ color: ML_WARN }}>1 short · 2 in transit</span>
          </div>
          <div style={{ flex: 1, overflow: "auto" }}>
            {longLead.map((it, i) => {
              const short = it.on_hand < it.need;
              const sevTone = it.severity === "critical" ? ML_BAD : it.severity === "high" ? ML_WARN : ML_INK_3;
              return (
                <div key={it.pn} style={{
                  padding: "12px 14px",
                  borderBottom: "1px solid " + ML_LINE_S,
                  background: short ? "color-mix(in oklch, " + ML_BAD + " 5%, transparent)" : "transparent",
                }}>
                  <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", gap: 8 }}>
                    <span className="mono" style={{ fontSize: 12, color: ML_INK_3 }}>{it.pn}</span>
                    <Pill tone={_ml_sev(it.severity)}>{it.severity}</Pill>
                  </div>
                  <div style={{ marginTop: 4, fontSize: 12.5, color: ML_INK }}>{it.name}</div>
                  <div className="mono" style={{ fontSize: 12, color: ML_INK_3, marginTop: 2 }}>
                    {it.supplier}
                  </div>

                  <div style={_ML_NEED_GRID_STYLE}>
                    <div>
                      <div className="label" style={{ fontSize: 12, color: ML_INK_3 }}>NEED</div>
                      <div className="mono tnum" style={{ fontSize: 13, color: ML_INK }}>{it.need}</div>
                    </div>
                    <div>
                      <div className="label" style={{ fontSize: 12, color: ML_INK_3 }}>ON HAND</div>
                      <div className="mono tnum" style={{ fontSize: 13, color: short ? ML_BAD : ML_INK }}>{it.on_hand}</div>
                    </div>
                    <div>
                      <div className="label" style={{ fontSize: 12, color: ML_INK_3 }}>ETA</div>
                      <div className="mono tnum" style={{ fontSize: 13, color: ML_INK }}>{it.eta_days} d</div>
                      <div className="mono" style={{ fontSize: 12, color: ML_INK_3 }}>{it.eta_date}</div>
                    </div>
                  </div>

                  <div style={{ fontSize: 12, color: ML_INK_2, marginTop: 8, lineHeight: 1.45 }}>
                    {it.note}
                  </div>
                  <div className="mono" style={{ fontSize: 12, color: sevTone, marginTop: 6 }}>
                    blocks → {it.blocks}
                  </div>

                  <div style={{ display: "flex", gap: 6, marginTop: 8 }}>
                    {it.pn === "50.01" ? (
                      <Btn onClick={() => setShowRiskPanel(true)}>
                        Open risk panel
                      </Btn>
                    ) : (
                      <>
                        <Btn onClick={() => window.forgeToast && window.forgeToast("Expedite queued — wired in v2")}>Expedite</Btn>
                        <Btn icon="Sparkle" onClick={() => window.forgeToast && window.forgeToast("Suggest mitigation queued — wired in v2")}>Suggest mitigation</Btn>
                      </>
                    )}
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        {/* ── Column 2 · Tomorrow's run progression ──────────── */}
        <div style={{ borderRight: "1px solid " + ML_LINE, display: "flex", flexDirection: "column", minHeight: 0 }}>
          <div className="label" style={{
            padding: "8px 12px",
            borderBottom: "1px solid " + ML_LINE,
            background: ML_BG,
            display: "flex", justifyContent: "space-between", alignItems: "center",
          }}>
            <span>RUN READINESS · 24-MILL BATCH</span>
            <span className="mono" style={{ color: ML_INK_3 }}>{tomorrow.units_done}/{tomorrow.units_total} done</span>
          </div>
          <div style={{ padding: "8px 12px", borderBottom: "1px solid " + ML_LINE_S, background: ML_BG_2 }}>
            <div className="label" style={{ fontSize: 12, color: ML_INK_3 }}>SEQUENCE</div>
            <div style={{ fontSize: 12, color: ML_INK_2, marginTop: 3, lineHeight: 1.4 }}>{tomorrow.target}</div>
          </div>

          <div style={{ flex: 1, overflow: "auto" }}>
            {progression.map(p => {
              const tone = p.tone === "warn" ? ML_WARN : p.tone === "ok" ? ML_OK : p.tone === "info" ? ML_INFO : ML_INK_3;
              return (
                <div key={p.wo} style={{
                  padding: "10px 12px",
                  borderBottom: "1px solid " + ML_LINE_S,
                }}>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 6 }}>
                    <span className="mono" style={{ fontSize: 12, color: ML_INK_3 }}>{p.wo}</span>
                    <span className="mono" style={{ fontSize: 12, color: tone }}>{p.station}</span>
                  </div>
                  <div style={{ fontSize: 12, color: ML_INK, marginTop: 3 }}>{p.unit}</div>
                  <div style={{ marginTop: 6, height: 5, background: ML_BG_3, borderRadius: 2, overflow: "hidden", border: "1px solid " + ML_LINE_S }}>
                    <div style={{
                      width: (p.progress * 100).toFixed(1) + "%",
                      height: "100%",
                      background: tone,
                    }} />
                  </div>
                  <div style={{ display: "flex", justifyContent: "space-between", marginTop: 3 }}>
                    <span className="mono" style={{ fontSize: 12, color: ML_INK_3 }}>{p.status}</span>
                    <span className="mono" style={{ fontSize: 12, color: ML_INK_3 }}>{(p.progress * 100).toFixed(0)}%</span>
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        {/* ── Column 3 · Operators · skill matrix ────────────── */}
        <div style={{ borderRight: "1px solid " + ML_LINE, display: "flex", flexDirection: "column", minHeight: 0 }}>
          <div className="label" style={{
            padding: "8px 12px",
            borderBottom: "1px solid " + ML_LINE,
            background: ML_BG,
            display: "flex", justifyContent: "space-between", alignItems: "center",
          }}>
            <span>OPERATORS · {tomorrow.shift.split(" ")[0].toUpperCase()}</span>
            <span style={{ color: ML_OK }}>{operators.length}/5 confirmed</span>
          </div>
          <div style={{ flex: 1, overflow: "auto" }}>
            {operators.map(o => (
              <div key={o.name} style={{ padding: "10px 12px", borderBottom: "1px solid " + ML_LINE_S }}>
                <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 4 }}>
                  <_MLAvatar name={o.name} size={24} />
                  <div style={{ minWidth: 0 }}>
                    <div style={{ color: ML_INK, fontSize: 12 }}>{o.name}</div>
                    <div style={{ fontSize: 12, color: ML_INK_3 }}>{o.role}</div>
                  </div>
                </div>
                <div style={{
                  display: "grid",
                  gridTemplateColumns: "70px 1fr",
                  gap: 4,
                  marginTop: 4,
                  fontSize: 12,
                  fontFamily: ML_FONT_MN,
                }}>
                  {Object.entries(o.skills).map(([k, v]) => (
                    <React.Fragment key={k}>
                      <div style={{ color: ML_INK_3 }}>{k}</div>
                      <_MLSkillBar v={v} />
                    </React.Fragment>
                  ))}
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* ── Column 4 · Machines · uptime · risk · verdict ──── */}
        <div style={{ display: "flex", flexDirection: "column", minHeight: 0 }}>
          <div className="label" style={{
            padding: "8px 12px",
            borderBottom: "1px solid " + ML_LINE,
            background: ML_BG,
            display: "flex", justifyContent: "space-between", alignItems: "center",
          }}>
            <span>MACHINE UPTIME · 30 d</span>
            <span className="mono" style={{ color: ML_OK }}>{(uptimeAvg * 100).toFixed(1)}% avg</span>
          </div>
          <div style={{ flex: 1, overflow: "auto" }}>
            {machines.map(m => {
              const tone = m.status === "warn" ? ML_WARN : ML_OK;
              return (
                <div key={m.id} style={{ padding: "8px 12px", borderBottom: "1px solid " + ML_LINE_S }}>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                    <span className="mono" style={{ fontSize: 12, color: ML_INK_3 }}>{m.id}</span>
                    <span className="mono tnum" style={{ fontSize: 12, color: tone }}>{(m.uptime * 100).toFixed(1)} %</span>
                  </div>
                  <div style={{ fontSize: 12, color: ML_INK, marginTop: 3 }}>{m.name}</div>
                  <div style={{
                    marginTop: 4, height: 4, background: ML_BG_3, borderRadius: 2, overflow: "hidden",
                    border: "1px solid " + ML_LINE_S,
                  }}>
                    <div style={{ width: (m.uptime * 100) + "%", height: "100%", background: tone }} />
                  </div>
                  <div className="mono" style={{ fontSize: 12, color: ML_INK_3, marginTop: 4 }}>{m.note}</div>
                </div>
              );
            })}

            {/* ── Calculated risk panel · GMN dual-source ───── */}
            <div style={{
              margin: 12,
              padding: 12,
              border: "1px solid " + ML_BAD,
              borderLeft: "3px solid " + ML_BAD,
              borderRadius: 3,
              background: "color-mix(in oklch, " + ML_BAD + " 6%, " + ML_BG + ")",
            }}>
              <div className="label" style={{ color: ML_BAD, fontSize: 12, marginBottom: 4 }}>
                CALCULATED RISK
              </div>
              <div style={{ fontSize: 12, color: ML_INK, lineHeight: 1.45 }}>
                <b>No real dual-source for GMN spindle</b> (HSK-A63, 24k rpm, P/N <span className="mono">50.01</span>).
              </div>
              <div style={{ fontSize: 12, color: ML_INK_2, marginTop: 6, lineHeight: 1.45 }}>
                Kessler &amp; Weiss carry electric spindles but <b>not at the &lt;0.4 µm runout</b> spec the
                MTL-220 acceptance test demands. Re-qualifying a substitute would re-open ECO-MS-0017
                geometric envelope and trigger PPAP Level 3 re-submission.
              </div>
              <div style={{ marginTop: 8, padding: 8, background: ML_BG_3, border: "1px dashed " + ML_LINE, borderRadius: 3 }}>
                <div className="mono" style={{ fontSize: 12, color: ML_INK_3, lineHeight: 1.5 }}>
                  exposure&nbsp;&nbsp;&nbsp;= 18 of 24 spindles in transit · 6 on hand<br/>
                  worst case&nbsp;= GMN slip 30 d → batch-2 release moves 2026-12 → 2027-01<br/>
                  mitigation = (a) accelerate batch-1 close, (b) carry 1 buffer spindle, (c) hot-line GMN ops
                </div>
              </div>
              <div style={{ display: "flex", gap: 6, marginTop: 8 }}>
                <Btn onClick={() => setShowRiskPanel(true)}>Risk detail</Btn>
                <Btn icon="Sparkle" onClick={() => window.forgeToast && window.forgeToast("Draft mitigation queued — wired in v2")}>Draft mitigation</Btn>
              </div>
            </div>

            {/* ── Verdict footer ─────────────────────────── */}
            <div style={{ padding: "12px 14px", fontSize: 12, color: ML_INK_2, lineHeight: 1.5, borderTop: "1px solid " + ML_LINE_S }}>
              <div className="label" style={{ marginBottom: 4, color: ML_INK_3 }}>READINESS VERDICT</div>
              Line is <b style={{ color: ML_WARN }}>conditionally ready</b> for {tomorrow.shift.split(" ")[0]} on{" "}
              <span className="mono">{tomorrow.date}</span>. Lap-stone reorder must clear by{" "}
              <span className="mono">2026-05-23</span> to keep granite re-grind on plan;
              spindle path remains the <b>180-d critical path</b>, not the 11-d ECO delta.
              FAI rehearsal on S/N 0001 stays anchored at <span className="mono">2026-08-14</span>.
            </div>
          </div>
        </div>
      </div>

      {/* ── Risk detail modal ──────────────────────────────────── */}
      {showRiskPanel && (
        <_MLModal
          title="GMN spindle · dual-source feasibility"
          body={
            <div>
              <div style={{ marginBottom: 10, fontSize: 12, color: ML_INK_2 }}>
                Three candidates evaluated against the <span className="mono">50.01</span> spec
                (HSK-A63, 24k rpm, &lt;0.4 µm TIR runout, IATF 16949 PPAP feasible).
              </div>
              {(function() {
                var i18n = (typeof window !== "undefined") ? window.forgeI18n : null;
                var stMoney = (i18n && i18n.formatMoneyMinor) ? (i18n.formatMoneyMinor("640000", "EUR") || "€6,400") : "€6,400";
                return [
                  { name: "Weiss Spindeltechnologie", loc: "Maroldsweisach, DE", lt: 200, fit: 78, note: "Closest geometry · runout spec 0.6 µm at 24k · PPAP re-qual estimated 90 d" },
                  { name: "Kessler",                  loc: "Bad Buchau, DE",     lt: 165, fit: 72, note: "Already supplies 50.00 head · spindle lineup tops out at 18k rpm · would force speed de-rate" },
                  { name: "Step-Tec (GF)",            loc: "Luterbach, CH",      lt: 220, fit: 84, note: "Premium fit · runout 0.3 µm · ECO-MS-0017 envelope re-test required · cost +" + stMoney + " / unit" },
                ];
              })().map(s => (
                <div key={s.name} role="button" tabIndex={0} style={{
                  padding: 10, marginBottom: 8,
                  border: "1px solid " + ML_LINE,
                  borderRadius: 3,
                  background: picked === s.name ? "color-mix(in oklch, " + ML_ACCENT + " 8%, transparent)" : ML_BG,
                  cursor: "pointer",
                }} onClick={() => setPicked(s.name)} onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); setPicked(s.name); } }}>
                  <div style={{ display: "flex", justifyContent: "space-between" }}>
                    <b style={{ fontSize: 13, color: ML_INK }}>{s.name}</b>
                    <span className="mono" style={{ fontSize: 12, color: ML_INK_3 }}>{s.loc}</span>
                  </div>
                  <div style={{ fontSize: 12, color: ML_INK_3, marginTop: 4 }}>
                    LT <b className="mono">{s.lt} d</b> · spec fit <b className="mono">{s.fit}%</b>
                  </div>
                  <div style={{ fontSize: 12, color: ML_INK_2, marginTop: 6, lineHeight: 1.45 }}>{s.note}</div>
                </div>
              ))}
              <div style={_ML_RECO_BOX_STYLE}>
                <b>Recommendation:</b> hold GMN as primary, carry one buffer spindle in
                stores, schedule a Step-Tec audit visit in Q3 2026 against an MTL-220 Rev E
                envelope refresh, not against the active Rev D batch.
              </div>
            </div>
          }
          onCancel={() => { setShowRiskPanel(false); setPicked(null); }}
          onConfirm={_mlScheduleAudit}
          confirmLabel={picked ? "Schedule audit · " + picked : "Acknowledge"}
        />
      )}

      {/* ── Lock-line modal ────────────────────────────────────── */}
      {showLockModal && (
        <_MLModal
          title={"Lock line · " + tomorrow.date}
          body={
            <div style={{ fontSize: 12, color: ML_INK_2, lineHeight: 1.5 }}>
              Locking the line freezes WO sequence and operator assignments for{" "}
              <b className="mono">{tomorrow.shift}</b>. Outstanding items will stay flagged but will
              not block the lock:
              <ul style={{ margin: "10px 0 0 18px", padding: 0 }}>
                <li>Granite lap stones · short by 4 · ETA <span className="mono">2026-05-23</span></li>
                <li>GMN spindle batch · 12 of 18 confirmed · long-lead acknowledged</li>
                <li>ECO-MS-0017 · Quality CMM gauge R&amp;R sign-off pending</li>
              </ul>
              <div style={{ marginTop: 10, color: ML_INK_3 }}>
                Locking emits <span className="mono">LINE_LOCKED</span> to the ledger and
                publishes the schedule to SAP B1 + proALPHA.
              </div>
            </div>
          }
          onCancel={() => setShowLockModal(false)}
          onConfirm={_mlLockAndPublish}
          confirmLabel="Lock & publish"
        />
      )}

      {/* W14B · toast for modal-confirm mutate results ───────────── */}
      {toast && (
        <div style={{
          position: "fixed", bottom: 24, right: 24,
          background: toast.kind === "err" ? ML_BAD : ML_INK,
          color: "var(--bg-0)",
          padding: "8px 14px", borderRadius: 3, fontSize: 12,
          boxShadow: "0 6px 20px rgba(0,0,0,0.18)", zIndex: 60,
          fontFamily: ML_FONT_MN,
        }}>
          {toast.msg}
        </div>
      )}
    </div>
  );
}

/* ────────────────────────────────────────────────────────────────────
   Route registration · /line/queue
   Defers to registerMittelstandRoute() (agent #3 owns registry-index.jsx).
   Falls back to registerPumpRoute() if a tenant uses the merge model and
   the dedicated registry isn't loaded yet.
   ──────────────────────────────────────────────────────────────────── */

(function _ml_register() {
  const route = {
    path: "/line/queue",
    mode: "line",
    title: "Line readiness · Mittelstand",
    renderer: function () { return React.createElement(ScreenMittelstandLine); },
  };
  if (typeof window !== "undefined") {
    if (typeof window.registerMittelstandRoute === "function") {
      window.registerMittelstandRoute(route);
    } else if (typeof window.registerPumpRoute === "function") {
      // fallback during partial-deploy windows · still surfaces the screen
      window.registerPumpRoute(route);
    }
    // Always expose the component for the registry-router to wire in case
    // it prefers component-name lookup (mirrors BUILTIN_ROUTES pattern).
    window.ScreenMittelstandLine = ScreenMittelstandLine;
  }
})();
})();
