// ===== Analyse → Arbeitssysteme =====
const { useState: useAsS, useMemo: useAsM } = React;

// Durchlaufdiagramm (Wiendahl): y-Achse = kumulierte Arbeit [h].
// Zugangskurve = Plan-Arbeit kumuliert nach Plan-Start. Abgangskurve = Arbeit kumuliert
// nach Abgangstermin (Ist-Ende bis heute, sonst Plan-Ende). Delta der Kurven = Bestand.
function DurchlaufDiagramm({ rows }) {
  const [zoom, setZoom] = useAsS({ s: 0, e: 1 });
  const today = window.AO_TODAY ? window.AO_TODAY.getTime() : new Date('2026-06-12T00:00:00Z').getTime();
  const tOf = (s) => new Date(s + 'T00:00:00Z').getTime();
  const work = (r) => r.istArbeit || r.planArbeit || 0;
  // Zugang: nach Plan-Start
  const zug = rows.filter(r => r.planStart).map(r => ({ t: tOf(r.planStart), w: work(r) })).sort((a, b) => a.t - b.t);
  // Abgang: Ist-Ende falls vorhanden, sonst Plan-Ende (Prognose)
  const abg = rows.map(r => ({ t: tOf(r.istEnde || r.planEnde), w: work(r), plan: !r.istEnde })).filter(p => p.t).sort((a, b) => a.t - b.t);
  if (!zug.length && !abg.length) return <div style={{ color: 'var(--muted)', fontSize: 12, textAlign: 'center', padding: 20 }}>Keine Daten im Filter</div>;
  const allT = [...zug, ...abg].map(p => p.t);
  const fMin = Math.min(...allT), fMax = Math.max(...allT), fSpan = (fMax - fMin) || 1;
  const tMin = fMin + zoom.s * fSpan, tMax = fMin + zoom.e * fSpan, span = (tMax - tMin) || 1;
  const W = 1000, H = 250, padL = 54, padB = 38, padT = 16, padR = 14;
  const plotW = W - padL - padR, plotH = H - padT - padB;
  const cum = (arr) => { let a = 0; return arr.map(p => ({ t: p.t, w: (a += p.w), plan: p.plan })); };
  const cz = cum(zug), ca = cum(abg);
  const wMax = Math.max(cz.length ? cz[cz.length - 1].w : 0, ca.length ? ca[ca.length - 1].w : 0) || 1;
  const x = (t) => padL + ((t - tMin) / span) * plotW;
  const y = (w) => padT + plotH * (1 - w / wMax);
  const zAt = (t) => { let v = 0; for (const p of cz) { if (p.t <= t) v = p.w; else break; } return v; };
  const aAt = (t) => { let v = 0; for (const p of ca) { if (p.t <= t) v = p.w; else break; } return v; };
  // Bestandskurve = Zugang − Abgang an jedem Ereigniszeitpunkt
  const evT = [...new Set([...cz, ...ca].map(p => p.t))].sort((a, b) => a - b);
  const best = evT.map(t => ({ t, w: Math.max(0, zAt(t) - aAt(t)) }));
  const step = (arr) => {
    if (!arr.length) return '';
    let prev = 0, d = `M${x(arr[0].t).toFixed(1)} ${y(0).toFixed(1)}`;
    arr.forEach(p => { d += ` L${x(p.t).toFixed(1)} ${y(prev).toFixed(1)} L${x(p.t).toFixed(1)} ${y(p.w).toFixed(1)}`; prev = p.w; });
    return d;
  };
  // Abgang in Ist (durchgezogen bis heute) und Plan (gestrichelt danach) aufteilen
  const caIst = ca.filter(p => p.t <= today), caPlan = ca.filter(p => p.t > today);
  const xToday = x(today);
  const ticks = [];
  const showDays = span <= 90 * 86400000; // taggenaue Achse bei ≤ ~3 Monaten Sichtfenster
  if (showDays) {
    const stepDays = span <= 21 * 86400000 ? 1 : span <= 45 * 86400000 ? 3 : 7;
    const d0 = new Date(tMin); d0.setUTCHours(0, 0, 0, 0);
    for (let t = d0.getTime(); t <= tMax; t += stepDays * 86400000) ticks.push(new Date(t));
  } else {
    for (let k = 0; k <= 6; k++) ticks.push(new Date(tMin + (span / 6) * k));
  }
  const onWheel = window.ocWheelZoom(zoom, setZoom);
  return (
    <svg onWheel={onWheel} onDoubleClick={() => setZoom({ s: 0, e: 1 })} viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="xMidYMid meet" style={{ width: '100%', height: '100%', display: 'block', fontFamily: 'var(--mono)', cursor: (zoom.s > 0 || zoom.e < 1) ? 'zoom-out' : 'zoom-in' }}>
      {[0, 0.25, 0.5, 0.75, 1].map((f, i) => { const yy = padT + plotH * (1 - f); return <g key={i}><line x1={padL} y1={yy} x2={W - padR} y2={yy} stroke="var(--line)" strokeWidth="0.5" /><text x={padL - 6} y={yy + 4} textAnchor="end" style={{ fontSize: 11, fill: 'var(--muted)' }}>{Math.round(wMax * f)}</text></g>; })}
      {ticks.map((t, i) => <text key={i} x={x(t.getTime())} y={H - 16} textAnchor="middle" style={{ fontSize: 9.5, fill: 'var(--muted)' }}>{showDays ? t.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' }) : t.toLocaleDateString('de-DE', { month: '2-digit', year: '2-digit' })}</text>)}
      {/* heute-Linie */}
      {today >= tMin && today <= tMax && <g><line x1={xToday} y1={padT} x2={xToday} y2={padT + plotH} stroke="var(--accent-ink)" strokeWidth="1" strokeDasharray="3 3" opacity="0.6" /><text x={xToday} y={padT - 4} textAnchor="middle" style={{ fontSize: 9.5, fill: 'var(--accent-ink)', fontWeight: 700 }}>heute</text></g>}
      {/* Bestandsfläche = Bereich ZWISCHEN Zugang und Abgang (0 wenn deckungsgleich) */}
      {(() => {
        const pts = evT.map(t => ({ x: x(t), yz: y(zAt(t)), ya: y(aAt(t)) }));
        if (pts.length < 2) return null;
        const top = pts.map(p => `${p.x.toFixed(1)} ${p.yz.toFixed(1)}`);
        const bot = pts.slice().reverse().map(p => `${p.x.toFixed(1)} ${p.ya.toFixed(1)}`);
        return <path d={`M${top.join(' L')} L${bot.join(' L')} Z`} fill="color-mix(in oklch, var(--accent) 14%, transparent)" stroke="none" />;
      })()}
      <path d={step(cz)} fill="none" stroke="#3269B4" strokeWidth="2.4" />
      <path d={step(caIst)} fill="none" stroke="#8C8A85" strokeWidth="2.4" />
      {caPlan.length > 0 && <path d={step([caIst[caIst.length - 1] || { t: today, w: 0 }, ...caPlan])} fill="none" stroke="#8C8A85" strokeWidth="2" strokeDasharray="5 4" />}
      {/* Bestandskurve (Zugang − Abgang), diskret als Treppe */}
      {(() => {
        if (!best.length) return null;
        let d = `M${x(best[0].t).toFixed(1)} ${y(0).toFixed(1)}`, prev = 0;
        best.forEach(p => { d += ` L${x(p.t).toFixed(1)} ${y(prev).toFixed(1)} L${x(p.t).toFixed(1)} ${y(p.w).toFixed(1)}`; prev = p.w; });
        return <path d={d} fill="none" stroke="#E0A53B" strokeWidth="1.8" />;
      })()}
      <text x={12} y={padT + plotH / 2} transform={`rotate(-90 12 ${padT + plotH / 2})`} textAnchor="middle" style={{ fontSize: 11, fill: 'var(--ink-2)' }}>kum. Arbeit [h]</text>
    </svg>
  );
}

// Kapazitätsauslastung je Tag (14-Tage-Vorschau): geplante Last vs. eingestellte Kapazität
function CapUtilChart({ data, onBar, activeDay }) {
  if (!data || !data.length) return <div style={{ color: 'var(--muted)', fontSize: 11.5, textAlign: 'center', padding: 20 }}>Keine Kapazität</div>;
  const W = 460, H = 188, padL = 40, padB = 40, padT = 14, padR = 10;
  const plotW = W - padL - padR, plotH = H - padT - padB;
  const yMax = Math.max(120, ...data.map(d => d.pct)) || 120;
  const n = data.length, slot = plotW / n, bw = Math.min(24, slot * 0.62);
  const y = (p) => padT + plotH * (1 - p / yMax);
  const y100 = y(100);
  return (
    <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="xMidYMid meet" style={{ width: '100%', height: '100%', display: 'block', fontFamily: 'var(--mono)' }}>
      {[0, 50, 100].map((t, i) => <g key={i}><line x1={padL} y1={y(t)} x2={W - padR} y2={y(t)} stroke="var(--line)" strokeWidth="0.5" /><text x={padL - 5} y={y(t) + 3} textAnchor="end" style={{ fontSize: 10, fill: 'var(--muted)' }}>{t}</text></g>)}
      <line x1={padL} y1={y100} x2={W - padR} y2={y100} stroke="var(--bad-ink)" strokeWidth="1" strokeDasharray="4 3" opacity="0.7" />
      {data.map((d, i) => {
        const cx = padL + slot * i + slot / 2, h = Math.max(0, (Math.min(d.pct, yMax) / yMax) * plotH);
        const over = d.pct > 100, closed = d.availH <= 0;
        return <g key={i}>
          <rect x={cx - bw / 2} y={padT + plotH - h} width={bw} height={h} rx="2" onClick={onBar ? () => onBar(d) : undefined} style={{ cursor: onBar ? 'pointer' : 'default' }} fill={(activeDay && +activeDay === +d.day) ? 'var(--accent-ink)' : closed ? 'var(--line-2)' : over ? 'var(--bad-ink)' : '#3269B4'}>
            <title>{`${d.day.toLocaleDateString('de-DE', { weekday: 'short', day: '2-digit', month: '2-digit' })} · ${Math.round(d.loadH)}h / ${Math.round(d.availH)}h · ${d.pct}%`}</title>
          </rect>
          {i % 2 === 0 && <text x={cx} y={H - 22} textAnchor="middle" style={{ fontSize: 8, fill: 'var(--muted)' }}>{d.day.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' })}</text>}
        </g>;
      })}
      <text x={11} y={padT + plotH / 2} transform={`rotate(-90 11 ${padT + plotH / 2})`} textAnchor="middle" style={{ fontSize: 10, fill: 'var(--ink-2)' }}>Auslastung %</text>
    </svg>
  );
}

function AsKpi({ label, value, unit, tone }) {
  return (
    <div style={{ padding: '11px 13px', background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 8 }}>
      <div className="label" style={{ fontSize: 9.5, marginBottom: 4 }}>{label}</div>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 4 }}>
        <span className="num" style={{ fontFamily: 'var(--mono)', fontSize: 21, fontWeight: 700, color: tone || 'var(--ink)' }}>{value}</span>
        {unit && <span style={{ fontSize: 11, color: 'var(--muted)' }}>{unit}</span>}
      </div>
    </div>
  );
}

const asFmt = (v, type) => {
  if (v == null || v === '') return '—';
  if (type === 'date') return window.aDe(v);
  if (type === 'num') return typeof v === 'number' ? v.toLocaleString('de-DE') : v;
  return v;
};

const AS_COLS = [
  { key: 'nr', label: 'Auftr.-Nr.', type: 'text' },
  { key: 'avo', label: 'AVO', type: 'text' },
  { key: 'avoBez', label: 'AVO-Bezeichnung', type: 'text' },
  { key: 'bez', label: 'Auftragsbezeichnung', type: 'text' },
  { key: 'kunde', label: 'Kunde', type: 'text' },
  { key: 'abc', label: 'ABC', type: 'text' },
  { key: 'score', label: 'Score', type: 'num' },
  { key: 'planStart', label: 'Plan-Start', type: 'date' },
  { key: 'istStart', label: 'Ist-Start', type: 'date' },
  { key: 'planEnde', label: 'Plan-Ende', type: 'date' },
  { key: 'istEnde', label: 'Ist-Ende', type: 'date' },
  { key: 'istDLZ', label: 'Ist-DLZ [Tage]', type: 'num' },
  { key: 'taZugang', label: 'TA Zugang [Tage]', type: 'num' },
  { key: 'taAbgang', label: 'TA Abgang [Tage]', type: 'num' },
  { key: 'istArbeit', label: 'Ist Arbeit [h]', type: 'num' },
  { key: 'status', label: 'Status', type: 'text' },
];

function ArbeitssystemeView({ capacityBySystem }) {
  const systeme = useAsM(() => (window.WORK_SYSTEMS || []).map(w => w.name), []);
  const [sys, setSys] = useAsS(systeme[0] || 'Drehzentrum CTX 4');
  const [sort, setSort] = useAsS({ key: 'nr', dir: 1 });
  const [colSearch, setColSearch] = useAsS({});
  const [barFilter, setBarFilter] = useAsS(null);
  const [catFilter, setCatFilter] = useAsS(null);   // {key,val,label,title}
  const [selRows, setSelRows] = useAsS(() => new Set());
  const [page, setPage] = useAsS(0);
  const perPage = 20;

  const sysRows = useAsM(() => {
    const opName = { 'Säge AS-1': 'Sägen / Zuschnitt', 'Drehzentrum CTX 4': 'Drehen', 'Drehzentrum Index G220': 'Drehen', 'Fräszentrum Hermle C42': 'Fräsen', 'Entgratzelle EC-3': 'Entgraten / Gleitschleifen', 'Messraum QS': 'Endprüfung' }[sys] || 'Bearbeitung';
    const byNr = Object.fromEntries((window.ORDERS || []).map(o => [o.nr, o]));
    return window.A_ORDERS.filter(r => r.system === sys).map(r => {
      const o = byNr[r.nr];
      let avo = r.avo, avoBez = opName;
      if (o && o.arbeitsplan) { const st = o.arbeitsplan.find(s => (window.WORK_SYSTEMS.find(w => w.id === s.wsId) || {}).name === sys); if (st) { avo = st.avo; avoBez = st.name; } }
      return { ...r, avo: avo || '0020', avoBez };
    });
  }, [sys]);

  const filtered = useAsM(() => {
    let r = sysRows.slice();
    Object.entries(colSearch).forEach(([k, q]) => { if (q) r = r.filter(x => x[k] != null && String(x[k]).toLowerCase().includes(q.toLowerCase())); });
    if (barFilter) r = r.filter(x => { const v = barFilter.field === 'dlzAbw' ? (x.istEnde ? x.istDLZ - x.planDLZ : null) : x[barFilter.field]; return v != null && v >= barFilter.min && v <= barFilter.max; });
    if (catFilter) {
      if (catFilter.key === 'status') r = r.filter(x => x.status === catFilter.val);
      else if (catFilter.key === 'treue') r = r.filter(x => x.istEnde && (catFilter.val === 'ontime' ? x.taAbgang <= 0 : x.taAbgang > 0));
      else if (catFilter.key === 'capDay') { const d0 = catFilter.val; r = r.filter(x => x.status === 'Laufend' && x.planStart && x.planEnde && new Date(x.planStart + 'T00:00:00Z') <= d0 && new Date(x.planEnde + 'T00:00:00Z') > d0); }
    }
    return r;
  }, [sysRows, colSearch, barFilter, catFilter]);

  const sorted = useAsM(() => {
    const r = filtered.slice();
    r.sort((a, b) => { let va = a[sort.key], vb = b[sort.key]; if (va == null) va = ''; if (vb == null) vb = ''; return (va < vb ? -1 : va > vb ? 1 : 0) * sort.dir; });
    return r;
  }, [filtered, sort]);

  const pageRows = sorted.slice(page * perPage, page * perPage + perPage);
  const pages = Math.ceil(sorted.length / perPage) || 1;

  const chartSrc = useAsM(() => selRows.size ? filtered.filter(r => selRows.has(r.nr)) : filtered, [filtered, selRows]);
  // Durchlaufdiagramm & Kennzahlen: immer alle Vorgänge des Systems (ungefiltert)
  const sysAll = sysRows;

  // Kennzahlen (ungefiltert, ganzes System) für KPI-Kachel & Durchlaufdiagramm
  const kf = useAsM(() => {
    const done = sysAll.filter(r => r.istEnde);
    const lauf = sysAll.filter(r => r.status === 'Laufend');
    const today = window.AO_TODAY ? window.AO_TODAY.getTime() : new Date('2026-06-12T00:00:00Z').getTime();
    const m = (a) => a.length ? a.reduce((x, y) => x + y, 0) / a.length : 0;
    const work = (r) => r.planArbeit || r.istArbeit || 0;
    const bestand = Math.round(lauf.reduce((s, r) => s + work(r), 0));
    const fourWk = 28 * 86400000;
    const recent = done.filter(r => { const t = new Date(r.istEnde + 'T00:00:00Z').getTime(); return today - t <= fourWk && t <= today; });
    const opDays = new Set(recent.map(r => r.istEnde)).size || 1;
    const leistung = recent.reduce((s, r) => s + work(r), 0) / opDays;
    const reichweite = leistung > 0 ? bestand / leistung : 0;
    const ontime = done.filter(r => r.taAbgang <= 0).length;
    return { bestand, leistung: Math.round(leistung * 10) / 10, reichweite: Math.round(reichweite * 10) / 10,
      dlzMean: m(done.map(r => r.istDLZ)), arbMean: m(sysAll.map(r => r.istArbeit)),
      treuePct: done.length ? Math.round(ontime / done.length * 100) : 0 };
  }, [sysAll]);

  // Kennzahlen + Diagrammdaten aus chartSrc
  const k = useAsM(() => {
    const done = chartSrc.filter(r => r.istEnde);
    const lauf = chartSrc.filter(r => r.status === 'Laufend');
    const today = window.AO_TODAY ? window.AO_TODAY.getTime() : new Date('2026-06-12T00:00:00Z').getTime();
    const m = (a) => a.length ? a.reduce((x, y) => x + y, 0) / a.length : 0;
    const sd = (a) => { if (a.length < 2) return 0; const mm = m(a); return Math.sqrt(a.reduce((s, x) => s + (x - mm) ** 2, 0) / (a.length - 1)); };
    const dlz = done.map(r => r.istDLZ);
    const arb = chartSrc.map(r => r.istArbeit);
    const taZ = chartSrc.filter(r => r.taZugang != null).map(r => r.taZugang);
    const taA = done.map(r => r.taAbgang);
    const dlzAbw = done.map(r => r.istDLZ - r.planDLZ);
    const ontime = done.filter(r => r.taAbgang <= 0).length;
    // Bestand = Summe offener Plan-Arbeit (laufende Vorgänge); Leistung = abgearbeitete
    // Plan-Arbeit pro Betriebskalendertag (letzte 4 Wochen); Reichweite = Bestand / Leistung.
    const work = (r) => r.planArbeit || r.istArbeit || 0;
    const bestand = Math.round(lauf.reduce((s, r) => s + work(r), 0));    // h offener Plan-Arbeit
    const fourWk = 28 * 86400000;
    const recent = done.filter(r => { const t = new Date(r.istEnde + 'T00:00:00Z').getTime(); return today - t <= fourWk && t <= today; });
    const doneWork = recent.reduce((s, r) => s + work(r), 0);            // h in 4 Wochen abgearbeitet
    const opDays = new Set(recent.map(r => r.istEnde)).size || 1;         // Betriebskalendertage mit Abgang
    const leistung = doneWork / opDays;                                   // h/Betriebstag
    const reichweite = leistung > 0 ? bestand / leistung : 0;             // Tage
    const abcTreue = ['A', 'B', 'C'].map(abc => { const g = done.filter(r => r.abc === abc); const ot = g.filter(r => r.taAbgang <= 0).length; return { abc, total: g.length, ontime: ot, pct: g.length ? Math.round(ot / g.length * 100) : 0 }; }).filter(d => d.total > 0);
    const planDates = chartSrc.map(r => r.planEnde).filter(Boolean);
    const istDates = done.map(r => r.istEnde).filter(Boolean);
    return {
      done: done.length, lauf: lauf.length, dlz, arb, taZ, taA, dlzAbw, dlzMean: m(dlz), dlzSd: sd(dlz),
      arbMean: m(arb), arbSd: sd(arb), taZMean: m(taZ), taZSd: sd(taZ), taAMean: m(taA), taASd: sd(taA), dlzAbwMean: m(dlzAbw), dlzAbwSd: sd(dlzAbw),
      treuePct: done.length ? Math.round(ontime / done.length * 100) : 0, ontime, mitTA: done.length - ontime, abcTreue, planDates, istDates,
      bestand, leistung: Math.round(leistung * 10) / 10, reichweite: Math.round(reichweite * 10) / 10,
      capUtil: (() => {
        const wsId = (window.WORK_SYSTEMS.find(w => w.name === sys) || {}).id;
        const cap = capacityBySystem && wsId ? capacityBySystem[wsId] : null;
        const capH = cap ? window.buildCapDayHours(cap) : null;
        const today = window.AO_TODAY ? new Date(window.AO_TODAY) : new Date('2026-06-12T00:00:00Z');
        const dayMs = 86400000;
        const load = {}; // dayIndex(0..13) -> geplante Arbeit h
        chartSrc.forEach(r => {
          if (r.status !== 'Laufend') return;
          const ps = new Date(r.planStart + 'T00:00:00Z'), pe = new Date(r.planEnde + 'T00:00:00Z');
          const days = Math.max(1, Math.round((pe - ps) / dayMs));
          const perDay = (r.istArbeit || r.planArbeit || 0) / days;
          for (let d = 0; d < 14; d++) { const day = new Date(today.getTime() + d * dayMs); if (day >= ps && day < pe) load[d] = (load[d] || 0) + perDay; }
        });
        return Array.from({ length: 14 }, (_, d) => {
          const day = new Date(today.getTime() + d * dayMs);
          const dayIdx = Math.round((day - today) / dayMs);
          const availH = capH ? capH(dayIdx) : 8;
          return { day, availH, loadH: load[d] || 0, pct: availH > 0 ? Math.round((load[d] || 0) / availH * 100) : 0 };
        });
      })(),
    };
  }, [chartSrc, sys, capacityBySystem]);

  const onBar = (field, title) => (min, max, bin, label) => { setBarFilter(b => (b && b.field === field && b.bin === bin) ? null : { field, min, max, bin, label, title }); setPage(0); };
  const abBin = (f) => (barFilter && barFilter.field === f) ? barFilter.bin : null;
  const abReset = (f) => (barFilter && barFilter.field === f) ? () => setBarFilter(null) : null;
  const CC = window.AOChartColors;

  const th = (c) => {
    const active = sort.key === c.key;
    return <th key={c.key} style={{ padding: '7px 10px', textAlign: c.type === 'num' ? 'right' : 'left', borderBottom: '1px solid var(--line-2)', background: 'var(--panel)', position: 'sticky', top: 0, zIndex: 1 }}>
      <div onClick={() => setSort(s => s.key === c.key ? { key: c.key, dir: -s.dir } : { key: c.key, dir: 1 })} style={{ cursor: 'pointer', fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '.06em', textTransform: 'uppercase', color: active ? 'var(--accent-ink)' : 'var(--muted)', whiteSpace: 'nowrap' }}>{c.label} {active ? (sort.dir === 1 ? '▲' : '▼') : ''}</div>
      <input value={colSearch[c.key] || ''} onChange={e => { setColSearch(s => ({ ...s, [c.key]: e.target.value })); setPage(0); }} placeholder="filtern…" style={{ width: '100%', marginTop: 4, height: 22, boxSizing: 'border-box', padding: '0 6px', fontSize: 11, border: '1px solid var(--line)', borderRadius: 4, background: 'var(--surface)', color: 'var(--ink)' }} />
    </th>;
  };

  return (
    <React.Fragment>
      <header style={{ flex: '0 0 auto', display: 'flex', alignItems: 'center', gap: 14, padding: '0 18px', height: 56, background: 'var(--panel)', borderBottom: '1px solid var(--line-2)' }}>
        <span style={{ fontSize: 14.5, fontWeight: 600 }}>Arbeitssysteme</span>
        <select value={sys} onChange={e => { setSys(e.target.value); setPage(0); setSelRows(new Set()); setBarFilter(null); }} style={{ height: 34, padding: '0 12px', borderRadius: 8, border: '1px solid var(--line-2)', background: 'var(--surface)', color: 'var(--ink)', fontSize: 13, fontWeight: 600, fontFamily: 'var(--sans)' }}>
          {systeme.map(s => <option key={s} value={s}>{s}</option>)}
        </select>
        <span className="label">{filtered.length} von {sysRows.length} Vorgängen</span>
        {barFilter && (
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 7, height: 28, padding: '0 6px 0 11px', borderRadius: 99, background: 'var(--accent)', border: '1px solid var(--accent-line)', color: 'var(--accent-ink)', fontSize: 12, fontWeight: 600 }}>
            {barFilter.title}: {barFilter.label}
            <button onClick={() => setBarFilter(null)} style={{ display: 'grid', placeItems: 'center', width: 18, height: 18, borderRadius: 99, border: 'none', cursor: 'pointer', background: 'color-mix(in oklch, var(--accent-ink) 18%, transparent)', color: 'var(--accent-ink)' }}><Icon name="close" size={12} /></button>
          </span>
        )}
        {catFilter && (
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 7, height: 28, padding: '0 6px 0 11px', borderRadius: 99, background: 'var(--accent)', border: '1px solid var(--accent-line)', color: 'var(--accent-ink)', fontSize: 12, fontWeight: 600 }}>
            {catFilter.title}: {catFilter.label}
            <button onClick={() => setCatFilter(null)} style={{ display: 'grid', placeItems: 'center', width: 18, height: 18, borderRadius: 99, border: 'none', cursor: 'pointer', background: 'color-mix(in oklch, var(--accent-ink) 18%, transparent)', color: 'var(--accent-ink)' }}><Icon name="close" size={12} /></button>
          </span>
        )}
        {selRows.size > 0 && (
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 7, height: 28, padding: '0 6px 0 11px', borderRadius: 99, background: '#3269B4', color: '#fff', fontSize: 12, fontWeight: 600 }}>
            {selRows.size} ausgewählt · Diagramme gefiltert
            <button onClick={() => setSelRows(new Set())} style={{ display: 'grid', placeItems: 'center', width: 18, height: 18, borderRadius: 99, border: 'none', cursor: 'pointer', background: 'rgba(255,255,255,.25)', color: '#fff' }}><Icon name="close" size={12} /></button>
          </span>
        )}
      </header>

      <main style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: 14, display: 'flex', flexDirection: 'column', gap: 14 }}>
        {/* Tabelle der Arbeitsvorgänge */}
        <div style={{ flexShrink: 0, background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 8, boxShadow: 'var(--shadow)', overflow: 'hidden' }}>
          <div style={{ height: 340, overflow: 'auto' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12.5 }}>
              <thead><tr>{AS_COLS.map(th)}</tr></thead>
              <tbody>
                {pageRows.map(r => {
                  const sel = selRows.has(r.nr);
                  return (
                    <tr key={r.nr} onClick={e => { const multi = e.ctrlKey || e.metaKey; setSelRows(s => { const n = multi ? new Set(s) : new Set(); if (s.has(r.nr) && (multi || s.size === 1)) n.delete(r.nr); else n.add(r.nr); return n; }); }}
                      onContextMenu={e => window.kikiMenu(e, { id: r.nr, label: `${r.nr} · ${r.bez}`, kind: 'Arbeitsvorgang' })}
                      style={{ borderBottom: '1px solid var(--line)', cursor: 'pointer', background: sel ? 'color-mix(in oklch, var(--accent) 30%, transparent)' : 'transparent', boxShadow: sel ? 'inset 3px 0 0 #3269B4' : 'none' }}>
                      {AS_COLS.map(c => (
                        <td key={c.key} style={{ padding: '7px 10px', whiteSpace: 'nowrap', textAlign: c.type === 'num' ? 'right' : 'left', fontFamily: c.type === 'num' || c.type === 'date' ? 'var(--mono)' : 'var(--sans)', fontSize: c.type === 'num' || c.type === 'date' ? 12 : 12.5, color: c.key === 'nr' ? 'var(--ink)' : 'var(--ink-2)', fontWeight: c.key === 'nr' ? 600 : 400 }}>
                          {c.key === 'status' ? <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 11.5, color: r.status === 'Laufend' ? 'var(--warn-ink)' : 'var(--ink-2)' }}><span style={{ width: 7, height: 7, borderRadius: 99, background: r.status === 'Laufend' ? 'var(--warn-ink)' : 'var(--good-ink)' }} />{r.status}</span>
                            : c.key === 'abc' ? <span className="num" style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: 18, height: 18, borderRadius: 4, fontFamily: 'var(--mono)', fontSize: 11, fontWeight: 700, background: r.abc === 'A' ? 'color-mix(in oklch, var(--good) 55%, var(--surface))' : r.abc === 'B' ? 'color-mix(in oklch, var(--warn) 55%, var(--surface))' : 'var(--line)', color: r.abc === 'A' ? 'var(--good-ink)' : r.abc === 'B' ? 'var(--warn-ink)' : 'var(--ink-2)' }}>{r.abc}</span>
                            : c.key === 'score' ? <ScoreBadge value={r.score} size="sm" />
                            : asFmt(r[c.key], c.type)}
                        </td>
                      ))}
                    </tr>
                  );
                })}
                {pageRows.length === 0 && <tr><td colSpan={AS_COLS.length} style={{ padding: 28, textAlign: 'center', color: 'var(--muted)' }}>Keine Vorgänge für dieses Arbeitssystem</td></tr>}
              </tbody>
            </table>
          </div>
          {pages > 1 && (
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: 8, padding: '8px 12px', borderTop: '1px solid var(--line)' }}>
              <button onClick={() => setPage(p => Math.max(0, p - 1))} disabled={page === 0} style={asPage(page === 0)}>‹</button>
              <span className="num" style={{ fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--ink-2)' }}>{page + 1} / {pages}</span>
              <button onClick={() => setPage(p => Math.min(pages - 1, p + 1))} disabled={page >= pages - 1} style={asPage(page >= pages - 1)}>›</button>
            </div>
          )}
        </div>

        {/* Kennzahlen (weiße Kachel) links · Durchlaufdiagramm rechts über 2 Kachelbreiten */}
        <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(0, 2fr)', gap: 14, alignItems: 'stretch' }}>
          <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 8, boxShadow: 'var(--shadow)', padding: 14, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, alignContent: 'start' }}>
            <AsKpi label="Bestand offene Plan-Arbeit" value={kf.bestand.toLocaleString('de-DE')} unit="h" tone="#3269B4" />
            <AsKpi label="Reichweite" value={kf.reichweite.toLocaleString('de-DE')} unit="Tage" />
            <AsKpi label="Leistung (4 Wo.)" value={kf.leistung.toLocaleString('de-DE')} unit="h/Tag" />
            <AsKpi label="Ø Durchlaufzeit" value={kf.dlzMean.toFixed(1).replace('.', ',')} unit="Tage" />
            <AsKpi label="Ø Ist-Arbeit" value={kf.arbMean.toFixed(0)} unit="h" />
            <AsKpi label="Termintreue" value={kf.treuePct} unit="%" tone={kf.treuePct >= 85 ? 'var(--good-ink)' : 'var(--warn-ink)'} />
          </div>
          <ChartCard title="Durchlaufdiagramm" sub="kum. Zugang · Abgang · Bestand — Scroll für Zeitachse">
            <div style={{ overflowX: 'auto', overflowY: 'hidden', width: '100%', height: '100%' }}>
              <div style={{ minWidth: 900, height: '100%' }}><DurchlaufDiagramm rows={sysAll} /></div>
            </div>
          </ChartCard>
        </div>

        {/* Diagramme — 3 pro Zeile */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 14 }}>
          {/* Zeile 1: Anzahl · Rückstand · Termintreue */}
          <ChartCard title="Anzahl Arbeitsvorgänge" sub={(k.done + k.lauf).toLocaleString('de-DE')} onReset={catFilter && catFilter.key === 'status' ? () => setCatFilter(null) : null}>
            <Donut centerLabel={(k.done + k.lauf).toLocaleString('de-DE')} segments={[{ label: 'Fertig', value: k.done, color: CC.ACCENT }, { label: 'Laufend', value: k.lauf, color: CC.GOLD }]}
              onSeg={(s) => { const val = s.label === 'Fertig' ? 'Fertiggemeldet' : 'Laufend'; setCatFilter(c => (c && c.key === 'status' && c.val === val) ? null : { key: 'status', val, title: 'Status', label: s.label }); setPage(0); }} />
          </ChartCard>
          <ChartCard title="Rückstand" sub={`${k.lauf} laufend`}>
            <CumLine planDates={k.planDates} istDates={k.istDates} />
          </ChartCard>
          <ChartCard title="Termintreue" sub={`${k.treuePct} %`} onReset={catFilter && catFilter.key === 'treue' ? () => setCatFilter(null) : null}>
            <Donut centerLabel={`${k.treuePct}%`} segments={[{ label: 'termintreu', value: k.ontime, color: CC.ACCENT }, { label: 'verspätet', value: k.mitTA, color: CC.GOLD }]}
              onSeg={(s) => { const val = s.label === 'termintreu' ? 'ontime' : 'late'; setCatFilter(c => (c && c.key === 'treue' && c.val === val) ? null : { key: 'treue', val, title: 'Termintreue', label: s.label }); setPage(0); }} />
          </ChartCard>
          {/* Zeile 2: Kapazitätsauslastung · Planzeiten · DLZ */}
          <ChartCard title="Kapazitätsauslastung / Tag" sub="Vorschau 2 Wochen" onReset={catFilter && catFilter.key === 'capDay' ? () => setCatFilter(null) : null}>
            <CapUtilChart data={k.capUtil} onBar={(d) => { setCatFilter(c => (c && c.key === 'capDay' && +c.val === +d.day) ? null : { key: 'capDay', val: d.day, title: 'Auslastung Tag', label: d.day.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' }) }); setPage(0); }} activeDay={catFilter && catFilter.key === 'capDay' ? catFilter.val : null} />
          </ChartCard>
          <ChartCard title="Planzeiten (Ist-Arbeit)" sub={`M ${k.arbMean.toFixed(0)} h · SD ${k.arbSd.toFixed(0)} h`} onReset={abReset('istArbeit')}>
            <Histogram values={k.arb} unit="in h" color={CC.ACCENT} onBar={onBar('istArbeit', 'Ist-Arbeit')} activeBin={abBin('istArbeit')} />
          </ChartCard>
          <ChartCard title="Durchlaufzeit" sub={`M ${k.dlzMean.toFixed(0)} T · SD ${k.dlzSd.toFixed(0)} T`} onReset={abReset('istDLZ')}>
            <Histogram values={k.dlz} unit="in Tagen" color={CC.ACCENT} onBar={onBar('istDLZ', 'Durchlaufzeit')} activeBin={abBin('istDLZ')} />
          </ChartCard>
          {/* Zeile 3: Abweichungen */}
          <ChartCard title="Terminabweichung Zugang" sub={`M ${k.taZMean.toFixed(0)} T · SD ${k.taZSd.toFixed(0)} T`} onReset={abReset('taZugang')}>
            <Histogram values={k.taZ} unit="in Tagen" color={CC.ACCENT} onBar={onBar('taZugang', 'Terminabw. Zugang')} activeBin={abBin('taZugang')} />
          </ChartCard>
          <ChartCard title="Durchlaufzeitabweichung" sub={`M ${k.dlzAbwMean.toFixed(0)} T · SD ${k.dlzAbwSd.toFixed(0)} T`} onReset={abReset('dlzAbw')}>
            <Histogram values={k.dlzAbw} unit="in Tagen" color={CC.ACCENT} onBar={onBar('dlzAbw', 'Durchlaufzeitabw.')} activeBin={abBin('dlzAbw')} />
          </ChartCard>
          <ChartCard title="Terminabweichung Abgang" sub={`M ${k.taAMean.toFixed(0)} T · SD ${k.taASd.toFixed(0)} T`} onReset={abReset('taAbgang')}>
            <Histogram values={k.taA} unit="in Tagen" color={CC.ACCENT} onBar={onBar('taAbgang', 'Terminabw. Abgang')} activeBin={abBin('taAbgang')} />
          </ChartCard>
        </div>
      </main>
    </React.Fragment>
  );
}
const asPage = (dis) => ({ width: 28, height: 28, borderRadius: 6, border: '1px solid var(--line-2)', background: 'var(--surface)', color: dis ? 'var(--line-2)' : 'var(--ink-2)', cursor: dis ? 'default' : 'pointer', fontSize: 15 });

Object.assign(window, { ArbeitssystemeView });
