const { useState, useEffect, useMemo, useRef } = React;
const {
  FileText, CheckCircle2, Archive, XCircle, Clock,
  Search, ChevronRight, History, Eye, RefreshCw, ShieldCheck, X
} = Icons;

// ---- Band Alpin Erscheinungsbild (identisch zur Haupt-App) ----
const PRIMARY = "#0A7E8C";        // --ba-primary
const PRIMARY_DARK = "#086874";   // --ba-primary-deep
const PRIMARY_TINT = "#EAF6F7";   // --ba-hervor-bg
const INK = "#0D1418";            // --ba-ink
const SLATE = "#38444B";          // --ba-ink-secondary
const SLATE_SOFT = "#66757D";     // --ba-ink-mute
const HAIRLINE = "#E2E6E8";       // --ba-hairline
const CANVAS = "#F2F4F5";         // --ba-canvas-soft

const STATUS = {
  gueltig:        { label: "Gültig",         dot: "#0F7B4F", bg: "#E8F4EE", fg: "#0F7B4F", icon: CheckCircle2 },
  ersetzt:        { label: "Ersetzt",        dot: "#66757D", bg: "#F2F4F5", fg: "#38444B", icon: Archive },
  ungueltig:      { label: "Ungültig",       dot: "#C2274B", bg: "#FBEAEE", fg: "#C2274B", icon: XCircle },
  in_bearbeitung: { label: "In Bearbeitung", dot: "#B57314", bg: "#FBF2E6", fg: "#B57314", icon: Clock },
};
const STATUS_ORDER = ["gueltig", "ersetzt", "in_bearbeitung", "ungueltig"];

const CHAPTERS = [
  { id: "00", name: "QM-Handbuch" },
  { id: "04", name: "Kontext der Organisation" },
  { id: "05", name: "Führung" },
  { id: "06", name: "Planung" },
  { id: "07", name: "Unterstützung" },
  { id: "08", name: "Betrieb" },
  { id: "09", name: "Bewertung der Leistung" },
  { id: "10", name: "Verbesserung" },
  { id: "FO", name: "Formulare & Vorlagen" },
];

// Gleicher Seed wie Haupt-App — dient nur als Anzeige, bevor der erste Sync-Abruf kommt.
const SEED = [
  ["BA-QM-00-01", "QM-Handbuch Band Alpin GmbH", "00", "Handbuch"],
  ["BA-QM-04-01", "Kontext- und Klimawandel-Relevanzanalyse (4.1)", "04", "Analyse"],
  ["BA-QM-04-02", "Interessierte Parteien & deren Anforderungen (4.2)", "04", "Analyse"],
  ["BA-QM-04-03", "Geltungsbereich des QM-Systems (4.3)", "04", "Dokument"],
  ["BA-QM-05-01", "Qualitätspolitik", "05", "Dokument"],
  ["BA-QM-05-02", "Organigramm & Verantwortlichkeiten", "05", "Dokument"],
  ["BA-QM-06-01", "Risikobewertung und Risikomaßnahmen (6.1.2)", "06", "Verfahrensanweisung"],
  ["BA-QM-06-02", "Chancenbewertung und Chancenmaßnahmen (6.1.3)", "06", "Verfahrensanweisung"],
  ["BA-QM-06-03", "Qualitätsziele und Planung zu deren Erreichung (6.2)", "06", "Dokument"],
  ["BA-QM-06-04", "Planung von Änderungen (6.3)", "06", "Verfahrensanweisung"],
  ["BA-QM-07-01", "Kompetenzmatrix / Schulungsplan", "07", "Dokument"],
  ["BA-QM-07-02", "Infrastruktur- und Prozessumgebungskonzept (7.1.3/7.1.4)", "07", "Dokument"],
  ["BA-QM-07-03", "VA Lenkung dokumentierter Information", "07", "Verfahrensanweisung"],
  ["BA-QM-08-01", "VA Auftragsabwicklung", "08", "Verfahrensanweisung"],
  ["BA-QM-08-02", "VA Beschaffung & Lieferantenbewertung", "08", "Verfahrensanweisung"],
  ["BA-QM-08-03", "VA Reklamationsbearbeitung", "08", "Verfahrensanweisung"],
  ["BA-QM-08-04", "Produkt-/Dienstleistungsfreigabe", "08", "Verfahrensanweisung"],
  ["BA-QM-09-01", "VA Internes Audit", "09", "Verfahrensanweisung"],
  ["BA-QM-09-02", "VA Managementbewertung", "09", "Verfahrensanweisung"],
  ["BA-QM-09-03", "Kundenzufriedenheitsanalyse", "09", "Dokument"],
  ["BA-QM-10-01", "VA Korrektur- & Vorbeugemaßnahmen", "10", "Verfahrensanweisung"],
  ["BA-QM-10-02", "KVP-Verbesserungsprozess", "10", "Verfahrensanweisung"],
  ["BA-FO-01", "Auditcheckliste", "FO", "Formular"],
  ["BA-FO-02", "Reklamationsformular", "FO", "Formular"],
  ["BA-FO-03", "Schulungsnachweis", "FO", "Formular"],
].map(([docNr, name, chapter, category], i) => ({
  id: `seed-${i}`,
  docNr, name, chapter, category,
  version: "1.0",
  status: "in_bearbeitung",
  creator: "", checker: "", approver: "", approvalDate: "",
  notes: "",
  history: [],
  hasFile: false,
}));

