// ===== Admin-Panel: Unterseiten Einplanung · Rüstzeitmatrix · Kapazitätsplanung =====
const { useState, useEffect } = React;


const ADMIN_PAGES = [
  { id: 'einplanung', label: 'Einplanung', icon: 'sliders', sub: 'Ziele · Frozen Zone · Score · Restriktionen' },
  { id: 'ruest', label: 'Rüstzeitmatrix', icon: 'grid', sub: 'Rüstzeiten Werkstoff → Werkstoff' },
  { id: 'uebergang', label: 'Übergangszeiten', icon: 'arrow', sub: 'Min-Übergangszeit · Reichweite je System' },
  { id: 'kapazitaet', label: 'Kapazitätsplanung', icon: 'calendar', sub: 'Rollierende Jahreskapazität' },
  { id: 'doku', label: 'Dokumentation', icon: 'info', sub: 'Vorgehen & Annahmen der Durchlaufplanung' },
];

function AdminPanel({ open, onClose, state, set, initial }) {
  const [page, setPage] = useState(initial || 'einplanung');
  useEffect(() => { if (open && initial) setPage(initial); }, [open, initial]);
  if (!open) return null;

  const matIds = Object.keys(window.MATERIALS);
  const addRule = () => set(s => ({ ...s, restrictions: [...s.restrictions, { id: Date.now(), from: 'TI5', to: 'MS58', active: true }] }));
  const updRule = (id, patch) => set(s => ({ ...s, restrictions: s.restrictions.map(r => r.id === id ? { ...r, ...patch } : r) }));
  const delRule = (id) => set(s => ({ ...s, restrictions: s.restrictions.filter(r => r.id !== id) }));
  const setCapFor = (sysId, fn) => set(s => ({ ...s, capacityBySystem: { ...s.capacityBySystem, [sysId]: fn(s.capacityBySystem[sysId]) } }));

  const goals = [
    { k: 'durchlauf', t: 'Durchlaufzeit', d: 'kurze Vorgänge / schnelle Fertigstellung zuerst' },
    { k: 'ruesten', t: 'Rüsten', d: 'gleiche Werkstoffe gruppieren, Rüstwechsel minimieren' },
    { k: 'termin', t: 'Termintreue', d: 'früheste Endtermine bevorzugen' },
  ];
  const goalSum = (() => { const g = state.goalBySystem[state.workSystem]; return g.durchlauf + g.ruesten + g.termin || 1; })();
  const goalCur = state.goalBySystem[state.workSystem];

  return (
    <>
      <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(63,62,61,.34)', zIndex: 40, animation: 'rowIn .18s' }} />
      <div style={{ position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%,-50%)',
        width: 'min(1180px, 95vw)', height: 'min(860px, 90vh)', background: 'var(--surface)', zIndex: 41,
        borderRadius: 12, boxShadow: '0 24px 80px rgba(63,62,61,.28)', border: '1px solid var(--line-2)',
        display: 'flex', flexDirection: 'column', overflow: 'hidden', animation: 'popIn .22s cubic-bezier(.2,.8,.2,1)' }}>
        <style>{`@keyframes popIn{from{opacity:0;transform:translate(-50%,-46%) scale(.98)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}`}</style>

        <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '14px 18px', borderBottom: '1px solid var(--line)', flex: '0 0 auto' }}>
          <Icon name="settings" size={17} style={{ color: 'var(--ink-2)' }} />
          <div style={{ fontWeight: 600, fontSize: 14.5 }}>Admin — Parametrierung</div>
          <span className="num" style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--muted)', marginLeft: 4 }}>{state.workSystem}</span>
          <button onClick={onClose} style={{ marginLeft: 'auto', width: 30, height: 30, border: '1px solid var(--line-2)', borderRadius: 6, background: 'var(--surface)', display: 'grid', placeItems: 'center', color: 'var(--ink-2)' }}><Icon name="close" size={15} /></button>
        </div>

        <div style={{ display: 'flex', flex: 1, minHeight: 0 }}>
          {/* Navigation */}
          <nav style={{ width: 226, flex: '0 0 auto', borderRight: '1px solid var(--line)', padding: 12, background: 'var(--surface-2)', display: 'flex', flexDirection: 'column', gap: 4 }}>
            {ADMIN_PAGES.map(p => {
              const on = page === p.id;
              return (
                <button key={p.id} onClick={() => setPage(p.id)} style={{
                  display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px', borderRadius: 8, textAlign: 'left',
                  border: '1px solid ' + (on ? 'var(--accent-line)' : 'transparent'),
                  background: on ? 'var(--accent)' : 'transparent', color: 'var(--ink)', cursor: 'pointer' }}>
                  <Icon name={p.icon} size={16} style={{ color: on ? 'var(--accent-ink)' : 'var(--ink-2)', flex: '0 0 auto' }} />
                  <span style={{ minWidth: 0 }}>
                    <div style={{ fontSize: 13, fontWeight: 600 }}>{p.label}</div>
                    <div style={{ fontSize: 10.5, color: 'var(--muted)', lineHeight: 1.3 }}>{p.sub}</div>
                  </span>
                </button>
              );
            })}
          </nav>

          {/* Inhalt */}
          <div style={{ flex: 1, minWidth: 0, overflow: 'auto', padding: '6px 24px 30px' }}>
            {page === 'einplanung' && (
              <div>
                <Section icon="target" title="Optimierungsziel" desc={`Gewichtung der Solver-Ziele für ${state.workSystem} — je Arbeitssystem getrennt. Die Werte werden relativ zueinander normiert; der berechnete Score bleibt die Grundpriorität.`}>
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 12, maxWidth: 560 }}>
                    {goals.map(g => (
                      <div key={g.k} style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
                        <div style={{ flex: 1, minWidth: 0 }}>
                          <div style={{ fontSize: 13, fontWeight: 500 }}>{g.t}</div>
                          <div style={{ fontSize: 11, color: 'var(--muted)' }}>{g.d}</div>
                        </div>
                        <div style={{ width: 200 }}><Slider value={goalCur[g.k]} onChange={v => set(s => ({ ...s, goalBySystem: { ...s.goalBySystem, [s.workSystem]: { ...s.goalBySystem[s.workSystem], [g.k]: v } } }))} /></div>
                        <span className="num" style={{ width: 44, textAlign: 'right', fontFamily: 'var(--mono)', fontSize: 12.5, color: 'var(--accent-ink)', fontWeight: 600 }}>{Math.round(goalCur[g.k] / goalSum * 100)}%</span>
                      </div>
                    ))}
                  </div>
                </Section>

                <Section icon="lock" title="Frozen Zone" desc="Anzahl Schichten in der Zukunft, die nicht mehr umgeplant werden. Neue Arbeitsvorgänge werden erst danach eingeplant.">
                  <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
                    <div style={{ display: 'flex', gap: 5, flexWrap: 'wrap' }}>
                      {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(n => (
                        <button key={n} onClick={() => set(s => ({ ...s, frozenShifts: n }))}
                          style={{ width: 40, height: 40, borderRadius: 7, border: '1px solid',
                            borderColor: state.frozenShifts === n ? 'var(--accent-ink)' : 'var(--line-2)',
                            background: state.frozenShifts === n ? 'var(--accent)' : 'var(--surface)',
                            color: state.frozenShifts === n ? 'var(--accent-ink)' : 'var(--ink-2)',
                            fontFamily: 'var(--mono)', fontSize: 15, fontWeight: 600 }}>{n}</button>
                      ))}
                    </div>
                    <div style={{ fontSize: 12, color: 'var(--muted)' }}>Schichten<br /><span style={{ color: 'var(--ink-2)' }}>≈ {(state.frozenShifts * window.SHIFT_HOURS)} h eingefroren</span></div>
                  </div>
                </Section>

                <Section icon="sliders" title="Score-Gewichtung" desc="Priorität jedes Kriteriums von 1 (niedrig) bis 9 (hoch). „–“ schaltet das Kriterium aus. Der Gesamt-Score (1–9) ist der gewichtete Mittelwert."
                  info={<InfoTip>
                    <b style={{ color: 'var(--surface)' }}>Wie wird der Score berechnet?</b>
                    <div style={{ marginTop: 6 }}>Es ist ein <b style={{ color: 'var(--surface)' }}>gewichteter Mittelwert</b>. Jedes Kriterium erhält aus den Auftragsdaten einen Teilwert von 1–9 (z.B. wenig Schlupf → hoch, hoher Wert → hoch). Dieser wird mit der hier eingestellten Priorität gewichtet:</div>
                    <div style={{ marginTop: 8, padding: '7px 9px', background: 'rgba(255,255,255,.08)', borderRadius: 6, fontFamily: 'var(--mono)', fontSize: 11 }}>
                      Score = ⌈ Σ(Priorität × Teilwert) ÷ Σ Priorität ⌉
                    </div>
                    <div style={{ marginTop: 8 }}>Das Ergebnis wird auf <b style={{ color: 'var(--surface)' }}>1–9</b> gerundet/begrenzt. Kriterien auf „–“ (Priorität 0) fließen nicht ein. Der berechnete Score steht je Auftrag in der Fertigungsauftrags-Tabelle und ist die Grundpriorität für den Solver.</div>
                    <div style={{ marginTop: 8, paddingTop: 8, borderTop: '1px solid rgba(255,255,255,.15)' }}><b style={{ color: 'var(--surface)' }}>Beispiel:</b> nur „Kunde“ aktiv, alle anderen auf „–“ → der Score ist exakt der A/B/C-Wert (A=9, B=5, C=2). Die Priorität-Stufe selbst spielt dann keine Rolle, da sie sich im Mittelwert herauskürzt.</div>
                  </InfoTip>}>
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 11, maxWidth: 560 }}>
                    {window.CRITERIA.filter(c => c.key !== 'kunde').map(c => (
                      <div key={c.key} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                        <div style={{ flex: 1, minWidth: 0 }}>
                          <div style={{ fontSize: 13, fontWeight: 500 }}>{c.label}</div>
                          <div style={{ fontSize: 11, color: 'var(--muted)' }}>{c.hint}</div>
                        </div>
                        <StepRange value={state.weights[c.key]} onChange={v => set(s => ({ ...s, weights: { ...s.weights, [c.key]: v } }))} />
                      </div>
                    ))}
                  </div>
                  <div style={{ marginTop: 16, padding: 12, background: 'var(--surface-2)', border: '1px solid var(--line)', borderRadius: 7, maxWidth: 560 }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                      <button onClick={() => set(s => ({ ...s, weights: { ...s.weights, kunde: s.weights.kunde ? 0 : (window.DEFAULT_WEIGHTS.kunde || 6) } }))}
                        title={state.weights.kunde ? 'Kunde-Kriterium ausschalten' : 'Kunde-Kriterium einschalten'}
                        style={{ display: 'inline-flex', alignItems: 'center', gap: 6, height: 24, padding: '0 9px 0 7px', borderRadius: 6, border: '1px solid', flex: '0 0 auto',
                          borderColor: state.weights.kunde ? 'var(--accent-ink)' : 'var(--line-2)',
                          background: state.weights.kunde ? 'var(--accent-ink)' : 'var(--surface)',
                          color: state.weights.kunde ? '#fff' : 'var(--muted)',
                          fontSize: 11.5, fontWeight: 600, cursor: 'pointer' }}>
                        <span style={{ width: 14, height: 14, borderRadius: 4, display: 'grid', placeItems: 'center', background: state.weights.kunde ? 'rgba(255,255,255,.2)' : 'var(--surface-2)', border: state.weights.kunde ? 'none' : '1px solid var(--line-2)' }}>
                          {state.weights.kunde ? <Icon name="check" size={11} /> : null}
                        </span>
                        {state.weights.kunde ? 'An' : 'Aus'}
                      </button>
                      <L>Kunden-Segment → Score</L>
                    </div>
                    <div style={{ display: 'flex', gap: 18, marginTop: 10, opacity: state.weights.kunde ? 1 : 0.45 }}>
                      {['A', 'B', 'C'].map(seg => (
                        <div key={seg} style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
                          <SegBadge seg={seg} />
                          <select value={state.kundeMap[seg]} onChange={e => set(s => ({ ...s, kundeMap: { ...s.kundeMap, [seg]: +e.target.value } }))} style={selStyle}>
                            {[1, 2, 3, 4, 5, 6, 7, 8, 9].map(n => <option key={n} value={n}>{n}</option>)}
                          </select>
                        </div>
                      ))}
                    </div>
                  </div>

                  {/* Live-Vorschau: Auftrags-Scores aktualisieren sich sofort */}
                  <div style={{ marginTop: 16, maxWidth: 640 }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
                      <L>Live-Vorschau · Score je Auftrag</L>
                      <span style={{ fontSize: 11, color: 'var(--muted)' }}>aktualisiert sich beim Verstellen</span>
                    </div>
                    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, minmax(0,1fr))', gap: 6 }}>
                      {window.ORDERS.filter(o => !o.released).map(o => {
                        const r = window.computeScore(o, state.weights, state.kundeMap);
                        return (
                          <div key={o.nr} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6px 8px', background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 6, minWidth: 0 }}>
                            <span className="num" style={{ fontFamily: 'var(--mono)', fontSize: 11.5, fontWeight: 600, color: 'var(--ink-2)' }}>{o.nr.replace('FA-', '')}</span>
                            <MatChip mat={o.mat} />
                            <span style={{ fontSize: 11.5, color: 'var(--ink)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', flex: 1, minWidth: 0 }}>{o.kurz}</span>
                            <SegBadge seg={window.CUSTOMERS[o.kunde] || 'C'} />
                            <ScoreBadge value={r.total} size="sm" />
                          </div>
                        );
                      })}
                    </div>
                  </div>
                </Section>

                <Section icon="alert" title="Restriktionen" desc="Verbotene Werkstoff-Folgen. Der Solver vermeidet, dass „von“ direkt von „nach“ gefertigt wird.">
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 8, maxWidth: 620 }}>
                    {state.restrictions.map(r => (
                      <div key={r.id} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 10px', background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 7, opacity: r.active ? 1 : 0.5 }}>
                        <button onClick={() => updRule(r.id, { active: !r.active })} title="aktiv/inaktiv"
                          style={{ width: 18, height: 18, borderRadius: 5, border: '1px solid', borderColor: r.active ? 'var(--accent-ink)' : 'var(--line-2)', background: r.active ? 'var(--accent-ink)' : 'var(--surface)', color: '#fff', display: 'grid', placeItems: 'center' }}>
                          {r.active && <Icon name="check" size={12} />}
                        </button>
                        <select value={r.from} onChange={e => updRule(r.id, { from: e.target.value })} style={selStyle}>
                          {matIds.map(m => <option key={m} value={m}>{window.MATERIALS[m].id}</option>)}
                        </select>
                        <span style={{ fontSize: 11.5, color: 'var(--muted)', whiteSpace: 'nowrap', display: 'inline-flex', alignItems: 'center', gap: 4 }}>nicht direkt vor <Icon name="arrow" size={13} /></span>
                        <select value={r.to} onChange={e => updRule(r.id, { to: e.target.value })} style={selStyle}>
                          {matIds.map(m => <option key={m} value={m}>{window.MATERIALS[m].id}</option>)}
                        </select>
                        <button onClick={() => delRule(r.id)} style={{ marginLeft: 'auto', width: 26, height: 26, border: '1px solid var(--line-2)', borderRadius: 6, background: 'var(--surface)', color: 'var(--muted)', display: 'grid', placeItems: 'center' }}><Icon name="close" size={13} /></button>
                      </div>
                    ))}
                    <button onClick={addRule} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, alignSelf: 'flex-start', height: 32, padding: '0 12px', borderRadius: 6, border: '1px dashed var(--line-2)', background: 'transparent', color: 'var(--ink-2)', fontSize: 12.5 }}>
                      <Icon name="plus" size={14} /> Regel hinzufügen
                    </button>
                  </div>
                </Section>
              </div>
            )}

            {page === 'ruest' && (
              <div style={{ paddingTop: 18 }}>
                <PageHead icon="grid" title="Rüstzeitmatrix" />
                <RuestMatrix matrix={state.setupMatrix}
                  onCell={(from, to, val) => set(s => ({ ...s, setupMatrix: { ...s.setupMatrix, [from]: { ...s.setupMatrix[from], [to]: val } }, solved: null }))}
                  onErst={(val) => set(s => ({ ...s, setupMatrix: { ...s.setupMatrix, erst: val }, solved: null }))}
                  onReset={() => set(s => ({ ...s, setupMatrix: window.buildDefaultMatrix(), solved: null }))} />
              </div>
            )}

            {page === 'kapazitaet' && (
              <div style={{ paddingTop: 18 }}>
                <PageHead icon="calendar" title="Kapazitätsplanung" sub="Rollierende Jahreskapazität — Parameter pflegen, Zeiträume markieren, einzelne Tage anpassen." />
                <CapacityPlanner capBySystem={state.capacityBySystem} setCapFor={setCapFor} currentSystem={state.workSystem} />
              </div>
            )}

            {page === 'uebergang' && (
              <div style={{ paddingTop: 18 }}>
                <PageHead icon="arrow" title="Übergangszeiten" sub="Min-Übergangszeit je Arbeitssystem mit aktueller und durchschnittlicher Auftragsreichweite." />
                <TransitionTimes
                  transitionBySystem={state.transitionBySystem}
                  setTransition={(sysId, val) => set(s => ({ ...s, transitionBySystem: { ...s.transitionBySystem, [sysId]: val } }))}
                  capBySystem={state.capacityBySystem}
                  currentSystem={state.workSystem} />
              </div>
            )}

            {page === 'doku' && (
              <div style={{ paddingTop: 18 }}>
                <PageHead icon="info" title="Dokumentation" sub="So entsteht die Durchlaufplanung — Vorgehen und getroffene Annahmen." />
                <DocPage />
              </div>
            )}
          </div>
        </div>
      </div>
    </>
  );
}

