---
import Layout from "../../layouts/Layout.astro";
import type { Locale } from "../../i18n/config";

const lang: Locale = "de";

// ─── Interne Bestellverwaltung — NUR für qciga/vanvan (siehe functions/_middleware.js, diese
// Seite bleibt immer hinter dem Zugangscode, auch wenn der Rest der Seite mal öffentlich wird,
// UND zusätzlich schützt dieselbe Middleware die dazugehörige API unter /api/verwaltung/*). ───
//
// Echtes Bestellsystem seit Phase 2 (Cloudflare D1, siehe functions/api/orders.js +
// functions/api/verwaltung/): Diese Seite selbst ist als statische Astro-Seite gebaut (wie die
// ganze restliche Seite), lädt die eigentlichen Bestelldaten aber zur LAUFZEIT per fetch() aus
// der Datenbank (siehe <script> unten) — es gibt hier also KEINE Beispieldaten mehr, sondern
// echte, live einlaufende Bestellungen aus dem Checkout.
//
// 03.08.2026, zweite Ausbaustufe: auf ausdrücklichen Wunsch ("perfektioniere diese Seite aufs
// Maximum") um alles erweitert, was ein echtes kleines Shop-Team im Alltag wirklich braucht und
// vorher fehlte — Suche, Zeitraum-Filter, Sortierung, CSV-Export für die Buchhaltung, direkt
// editierbare Tracking-Nummer, Ein-Klick-Kopieren von E-Mail/Adresse fürs Versandlabel, eine
// echte PDF-Rechnung pro Bestellung (nutzt dieselbe jsPDF-Funktion wie im Kundenkonto), Warnung
// bei offenen Bestellungen, die schon länger liegen, Stammkundinnen-Kennzeichnung, und ein
// dezenter Hinweis, wenn im Hintergrund neue Bestellungen eingetrudelt sind.
---
<Layout
  title="Bestellverwaltung"
  description="Interne Bestellübersicht — nur für qciga und VanVan sichtbar."
  lang={lang}
  path="/verwaltung/"
  noindex={true}