const POLL_MS = 4000;

// Die Auditor-Ansicht kennt keinen Download. Sie öffnet das Dokument zum
// Lesen im Browser — mehr braucht eine Prüfung nicht, und Unterlagen gehen
// nicht ohne unser Zutun aus dem Haus.
function oeffneVorschau(doc) {
  // "v" erzwingt bei jedem Öffnen eine neue URL, damit ein Handy-Browser nie
  // eine veraltete, lokal gespeicherte Fassung weiterzeigt. Siehe app.jsx.
  const q = new URLSearchParams({ chapter: doc.chapter, docNr: doc.docNr, status: doc.status, v: String(Date.now()) });
  window.open(`/api/documents/${doc.id}/file?${q.toString()}`, "_blank");
}

// Die Gipfel-A-Wortmarke, inline gesetzt — nur inline erbt sie Archivo und die
// Farbe ihrer Umgebung. Geometrie unverändert aus ci/logo-wortmarke.svg.
function Wortmarke() {
  const schrift = { fontFamily: "'Archivo', system-ui, sans-serif", fontWeight: 700, letterSpacing: "6.4px", fontSize: "20px" };
  return (
    <svg className="ba-wortmarke-svg" viewBox="0 0 172 19" role="img" aria-label="BandAlpin">
      <text x="0" y="18" className="ink" style={schrift}>BAND</text>
      <path d="M83.93 18 L91.89 3.15 L99.85 18" fill="none" className="akzent-strich" strokeWidth="2.5" />
      <text x="105.28" y="18" className="akzent" style={schrift}>LPIN</text>
    </svg>
  );
}

function StatusChip({ status }) {
  const s = STATUS[status] || STATUS.in_bearbeitung;
  const Icon = s.icon;
  return (
    <span className="inline-flex items-center gap-1.5 rounded-full py-1 pl-2 pr-2.5 text-xs font-semibold" style={{ backgroundColor: s.bg, color: s.fg }}>
      <Icon size={12} strokeWidth={2.75} /> {s.label}
    </span>
  );
}

function Modal({ title, subtitle, onClose, children }) {
  return (
    <div
      className="fixed inset-0 z-50 flex items-center justify-center p-4"
      style={{ backgroundColor: "rgba(17,22,31,0.45)", backdropFilter: "blur(2px)" }}
      onClick={onClose}
    >
      <div className="w-full max-w-lg overflow-hidden rounded-2xl bg-white shadow-2xl" onClick={(e) => e.stopPropagation()}>
        <div className="flex items-start justify-between px-6 py-5" style={{ borderBottom: `1px solid ${HAIRLINE}` }}>
          <div>
            <h3 className="text-[15px] font-bold tracking-tight" style={{ color: INK }}>{title}</h3>
            {subtitle && <p className="mt-0.5 text-xs" style={{ color: SLATE_SOFT }}>{subtitle}</p>}
          </div>
          <button onClick={onClose} className="rounded-full p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600">
            <X size={16} />
          </button>
        </div>
        <div className="max-h-[70vh] overflow-y-auto px-6 py-5">{children}</div>
      </div>
    </div>
  );
}