function DocStep({ n, title, children }) {
  return (
    <div style={{ display: 'flex', gap: 12, marginBottom: 14 }}>
      <span className="num" style={{ flex: '0 0 auto', width: 26, height: 26, borderRadius: 99, display: 'grid', placeItems: 'center', background: 'var(--accent)', color: 'var(--accent-ink)', fontFamily: 'var(--mono)', fontSize: 13, fontWeight: 700 }}>{n}</span>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontWeight: 600, fontSize: 13.5, marginBottom: 3 }}>{title}</div>
        <div style={{ fontSize: 12.5, color: 'var(--ink-2)', lineHeight: 1.55 }}>{children}</div>
      </div>
    </div>
  );
}

function DocCard({ title, items }) {
  return (
    <div style={{ background: 'var(--surface)', border: '1px solid var(--line)', borderRadius: 9, padding: '13px 15px' }}>
      <div className="label" style={{ marginBottom: 9 }}>{title}</div>
      <ul style={{ margin: 0, paddingLeft: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 7 }}>
        {items.map((it, i) => (
          <li key={i} style={{ display: 'flex', gap: 8, fontSize: 12, color: 'var(--ink-2)', lineHeight: 1.5 }}>
            <span style={{ flex: '0 0 auto', width: 5, height: 5, borderRadius: 99, background: 'var(--accent-ink)', marginTop: 6 }} />
            <span><b style={{ color: 'var(--ink)', fontWeight: 600 }}>{it[0]}</b> — {it[1]}</span>
          </li>
        ))}
      </ul>
    </div>
  );
}