>
  {/* Van's-Logo als mehrere kleine, sehr dezente Wasserzeichen, verteilt über den GESAMTEN
      Seitenhintergrund — fix positioniert (bleiben beim Scrollen stehen), sechs unterschiedlich
      große/schnelle/gegenläufig rotierende Kopien (gold/violett/cyan eingefärbt), exakt dieselbe
      CSS-Technik wie auf der Zugangscode-Seite (invert()+sepia()+mix-blend-mode:screen). Auf
      ausdrücklichen Wunsch (04.08.2026): statt zwei großer, zentrierter Logos (wirkte wie EIN
      großer Fleck) jetzt viele kleine, über die ganze Fläche verstreut. Auf ausdrücklichen
      Wunsch: die ganze Seite soll sich für VanVan "ultra speziell" anfühlen. */}
  <div class="verwaltung-logo-bg verwaltung-logo-bg-1" aria-hidden="true"></div>
  <div class="verwaltung-logo-bg verwaltung-logo-bg-2" aria-hidden="true"></div>
  <div class="verwaltung-logo-bg verwaltung-logo-bg-3" aria-hidden="true"></div>
  <div class="verwaltung-logo-bg verwaltung-logo-bg-4" aria-hidden="true"></div>
  <div class="verwaltung-logo-bg verwaltung-logo-bg-5" aria-hidden="true"></div>
  <div class="verwaltung-logo-bg verwaltung-logo-bg-6" aria-hidden="true"></div>

  <section class="section-tight">
    <div class="container">
      <p class="todo-note">
        🔒 Interner Bereich, nur für dich und VanVan sichtbar (siehe Zugangscode-Gate) — bleibt
        so, auch wenn der Rest der Seite mal öffentlich wird. Alles unten sind ECHTE
        Bestellungen aus der Datenbank, live vom Checkout befüllt.
      </p>
      {/* Abmelde-Button (04.08.2026, auf ausdrücklichen Wunsch): rechts über der Hero-Kiste,
          eigens "speziell" gestaltet (wandernder Verlaufsrand + Funkeln, siehe .verwaltung-logout-btn
          in global.css) — passend zum Rest der Seite, statt eines schlichten Standard-Buttons.
          Löscht beim Klick ALLE drei Zugangs-Cookies (normale Sitzung, Rollen-Anzeige, tägliche
          Verwaltungs-Sitzung) über POST /gate-logout und springt danach zur Zugangscode-Seite. */}
      <div class="verwaltung-topbar">
        <button type="button" class="verwaltung-logout-btn" id="verwaltung-logout-btn">
          <span class="verwaltung-logout-sparkle" aria-hidden="true">✨</span>
          <span aria-hidden="true">🚪</span> Abmelden
        </button>
      </div>
      <div class="verwaltung-hero">
        <span class="verwaltung-hero-sparkle verwaltung-hero-sparkle-1" aria-hidden="true">✨</span>
        <span class="verwaltung-hero-sparkle verwaltung-hero-sparkle-2" aria-hidden="true">✨</span>
        <span class="eyebrow">Verwaltung</span>
        {/* Rollenbasierte, tageszeitabhängige Begrüßung (liest das nicht-httpOnly Cookie
            "vandiy_gate_role", dasselbe, das auch den Vorschau-Umschalter in Layout.astro
            freischaltet) — auf ausdrücklichen Wunsch: diese Seite soll sich für VanVan "richtig
            speziell" anfühlen, nicht wie eine trockene Admin-Oberfläche. */}
        <p class="verwaltung-greeting" id="verwaltung-greeting"></p>
        <h1>📊 Bestellverwaltung</h1>
        <p class="lead">Behalte jederzeit den Überblick: wie viele Bestellungen offen, in Bearbeitung, versendet oder abgeschlossen sind — plus eine Auswertung, was sich am besten verkauft und woher eure Kundschaft kommt.</p>
        <div class="verwaltung-hero-settings">
          <button type="button" class="verwaltung-toggle-btn" id="verwaltung-sound-toggle" aria-pressed="false">🔈 Ton aus</button>
          <button type="button" class="verwaltung-toggle-btn" id="verwaltung-notify-toggle" aria-pressed="false">🔕 Benachrichtigungen aus</button>
        </div>
      </div>
    </div>
  </section>

  <section class="section-tight" id="verwaltung-loading">
    <div class="container">
      <p class="small">⏳ Bestellungen werden geladen …</p>
    </div>
  </section>

  <section class="section-tight" id="verwaltung-error" style="display:none;">
    <div class="container">
      <p class="todo-note" style="border-color: var(--c-sale); color: var(--c-sale);" id="verwaltung-error-text"></p>
      <button type="button" class="btn btn-outline btn-sm" id="verwaltung-retry-btn">🔄 Erneut versuchen</button>
    </div>
  </section>

  <div id="verwaltung-content" style="display:none;">
    <section class="section-tight">
      <div class="container">
        {/* Jede zusammengehörige Gruppe bekommt jetzt ihre eigene, farblich eigenständige "Kiste"
            (siehe .verwaltung-box in global.css) — statt loser Kacheln/Absätze auf der Seite. */}
        <div class="verwaltung-box" style="--box-color: var(--c-accent);" data-icon="📊">
          <div class="verwaltung-box-head">
            <span class="verwaltung-box-icon" aria-hidden="true">📊</span>
            <div class="verwaltung-box-headtext">
              <span class="verwaltung-box-kicker">Live-Überblick</span>
              <h2>Bestellstatus</h2>
            </div>
          </div>
          <div class="verwaltung-box-body">
            <div class="verwaltung-stat-grid">
              {/* Neu seit der echten PayPal-Anbindung: Überweisungs-Bestellungen starten mit
                  Status "zahlungOffen" (Geld noch nicht da) statt fälschlich sofort "bezahlt" zu
                  heißen — eigene Kachel, damit sofort auffällt, worauf noch gewartet wird. */}
              <button type="button" class="card verwaltung-stat-tile" data-filter="zahlungOffen">
                <span class="verwaltung-stat-icon" aria-hidden="true">⏳</span>
                <span class="verwaltung-stat-value" id="stat-zahlungOffen">0</span>
                <span class="verwaltung-stat-label">Zahlung ausstehend</span>
              </button>
              <button type="button" class="card verwaltung-stat-tile" data-filter="offen">
                <span class="verwaltung-stat-icon" aria-hidden="true">🆕</span>
                <span class="verwaltung-stat-value" id="stat-offen">0</span>
                <span class="verwaltung-stat-label">Offen</span>
              </button>
              <button type="button" class="card verwaltung-stat-tile" data-filter="inBearbeitung">
                <span class="verwaltung-stat-icon" aria-hidden="true">⚙️</span>
                <span class="verwaltung-stat-value" id="stat-inBearbeitung">0</span>
                <span class="verwaltung-stat-label">In Bearbeitung</span>
              </button>
              <button type="button" class="card verwaltung-stat-tile" data-filter="versendet">
                <span class="verwaltung-stat-icon" aria-hidden="true">🚚</span>
                <span class="verwaltung-stat-value" id="stat-versendet">0</span>
                <span class="verwaltung-stat-label">Versendet</span>
              </button>
              <button type="button" class="card verwaltung-stat-tile" data-filter="abgeschlossen">
                <span class="verwaltung-stat-icon" aria-hidden="true">✅</span>
                <span class="verwaltung-stat-value" id="stat-abgeschlossen">0</span>
                <span class="verwaltung-stat-label">Abgeschlossen</span>
              </button>
              <div class="card verwaltung-stat-tile verwaltung-stat-tile-highlight">
                <span class="verwaltung-stat-icon" aria-hidden="true">💶</span>
                <span class="verwaltung-stat-value" id="stat-umsatz">–</span>
                <span class="verwaltung-stat-label" id="stat-umsatz-label">Gesamtumsatz</span>
              </div>
            </div>
          </div>
        </div>

        {/* Zweite Kennzahlen-Kiste — Dinge, die im ersten Entwurf fehlten, aber im Alltag sehr
            wichtig sind: wie viel kommt gerade neu rein, und wie hoch ist der durchschnittliche
            Bestellwert (wichtig für Preis-/Werbeentscheidungen). "Heute"/"7 Tage" sind zusätzlich
            anklickbar und setzen direkt den Zeitraum-Filter unten. */}
        <div class="verwaltung-box" style="--box-color: #9b7fd6;" data-icon="📈">
          <div class="verwaltung-box-head">
            <span class="verwaltung-box-icon" aria-hidden="true">📈</span>
            <div class="verwaltung-box-headtext">
              <span class="verwaltung-box-kicker">Performance</span>
              <h2>Kennzahlen</h2>
            </div>
          </div>
          <div class="verwaltung-box-body">
            <div class="verwaltung-stat-grid verwaltung-stat-grid-secondary">
              <button type="button" class="card verwaltung-stat-tile verwaltung-stat-tile-mini" data-zeitraum="heute">
                <span class="verwaltung-stat-icon" aria-hidden="true">📅</span>
                <span class="verwaltung-stat-value" id="stat-heute">0</span>
                <span class="verwaltung-stat-label">Bestellungen heute</span>
              </button>
              <button type="button" class="card verwaltung-stat-tile verwaltung-stat-tile-mini" data-zeitraum="7tage">
                <span class="verwaltung-stat-icon" aria-hidden="true">🗓️</span>
                <span class="verwaltung-stat-value" id="stat-7tage">0</span>
                <span class="verwaltung-stat-label">Letzte 7 Tage</span>
              </button>
              <button type="button" class="card verwaltung-stat-tile verwaltung-stat-tile-mini" data-zeitraum="monat">
                <span class="verwaltung-stat-icon" aria-hidden="true">📆</span>
                <span class="verwaltung-stat-value" id="stat-monat">0</span>
                <span class="verwaltung-stat-label" id="stat-monat-label">Diesen Monat</span>
              </button>
              <div class="card verwaltung-stat-tile verwaltung-stat-tile-mini">
                <span class="verwaltung-stat-icon" aria-hidden="true">📈</span>
                <span class="verwaltung-stat-value" id="stat-avg">–</span>
                <span class="verwaltung-stat-label">Ø Bestellwert</span>
              </div>
              <div class="card verwaltung-stat-tile verwaltung-stat-tile-mini" id="stat-attention-tile" style="display:none;">
                <span class="verwaltung-stat-icon" aria-hidden="true">⚠️</span>
                <span class="verwaltung-stat-value" id="stat-attention">0</span>
                <span class="verwaltung-stat-label">Brauchen Aufmerksamkeit</span>
              </div>
            </div>
            {/* Handgebautes SVG-Sparkline-Chart (kein npm-Paket nötig, komplett lokal) — zeigt den
                Umsatzverlauf der letzten 14 Tage auf einen Blick, plus Prozent-Vergleich zur
                Vorwoche direkt daneben. */}
            <div class="verwaltung-sparkline-wrap">
              <div class="verwaltung-sparkline-head">
                <span class="small">📉 Umsatztrend — letzte 14 Tage</span>
                <span class="verwaltung-trend" id="verwaltung-week-trend"></span>
              </div>
              <svg id="verwaltung-sparkline" viewBox="0 0 280 60" preserveAspectRatio="none" aria-hidden="true"></svg>
            </div>
          </div>
        </div>

        {/* Auswertung (Bestseller/Herkunft/Stammkundschaft): jede Kiste ist jetzt SELBST der
            Klick-Auslöser (Wunsch: "es sollten Kisten sein wo man drauf drückt und dann gehen die
            anderen Sachen auf") — kein separater Knopf mehr davor. Jede Box startet eingeklappt
            (nur Kopfzeile sichtbar) und klappt beim Klick auf die Kopfzeile ihren eigenen Inhalt
            auf, unabhängig von den anderen beiden Kisten. Bewusst in DERSELBEN Section wie die
            Bestellstatus-/Kennzahlen-Kisten oben (nicht in einer eigenen <section>), sonst
            addieren sich die Section-Innenabstände zu einer viel zu großen Lücke dazwischen. */}
        <div id="verwaltung-auswertung-wrapper">
          <div class="verwaltung-box verwaltung-box-collapsible is-collapsed" style="--box-color: #e3b23c;" data-collapsible-box data-icon="🏆">
            <button type="button" class="verwaltung-box-head verwaltung-box-head-btn" aria-expanded="false">
              <span class="verwaltung-box-icon" aria-hidden="true">🏆</span>
              <div class="verwaltung-box-headtext">
                <span class="verwaltung-box-kicker">Top-Verkäufe</span>
                <h2>Bestseller je Kategorie</h2>
              </div>
              <span class="verwaltung-box-chevron" aria-hidden="true">▾</span>
            </button>
            <div class="verwaltung-box-body">
              <div class="verwaltung-box-body-inner">
                <div class="verwaltung-box-empty" id="verwaltung-kat-empty" style="display:none;">
                  <span class="verwaltung-box-empty-icon" aria-hidden="true">🧶</span>
                  <p>Noch keine ausgewerteten Verkäufe.</p>
                  <p class="small">Hier siehst du bald, welche Produkte je Kategorie am besten laufen (stornierte Bestellungen zählen nicht mit).</p>
                </div>
                {/* Jede Kategorie ist eine eigene Kachel im selben Stil wie die Bestellstatus-
                    Kacheln oben — Klick öffnet direkt darunter die volle Produktliste. */}
                <div class="verwaltung-analyse-grid" id="verwaltung-kat-grid"></div>
                <div class="verwaltung-analyse-detail" id="verwaltung-kat-detail" hidden></div>
              </div>
            </div>
          </div>

          <div class="verwaltung-box verwaltung-box-collapsible is-collapsed" style="--box-color: #6ecb8f;" data-collapsible-box data-icon="🌍">
            <button type="button" class="verwaltung-box-head verwaltung-box-head-btn" aria-expanded="false">
              <span class="verwaltung-box-icon" aria-hidden="true">🌍</span>
              <div class="verwaltung-box-headtext">
                <span class="verwaltung-box-kicker">Geografie</span>
                <h2>Herkunft der Bestellungen</h2>
              </div>
              <span class="verwaltung-box-chevron" aria-hidden="true">▾</span>
            </button>
            <div class="verwaltung-box-body">
              <div class="verwaltung-box-body-inner">
                <div class="verwaltung-box-empty" id="verwaltung-land-empty" style="display:none;">
                  <span class="verwaltung-box-empty-icon" aria-hidden="true">🗺️</span>
                  <p>Noch keine Bestellungen.</p>
                  <p class="small">Sobald Bestellungen eingehen, siehst du hier den Anteil je Land (DE/AT/CH/LU).</p>
                </div>
                <div class="verwaltung-analyse-grid" id="verwaltung-land-grid"></div>
                <div class="verwaltung-analyse-detail" id="verwaltung-land-detail" hidden></div>
              </div>
            </div>
          </div>

          <div class="verwaltung-box verwaltung-box-collapsible is-collapsed" style="--box-color: var(--c-sale);" data-collapsible-box data-icon="👑">
            <button type="button" class="verwaltung-box-head verwaltung-box-head-btn" aria-expanded="false">
              <span class="verwaltung-box-icon" aria-hidden="true">👑</span>
              <div class="verwaltung-box-headtext">
                <span class="verwaltung-box-kicker">Treue &amp; Wiederkehr</span>
                <h2>Stammkundschaft</h2>
              </div>
              <span class="verwaltung-box-chevron" aria-hidden="true">▾</span>
            </button>
            <div class="verwaltung-box-body">
              <div class="verwaltung-box-body-inner">
                <div class="verwaltung-box-empty" id="verwaltung-kunden-empty" style="display:none;">
                  <span class="verwaltung-box-empty-icon" aria-hidden="true">💌</span>
                  <p>Noch keine wiederkehrende Kundschaft.</p>
                  <p class="small">Sobald jemand zum zweiten Mal bestellt, erscheint sie hier — sortiert nach bisherigem Umsatz.</p>
                </div>
                <div class="verwaltung-analyse-grid" id="verwaltung-kunden-grid"></div>
                <div class="verwaltung-analyse-detail" id="verwaltung-kunden-detail" hidden></div>
              </div>
            </div>
          </div>
        </div>

        {/* Bewusst in DERSELBEN Section wie die Kisten oben (nicht in einer eigenen <section>) —
            sonst addieren sich die Section-Innenabstände wieder zu einer viel zu großen Lücke. */}
        <div class="verwaltung-box" style="--box-color: var(--c-accent);" data-icon="📦">
          <div class="verwaltung-box-head">
            <span class="verwaltung-box-icon" aria-hidden="true">📦</span>
            <div class="verwaltung-box-headtext">
              <span class="verwaltung-box-kicker">Vollständige Liste</span>
              <h2>Alle Bestellungen</h2>
            </div>
          </div>
          <div class="verwaltung-box-body">
            <div class="verwaltung-new-banner" id="verwaltung-new-banner" style="display:none;">
              <span>🔔 <strong id="verwaltung-new-count"></strong> neue Bestellung(en) seit dem letzten Laden</span>
              <button type="button" class="btn btn-primary btn-sm" id="verwaltung-new-refresh-btn">Jetzt aktualisieren</button>
            </div>

            <div class="verwaltung-toolbar">
              <label class="sr-only" for="verwaltung-search">Suche nach Bestellnummer, Name oder E-Mail</label>
              <input type="search" id="verwaltung-search" class="verwaltung-input" placeholder="🔍 Suche nach Bestellnummer, Name oder E-Mail …" />
              <label class="sr-only" for="verwaltung-zeitraum">Zeitraum filtern</label>
              <select id="verwaltung-zeitraum" class="verwaltung-input verwaltung-select">
                <option value="alle">Alle Zeiträume</option>
                <option value="heute">Heute</option>
                <option value="7tage">Letzte 7 Tage</option>
                <option value="monat">Dieser Monat</option>
                <option value="30tage">Letzte 30 Tage</option>
              </select>
              <label class="sr-only" for="verwaltung-sort">Sortierung</label>
              <select id="verwaltung-sort" class="verwaltung-input verwaltung-select">
                <option value="neu">Neueste zuerst</option>
                <option value="alt">Älteste zuerst</option>
                <option value="wert-ab">Höchster Wert zuerst</option>
                <option value="wert-auf">Niedrigster Wert zuerst</option>
              </select>
              <button type="button" class="btn btn-outline btn-sm" id="verwaltung-csv-btn">📄 CSV-Export</button>
            </div>

            <nav class="verwaltung-filter" aria-label="Nach Status filtern">
              <button type="button" class="verwaltung-filter-btn is-active" data-filter="alle">Alle (<span id="filter-count-alle">0</span>)</button>
              <button type="button" class="verwaltung-filter-btn" data-filter="zahlungOffen">Zahlung ausstehend (<span id="filter-count-zahlungOffen">0</span>)</button>
              <button type="button" class="verwaltung-filter-btn" data-filter="offen">Offen (<span id="filter-count-offen">0</span>)</button>
              <button type="button" class="verwaltung-filter-btn" data-filter="inBearbeitung">In Bearbeitung (<span id="filter-count-inBearbeitung">0</span>)</button>
              <button type="button" class="verwaltung-filter-btn" data-filter="versendet">Versendet (<span id="filter-count-versendet">0</span>)</button>
              <button type="button" class="verwaltung-filter-btn" data-filter="abgeschlossen">Abgeschlossen (<span id="filter-count-abgeschlossen">0</span>)</button>
              <button type="button" class="verwaltung-filter-btn" data-filter="storniert">Storniert (<span id="filter-count-storniert">0</span>)</button>
            </nav>

            <div class="verwaltung-box-empty" id="verwaltung-empty" style="display:none;">
              <span class="verwaltung-box-empty-icon" aria-hidden="true">📭</span>
              <p>Noch keine Bestellungen eingegangen.</p>
              <p class="small">Sobald die erste Bestellung im Checkout abgeschickt wird, erscheint sie sofort hier.</p>
            </div>
            <p class="small" id="verwaltung-no-match" style="display:none;">Keine Bestellung passt zur aktuellen Suche/Filterung.</p>
            <div class="order-list" id="verwaltung-order-list"></div>
          </div>
        </div>
      </div>
    </section>

  </div>

  {/* Meilenstein-Feier (z.B. "Bestellung Nr. 50!"): Konfetti-Overlay + Erfolgs-Banner, siehe
      pruefeMeilenstein() im Skript unten. Bewusst außerhalb von #verwaltung-content, damit sie
      unabhängig vom Lade-/Fehlerzustand jederzeit sichtbar sein können. */}
  <div id="verwaltung-confetti" aria-hidden="true"></div>
  <div class="verwaltung-milestone-toast" id="verwaltung-milestone-toast" role="status" aria-live="polite" hidden></div>