function ReadRow({ label, value }) {
  return (
    <div className="mb-3">
      <div className="text-[11px] font-bold uppercase tracking-wide" style={{ color: SLATE_SOFT }}>{label}</div>
      <div className="mt-0.5 text-sm" style={{ color: value ? INK : SLATE_SOFT }}>{value || "— nicht angegeben —"}</div>
    </div>
  );
}

const inputCls =
  "w-full rounded-lg border px-3 py-2 text-sm outline-none transition focus:border-[#3D83FC] focus:ring-2 focus:ring-[#3D83FC]/15";

/* ------------------------------------------------------------------ */
/* Login — eigene Auditor-Anmeldung, getrennt von der Haupt-App        */
/* (seit 18.08.2026; vorher teilte sich diese Ansicht die Sitzung mit   */
/* der vollen App, ein Auditor-Passwort hätte also volle Schreibrechte  */
/* über die API gegeben, nur in der Oberfläche versteckt). Ein Passwort */
/* einrichten kann nur eine bereits angemeldete Haupt-App-Sitzung.      */
/* ------------------------------------------------------------------ */
function NotConfiguredScreen() {
  return (
    <div className="flex min-h-screen items-center justify-center px-4" style={{ backgroundColor: CANVAS, fontFamily: "'Inter', -apple-system, 'Segoe UI', sans-serif" }}>
      <div className="w-full max-w-sm rounded-2xl bg-white p-6 shadow-sm" style={{ border: `1px solid ${HAIRLINE}` }}>
        <h2 className="mb-1 text-lg font-bold tracking-tight" style={{ color: INK }}>Noch kein Auditor-Passwort eingerichtet</h2>
        <p className="mb-4 text-sm" style={{ color: SLATE_SOFT }}>
          Für die Auditor-Ansicht ist noch kein eigenes Passwort vergeben. Das geschieht in der Haupt-App unter „Auditor-Zugang“.
        </p>
      </div>
    </div>
  );
}