function DocFormula({ children }) {
  return <div className="num" style={{ fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--accent-ink)', background: 'var(--surface-2)', border: '1px solid var(--line)', borderRadius: 6, padding: '7px 10px', margin: '6px 0', display: 'inline-block' }}>{children}</div>;
}

function DocPage() {
  return (
    <div style={{ maxWidth: 880, paddingBottom: 30 }}>
      {/* Ablauf */}
      <div style={{ marginBottom: 8, fontWeight: 600, fontSize: 14 }}>1 · Wie die Durchlaufplanung entsteht</div>
      <div style={{ fontSize: 12, color: 'var(--muted)', marginBottom: 14, lineHeight: 1.5 }}>
        Die <b style={{ color: 'var(--ink-2)' }}>Feinplanung ist führend</b>: Sie bestimmt je Arbeitssystem die Reihenfolge. Die Durchlaufplanung bildet diese Ergebnisse systemübergreifend ab und verkettet sie entlang der Arbeitspläne.
      </div>
      <DocStep n="1" title="Score je Auftrag">
        Aus den Kriterien (Schlupf, Wert, Kunde ABC, Plan-Start/-Ende) wird ein gewichteter Score 1–9 gebildet — Grundpriorität für den Solver.
      </DocStep>
      <DocStep n="2" title="Reihenfolge je System (Feinplanung)">
        Pro Arbeitssystem erzeugt der Solver aus Score + Optimierungsziel (Durchlaufzeit / Rüsten / Termintreue) eine Reihenfolge. Fixierte Vorgänge bleiben an ihrer Position; Restriktionen (verbotene Werkstofffolgen) werden vermieden.
      </DocStep>
      <DocStep n="3" title="Terminierung mit Kapazität">
        Jeder Vorgang wird in offene Schichten eingelastet (Rüsten + Bearbeitung). Geschlossene Schichten/Tage werden übersprungen; „splitten erlaubt" teilt über Schicht-/Tagesgrenzen.
      </DocStep>
      <DocStep n="4" title="Verkettung über die Stufen">
        Stufenweise in Routing-Reihenfolge (Sägen → Drehen → Fräsen → … → Prüfen). Ein nachgelagerter Vorgang startet frühestens, wenn der Vorgänger fertig ist plus Übergangszeit.
        <DocFormula>früheste Ankunft = Ende Vorstufe + Min-Übergangszeit</DocFormula>
      </DocStep>
      <DocStep n="5" title="Kennzahlen & Widgets">
        Aus der verketteten Belegung folgen Ø Durchlaufzeit, Termintreue, Auslastung (Ø über die Frozen Zone) und Reichweite je System.
      </DocStep>

      {/* Optimierer */}
      <div style={{ margin: '20px 0 8px', fontWeight: 600, fontSize: 14 }}>2 · Mathematischer Ansatz & Optimierer</div>
      <div style={{ fontSize: 12.5, color: 'var(--ink-2)', lineHeight: 1.55, marginBottom: 12 }}>
        <b style={{ color: 'var(--ink)' }}>Berechnen</b> nutzt eine <b style={{ color: 'var(--ink)' }}>Greedy-Heuristik</b> (Dispatching): Position für Position wird der Vorgang mit dem höchsten Nutzen gewählt — eine gewichtete Kombination aus Score, Rüstvermeidung, kurzer Bearbeitung (SPT) und früher Fälligkeit (EDD). Die Mischung steuern die Optimierungsziel-Regler.
        <DocFormula>V(i) = 0,9·Score + w_Rüst·(1−Rüstzeit) + w_DLZ·(1−Dauer) + w_Termin·(1−Plan-Ende) − Strafe·Restriktion</DocFormula>
      </div>
      <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start', background: 'color-mix(in oklch, var(--accent) 12%, var(--surface))', border: '1px solid var(--accent-line)', borderRadius: 9, padding: '13px 15px' }}>
        <span style={{ flex: '0 0 auto', display: 'grid', placeItems: 'center', width: 30, height: 30, borderRadius: 7, background: 'var(--accent)', color: 'var(--accent-ink)' }}><Icon name="target" size={17} /></span>
        <div style={{ fontSize: 12.5, color: 'var(--ink-2)', lineHeight: 1.55 }}>
          <b style={{ color: 'var(--ink)' }}>Optimieren</b> verbessert die Greedy-Reihenfolge per <b style={{ color: 'var(--ink)' }}>lokaler Suche (Or-opt)</b>: Vorgänge werden testweise an andere Positionen verschoben und nur übernommen, wenn die echte Belegung besser wird. Bewertet wird eine gewichtete Zielfunktion aus <b style={{ color: 'var(--ink)' }}>Σ Rüstzeit, Makespan und Verspätung</b> — Gewichte aus den Reglern. Fixierte Vorgänge bleiben an ihrer Position, Ankunftstermine werden eingehalten.
          <div style={{ marginTop: 6 }}>Nach dem Lauf zeigt ein Banner die Verbesserung gegenüber Greedy (z. B. „Rüsten −22 %"). Typischer Hebel: <b style={{ color: 'var(--ink)' }}>5–20 % weniger Rüstzeit/Verspätung</b>; die mittlere Durchlaufzeit ist per SPT bereits nahe optimal.</div>
        </div>
      </div>

      {/* Formeln */}
      <div style={{ margin: '20px 0 8px', fontWeight: 600, fontSize: 14 }}>3 · Wichtige Formeln</div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 8 }}>
        <DocCard title="Score & Zeiten" items={[
          ['Score', 'Σ(Priorität × Teilwert) ÷ Σ Priorität, gerundet auf 1–9'],
          ['Auftragsdauer', 'Rüstdauer + Losgröße × Einzelzeit'],
          ['Schlupf', 'Plan-Endtermin − verbleibender Restarbeitsinhalt'],
          ['Andler-Losgröße', '√(2 × Jahresbedarf × Rüstkosten ÷ (Zinssatz × Teilewert))'],
        ]} />
        <DocCard title="Auswertung" items={[
          ['Durchlaufzeit', 'letzter Vorgang − erster Vorgang (in Tagen)'],
          ['Termintreue', 'fertig bis Ende des Plan-Ende-Tages (tagesgenau)'],
          ['Auslastung', 'belegte h ÷ Kapazität, gemittelt über die Frozen Zone'],
          ['Reichweite', 'Auftragsbestand (h) ÷ Netto-Tageskapazität'],
        ]} />
      </div>

      {/* Annahmen */}
      <div style={{ margin: '20px 0 8px', fontWeight: 600, fontSize: 14 }}>4 · Getroffene Annahmen</div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <DocCard title="Zeitmodell & Kapazität" items={[
          ['Schichtmodell', '3 Schichten/Tag à 8 h (Früh 06:00 / Spät 14:00 / Nacht 22:00)'],
          ['1 Tag', '= 3 Schichten = 24 h; Wochenenden standardmäßig geschlossen'],
          ['Netto-Kapazität', 'Schichten × Systeme × (8 h − Pausen) × OEE'],
          ['Frozen Zone', 'N offene Schichten in die Zukunft sind fixiert'],
        ]} />
        <DocCard title="Fluss & Kosten" items={[
          ['Eine Maschine', 'bearbeitet einen Vorgang exklusiv; kein paralleler Auftrag'],
          ['Übergangszeit', 'fixe Min-Liege-/Transportzeit je System (Stammdaten)'],
          ['Rüsten', 'abhängig vom Werkstoffwechsel laut Rüstzeitmatrix'],
          ['Kostensätze', 'Teilewert, Lohn, Maschinenstundensatz aus Stammdaten'],
        ]} />
      </div>

      <div style={{ marginTop: 14, padding: '11px 14px', background: 'color-mix(in oklch, var(--warn) 22%, var(--surface))', border: '1px solid color-mix(in oklch, var(--warn) 45%, var(--line))', borderRadius: 8, fontSize: 11.5, color: 'var(--ink-2)', lineHeight: 1.55 }}>
        <b style={{ color: 'var(--ink)' }}>Hinweis:</b> Die Reihenfolge der Feinplanung wird strikt eingehalten — der Solver zieht keine später einplanten Vorgänge automatisch vor (außer im Modus „Lücken füllen"). Manuelle Eingriffe (Ziehen, Fixieren, Splitten, Losgröße übernehmen) überschreiben die Automatik.
      </div>
    </div>
  );
}

function PageHead({ icon, title, sub }) {
  return (
    <div style={{ marginBottom: 16 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 9 }}>
        <Icon name={icon} size={18} style={{ color: 'var(--ink-2)' }} />
        <span style={{ fontWeight: 600, fontSize: 16 }}>{title}</span>
      </div>
      {sub && <div style={{ fontSize: 12.5, color: 'var(--muted)', marginTop: 4 }}>{sub}</div>}
    </div>
  );
}

function Section({ icon, title, desc, info, children }) {
  return (
    <div style={{ padding: '18px 0', borderBottom: '1px solid var(--line)' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 5 }}>
        <Icon name={icon} size={15} style={{ color: 'var(--ink-2)' }} />
        <span style={{ fontWeight: 600, fontSize: 13.5 }}>{title}</span>
        {info}
      </div>
      <div style={{ fontSize: 12, color: 'var(--muted)', marginBottom: 14, maxWidth: 540, lineHeight: 1.5 }}>{desc}</div>
      {children}
    </div>
  );
}

// Hover-Infobox
function InfoTip({ width = 320, children }) {
  const [open, setOpen] = useState(false);
  return (
    <span style={{ position: 'relative', display: 'inline-flex' }} onMouseEnter={() => setOpen(true)} onMouseLeave={() => setOpen(false)}>
      <Icon name="info" size={14} style={{ color: open ? 'var(--accent-ink)' : 'var(--muted)', cursor: 'help' }} />
      {open && (
        <div style={{ position: 'absolute', top: 'calc(100% + 7px)', left: -6, width, zIndex: 20,
          background: 'var(--ink)', color: 'var(--surface-2)', borderRadius: 8, padding: '11px 13px',
          fontSize: 11.5, lineHeight: 1.55, fontWeight: 400, boxShadow: '0 10px 30px rgba(63,62,61,.3)' }}>
          <span style={{ position: 'absolute', top: -5, left: 9, width: 10, height: 10, background: 'var(--ink)', transform: 'rotate(45deg)' }} />
          {children}
        </div>
      )}
    </span>
  );
}

const selStyle = { fontFamily: 'var(--mono)', fontSize: 12, padding: '5px 8px', borderRadius: 6, border: '1px solid var(--line-2)', background: 'var(--surface)', color: 'var(--ink)' };

Object.assign(window, { AdminPanel, Section });