</Layout>

<script type="module">
  import { getCategory } from "../../data/categories";
  import { formatPrice } from "../../i18n/format";
  import { rechnungAlsPdfHerunterladen } from "../../scripts/invoice-pdf";

  const lang = "de";
  const STATUS_LABEL = {
    zahlungOffen: "Zahlung ausstehend",
    bezahlt: "Bezahlt",
    bearbeitung: "In Bearbeitung",
    versandVorbereitet: "Versand wird vorbereitet",
    versendet: "Versendet",
    abgeschlossen: "Abgeschlossen",
    storniert: "Storniert",
  };
  const LAND_NAME = { de: "Deutschland", at: "Österreich", ch: "Schweiz", lu: "Luxemburg" };
  const LAND_FLAGGE = { de: "🇩🇪", at: "🇦🇹", ch: "🇨🇭", lu: "🇱🇺" };
  // Nur noch PayPal (echt, server-verifiziert) und Überweisung (Vorkasse) — Klarna und die
  // frühere eigene Kreditkarten-Eingabemaske wurden auf ausdrücklichen Wunsch entfernt (siehe
  // Vault-Doku: Klarna bräuchte eine eigene Händlerprüfung + Bonitätsprüfungs-Pflichten, eine
  // eigene Kartenmaske wäre PCI-DSS-pflichtig gewesen).
  const ZAHLUNGSART_LABEL = { paypal: "💙 PayPal", ueberweisung: "🏦 Überweisung" };
  const INVOICE_LABELS = {
    title: "Rechnung", numberLabel: "Rechnungsnummer", dateLabel: "Rechnungsdatum",
    sellerLabel: "Verkäufer", billToLabel: "Rechnungsempfänger",
    itemLabel: "Artikel", qtyLabel: "Menge", unitPriceLabel: "Einzelpreis", sumLabel: "Gesamtbetrag",
    totalLabel: "Gesamt", vatNote: "Gemäß §19 UStG wird keine Umsatzsteuer berechnet und ausgewiesen.",
  };
  // Ab wie vielen Tagen eine noch offene ("bezahlt") Bestellung als "braucht Aufmerksamkeit"
  // markiert wird — soll verhindern, dass mal eine Bestellung vergessen wird.
  const ALTER_SCHWELLE_TAGE = 3;
  const MS_PRO_TAG = 24 * 60 * 60 * 1000;

  // 04.08.2026, dritte Ausbaustufe auf ausdrücklichen Wunsch ("richtig speziell für VanVan
  // machen, die Erfahrung um 10000% verbessern"): persönliche Begrüßung, Umsatz-Sparkline +
  // Wochenvergleich, animierte Kennzahlen, Status-Fortschrittsbalken mit Ein-Klick-Weiterschalten,
  // Konfetti bei runden Bestellzahlen-Meilensteinen, Tab-Titel-Badge für offene Bestellungen,
  // sowie optionaler Ton/Desktop-Benachrichtigung bei neuen Bestellungen — alles handgebaut, ohne
  // externe Bibliotheken oder Kosten (SVG-Sparkline, Web-Audio-Ton statt Audio-Datei, Notification-
  // API direkt vom Browser).
  const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  const urspruenglicherTitel = document.title;
  const SOUND_KEY = "vandiy_verwaltung_sound";
  const NOTIFY_KEY = "vandiy_verwaltung_notify";
  const MILESTONE_KEY = "vandiy_verwaltung_last_milestone";
  // Nächster logischer Status beim Ein-Klick-Weiterschalten-Knopf auf jeder Bestellkarte —
  // deckt sich mit der Reihenfolge aus bucket() oben, nur feiner (bearbeitung/versandVorbereitet
  // sind im Bucket zusammengefasst, hier aber zwei echte Zwischenschritte).
  const STATUS_NEXT = {
    zahlungOffen: "bezahlt",
    bezahlt: "bearbeitung",
    bearbeitung: "versandVorbereitet",
    versandVorbereitet: "versendet",
    versendet: "abgeschlossen",
    abgeschlossen: null,
    storniert: null,
  };

  function leseRolle() {
    const treffer = document.cookie.match(/(?:^|;\s*)vandiy_gate_role=([^;]+)/);
    return treffer ? decodeURIComponent(treffer[1]) : null;
  }
  function zeitgruss() {
    const stunde = new Date().getHours();
    if (stunde < 5) return { text: "Na, noch wach", icon: "🌙" };
    if (stunde < 11) return { text: "Guten Morgen", icon: "☀️" };
    if (stunde < 14) return { text: "Guten Tag", icon: "🌤️" };
    if (stunde < 18) return { text: "Schönen Nachmittag", icon: "🌼" };
    if (stunde < 22) return { text: "Guten Abend", icon: "🌇" };
    return { text: "Na, noch wach", icon: "🌙" };
  }
  function renderGreeting() {
    const rolle = leseRolle();
    const name = rolle === "vanvan" ? "VanVan" : rolle === "qciga" ? "qciga" : null;
    const { text, icon } = zeitgruss();
    const el = document.getElementById("verwaltung-greeting");
    if (el) el.textContent = name ? `${icon} ${text}, ${name}!` : `${icon} ${text}!`;
  }
  renderGreeting();

  // ── Ton bei neuen Bestellungen: kein Audio-File nötig, ein kurzes, warmes Zwei-Ton-Glöckchen
  //    wird direkt per Web-Audio-API synthetisiert. ──
  function toneEnabled() { return localStorage.getItem(SOUND_KEY) === "1"; }
  function notifyEnabled() { return localStorage.getItem(NOTIFY_KEY) === "1"; }
  function spieleGlockenton() {
    try {
      const AudioCtx = window.AudioContext || window.webkitAudioContext;
      if (!AudioCtx) return;
      const ctx = new AudioCtx();
      const jetzt = ctx.currentTime;
      [880, 1320].forEach((freq, i) => {
        const osc = ctx.createOscillator();
        const gain = ctx.createGain();
        osc.type = "sine";
        osc.frequency.value = freq;
        const start = jetzt + i * 0.1;
        gain.gain.setValueAtTime(0.0001, start);
        gain.gain.exponentialRampToValueAtTime(0.16, start + 0.02);
        gain.gain.exponentialRampToValueAtTime(0.0001, start + 0.55);
        osc.connect(gain).connect(ctx.destination);
        osc.start(start);
        osc.stop(start + 0.6);
      });
      setTimeout(() => ctx.close(), 900);
    } catch {
      // Browser ohne Web-Audio-Unterstützung — kein Problem, der Ton ist nur ein Bonus.
    }
  }

  const soundToggleBtn = document.getElementById("verwaltung-sound-toggle");
  const notifyToggleBtn = document.getElementById("verwaltung-notify-toggle");
  function aktualisiereToggleUI() {
    const sound = toneEnabled();
    if (soundToggleBtn) {
      soundToggleBtn.setAttribute("aria-pressed", String(sound));
      soundToggleBtn.textContent = sound ? "🔊 Ton an" : "🔈 Ton aus";
      soundToggleBtn.classList.toggle("is-active", sound);
    }
    const notify = notifyEnabled() && typeof Notification !== "undefined" && Notification.permission === "granted";
    if (notifyToggleBtn) {
      notifyToggleBtn.setAttribute("aria-pressed", String(notify));
      notifyToggleBtn.textContent = notify ? "🔔 Benachrichtigungen an" : "🔕 Benachrichtigungen aus";
      notifyToggleBtn.classList.toggle("is-active", notify);
    }
  }
  soundToggleBtn?.addEventListener("click", () => {
    localStorage.setItem(SOUND_KEY, toneEnabled() ? "0" : "1");
    aktualisiereToggleUI();
    if (toneEnabled()) spieleGlockenton();
  });
  notifyToggleBtn?.addEventListener("click", async () => {
    if (typeof Notification === "undefined") {
      alert("Dein Browser unterstützt leider keine Desktop-Benachrichtigungen.");
      return;
    }
    if (Notification.permission === "denied") {
      alert("Benachrichtigungen sind für diese Seite im Browser blockiert — bitte in den Website-Einstellungen des Browsers wieder erlauben.");
      return;
    }
    if (Notification.permission !== "granted") {
      const ergebnis = await Notification.requestPermission();
      if (ergebnis !== "granted") { aktualisiereToggleUI(); return; }
    }
    localStorage.setItem(NOTIFY_KEY, notifyEnabled() ? "0" : "1");
    aktualisiereToggleUI();
  });
  aktualisiereToggleUI();

  // ── Abmelden: löscht serverseitig alle drei Zugangs-Cookies (siehe POST /gate-logout in
  //    functions/_middleware.js) und springt danach zur Zugangscode-Seite. Läuft bewusst OHNE
  //    Rückfragedialog (gleiches Verhalten wie der Logout-Button im Kundenkonto). ──
  const logoutBtn = document.getElementById("verwaltung-logout-btn");
  logoutBtn?.addEventListener("click", () => {
    logoutBtn.disabled = true;
    logoutBtn.textContent = "Wird abgemeldet …";
    fetch("/gate-logout", { method: "POST" })
      .catch(() => {})
      .finally(() => { window.location.href = "/gate"; });
  });

  // ── Meilenstein-Feier: Konfetti + Banner, sobald eine runde Bestell-Gesamtzahl erreicht wird
  //    (10er-Schritte bis 100, 25er bis 500, danach 50er). Zählt ALLE Bestellungen (auch
  //    stornierte/noch unbezahlte) — es geht um "die wievielte Bestellung ist reingekommen",
  //    nicht um Umsatz. Feuert bewusst NICHT beim allerersten Laden dieser neuen Funktion (sonst
  //    würde ein längst bestehender Bestand sofort ein Feuerwerk auslösen) — erst ab der
  //    nächsten tatsächlich neu überschrittenen Schwelle. ──
  function istMeilenstein(n) {
    if (n < 10) return false;
    if (n <= 100) return n % 10 === 0;
    if (n <= 500) return n % 25 === 0;
    return n % 50 === 0;
  }
  function starteKonfetti() {
    const container = document.getElementById("verwaltung-confetti");
    if (!container) return;
    const FARBEN = ["#e3b23c", "#9b7fd6", "#5fd3ec", "#e7879a", "#6ecb8f"];
    for (let i = 0; i < 60; i++) {
      const stueck = document.createElement("span");
      stueck.className = "verwaltung-confetti-piece";
      stueck.style.left = `${Math.random() * 100}vw`;
      stueck.style.background = FARBEN[Math.floor(Math.random() * FARBEN.length)];
      stueck.style.animationDuration = `${2.2 + Math.random() * 1.6}s`;
      stueck.style.animationDelay = `${Math.random() * 0.5}s`;
      stueck.style.setProperty("--drift", `${Math.random() * 160 - 80}px`);
      stueck.style.setProperty("--rot", `${Math.random() * 720 - 360}deg`);
      stueck.addEventListener("animationend", () => stueck.remove());
      container.appendChild(stueck);
    }
  }
  function zeigeMeilenstein(n) {
    const toast = document.getElementById("verwaltung-milestone-toast");
    if (!toast) return;
    toast.innerHTML = `🎉 <strong>Bestellung Nr. ${n}!</strong> Ihr seid großartig — weiter so! 🧶`;
    toast.hidden = false;
    requestAnimationFrame(() => toast.classList.add("is-visible"));
    if (!prefersReducedMotion) starteKonfetti();
    setTimeout(() => {
      toast.classList.remove("is-visible");
      setTimeout(() => { toast.hidden = true; }, 500);
    }, 5000);
  }
  function pruefeMeilenstein(gesamtAnzahl) {
    const letzter = Number(localStorage.getItem(MILESTONE_KEY) || 0);
    localStorage.setItem(MILESTONE_KEY, String(gesamtAnzahl));
    if (gesamtAnzahl <= letzter || letzter === 0) return;
    let erreicht = null;
    for (let n = letzter + 1; n <= gesamtAnzahl; n++) {
      if (istMeilenstein(n)) erreicht = n;
    }
    if (erreicht) zeigeMeilenstein(erreicht);
  }

  function bucket(status) {
    if (status === "storniert") return "storniert";
    if (status === "zahlungOffen") return "zahlungOffen";
    if (status === "bezahlt") return "offen";
    if (status === "bearbeitung" || status === "versandVorbereitet") return "inBearbeitung";
    if (status === "versendet") return "versendet";
    return "abgeschlossen";
  }

  const loadingEl = document.getElementById("verwaltung-loading");
  const errorEl = document.getElementById("verwaltung-error");
  const errorTextEl = document.getElementById("verwaltung-error-text");
  const contentEl = document.getElementById("verwaltung-content");
  const searchInput = document.getElementById("verwaltung-search");
  const zeitraumSelect = document.getElementById("verwaltung-zeitraum");
  const sortSelect = document.getElementById("verwaltung-sort");

  let alleBestellungen = [];
  let bekannteIds = new Set();
  let erstesLaden = true;
  // Merkt sich die zuletzt berechneten Auswertungsdaten, damit die Detail-Panels (Klick auf eine
  // Kategorie-/Land-/Kundschafts-Kachel) darauf zugreifen können, ohne alles neu zu berechnen.
  let letzteKategorien = [];
  let letzteLaender = [];
  let letzteKunden = [];
  let letzteAktive = [];
  // Merkt sich den zuletzt ANGEZEIGTEN Wert jeder animierten Kennzahl, damit setNumber() beim
  // nächsten render() weiß, von wo aus hochgezählt werden soll (statt immer wieder ab 0).
  const vorherigeZahlen = {};

  async function ladeUndRendere() {
    loadingEl.style.display = "";
    errorEl.style.display = "none";
    document.getElementById("verwaltung-new-banner").style.display = "none";
    try {
      const res = await fetch("/api/verwaltung/orders");
      const data = await res.json().catch(() => null);
      if (!res.ok || !data?.ok) {
        throw new Error(data?.error || `Server antwortete mit Status ${res.status}.`);
      }
      alleBestellungen = data.orders;
      bekannteIds = new Set(alleBestellungen.map((b) => b.id));
      erstesLaden = false;
      render();
      pruefeMeilenstein(alleBestellungen.length);
      loadingEl.style.display = "none";
      contentEl.style.display = "";
    } catch (err) {
      loadingEl.style.display = "none";
      errorEl.style.display = "";
      errorTextEl.textContent = "⚠️ Bestellungen konnten nicht geladen werden: " + (err instanceof Error ? err.message : String(err));
    }
  }

  // Leiser Hintergrund-Check alle 45s: lädt neu, vergleicht nur die IDs, ERSETZT aber nicht
  // sofort die Ansicht (damit man beim Durchsehen/Filtern nicht unterbrochen wird) — stattdessen
  // erscheint nur ein dezenter Hinweis-Banner mit "Jetzt aktualisieren"-Knopf.
  async function pruefeNeueBestellungenImHintergrund() {
    if (erstesLaden || document.hidden) return;
    try {
      const res = await fetch("/api/verwaltung/orders");
      const data = await res.json().catch(() => null);
      if (!res.ok || !data?.ok) return;
      const neue = data.orders.filter((b) => !bekannteIds.has(b.id));
      if (neue.length > 0) {
        const banner = document.getElementById("verwaltung-new-banner");
        document.getElementById("verwaltung-new-count").textContent = String(neue.length);
        banner.style.display = "flex";

        if (toneEnabled()) spieleGlockenton();
        if (notifyEnabled() && typeof Notification !== "undefined" && Notification.permission === "granted") {
          const benachrichtigung = new Notification(
            neue.length > 1 ? `🧶 ${neue.length} neue Bestellungen` : "🧶 Neue Bestellung",
            { body: neue.slice(0, 3).map((b) => `${b.bestellnummer || `#${b.id}`} · ${b.kunde_name}`).join("\n"), icon: "/favicon-32x32.png" }
          );
          benachrichtigung.onclick = () => { window.focus(); benachrichtigung.close(); };
        }
      }
    } catch {
      // Stiller Fehlschlag — der nächste reguläre Refresh/Retry fängt es wieder ein, kein Grund
      // die Ansicht deswegen zu stören.
    }
  }
  setInterval(pruefeNeueBestellungenImHintergrund, 45000);

  function setText(id, text) {
    const el = document.getElementById(id);
    if (el) el.textContent = text;
  }

  // ── Zahlen zählen sanft hoch statt abrupt zu springen — macht die Kennzahlen-Kacheln beim
  //    Laden/Aktualisieren spürbar lebendiger. Reines requestAnimationFrame, kein Paket nötig,
  //    respektiert prefers-reduced-motion (dann sofortiger Sprung wie vorher). ──
  function animateNumber(el, von, bis, format) {
    const formatFn = format || ((n) => String(Math.round(n)));
    if (von === bis || prefersReducedMotion) { el.textContent = formatFn(bis); return; }
    const start = performance.now();
    const dauer = 700;
    function tick(jetzt) {
      const t = Math.min(1, (jetzt - start) / dauer);
      const eased = 1 - Math.pow(1 - t, 3);
      el.textContent = formatFn(von + (bis - von) * eased);
      if (t < 1) requestAnimationFrame(tick);
      else el.textContent = formatFn(bis);
    }
    requestAnimationFrame(tick);
  }
  function setNumber(id, zahl, format) {
    const el = document.getElementById(id);
    if (!el) return;
    const von = vorherigeZahlen[id] ?? 0;
    vorherigeZahlen[id] = zahl;
    animateNumber(el, von, zahl, format);
  }

  function sortiere(liste, modus) {
    const kopie = [...liste];
    switch (modus) {
      case "alt": return kopie.sort((a, b) => new Date(a.created_at) - new Date(b.created_at));
      case "wert-ab": return kopie.sort((a, b) => Number(b.summe) - Number(a.summe));
      case "wert-auf": return kopie.sort((a, b) => Number(a.summe) - Number(b.summe));
      default: return kopie.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
    }
  }

  // ── Umsatz-Sparkline (letzte 14 Tage) + Wochenvergleich: reines handgebautes SVG, kein
  //    Chart-Paket nötig. "aktive" = weder storniert noch (bei Überweisung) unbezahlt. ──
  function renderSparkline(aktive) {
    const svg = document.getElementById("verwaltung-sparkline");
    const trendEl = document.getElementById("verwaltung-week-trend");
    if (!svg || !trendEl) return;

    const heute = new Date();
    heute.setHours(0, 0, 0, 0);
    const tage = Array.from({ length: 14 }, (_, i) => {
      const tag = new Date(heute);
      tag.setDate(tag.getDate() - (13 - i));
      return tag.getTime();
    });
    const werte = tage.map((start) => {
      const ende = start + MS_PRO_TAG;
      return aktive
        .filter((b) => { const t = new Date(b.created_at).getTime(); return t >= start && t < ende; })
        .reduce((s, b) => s + Number(b.summe), 0);
    });

    const max = Math.max(1, ...werte);
    const w = 280, h = 60, pad = 4;
    const stepX = (w - pad * 2) / (werte.length - 1);
    const punkte = werte.map((v, i) => [pad + i * stepX, h - pad - (v / max) * (h - pad * 2)]);
    const linePath = punkte.map((p, i) => `${i === 0 ? "M" : "L"}${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(" ");
    const areaPath = `${linePath} L${punkte[punkte.length - 1][0].toFixed(1)},${h - pad} L${punkte[0][0].toFixed(1)},${h - pad} Z`;

    svg.innerHTML = `
      <defs>
        <linearGradient id="verwaltung-sparkline-grad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" style="stop-color:var(--c-accent); stop-opacity:0.45" />
          <stop offset="100%" style="stop-color:var(--c-accent); stop-opacity:0" />
        </linearGradient>
      </defs>
      <path d="${areaPath}" fill="url(#verwaltung-sparkline-grad)" stroke="none"></path>
      <path d="${linePath}" fill="none" stroke="var(--c-accent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
    `;

    const letzte7 = werte.slice(7).reduce((s, v) => s + v, 0);
    const vorherige7 = werte.slice(0, 7).reduce((s, v) => s + v, 0);
    if (letzte7 === 0 && vorherige7 === 0) {
      trendEl.textContent = "";
      trendEl.className = "verwaltung-trend";
    } else if (vorherige7 === 0) {
      trendEl.textContent = "🚀 neu diese Woche";
      trendEl.className = "verwaltung-trend verwaltung-trend-up";
    } else {
      const delta = Math.round(((letzte7 - vorherige7) / vorherige7) * 100);
      const auf = delta >= 0;
      trendEl.textContent = `${auf ? "▲" : "▼"} ${Math.abs(delta)}% ggü. Vorwoche`;
      trendEl.className = `verwaltung-trend ${auf ? "verwaltung-trend-up" : "verwaltung-trend-down"}`;
    }
  }

  function render() {
    // "aktive" = zählt für Umsatz/Auswertung: weder storniert noch (bei Überweisung) noch gar
    // nicht bezahlt — sonst würde Geld gezeigt, das VanVan noch gar nicht hat.
    const aktive = alleBestellungen.filter((b) => b.status !== "storniert" && b.status !== "zahlungOffen");
    letzteAktive = aktive;
    renderSparkline(aktive);

    // Die Auswertungs-Detail-Panels zeigen ggf. veraltete Daten, sobald sich die Bestellliste
    // ändert (z.B. neuer Status) — bei jedem Rendern lieber wieder einklappen, statt falsche
    // Zahlen stehen zu lassen. Ein erneuter Klick zeigt die aktuellen Daten sofort wieder an.
    ["kat", "land", "kunden"].forEach((gruppe) => {
      document.getElementById(`verwaltung-${gruppe}-detail`)?.setAttribute("hidden", "");
    });
    document.querySelectorAll(".verwaltung-stat-tile.is-active").forEach((t) => t.classList.remove("is-active"));

    // ── Buckets für die Stat-Kacheln + Filterleiste ──
    const buckets = { zahlungOffen: 0, offen: 0, inBearbeitung: 0, versendet: 0, abgeschlossen: 0, storniert: 0 };
    alleBestellungen.forEach((b) => { buckets[bucket(b.status)]++; });
    setNumber("stat-zahlungOffen", buckets.zahlungOffen);
    setNumber("stat-offen", buckets.offen);
    setNumber("stat-inBearbeitung", buckets.inBearbeitung);
    setNumber("stat-versendet", buckets.versendet);
    setNumber("stat-abgeschlossen", buckets.abgeschlossen);

    // Tab-Titel zeigt auf einen Blick, wie viel es zu tun gibt — auch wenn der Tab gerade nicht
    // aktiv ist (z.B. weil man in einem anderen Fenster arbeitet).
    const dringend = buckets.zahlungOffen + buckets.offen;
    document.title = dringend > 0 ? `🔴 ${dringend} · ${urspruenglicherTitel}` : urspruenglicherTitel;

    setText("filter-count-alle", String(alleBestellungen.length));
    setText("filter-count-zahlungOffen", String(buckets.zahlungOffen));
    setText("filter-count-offen", String(buckets.offen));
    setText("filter-count-inBearbeitung", String(buckets.inBearbeitung));
    setText("filter-count-versendet", String(buckets.versendet));
    setText("filter-count-abgeschlossen", String(buckets.abgeschlossen));
    setText("filter-count-storniert", String(buckets.storniert));

    // ── Umsatz + Ø Bestellwert: stornierte UND noch nicht bezahlte (zahlungOffen) Bestellungen
    //    zählen bewusst NICHT mit — sonst würde der Umsatz Geld zeigen, das noch gar nicht da
    //    ist. ──
    const gesamtumsatz = aktive.reduce((s, b) => s + Number(b.summe), 0);
    setNumber("stat-umsatz", gesamtumsatz, (n) => formatPrice(n, lang));
    setText("stat-umsatz-label", `Gesamtumsatz (${aktive.length} Bestellung${aktive.length === 1 ? "" : "en"})`);
    if (aktive.length > 0) {
      setNumber("stat-avg", gesamtumsatz / aktive.length, (n) => formatPrice(n, lang));
    } else {
      setText("stat-avg", "–");
      vorherigeZahlen["stat-avg"] = 0;
    }

    // ── Heute / letzte 7 Tage / diesen Monat + "braucht Aufmerksamkeit" ──
    const jetzt = Date.now();
    const heuteStr = new Date().toLocaleDateString("de-DE");
    const heuteCount = aktive.filter((b) => new Date(b.created_at).toLocaleDateString("de-DE") === heuteStr).length;
    const siebenTageCount = aktive.filter((b) => jetzt - new Date(b.created_at).getTime() <= 7 * MS_PRO_TAG).length;
    // "Diesen Monat" = echter Kalendermonat (1. bis heute), nicht "letzte 30 Tage" — deshalb ein
    // eigenes Feld statt einfach den 30-Tage-Wert zu verwenden.
    const heuteDatum = new Date();
    const monatsStart = new Date(heuteDatum.getFullYear(), heuteDatum.getMonth(), 1).getTime();
    const monatCount = aktive.filter((b) => new Date(b.created_at).getTime() >= monatsStart).length;
    const monatUmsatz = aktive.filter((b) => new Date(b.created_at).getTime() >= monatsStart).reduce((s, b) => s + Number(b.summe), 0);
    setNumber("stat-heute", heuteCount);
    setNumber("stat-7tage", siebenTageCount);
    setNumber("stat-monat", monatCount);
    setText(
      "stat-monat-label",
      `Diesen Monat${monatCount > 0 ? ` (${formatPrice(monatUmsatz, lang)})` : ""}`
    );

    // Bewusst über ALLE Bestellungen (nicht nur "aktive"): eine seit Tagen unbezahlte
    // Überweisungs-Bestellung ("zahlungOffen") braucht mindestens genauso dringend Aufmerksamkeit
    // wie eine liegen gebliebene bezahlte Bestellung — sonst würde sie einfach vergessen.
    const attentionIds = new Set(
      alleBestellungen
        .filter((b) => (b.status === "bezahlt" || b.status === "zahlungOffen") && jetzt - new Date(b.created_at).getTime() > ALTER_SCHWELLE_TAGE * MS_PRO_TAG)
        .map((b) => b.id)
    );
    const attentionTile = document.getElementById("stat-attention-tile");
    if (attentionIds.size > 0) {
      setNumber("stat-attention", attentionIds.size);
      attentionTile.style.display = "";
    } else {
      attentionTile.style.display = "none";
      vorherigeZahlen["stat-attention"] = 0;
    }

    // ── Stammkundinnen: E-Mail kommt in mehr als einer Bestellung vor. ──
    const emailCounts = new Map();
    alleBestellungen.forEach((b) => emailCounts.set(b.kunde_email, (emailCounts.get(b.kunde_email) ?? 0) + 1));

    // ── Bestellliste (sortiert nach aktuell gewähltem Modus) ──
    const listEl = document.getElementById("verwaltung-order-list");
    const emptyEl = document.getElementById("verwaltung-empty");
    if (alleBestellungen.length === 0) {
      listEl.innerHTML = "";
      emptyEl.style.display = "";
    } else {
      emptyEl.style.display = "none";
      const sortiert = sortiere(alleBestellungen, sortSelect.value);
      listEl.innerHTML = sortiert.map((b) => {
        const land = b.land;
        const artikelHtml = b.artikel.map((a) =>
          `<li><span>${a.menge}× ${escapeHtml(a.name)}${a.gratis ? " <span class=\"small\">(gratis)</span>" : ""}</span><span class="order-item-price">${formatPrice(a.preis * a.menge, lang)}</span></li>`
        ).join("");
        const datum = new Date(b.created_at).toLocaleDateString("de-DE", { year: "numeric", month: "2-digit", day: "2-digit" });
        const istNeu = jetzt - new Date(b.created_at).getTime() < MS_PRO_TAG;
        const brauchtAufmerksamkeit = attentionIds.has(b.id);
        const istStammkundin = (emailCounts.get(b.kunde_email) ?? 0) > 1;
        const adresse = [b.strasse, `${b.plz} ${b.ort}`.trim(), LAND_NAME[land] || land].filter(Boolean).join(", ");
        const suchtext = `${b.bestellnummer ?? ""} ${b.kunde_name} ${b.kunde_email}`.toLowerCase();

        return `
          <div class="card order-card order-card-${b.status}${brauchtAufmerksamkeit ? " order-card-attention" : ""}" data-bucket="${bucket(b.status)}" data-order-id="${b.id}" data-created="${b.created_at}" data-search="${escapeHtml(suchtext)}">
            <div class="order-card-head">
              <div>
                <span class="order-no">${LAND_FLAGGE[land] || ""} ${escapeHtml(b.bestellnummer || `#${b.id}`)}</span>
                ${istNeu ? `<span class="verwaltung-chip verwaltung-chip-new">🆕 Neu</span>` : ""}
                ${istStammkundin ? `<span class="verwaltung-chip verwaltung-chip-stamm">🔁 Stammkundin</span>` : ""}
                ${brauchtAufmerksamkeit ? `<span class="verwaltung-chip verwaltung-chip-attention">⚠️ Braucht Aufmerksamkeit</span>` : ""}
                <br />
                <span class="small order-meta">${datum} · ${LAND_NAME[land] || land} · ${escapeHtml(b.kunde_name)} · ${escapeHtml(b.kunde_email)}${b.zahlungsart ? ` · ${ZAHLUNGSART_LABEL[b.zahlungsart] || escapeHtml(b.zahlungsart)}` : ""}</span>
              </div>
              <span class="badge order-status order-status-${b.status}">${STATUS_LABEL[b.status] || b.status}</span>
            </div>
            <ul class="order-items">${artikelHtml}</ul>
            ${stepperHtml(b.status)}
            <div class="verwaltung-copy-row">
              <button type="button" class="btn btn-outline btn-xs verwaltung-copy-btn" data-copy="${escapeHtml(b.kunde_email)}">📧 E-Mail kopieren</button>
              <button type="button" class="btn btn-outline btn-xs verwaltung-copy-btn" data-copy="${escapeHtml(`${b.kunde_name}\n${adresse}`)}">📍 Adresse kopieren</button>
              <button type="button" class="btn btn-outline btn-xs verwaltung-pdf-btn" data-order-id="${b.id}">🧾 Rechnung als PDF</button>
              <span class="small verwaltung-copy-hint" data-hint-for="${b.id}" style="display:none;">✅ kopiert</span>
            </div>
            <div class="order-card-foot verwaltung-order-foot">
              <span class="order-total">Summe: <strong>${formatPrice(Number(b.summe), lang)}</strong></span>
              <div class="verwaltung-tracking-edit">
                <input type="text" class="verwaltung-input verwaltung-tracking-input" data-order-id="${b.id}" placeholder="Tracking-Nummer" aria-label="Tracking-Nummer für Bestellung ${escapeHtml(b.bestellnummer || `#${b.id}`)}" value="${escapeHtml(b.tracking || "")}" />
                <button type="button" class="btn btn-outline btn-xs verwaltung-tracking-save" data-order-id="${b.id}">💾</button>
              </div>
              <div class="verwaltung-status-edit">
                <select class="verwaltung-status-select" data-order-id="${b.id}">
                  ${Object.entries(STATUS_LABEL).map(([val, label]) => `<option value="${val}" ${val === b.status ? "selected" : ""}>${label}</option>`).join("")}
                </select>
                ${STATUS_NEXT[b.status] ? `<button type="button" class="btn btn-primary btn-xs verwaltung-advance-btn" data-order-id="${b.id}" data-next-status="${STATUS_NEXT[b.status]}">→ ${STATUS_LABEL[STATUS_NEXT[b.status]]}</button>` : ""}
                <span class="small verwaltung-status-saved" data-order-id="${b.id}" style="display:none;">✅ gespeichert</span>
              </div>
            </div>
          </div>
        `;
      }).join("");

      listEl.querySelectorAll(".verwaltung-status-select").forEach((select) => {
        select.addEventListener("change", () => statusAendern(select));
      });
      listEl.querySelectorAll(".verwaltung-advance-btn").forEach((btn) => {
        btn.addEventListener("click", () => statusVorwaerts(btn));
      });
      listEl.querySelectorAll(".verwaltung-copy-btn").forEach((btn) => {
        btn.addEventListener("click", () => kopieren(btn));
      });
      listEl.querySelectorAll(".verwaltung-pdf-btn").forEach((btn) => {
        btn.addEventListener("click", () => rechnungDrucken(btn.dataset.orderId));
      });
      listEl.querySelectorAll(".verwaltung-tracking-save").forEach((btn) => {
        btn.addEventListener("click", () => trackingSpeichern(btn.dataset.orderId));
      });
      listEl.querySelectorAll(".verwaltung-tracking-input").forEach((input) => {
        input.addEventListener("keydown", (e) => { if (e.key === "Enter") trackingSpeichern(input.dataset.orderId); });
      });
    }

    // ── Auswertung: meistverkaufte Produkte je Kategorie (stornierte Bestellungen ausgeschlossen) ──
    const mengeProSlug = new Map(); // slug -> { name, kategorie, menge }
    aktive.forEach((b) => b.artikel.forEach((a) => {
      const eintrag = mengeProSlug.get(a.produkt_slug) ?? { name: a.name, kategorie: a.kategorie_slug, menge: 0 };
      eintrag.menge += a.menge;
      mengeProSlug.set(a.produkt_slug, eintrag);
    }));
    const kategorienMitProdukten = new Map();
    mengeProSlug.forEach((eintrag, slug) => {
      if (!eintrag.kategorie) return;
      const liste = kategorienMitProdukten.get(eintrag.kategorie) ?? [];
      liste.push({ slug, name: eintrag.name, menge: eintrag.menge });
      kategorienMitProdukten.set(eintrag.kategorie, liste);
    });
    const auswertungKategorien = Array.from(kategorienMitProdukten.entries())
      .map(([kategorieSlug, produkte]) => {
        const kat = getCategory(kategorieSlug);
        const sortiert = produkte.sort((a, b) => b.menge - a.menge);
        const maxMenge = sortiert[0]?.menge ?? 1;
        return {
          slug: kategorieSlug,
          name: kat?.name?.[lang] ?? kategorieSlug,
          icon: kat?.icon ?? "📦",
          gesamtMenge: sortiert.reduce((s, p) => s + p.menge, 0),
          // Volle Liste (nicht mehr auf 4 gekürzt) — die Kachel selbst zeigt nur die Summe, die
          // vollständige Rangliste erscheint erst im aufklappbaren Detail-Panel darunter.
          produkte: sortiert.map((p) => ({ ...p, prozent: Math.round((p.menge / maxMenge) * 100) })),
        };
      })
      .sort((a, b) => b.gesamtMenge - a.gesamtMenge);
    letzteKategorien = auswertungKategorien;

    const katGrid = document.getElementById("verwaltung-kat-grid");
    const katEmpty = document.getElementById("verwaltung-kat-empty");
    if (auswertungKategorien.length === 0) {
      katGrid.innerHTML = "";
      katEmpty.style.display = "";
    } else {
      katEmpty.style.display = "none";
      katGrid.innerHTML = auswertungKategorien.map((k) => `
        <button type="button" class="card verwaltung-stat-tile" data-kat-tile="${escapeHtml(k.slug)}">
          <span class="verwaltung-stat-icon" aria-hidden="true">${k.icon}</span>
          <span class="verwaltung-stat-value">${k.gesamtMenge}</span>
          <span class="verwaltung-stat-label">${escapeHtml(k.name)}</span>
        </button>
      `).join("");
    }

    // ── Auswertung: Bestellungen nach Land (stornierte ausgeschlossen) ──
    const landCounts = new Map();
    aktive.forEach((b) => landCounts.set(b.land, (landCounts.get(b.land) ?? 0) + 1));
    const maxLandCount = Math.max(1, ...Array.from(landCounts.values()));
    const auswertungLaender = Array.from(landCounts.entries())
      .sort((a, b) => b[1] - a[1])
      .map(([land, count]) => ({
        land, name: LAND_NAME[land] || land, flagge: LAND_FLAGGE[land] || "",
        count, prozent: aktive.length > 0 ? Math.round((count / aktive.length) * 100) : 0,
        balken: Math.round((count / maxLandCount) * 100),
      }));
    letzteLaender = auswertungLaender;

    const landGrid = document.getElementById("verwaltung-land-grid");
    const landEmpty = document.getElementById("verwaltung-land-empty");
    if (auswertungLaender.length === 0) {
      landGrid.innerHTML = "";
      landEmpty.style.display = "";
    } else {
      landEmpty.style.display = "none";
      landGrid.innerHTML = auswertungLaender.map((l) => `
        <button type="button" class="card verwaltung-stat-tile" data-land-tile="${l.land}">
          <span class="verwaltung-stat-icon" aria-hidden="true">${l.flagge}</span>
          <span class="verwaltung-stat-value">${l.count}</span>
          <span class="verwaltung-stat-label">${escapeHtml(l.name)} · ${l.prozent}%</span>
        </button>
      `).join("");
    }

    // ── NEU: Beste Kundinnen (Umsatz pro E-Mail, nur wer mehr als 1× bestellt hat) ──
    const umsatzProKundin = new Map(); // email -> { name, summe, anzahl }
    aktive.forEach((b) => {
      const eintrag = umsatzProKundin.get(b.kunde_email) ?? { name: b.kunde_name, summe: 0, anzahl: 0 };
      eintrag.summe += Number(b.summe);
      eintrag.anzahl += 1;
      umsatzProKundin.set(b.kunde_email, eintrag);
    });
    const besteKunden = Array.from(umsatzProKundin.entries())
      .filter(([, v]) => v.anzahl > 1)
      .map(([email, v]) => ({ email, ...v }))
      .sort((a, b) => b.summe - a.summe)
      .slice(0, 8);
    letzteKunden = besteKunden;
    const kundenEmpty = document.getElementById("verwaltung-kunden-empty");
    const kundenGrid = document.getElementById("verwaltung-kunden-grid");
    if (besteKunden.length === 0) {
      kundenGrid.innerHTML = "";
      kundenEmpty.style.display = "";
    } else {
      kundenEmpty.style.display = "none";
      kundenGrid.innerHTML = besteKunden.map((k) => `
        <button type="button" class="card verwaltung-stat-tile" data-kunden-tile="${escapeHtml(k.email)}">
          <span class="verwaltung-stat-icon" aria-hidden="true">👑</span>
          <span class="verwaltung-stat-value">${formatPrice(k.summe, lang)}</span>
          <span class="verwaltung-stat-label">${escapeHtml(k.name)} · ${k.anzahl}×</span>
        </button>
      `).join("");
    }

    wendeFilterAn();
  }

  // ── Detail-Panels für die Auswertungs-Kacheln: erscheinen genau unter der jeweiligen Kachel-
  //    Reihe (siehe .verwaltung-analyse-detail), sobald man draufklickt — mit der VOLLSTÄNDIGEN
  //    Liste (nicht mehr nur den Top 4/8 wie vorher direkt auf der Kachel). ──
  function zeigeKatDetail(slug) {
    const k = letzteKategorien.find((x) => x.slug === slug);
    const panel = document.getElementById("verwaltung-kat-detail");
    if (!k) { panel.setAttribute("hidden", ""); return; }
    panel.innerHTML = `
      <div class="verwaltung-analyse-detail-head">
        <h3>${k.icon} ${escapeHtml(k.name)} — ${k.produkte.length} Produkt${k.produkte.length === 1 ? "" : "e"}</h3>
        <button type="button" class="verwaltung-analyse-close" data-close-detail="kat" aria-label="Schließen">✕</button>
      </div>
      <div class="verwaltung-bar-list">
        ${k.produkte.map((p) => `
          <div class="verwaltung-bar-row">
            <div class="verwaltung-bar-head"><span>${escapeHtml(p.name)}</span><span class="small">${p.menge}× verkauft</span></div>
            <div class="verwaltung-bar-track"><div class="verwaltung-bar-fill" style="width:${p.prozent}%"></div></div>
          </div>
        `).join("")}
      </div>
    `;
    panel.removeAttribute("hidden");
    document.querySelectorAll("[data-kat-tile]").forEach((t) => t.classList.toggle("is-active", t.dataset.katTile === slug));
  }

  function zeigeLandDetail(land) {
    const l = letzteLaender.find((x) => x.land === land);
    const panel = document.getElementById("verwaltung-land-detail");
    if (!l) { panel.setAttribute("hidden", ""); return; }
    const bestellungen = letzteAktive.filter((b) => b.land === land).sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
    panel.innerHTML = `
      <div class="verwaltung-analyse-detail-head">
        <h3>${l.flagge} ${escapeHtml(l.name)} — ${bestellungen.length} Bestellung${bestellungen.length === 1 ? "" : "en"}</h3>
        <button type="button" class="verwaltung-analyse-close" data-close-detail="land" aria-label="Schließen">✕</button>
      </div>
      ${bestellungen.map((b) => `
        <div class="verwaltung-analyse-order-row">
          <span>${escapeHtml(b.bestellnummer || `#${b.id}`)} · ${escapeHtml(b.kunde_name)}</span>
          <span class="small">${new Date(b.created_at).toLocaleDateString("de-DE")} · ${formatPrice(Number(b.summe), lang)}</span>
        </div>
      `).join("")}
    `;
    panel.removeAttribute("hidden");
    document.querySelectorAll("[data-land-tile]").forEach((t) => t.classList.toggle("is-active", t.dataset.landTile === land));
  }

  function zeigeKundeDetail(email) {
    const k = letzteKunden.find((x) => x.email === email);
    const panel = document.getElementById("verwaltung-kunden-detail");
    if (!k) { panel.setAttribute("hidden", ""); return; }
    const bestellungen = letzteAktive.filter((b) => b.kunde_email === email).sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
    panel.innerHTML = `
      <div class="verwaltung-analyse-detail-head">
        <h3>👑 ${escapeHtml(k.name)} <span class="small">(${escapeHtml(email)})</span> — ${bestellungen.length} Bestellung${bestellungen.length === 1 ? "" : "en"}</h3>
        <button type="button" class="verwaltung-analyse-close" data-close-detail="kunden" aria-label="Schließen">✕</button>
      </div>
      ${bestellungen.map((b) => `
        <div class="verwaltung-analyse-order-row">
          <span>${escapeHtml(b.bestellnummer || `#${b.id}`)}</span>
          <span class="small">${new Date(b.created_at).toLocaleDateString("de-DE")} · ${formatPrice(Number(b.summe), lang)}</span>
        </div>
      `).join("")}
    `;
    panel.removeAttribute("hidden");
    document.querySelectorAll("[data-kunden-tile]").forEach((t) => t.classList.toggle("is-active", t.dataset.kundenTile === email));
  }

  // ── Visueller Status-Fortschrittsbalken pro Bestellkarte — auf einen Blick sehen, wo eine
  //    Bestellung im Ablauf steht, statt es aus einem Dropdown-Text ablesen zu müssen. Nutzt
  //    dieselben vier Stufen wie bucket()/die Filterleiste oben, damit beides zusammenpasst.
  //    "zahlungOffen" und "storniert" fallen aus dem linearen Ablauf raus und bekommen einen
  //    eigenen Hinweis statt der Punkte-Reihe. ──
  const STEPPER_STUFEN = [
    { key: "offen", label: "Offen", icon: "🆕" },
    { key: "inBearbeitung", label: "Bearbeitung", icon: "⚙️" },
    { key: "versendet", label: "Versendet", icon: "🚚" },
    { key: "abgeschlossen", label: "Fertig", icon: "✅" },
  ];
  function stepperHtml(status) {
    if (status === "storniert") {
      return `<div class="verwaltung-stepper verwaltung-stepper-storniert">🚫 Storniert</div>`;
    }
    if (status === "zahlungOffen") {
      return `<div class="verwaltung-stepper verwaltung-stepper-pending">⏳ Wartet auf Zahlungseingang</div>`;
    }
    const aktuelleStufe = bucket(status);
    const idx = STEPPER_STUFEN.findIndex((s) => s.key === aktuelleStufe);
    return `<div class="verwaltung-stepper">
      ${STEPPER_STUFEN.map((s, i) => `
        <span class="verwaltung-stepper-step ${i < idx ? "is-done" : i === idx ? "is-current" : ""}">
          <span class="verwaltung-stepper-dot" aria-hidden="true">${i < idx ? "✓" : s.icon}</span>
          <span class="verwaltung-stepper-label">${s.label}</span>
        </span>${i < STEPPER_STUFEN.length - 1 ? `<span class="verwaltung-stepper-line ${i < idx ? "is-done" : ""}" aria-hidden="true"></span>` : ""}
      `).join("")}
    </div>`;
  }

  function escapeHtml(str) {
    return String(str ?? "").replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));
  }

  // Gemeinsamer Kern für BEIDE Wege, den Status zu ändern (Dropdown ODER der neue "→ nächster
  // Schritt"-Schnellknopf) — spart Doppelcode und garantiert, dass beide exakt gleich speichern.
  async function speichereStatus(orderId, neuerStatus) {
    const res = await fetch(`/api/verwaltung/orders/${orderId}`, {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ status: neuerStatus }),
    });
    const data = await res.json().catch(() => null);
    if (!res.ok || !data?.ok) throw new Error(data?.error || "Speichern fehlgeschlagen.");
    const b = alleBestellungen.find((o) => String(o.id) === String(orderId));
    if (b) b.status = neuerStatus;
  }

  async function statusAendern(select) {
    const orderId = select.dataset.orderId;
    const neuerStatus = select.value;
    select.disabled = true;
    try {
      await speichereStatus(orderId, neuerStatus);
      render();
      const savedHint = document.querySelector(`.verwaltung-status-saved[data-order-id="${orderId}"]`);
      if (savedHint) {
        savedHint.style.display = "inline";
        setTimeout(() => { savedHint.style.display = "none"; }, 2000);
      }
    } catch (err) {
      alert("⚠️ Status konnte nicht gespeichert werden: " + (err instanceof Error ? err.message : String(err)));
      select.disabled = false;
    }
  }

  // Ein-Klick-Weiterschalten zum nächsten logischen Status (siehe STATUS_NEXT oben) — direkt auf
  // der Bestellkarte, ohne erst das Dropdown öffnen zu müssen. Das Dropdown bleibt für gezielte
  // Sprünge (z.B. direkt auf "Storniert") weiterhin verfügbar.
  async function statusVorwaerts(btn) {
    const orderId = btn.dataset.orderId;
    const neuerStatus = btn.dataset.nextStatus;
    if (!neuerStatus) return;
    btn.disabled = true;
    try {
      await speichereStatus(orderId, neuerStatus);
      render();
    } catch (err) {
      alert("⚠️ Status konnte nicht gespeichert werden: " + (err instanceof Error ? err.message : String(err)));
      btn.disabled = false;
    }
  }

  async function trackingSpeichern(orderId) {
    const input = document.querySelector(`.verwaltung-tracking-input[data-order-id="${orderId}"]`);
    const saveBtn = document.querySelector(`.verwaltung-tracking-save[data-order-id="${orderId}"]`);
    if (!input) return;
    saveBtn.disabled = true;
    try {
      const res = await fetch(`/api/verwaltung/orders/${orderId}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ tracking: input.value.trim() }),
      });
      const data = await res.json().catch(() => null);
      if (!res.ok || !data?.ok) throw new Error(data?.error || "Speichern fehlgeschlagen.");
      const b = alleBestellungen.find((o) => String(o.id) === String(orderId));
      if (b) b.tracking = input.value.trim();
      saveBtn.textContent = "✅";
      setTimeout(() => { saveBtn.textContent = "💾"; }, 1500);
    } catch (err) {
      alert("⚠️ Tracking-Nummer konnte nicht gespeichert werden: " + (err instanceof Error ? err.message : String(err)));
    } finally {
      saveBtn.disabled = false;
    }
  }

  async function kopieren(btn) {
    const text = btn.dataset.copy;
    try {
      await navigator.clipboard.writeText(text);
      const card = btn.closest(".order-card");
      const hint = card?.querySelector(".verwaltung-copy-hint");
      if (hint) {
        hint.style.display = "inline";
        setTimeout(() => { hint.style.display = "none"; }, 1600);
      }
    } catch {
      alert("Kopieren nicht möglich — bitte manuell markieren:\n\n" + text);
    }
  }

  function rechnungDrucken(orderId) {
    const b = alleBestellungen.find((o) => String(o.id) === String(orderId));
    if (!b) return;
    rechnungAlsPdfHerunterladen({
      nummer: b.bestellnummer || `#${b.id}`,
      datum: new Date(b.created_at).toLocaleDateString("de-DE"),
      artikel: b.artikel.map((a) => ({ name: a.name, menge: a.menge, preis: a.preis })),
      summe: Number(b.summe),
      empfaenger: b.kunde_name,
      lang: "de",
      labels: INVOICE_LABELS,
    });
  }

  // ── Kombinierter Filter: Status-Kachel/Filterleiste + Suche + Zeitraum wirken alle
  //    gleichzeitig (UND-Verknüpft), rein clientseitig über die schon gerenderten Karten. ──
  let aktuellerStatusFilter = "alle";

  function wendeFilterAn() {
    const suchtext = searchInput.value.trim().toLowerCase();
    const zeitraum = zeitraumSelect.value;
    const jetzt = Date.now();
    const zeitraumMs = zeitraum === "heute" ? MS_PRO_TAG : zeitraum === "7tage" ? 7 * MS_PRO_TAG : zeitraum === "30tage" ? 30 * MS_PRO_TAG : null;
    // "Dieser Monat" ist kein festes Zeitfenster (wie die anderen), sondern der echte
    // Kalendermonat ab dem 1. — deshalb separat berechnet statt über zeitraumMs.
    const heuteDatum = new Date();
    const monatsStart = zeitraum === "monat" ? new Date(heuteDatum.getFullYear(), heuteDatum.getMonth(), 1).getTime() : null;

    let sichtbar = 0;
    document.querySelectorAll("#verwaltung-order-list .order-card").forEach((card) => {
      const matchStatus = aktuellerStatusFilter === "alle" || card.dataset.bucket === aktuellerStatusFilter;
      const matchSuche = !suchtext || card.dataset.search.includes(suchtext);
      const erstelltMs = new Date(card.dataset.created).getTime();
      const matchZeitraum = monatsStart !== null
        ? erstelltMs >= monatsStart
        : !zeitraumMs || jetzt - erstelltMs <= zeitraumMs;
      const zeigen = matchStatus && matchSuche && matchZeitraum;
      card.style.display = zeigen ? "" : "none";
      if (zeigen) sichtbar++;
    });

    const hatBestellungen = alleBestellungen.length > 0;
    document.getElementById("verwaltung-no-match").style.display = hatBestellungen && sichtbar === 0 ? "" : "none";
  }

  document.addEventListener("click", (e) => {
    const filterBtn = e.target.closest("[data-filter]");
    if (filterBtn) {
      const f = filterBtn.dataset.filter;
      if (f) {
        aktuellerStatusFilter = f;
        document.querySelectorAll(".verwaltung-filter-btn").forEach((b) => b.classList.toggle("is-active", b.dataset.filter === f));
        wendeFilterAn();
        if (filterBtn.classList.contains("verwaltung-stat-tile")) {
          document.getElementById("verwaltung-order-list")?.scrollIntoView({ behavior: "smooth", block: "start" });
        }
      }
      return;
    }
    const zeitraumBtn = e.target.closest("[data-zeitraum]");
    if (zeitraumBtn) {
      zeitraumSelect.value = zeitraumBtn.dataset.zeitraum;
      wendeFilterAn();
      document.getElementById("verwaltung-order-list")?.scrollIntoView({ behavior: "smooth", block: "start" });
      return;
    }

    // ── Auswertungs-Kacheln: Klick öffnet das Detail-Panel direkt darunter, nochmal draufklicken
    //    klappt es wieder ein. ──
    const katTile = e.target.closest("[data-kat-tile]");
    if (katTile) {
      const schonOffen = katTile.classList.contains("is-active");
      if (schonOffen) {
        document.getElementById("verwaltung-kat-detail").setAttribute("hidden", "");
        katTile.classList.remove("is-active");
      } else {
        zeigeKatDetail(katTile.dataset.katTile);
      }
      return;
    }
    const landTile = e.target.closest("[data-land-tile]");
    if (landTile) {
      const schonOffen = landTile.classList.contains("is-active");
      if (schonOffen) {
        document.getElementById("verwaltung-land-detail").setAttribute("hidden", "");
        landTile.classList.remove("is-active");
      } else {
        zeigeLandDetail(landTile.dataset.landTile);
      }
      return;
    }
    const kundenTile = e.target.closest("[data-kunden-tile]");
    if (kundenTile) {
      const schonOffen = kundenTile.classList.contains("is-active");
      if (schonOffen) {
        document.getElementById("verwaltung-kunden-detail").setAttribute("hidden", "");
        kundenTile.classList.remove("is-active");
      } else {
        zeigeKundeDetail(kundenTile.dataset.kundenTile);
      }
      return;
    }
    const closeDetailBtn = e.target.closest("[data-close-detail]");
    if (closeDetailBtn) {
      const gruppe = closeDetailBtn.dataset.closeDetail;
      document.getElementById(`verwaltung-${gruppe}-detail`)?.setAttribute("hidden", "");
      document.querySelectorAll(`[data-${gruppe}-tile]`).forEach((t) => t.classList.remove("is-active"));
      return;
    }
  });

  searchInput.addEventListener("input", wendeFilterAn);
  zeitraumSelect.addEventListener("change", wendeFilterAn);
  sortSelect.addEventListener("change", render);

  document.getElementById("verwaltung-new-refresh-btn")?.addEventListener("click", ladeUndRendere);
  document.getElementById("verwaltung-retry-btn")?.addEventListener("click", ladeUndRendere);

  // ── Auswertung (Bestseller/Herkunft/Stammkundschaft): jede Kiste ist SELBST der Klick-
  //    Auslöser für ihren eigenen Inhalt — kein separater Knopf mehr davor. Alle drei starten
  //    eingeklappt (nur Kopfzeile sichtbar) und lassen sich unabhängig voneinander auf-/zuklappen. ──
  document.querySelectorAll("[data-collapsible-box] > .verwaltung-box-head-btn").forEach((btn) => {
    btn.addEventListener("click", () => {
      const box = btn.closest("[data-collapsible-box]");
      const wirdJetztGeoeffnet = box.classList.contains("is-collapsed");
      box.classList.toggle("is-collapsed");
      btn.setAttribute("aria-expanded", String(wirdJetztGeoeffnet));
      if (wirdJetztGeoeffnet) {
        box.scrollIntoView({ behavior: "smooth", block: "start" });
      }
    });
  });

  // ── CSV-Export: exportiert genau die aktuell sichtbare (gefilterte) Liste — für die
  //    Buchhaltung/Steuer, komplett clientseitig, keine Serverkosten. ──
  document.getElementById("verwaltung-csv-btn").addEventListener("click", () => {
    const sichtbareIds = Array.from(document.querySelectorAll("#verwaltung-order-list .order-card"))
      .filter((c) => c.style.display !== "none")
      .map((c) => c.dataset.orderId);
    const bestellungen = alleBestellungen.filter((b) => sichtbareIds.includes(String(b.id)));
    if (bestellungen.length === 0) {
      alert("Keine Bestellungen zum Exportieren (aktuelle Filterung ergibt 0 Treffer).");
      return;
    }
    const kopf = ["Bestellnummer", "Datum", "Status", "Kunde", "E-Mail", "Land", "PLZ", "Ort", "Straße", "Artikel", "Zwischensumme", "Versand", "Rabatt", "Summe", "Zahlungsart", "Tracking"];
    const csvZeile = (werte) => werte.map((w) => `"${String(w ?? "").replace(/"/g, '""')}"`).join(";");
    const zeilen = [csvZeile(kopf)];
    bestellungen.forEach((b) => {
      zeilen.push(csvZeile([
        b.bestellnummer || `#${b.id}`,
        new Date(b.created_at).toLocaleDateString("de-DE"),
        STATUS_LABEL[b.status] || b.status,
        b.kunde_name,
        b.kunde_email,
        LAND_NAME[b.land] || b.land,
        b.plz,
        b.ort,
        b.strasse,
        b.artikel.map((a) => `${a.menge}x ${a.name}`).join(" | "),
        b.zwischensumme,
        b.versandkosten,
        b.rabatt_gesamt,
        b.summe,
        b.zahlungsart,
        b.tracking || "",
      ]));
    });
    const csv = "﻿" + zeilen.join("\r\n"); // BOM voran, damit Excel Umlaute korrekt zeigt
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `bestellungen-${new Date().toISOString().slice(0, 10)}.csv`;
    a.click();
    URL.revokeObjectURL(url);
  });

  ladeUndRendere();
</script>