function AuthScreen({ aufErfolg }) {
  const [pw, setPw] = useState("");
  const [fehler, setFehler] = useState("");
  const [busy, setBusy] = useState(false);

  const absenden = async () => {
    setFehler("");
    if (!pw) return setFehler("Passwort eingeben.");
    setBusy(true);
    try {
      const r = await fetch("/api/auth/auditor-login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ password: pw }) });
      const j = await r.json().catch(() => ({}));
      if (r.ok) { aufErfolg(); return; }
      setFehler(j.error || "Fehler.");
    } catch {
      setFehler("Keine Verbindung zum Server.");
    }
    setBusy(false);
  };

  return (
    <div className="flex min-h-screen items-center justify-center px-4" style={{ backgroundColor: CANVAS, fontFamily: "'Inter', -apple-system, 'Segoe UI', sans-serif" }}>
      <div className="w-full max-w-sm rounded-2xl bg-white p-6 shadow-sm" style={{ border: `1px solid ${HAIRLINE}` }}>
        <h2 className="mb-1 text-lg font-bold tracking-tight" style={{ color: INK }}>Anmelden</h2>
        <p className="mb-4 text-sm" style={{ color: SLATE_SOFT }}>
          Diese Auditor-Ansicht ist passwortgeschützt und nur zum Lesen — kein Download, keine Änderung.
        </p>
        <label className="mb-3 block text-sm">
          <span className="font-medium" style={{ color: SLATE }}>Passwort</span>
          <input type="password" value={pw} autoFocus
            autoComplete="current-password"
            onChange={(e) => setPw(e.target.value)}
            onKeyDown={(e) => { if (e.key === "Enter") absenden(); }}
            className={`mt-1 ${inputCls}`} style={{ borderColor: HAIRLINE }} />
        </label>
        {fehler && <div className="mb-3 rounded-lg px-3 py-2 text-sm" style={{ backgroundColor: "#FDECEC", color: "#B93330", border: "1px solid #F5C6C5" }}>{fehler}</div>}
        <button onClick={absenden} disabled={busy}
          className="w-full rounded-lg px-4 py-2 text-sm font-semibold text-white shadow-sm transition hover:brightness-110 disabled:opacity-40"
          style={{ backgroundColor: PRIMARY }}>
          Anmelden
        </button>
      </div>
    </div>
  );
}

function App() {
  const [authState, setAuthState] = useState(null); // null = wird geladen
  const [documents, setDocuments] = useState(SEED);
  const [lastSync, setLastSync] = useState(null);
  const [syncState, setSyncState] = useState("connecting"); // connecting | live | error
  const [activeChapter, setActiveChapter] = useState("ALLE");
  const [activeStatus, setActiveStatus] = useState("ALLE");
  const [query, setQuery] = useState("");
  const [selectedDoc, setSelectedDoc] = useState(null);
  const lastJson = useRef(null);

  const authPruefen = () => {
    fetch("/api/auth/auditor-status")
      .then((r) => r.json())
      .then((s) => setAuthState(s))
      .catch(() => setAuthState({ configured: true, authenticated: false, verbindungsFehler: true }));
  };

  const abmelden = async () => {
    await fetch("/api/auth/auditor-logout", { method: "POST" });
    authPruefen();
  };

  useEffect(() => { authPruefen(); }, []);

  async function fetchDocs() {
    try {
      const r = await fetch("/api/daten");
      if (r.status === 401) { setAuthState({ configured: true, authenticated: false }); return; }
      const json = await r.json();
      if (json && json.value) {
        if (json.value !== lastJson.current) {
          lastJson.current = json.value;
          const parsed = JSON.parse(json.value);
          if (Array.isArray(parsed)) setDocuments(parsed);
        }
      }
      setSyncState("live");
      setLastSync(new Date());
    } catch (e) {
      setSyncState((s) => (s === "live" ? "live" : "error"));
      setLastSync(new Date());
    }
  }

  useEffect(() => {
    if (!authState?.authenticated) return;
    fetchDocs();
    const interval = setInterval(fetchDocs, POLL_MS);
    return () => clearInterval(interval);
  }, [authState]);

  const counts = useMemo(() => {
    const c = { gueltig: 0, ersetzt: 0, ungueltig: 0, in_bearbeitung: 0 };
    documents.forEach((d) => { c[d.status] = (c[d.status] || 0) + 1; });
    return c;
  }, [documents]);

  const filtered = useMemo(() => {
    return documents.filter((d) => {
      if (activeChapter !== "ALLE" && d.chapter !== activeChapter) return false;
      if (activeStatus !== "ALLE" && d.status !== activeStatus) return false;
      if (query.trim()) {
        const q = query.toLowerCase();
        if (!d.name.toLowerCase().includes(q) && !d.docNr.toLowerCase().includes(q)) return false;
      }
      return true;
    });
  }, [documents, activeChapter, activeStatus, query]);

  // Nach Normkapitel gruppiert, in der Reihenfolge der Norm — dieselbe
  // Gliederung wie in der Haupt-App. Wer ein QM-System prüft, sucht in
  // Kapitel 8, nicht unter B.
  const gruppiert = useMemo(() => {
    const nach = new Map(CHAPTERS.map((c) => [c.id, []]));
    filtered.forEach((d) => {
      if (!nach.has(d.chapter)) nach.set(d.chapter, []);
      nach.get(d.chapter).push(d);
    });
    return [...nach.entries()]
      .filter(([, docs]) => docs.length)
      .map(([kap, docs]) => [kap, docs.sort((a, b) => a.docNr.localeCompare(b.docNr))]);
  }, [filtered]);

  const [zuKapitel, setZuKapitel] = useState({});
  const toggleKapitel = (kap) => setZuKapitel((z) => ({ ...z, [kap]: !z[kap] }));

  const chapterName = (id) => CHAPTERS.find((c) => c.id === id)?.name || id;
  const total = documents.length || 1;

  if (!authState) return <div className="flex min-h-screen items-center justify-center" style={{ color: SLATE_SOFT }}>Lade…</div>;
  if (!authState.configured) return <NotConfiguredScreen />;
  if (!authState.authenticated) return <AuthScreen aufErfolg={authPruefen} />;

  return (
    <div className="flex h-full min-h-[760px] w-full flex-col" style={{ backgroundColor: CANVAS, fontFamily: "'Inter', -apple-system, 'Segoe UI', sans-serif", color: INK }}>
      {/* Top bar */}
      <header className="ba-kopfband sticky top-0 z-30 flex items-center gap-5 px-6 py-4">
        <div className="flex items-center gap-3.5">
          <Wortmarke />
          <span className="h-6 w-px" style={{ backgroundColor: "#24343D" }} />
          <div className="leading-tight">
            <h1 className="text-[13px] font-bold tracking-tight">Auditor-Ansicht</h1>
            <p className="ba-kopf-unter ba-marke mt-0.5">ISO 9001:2015</p>
          </div>
        </div>

        <span className="ml-1 inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-[11px] font-bold" style={{ backgroundColor: PRIMARY_TINT, color: PRIMARY_DARK }}>
          <Eye size={12} /> Nur Lesen
        </span>

        {/* Kopfzeile ab hier baugleich zur Haupt-App (dieselben ba-zeile-
            Klassen, damit sie am Handy gleich umbricht). Weggelassen sind
            genau die Schaltflächen, die eine schreibende oder verwaltende
            Handlung auslösen — Auditor-Ansicht, Auditor-Zugang, SpritzgussQM
            Produktion, Speicheranzeige, Neues Dokument. Ein Auditor hat dort
            nichts zu tun; alles Übrige ist identisch. */}
        <div className="ba-zeile-2 ba-kopf-suche relative w-full">
          <Search size={14} className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2" style={{ color: SLATE_SOFT }} />
          <input
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Dokument oder Nr. suchen…"
            className="w-full rounded-lg border py-2 pl-8 pr-3 text-[13px] outline-none transition focus:ring-2"
            style={{ borderColor: HAIRLINE, backgroundColor: CANVAS }}
          />
        </div>

        <div className="ba-zeile-3 ba-kopf-aktionen ba-umbruch ba-luecke-y flex w-full min-w-0 items-center justify-end gap-x-3">
          <span className="hidden items-center gap-1.5 text-[11px] sm:flex" style={{ color: SLATE_SOFT }}>
            <span className="relative flex h-2 w-2">
              <span
                className="absolute inline-flex h-full w-full animate-ping rounded-full opacity-60"
                style={{ backgroundColor: syncState === "live" ? "#1E9150" : "#C7940D" }}
              />
              <span className="relative inline-flex h-2 w-2 rounded-full" style={{ backgroundColor: syncState === "live" ? "#1E9150" : "#C7940D" }} />
            </span>
            {syncState === "live" ? "Live-Synchronisation" : "Verbinde…"}
            {lastSync && <span className="hidden sm:inline">· aktualisiert {lastSync.toLocaleTimeString("de-DE")}</span>}
          </span>
          <button onClick={abmelden} className="text-[11px] underline underline-offset-2 whitespace-nowrap" style={{ color: SLATE_SOFT }}>
            Abmelden
          </button>
        </div>
      </header>

      {/* Statusleiste baugleich zur Haupt-App: dieselbe ba-flaeche, dieselbe
          Hairline als Verteilungsbalken, dieselben Kacheln mit der Zahl als
          Aussage. Vorher war das hier eine eigene Gestaltung (gerundete
          Karte, dicker Balken, Icon-Chips) — zwei Erscheinungsbilder für
          dasselbe System. */}
      <div className="px-6 pt-6">
        <div className="ba-flaeche">
          <div className="flex items-center justify-between px-5 pt-4">
            <span className="ba-marke">Status · gesamtes Dokumentensystem</span>
            <span className="ba-marke">{documents.length} Dokumente</span>
          </div>
          <div className="mt-3 flex w-full overflow-hidden" style={{ height: "3px", backgroundColor: HAIRLINE }}>
            {STATUS_ORDER.map((key) => {
              const pct = (counts[key] / total) * 100;
              if (!pct) return null;
              return <div key={key} style={{ width: `${pct}%`, backgroundColor: STATUS[key].dot }} title={`${STATUS[key].label}: ${counts[key]}`} />;
            })}
          </div>
          <div className="grid grid-cols-2 sm:grid-cols-4">
            {STATUS_ORDER.map((key) => {
              const s = STATUS[key];
              const active = activeStatus === key;
              return (
                <button
                  key={key}
                  onClick={() => setActiveStatus(active ? "ALLE" : key)}
                  className="px-5 py-4 text-left transition"
                  style={{
                    borderRight: `1px solid ${HAIRLINE}`,
                    backgroundColor: active ? PRIMARY_TINT : "transparent",
                    boxShadow: active ? `inset 0 -2px 0 ${PRIMARY}` : "none",
                  }}
                >
                  <span className="block">
                    {/* Größe als Inline-Wert: Tailwind ist hier ein statischer
                        Build, beliebige Klassen wie text-[26px] stehen nicht
                        darin und wirken lautlos nicht. */}
                    <div className="ba-num font-bold leading-none" style={{ color: counts[key] ? INK : SLATE_SOFT, fontSize: "26px" }}>
                      {counts[key] || 0}
                    </div>
                    <div className="ba-marke mt-1.5 flex items-center gap-1.5">
                      <span className="inline-block h-1.5 w-1.5 rounded-full" style={{ backgroundColor: s.dot }} />
                      {s.label}
                    </div>
                  </span>
                </button>
              );
            })}
          </div>
        </div>
      </div>

      {/* Seit 18.08.2026 dieselbe Gliederung wie die Haupt-App: jedes
          Normkapitel ein eigener Abschnitt mit Kennung, Überschrift und
          Vorspann, die Dokumente darunter als Karten. Vorher standen hier
          eine Ordner-Seitenleiste und eine Tabelle — zwei Darstellungen
          desselben Systems, was im Audit unnötig verwirrt. Was die Ansicht
          NICHT bekommt, ist irgendeine schreibende Handlung: Die Karten
          führen nur in die Leseansicht und zur Vorschau. */}
      <div className="ba-hauptbereich flex-1 px-4 py-5">
        <main className="flex-1 overflow-y-auto">
        <div className="mb-3 flex items-center justify-between px-1">
          <h2 className="text-[13px] font-semibold" style={{ color: SLATE }}>
            {activeChapter === "ALLE" ? "Alle Kapitel" : `${activeChapter} · ${chapterName(activeChapter)}`}
            {activeStatus !== "ALLE" && ` · ${STATUS[activeStatus].label}`}
          </h2>
          <span className="text-[12px]" style={{ color: SLATE_SOFT }}>{filtered.length} Dokument(e)</span>
        </div>

        <div className="overflow-hidden rounded-2xl bg-white shadow-sm" style={{ border: `1px solid ${HAIRLINE}` }}>
        {filtered.length === 0 ? (
          <div className="flex flex-col items-center justify-center gap-2 px-6 py-16 text-center">
            <FileText size={28} style={{ color: HAIRLINE }} />
            <p className="text-sm font-semibold" style={{ color: SLATE }}>Keine Dokumente in dieser Ansicht</p>
            <p className="text-xs" style={{ color: SLATE_SOFT }}>Filter anpassen, um mehr Dokumente zu sehen.</p>
          </div>
        ) : (
          <div className="ba-kapitelfolge">
            {gruppiert.map(([kap, docs]) => {
              const frei = docs.filter((d) => d.status === "gueltig").length;
              const zu = zuKapitel[kap];
              return (
                <section key={kap} className="ba-kapitel">
                  <button onClick={() => toggleKapitel(kap)} className="ba-kapitelkopf">
                    <span className="ba-marke ba-kapitelnr">Kapitel {kap}</span>
                    <h2 className="ba-kapiteltitel">{chapterName(kap)}</h2>
                    <p className="ba-kapitelvorspann">
                      {docs.length} {docs.length === 1 ? "Dokument" : "Dokumente"}
                      {" · "}
                      {frei === 0 ? "keines freigegeben" : `${frei} freigegeben`}
                    </p>
                    <span className="ba-kapitelpfeil" style={{ transform: zu ? "rotate(0deg)" : "rotate(90deg)" }}>
                      <ChevronRight size={16} />
                    </span>
                  </button>

                  {!zu && (
                    <div className="ba-kartenraster">
                      {docs.map((d) => (
                        <article key={d.id} className="ba-karte" onClick={() => setSelectedDoc(d)}>
                          <p className="ba-marke ba-karte-nr">{d.docNr}</p>
                          <h3 className="ba-karte-titel">{d.name}</h3>
                          <div className="ba-karte-fuss" onClick={(e) => e.stopPropagation()}>
                            <span className="ba-karte-status">
                              <span className="ba-punkt" style={{ backgroundColor: STATUS[d.status].dot }} />
                              {STATUS[d.status].label}
                            </span>
                            <span className="ba-karte-aktionen">
                              <span className="ba-num ba-karte-version">V{d.version}</span>
                              {d.hasFile && (
                                <button onClick={() => oeffneVorschau(d)} className="ba-karte-pdf">Ansehen</button>
                              )}
                            </span>
                          </div>
                        </article>
                      ))}
                    </div>
                  )}
                </section>
              );
            })}
          </div>
        )}
        </div>

        {/* Stand bisher in der Seitenleiste. Mit deren Wegfall sitzt der
            Hinweis unter der Liste — er erklärt, warum sich die Ansicht
            von selbst aktualisiert, und gehört damit ans Ende, nicht an
            den Anfang. */}
        <p className="mt-4 px-1 text-[11px]" style={{ color: SLATE_SOFT }}>
          Diese Ansicht ist ausschließlich lesend und aktualisiert sich automatisch alle {POLL_MS / 1000}s,
          sobald in der Haupt-App Dokumente angelegt, geändert, freigegeben oder ersetzt werden.
        </p>
        </main>
      </div>

      {/* Read-only detail modal */}
      {selectedDoc && (
        <Modal title={selectedDoc.docNr} subtitle={selectedDoc.name} onClose={() => setSelectedDoc(null)}>
          <div className="mb-4 flex items-center justify-between rounded-xl p-3" style={{ backgroundColor: CANVAS }}>
            <span className="text-xs" style={{ color: SLATE_SOFT }}>
              Version <strong style={{ color: INK }}>{selectedDoc.version}</strong> · Kapitel {selectedDoc.chapter} · {selectedDoc.category}
            </span>
            <StatusChip status={selectedDoc.status} />
          </div>

          {selectedDoc.hasFile && (
            <button
              onClick={() => oeffneVorschau(selectedDoc)}
              className="mb-4 flex items-center gap-1.5 rounded-lg px-3 py-2 text-xs font-semibold text-white shadow-sm hover:brightness-110"
              style={{ backgroundColor: PRIMARY }}
            >
              <Eye size={13} /> Dokument ansehen
            </button>
          )}

          <div className="grid grid-cols-2 gap-x-4">
            <ReadRow label="Ersteller" value={selectedDoc.creator} />
            <ReadRow label="Geprüft von (QMB)" value={selectedDoc.checker} />
            <ReadRow label="Freigegeben von (GF)" value={selectedDoc.approver} />
            <ReadRow label="Freigabedatum" value={selectedDoc.approvalDate} />
          </div>
          <ReadRow label="Bemerkung" value={selectedDoc.notes} />

          {selectedDoc.history && selectedDoc.history.length > 0 && (
            <div className="mt-4 pt-4" style={{ borderTop: `1px solid ${HAIRLINE}` }}>
              <p className="mb-2.5 flex items-center gap-1.5 text-[11px] font-bold uppercase tracking-wide" style={{ color: SLATE_SOFT }}>
                <History size={13} /> Änderungshistorie
              </p>
              <ul className="space-y-2">
                {selectedDoc.history.map((h, i) => (
                  <li key={i} className="rounded-xl p-2.5 text-xs" style={{ backgroundColor: CANVAS }}>
                    <span className="font-mono font-bold">V{h.version}</span> <span style={{ color: SLATE_SOFT }}>· {h.date} · {h.changedBy}</span>
                    <div className="mt-0.5" style={{ color: SLATE_SOFT }}>{h.description}</div>
                  </li>
                ))}
              </ul>
            </div>
          )}

          {(!selectedDoc.history || selectedDoc.history.length === 0) && (
            <p className="mt-2 text-xs" style={{ color: SLATE_SOFT }}>Noch keine Versionshistorie vorhanden.</p>
          )}
        </Modal>
      )}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
