<?php
define("ADMIN_USER", "admin");
define("ADMIN_PASS", "admin");

session_start();

if (isset($_GET["logout"])) {
    session_destroy();
    header("Location: timeline-admin.php");
    exit;
}

$loginError = "";
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["username"])) {
    if ($_POST["username"] === ADMIN_USER && $_POST["password"] === ADMIN_PASS) {
        $_SESSION["tl_admin"] = true;
        header("Location: timeline-admin.php");
        exit;
    } else {
        $loginError = "Zugriff verweigert!";
    }
}

if (empty($_SESSION["tl_admin"])) {
?>
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Timeline Login</title>
    <link href="https://fonts.googleapis.com/css2?family=Syne:wght@800&family=DM+Sans:wght@400&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
    <style>
        body{background:#0d0f14;color:#fff;font-family:"DM Sans",sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;padding:1rem;box-sizing:border-box}
        .card{background:#1c1f2a;padding:2rem;border-radius:20px;border:1px solid #2a2e3f;width:100%;max-width:360px;text-align:center}
        h1{font-family:"Syne",sans-serif;margin-bottom:1.5rem}
        .logo{width:52px;height:52px;border-radius:14px;background:#4f6ef7;display:inline-flex;align-items:center;justify-content:center;font-size:1.4rem;margin-bottom:1rem}
        .field{position:relative;margin-bottom:1rem;text-align:left}
        .field i{position:absolute;left:.9rem;top:50%;transform:translateY(-50%);color:#6b7184}
        input{width:100%;background:rgba(255,255,255,.05);border:1.5px solid #2a2e3f;padding:.75rem .9rem .75rem 2.5rem;border-radius:12px;color:#fff;font-size:1rem;box-sizing:border-box}
        input:focus{outline:none;border-color:#4f6ef7}
        button{width:100%;background:#4f6ef7;border:none;padding:.85rem;border-radius:12px;color:#fff;font-weight:700;font-size:1rem;cursor:pointer;margin-top:.5rem}
        button:hover{filter:brightness(1.1)}
        .error{color:#f05252;margin-bottom:1rem;font-size:.9rem;background:rgba(240,82,82,.1);padding:.6rem;border-radius:8px}
    </style>
</head>
<body>
    <div class="card">
        <div class="logo"><i class="fas fa-stream"></i></div>
        <h1>Timeline CMS</h1>
        <?php if ($loginError): ?><div class="error"><i class="fas fa-exclamation-circle"></i> <?= htmlspecialchars($loginError) ?></div><?php endif; ?>
        <form method="POST">
            <div class="field"><i class="fas fa-user"></i><input type="text" name="username" placeholder="Benutzername" required autofocus autocomplete="username"></div>
            <div class="field"><i class="fas fa-lock"></i><input type="password" name="password" placeholder="Passwort" required autocomplete="current-password"></div>
            <button type="submit"><i class="fas fa-sign-in-alt"></i> Einloggen</button>
        </form>
    </div>
</body>
</html>
<?php exit; }
// ── Ab hier eingeloggt ──────────────────────────────────────────────────
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Timeline CMS</title>

<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Syne:wght@400;600;700;800&family=DM+Sans:ital,wght@0,300;0,400;0,500;1,300&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">

<!-- TinyMCE (Community / Cloud – kostenlos mit API-Key, oder self-hosted) -->
<script src="tinymce/tinymce.min.js"></script>

<style>
/* ══════════════════════════════════════════════════════════════════════════
   DESIGN: Dark editorial / refined studio aesthetic
   Palette: near-black #0d0f14, accent electric-indigo #4f6ef7, warm cream #f5f0e8
══════════════════════════════════════════════════════════════════════════ */
:root {
    --ink:      #0d0f14;
    --ink2:     #1c1f2a;
    --ink3:     #2e3347;
    --muted:    #6b7184;
    --border:   #2a2e3f;
    --border2:  #e5e2da;
    --cream:    #f5f0e8;
    --white:    #ffffff;
    --accent:   #4f6ef7;
    --accent2:  #fc643f;
    --success:  #3ecf8e;
    --danger:   #f05252;
    --warn:     #f59e0b;
    --panel:    #161924;
    --card:     #1c2030;
    --radius:   12px;
    --radius-lg:20px;
    --shadow:   0 4px 24px rgba(0,0,0,.4);
    --ff-head:  'Syne', sans-serif;
    --ff-body:  'DM Sans', sans-serif;
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
    font-family: var(--ff-body);
    background: var(--ink);
    color: var(--white);
    min-height: 100vh;
    display: grid;
    grid-template-rows: auto 1fr;
    grid-template-columns: 260px 1fr;
    grid-template-areas: "sidebar header" "sidebar main";
}

/* ─── Sidebar ─────────────────────────────────────────────────────────── */
.sidebar {
    grid-area: sidebar;
    background: var(--panel);
    border-right: 1px solid var(--border);
    display: flex; flex-direction: column;
    height: 100vh; position: sticky; top: 0;
    padding: 0;
    overflow-y: auto;
}
.sidebar-brand {
    padding: 1.6rem 1.5rem;
    border-bottom: 1px solid var(--border);
    display: flex; align-items: center; gap: .8rem;
}
.brand-icon {
    width: 36px; height: 36px; border-radius: 10px;
    background: var(--accent); display: flex; align-items: center; justify-content: center;
    font-size: 1rem; color: #fff; flex-shrink: 0;
}
.brand-text { font-family: var(--ff-head); font-size: 1.05rem; font-weight: 700; line-height: 1.2; }
.brand-sub  { font-size: .7rem; color: var(--muted); font-weight: 400; }

.sidebar-nav { padding: 1rem .75rem; flex: 1; }
.nav-label { font-size: .68rem; font-weight: 700; letter-spacing: .1em; color: var(--muted);
             text-transform: uppercase; padding: .5rem .75rem; margin-top: .5rem; }
.nav-item {
    display: flex; align-items: center; gap: .75rem;
    padding: .6rem .9rem; border-radius: var(--radius);
    font-size: .88rem; font-weight: 500; color: #aab0c6;
    cursor: pointer; transition: all .18s; margin-bottom: 2px;
    border: none; background: none; width: 100%; text-align: left;
}
.nav-item:hover   { background: rgba(79,110,247,.12); color: #fff; }
.nav-item.active  { background: rgba(79,110,247,.2); color: var(--accent); }
.nav-item i       { width: 18px; text-align: center; }
.nav-badge {
    margin-left: auto; background: var(--accent); color: #fff;
    border-radius: 99px; padding: .1rem .5rem; font-size: .7rem; font-weight: 700;
}

.sidebar-footer {
    padding: 1rem 1.5rem;
    border-top: 1px solid var(--border);
    font-size: .78rem; color: var(--muted);
    display: flex; align-items: center; gap: .5rem;
}
.status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); flex-shrink: 0; }

/* ─── Header ─────────────────────────────────────────────────────────── */
.topbar {
    grid-area: header;
    background: var(--ink2);
    border-bottom: 1px solid var(--border);
    padding: .9rem 2rem;
    display: flex; align-items: center; justify-content: space-between;
    position: sticky; top: 0; z-index: 50;
}
.topbar-title { font-family: var(--ff-head); font-size: 1.15rem; font-weight: 700; }
.topbar-actions { display: flex; gap: .7rem; align-items: center; }
.btn {
    display: inline-flex; align-items: center; gap: .45rem;
    padding: .5rem 1.1rem; border-radius: var(--radius);
    font-family: var(--ff-body); font-size: .85rem; font-weight: 600;
    cursor: pointer; border: none; transition: all .18s;
    white-space: nowrap;
}
.btn:hover { filter: brightness(1.1); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn-primary { background: var(--accent); color: #fff; }
.btn-ghost   { background: rgba(255,255,255,.06); color: #ccc; border: 1px solid var(--border); }
.btn-ghost:hover { background: rgba(255,255,255,.12); color: #fff; }
.btn-danger  { background: var(--danger); color: #fff; }
.btn-success { background: var(--success); color: #000; }
.btn-sm      { padding: .35rem .75rem; font-size: .78rem; }
.btn-icon    { padding: .5rem .6rem; }

/* ─── Main ────────────────────────────────────────────────────────────── */
main {
    grid-area: main;
    padding: 2rem;
    overflow-y: auto;
}
.pane { display: none; }
.pane.active { display: block; }

/* ─── Stats ───────────────────────────────────────────────────────────── */
.stats-row { display: grid; grid-template-columns: repeat(4,1fr); gap: 1rem; margin-bottom: 2rem; }
.stat-card {
    background: var(--card); border-radius: var(--radius-lg);
    padding: 1.3rem 1.5rem; border: 1px solid var(--border);
    position: relative; overflow: hidden;
}
.stat-card::before {
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(135deg, rgba(79,110,247,.05) 0%, transparent 60%);
    pointer-events: none;
}
.stat-label { font-size: .75rem; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; }
.stat-value { font-family: var(--ff-head); font-size: 2.1rem; font-weight: 800; margin: .25rem 0 .1rem; }
.stat-sub   { font-size: .75rem; color: var(--muted); }
.stat-icon  { position: absolute; right: 1.2rem; top: 1.2rem; font-size: 1.8rem; opacity: .15; }

/* ─── Section heading ─────────────────────────────────────────────────── */
.section-head {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 1.2rem;
}
.section-head h2 { font-family: var(--ff-head); font-size: 1.1rem; font-weight: 700; }

/* ─── Entry List ──────────────────────────────────────────────────────── */
.entry-list { display: flex; flex-direction: column; gap: .6rem; }
.entry-card {
    background: var(--card); border-radius: var(--radius-lg);
    border: 1px solid var(--border);
    display: grid;
    grid-template-columns: 28px 52px 1fr auto;
    align-items: center; gap: 1rem;
    padding: .9rem 1.2rem;
    transition: border-color .2s, box-shadow .2s;
    cursor: default;
}
.entry-card:hover  { border-color: var(--accent); box-shadow: 0 0 0 1px rgba(79,110,247,.2); }
.entry-card.over   { border-color: var(--accent); background: rgba(79,110,247,.08); }
.entry-card.inactive { opacity: .45; }
.drag-handle { color: var(--muted); cursor: grab; font-size: 1rem; user-select: none; }
.drag-handle:active { cursor: grabbing; }
.entry-thumb {
    width: 52px; height: 52px; border-radius: 10px;
    background: var(--accent);
    display: flex; align-items: center; justify-content: center;
    font-size: 1.3rem; color: #fff; flex-shrink: 0; overflow: hidden;
}
.entry-thumb img { width: 100%; height: 100%; object-fit: cover; }
.entry-meta h3   { font-weight: 600; font-size: .95rem; margin-bottom: .2rem; line-height: 1.3; }
.entry-meta .preview {
    font-size: .78rem; color: var(--muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 460px;
}
.entry-meta .chips { display: flex; gap: .4rem; margin-top: .35rem; flex-wrap: wrap; }
.chip {
    display: inline-flex; align-items: center; gap: .3rem;
    background: rgba(255,255,255,.06); border-radius: 99px;
    padding: .1rem .55rem; font-size: .7rem; color: #aab0c6;
    border: 1px solid var(--border);
}
.chip.rev  { border-color: rgba(79,110,247,.4); color: var(--accent); }
.chip.img  { border-color: rgba(62,207,142,.4); color: var(--success); }
.chip.off  { border-color: rgba(240,82,82,.3); color: var(--danger); }
.entry-actions { display: flex; gap: .4rem; }

/* Empty state */
.empty-state {
    text-align: center; padding: 4rem 2rem;
    color: var(--muted);
}
.empty-state i { font-size: 3rem; margin-bottom: 1rem; opacity: .4; display: block; }

/* ─── Modal ───────────────────────────────────────────────────────────── */
.modal-backdrop {
    display: none; position: fixed; inset: 0;
    background: rgba(0,0,0,.7); z-index: 200;
    align-items: flex-start; justify-content: center;
    padding: 2rem 1rem; overflow-y: auto;
    backdrop-filter: blur(4px);
}
.modal-backdrop.open { display: flex; }
.modal {
    background: var(--card); border-radius: var(--radius-lg);
    border: 1px solid var(--border);
    width: min(780px, 100%);
    box-shadow: var(--shadow);
    animation: slideUp .25s ease;
    margin: auto;
}
@keyframes slideUp { from{opacity:0;transform:translateY(30px)} to{opacity:1;transform:none} }
.modal-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 1.4rem 1.8rem; border-bottom: 1px solid var(--border);
}
.modal-header h2 { font-family: var(--ff-head); font-size: 1.1rem; font-weight: 700; }
.modal-close {
    background: none; border: none; color: var(--muted);
    cursor: pointer; font-size: 1.2rem; line-height: 1;
    padding: .3rem; border-radius: 6px; transition: color .15s;
}
.modal-close:hover { color: #fff; }
.modal-body { padding: 1.8rem; }
.modal-footer {
    display: flex; gap: .7rem; justify-content: flex-end;
    padding: 1.2rem 1.8rem; border-top: 1px solid var(--border);
}

/* ─── Form ────────────────────────────────────────────────────────────── */
.form-row     { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1rem; }
.form-row.one { grid-template-columns: 1fr; }
.form-group   { display: flex; flex-direction: column; gap: .4rem; }
label         { font-size: .78rem; font-weight: 600; color: #8890a8; letter-spacing: .04em; text-transform: uppercase; }
input[type=text], input[type=url], select, textarea {
    background: rgba(255,255,255,.05); border: 1.5px solid var(--border);
    border-radius: var(--radius); color: #fff;
    font-family: var(--ff-body); font-size: .9rem;
    padding: .6rem .9rem; transition: border-color .2s;
    width: 100%;
}
input:focus, select:focus, textarea:focus {
    outline: none; border-color: var(--accent);
    background: rgba(79,110,247,.06);
}
input[type=color] {
    width: 100%; height: 2.6rem; border-radius: var(--radius); cursor: pointer;
    padding: .2rem; border: 1.5px solid var(--border); background: var(--ink3);
}
select option { background: var(--ink2); }
textarea { resize: vertical; min-height: 80px; }
.switch-row {
    display: flex; align-items: center; gap: .6rem;
    font-size: .88rem; color: #aab0c6;
}
.switch {
    position: relative; width: 40px; height: 22px; flex-shrink: 0;
}
.switch input { opacity: 0; width: 0; height: 0; }
.slider {
    position: absolute; inset: 0; cursor: pointer;
    background: var(--border); border-radius: 99px; transition: .3s;
}
.slider::before {
    content: ''; position: absolute;
    width: 16px; height: 16px; left: 3px; bottom: 3px;
    background: #fff; border-radius: 50%; transition: .3s;
}
input:checked + .slider { background: var(--accent); }
input:checked + .slider::before { transform: translateX(18px); }

/* ─── Image Upload ────────────────────────────────────────────────────── */
.upload-zone {
    border: 2px dashed var(--border); border-radius: var(--radius-lg);
    padding: 1.5rem; text-align: center; cursor: pointer;
    transition: all .2s; position: relative;
    background: rgba(255,255,255,.02);
}
.upload-zone:hover, .upload-zone.over {
    border-color: var(--accent); background: rgba(79,110,247,.06);
}
.upload-zone input[type=file] {
    position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%;
}
.upload-icon { font-size: 2rem; color: var(--muted); margin-bottom: .5rem; }
.upload-label { font-size: .85rem; color: var(--muted); }
.upload-label strong { color: var(--accent); }
.img-preview {
    width: 100%; max-height: 180px; object-fit: cover;
    border-radius: var(--radius); margin-top: .8rem; display: none;
}
.img-preview.show { display: block; }
.img-remove {
    background: var(--danger); color: #fff; border: none;
    border-radius: 6px; padding: .25rem .6rem; cursor: pointer;
    font-size: .75rem; margin-top: .4rem; display: none;
}
.img-remove.show { display: inline-flex; align-items: center; gap: .3rem; }

/* ─── Icon Picker ─────────────────────────────────────────────────────── */
.icon-picker-wrap { position: relative; }
.icon-selected-preview {
    display: flex; align-items: center; gap: .8rem;
    background: rgba(255,255,255,.05); border: 1.5px solid var(--border);
    border-radius: var(--radius); padding: .55rem .9rem; cursor: pointer;
    transition: border-color .2s;
}
.icon-selected-preview:hover { border-color: var(--accent); }
.icon-selected-preview .prev-icon {
    width: 36px; height: 36px; border-radius: 8px;
    background: var(--accent); display: flex; align-items: center;
    justify-content: center; font-size: 1.1rem; color: #fff; flex-shrink: 0;
}
.icon-selected-preview .prev-label { font-size: .88rem; color: #ccc; flex: 1; }
.icon-selected-preview .prev-arrow { color: var(--muted); font-size: .8rem; }
.icon-panel {
    display: none; margin-top: .5rem;
    background: var(--ink2); border: 1.5px solid var(--border);
    border-radius: var(--radius-lg); overflow: hidden;
}
.icon-panel.open { display: block; }
.icon-panel-head {
    padding: .7rem .8rem; border-bottom: 1px solid var(--border);
    display: flex; gap: .5rem; align-items: center;
}
.icon-panel-head input {
    flex: 1; font-size: .85rem; background: rgba(255,255,255,.07);
    border: 1.5px solid var(--border); border-radius: 8px;
    color: #fff; padding: .4rem .7rem;
}
.icon-panel-head input:focus { outline: none; border-color: var(--accent); }
.icon-cats {
    display: flex; gap: .3rem; padding: .5rem .8rem;
    border-bottom: 1px solid var(--border); flex-wrap: wrap;
}
.icon-cat-btn {
    padding: .2rem .65rem; border-radius: 99px; font-size: .72rem;
    font-weight: 600; cursor: pointer; border: 1.5px solid var(--border);
    background: none; color: var(--muted); transition: all .15s;
}
.icon-cat-btn:hover  { border-color: var(--accent); color: var(--accent); }
.icon-cat-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.icon-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
    gap: .4rem; padding: .8rem; max-height: 240px; overflow-y: auto;
}
.icon-opt {
    display: flex; flex-direction: column; align-items: center; gap: .3rem;
    padding: .6rem .3rem; border-radius: 10px; cursor: pointer;
    border: 2px solid transparent; transition: all .15s; text-align: center;
    background: rgba(255,255,255,.03);
}
.icon-opt:hover { background: rgba(79,110,247,.15); border-color: rgba(79,110,247,.3); }
.icon-opt.sel   { border-color: var(--accent); background: rgba(79,110,247,.2); }
.icon-opt i     { font-size: 1.4rem; color: #ccc; }
.icon-opt.sel i { color: var(--accent); }
.icon-opt span  { font-size: .6rem; color: var(--muted); line-height: 1.2;
                  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 60px; }
.icon-empty { text-align: center; padding: 1.5rem; color: var(--muted); font-size: .85rem; grid-column: 1/-1; }

/* ─── Icon Tabs ───────────────────────────────────────────────────────── */
.icon-tabs { display: flex; border-bottom: 1px solid var(--border); }
.icon-tab { flex: 1; padding: .6rem .5rem; font-size: .78rem; font-weight: 600; background: none; border: none; color: var(--muted); cursor: pointer; transition: all .15s; display: flex; align-items: center; justify-content: center; gap: .4rem; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.icon-tab:hover { color: #fff; }
.icon-tab.active { color: var(--accent); border-bottom-color: var(--accent); }

/* ─── SVG Upload ──────────────────────────────────────────────────────── */
.svg-upload-zone { border: 2px dashed var(--border); border-radius: var(--radius); padding: 1.2rem; text-align: center; cursor: pointer; transition: all .2s; background: rgba(255,255,255,.02); }
.svg-upload-zone:hover { border-color: var(--accent); background: rgba(79,110,247,.06); }
.svg-upload-icon { font-size: 1.8rem; color: var(--muted); display: block; margin-bottom: .4rem; }
.svg-upload-label { font-size: .82rem; color: var(--muted); }

/* ─── Config panel ────────────────────────────────────────────────────── */
.cfg-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem; }
.cfg-section {
    background: var(--card); border-radius: var(--radius-lg);
    border: 1px solid var(--border); padding: 1.5rem; margin-bottom: 1.2rem;
}
.cfg-section h3 {
    font-family: var(--ff-head); font-size: .95rem; font-weight: 700;
    margin-bottom: 1.2rem; padding-bottom: .7rem; border-bottom: 1px solid var(--border);
    display: flex; align-items: center; gap: .5rem; color: #ccc;
}

/* ─── Preview card ────────────────────────────────────────────────────── */
.preview-frame-wrap {
    background: var(--card); border-radius: var(--radius-lg);
    border: 1px solid var(--border); overflow: hidden;
}
.preview-toolbar {
    padding: .75rem 1.2rem; background: var(--panel);
    border-bottom: 1px solid var(--border);
    display: flex; align-items: center; gap: .8rem; font-size: .82rem;
}
.preview-dot { width: 10px; height: 10px; border-radius: 50%; }
.preview-frame-wrap iframe { width: 100%; height: 620px; border: none; display: block; }

/* ─── JSON panel ──────────────────────────────────────────────────────── */
.json-box {
    background: var(--ink); border: 1px solid var(--border);
    border-radius: var(--radius-lg); padding: 1.2rem;
    font-family: 'Courier New', monospace; font-size: .8rem;
    color: #a8b4d8; overflow-x: auto;
    max-height: 500px; overflow-y: auto;
    line-height: 1.6;
    white-space: pre;
}

/* ─── Toast ───────────────────────────────────────────────────────────── */
.toast-stack { position: fixed; bottom: 1.5rem; right: 1.5rem; z-index: 999; display: flex; flex-direction: column; gap: .5rem; }
.toast {
    background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius); padding: .75rem 1.1rem;
    font-size: .88rem; font-weight: 500; color: #fff;
    display: flex; align-items: center; gap: .6rem;
    box-shadow: var(--shadow);
    animation: toastIn .25s ease;
    min-width: 220px;
}
@keyframes toastIn { from{opacity:0;transform:translateX(30px)} to{opacity:1;transform:none} }
.toast.out { animation: toastOut .25s ease forwards; }
@keyframes toastOut { to{opacity:0;transform:translateX(30px)} }
.toast.success .t-icon { color: var(--success); }
.toast.error   .t-icon { color: var(--danger);  }
.toast.info    .t-icon { color: var(--accent);   }

/* ─── TinyMCE dark wrapper ────────────────────────────────────────────── */
.tinymce-wrap { margin-bottom: .5rem; }
.tinymce-wrap .tox-tinymce { border-radius: var(--radius) !important; border-color: var(--border) !important; }

/* ─── Scrollbar ───────────────────────────────────────────────────────── */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: var(--muted); }

/* ─── Responsive ──────────────────────────────────────────────────────── */
@media(max-width:900px) {
    body { grid-template-columns: 1fr; grid-template-areas: "header" "main"; }
    .sidebar { display: none; }
    .stats-row { grid-template-columns: 1fr 1fr; }
    .form-row  { grid-template-columns: 1fr; }
    .cfg-grid  { grid-template-columns: 1fr; }
    .entry-card { grid-template-columns: 28px 1fr auto; }
    .entry-thumb { display: none; }
}
</style>
</head>
<body>

<!-- ─── Sidebar ──────────────────────────────────────────────────────────── -->
<aside class="sidebar">
    <div class="sidebar-brand">
        <div class="brand-icon"><i class="fas fa-stream"></i></div>
        <div>
            <div class="brand-text">Timeline CMS</div>
            <div class="brand-sub">Mobirise Block Editor</div>
			<div class="brand-sub">V.Niederastroth 2026</div>
        </div>
    </div>
    <nav class="sidebar-nav">
        <div class="nav-label">Verwaltung</div>
        <button class="nav-item active" onclick="switchPane('entries')" id="nav-entries">
            <i class="fas fa-list-ul"></i> Einträge
            <span class="nav-badge" id="nav-badge">0</span>
        </button>
        <div class="nav-label">Ausgabe</div>
        <button class="nav-item" onclick="switchPane('preview')" id="nav-preview">
            <i class="fas fa-eye"></i> Vorschau
        </button>
        <button class="nav-item" onclick="switchPane('json')" id="nav-json">
            <i class="fas fa-code"></i> JSON Export
        </button>
        <div class="nav-label" style="margin-top:1rem;">Account</div>
        <a href="?logout=1" class="nav-item" style="color:var(--danger);text-decoration:none;">
            <i class="fas fa-sign-out-alt"></i> Abmelden
        </a>
    </nav>
    <div class="sidebar-footer">
        <span class="status-dot"></span>
        API verbunden &nbsp;·&nbsp; SQLite
    </div>
</aside>

<!-- ─── Topbar ────────────────────────────────────────────────────────────── -->
<header class="topbar">
    <div class="topbar-title" id="pane-title">Einträge verwalten</div>
    <div class="topbar-actions">
        <button class="btn btn-ghost btn-sm" onclick="openPreviewTab()">
            <i class="fas fa-external-link-alt"></i> Live-Vorschau
        </button>
        <button class="btn btn-primary" onclick="openModal()">
            <i class="fas fa-plus"></i> Neuer Eintrag
        </button>
    </div>
</header>

<!-- ─── Main ──────────────────────────────────────────────────────────────── -->
<main>

    <!-- ══ ENTRIES PANE ══ -->
    <div class="pane active" id="pane-entries">
        <div class="stats-row">
            <div class="stat-card">
                <div class="stat-label">Einträge gesamt</div>
                <div class="stat-value" id="st-total">–</div>
                <div class="stat-sub">in der Datenbank</div>
                <i class="fas fa-layer-group stat-icon"></i>
            </div>
            <div class="stat-card">
                <div class="stat-label">Aktiv / Sichtbar</div>
                <div class="stat-value" id="st-active">–</div>
                <div class="stat-sub">werden angezeigt</div>
                <i class="fas fa-eye stat-icon"></i>
            </div>
            <div class="stat-card">
                <div class="stat-label">Mit Bild</div>
                <div class="stat-value" id="st-imgs">–</div>
                <div class="stat-sub">haben Thumbnail</div>
                <i class="fas fa-image stat-icon"></i>
            </div>
            <div class="stat-card">
                <div class="stat-label">Reverse Einträge</div>
                <div class="stat-value" id="st-rev">–</div>
                <div class="stat-sub">links ausgerichtet</div>
                <i class="fas fa-exchange-alt stat-icon"></i>
            </div>
        </div>

        <div class="section-head">
            <h2>Timeline Einträge</h2>
            <span style="font-size:.8rem;color:var(--muted);">
                <i class="fas fa-grip-vertical"></i> Drag &amp; Drop zum Sortieren
            </span>
        </div>
        <div class="entry-list" id="entry-list">
            <!-- JS rendered -->
        </div>
    </div>

    <!-- ══ PREVIEW PANE ══ -->
    <div class="pane" id="pane-preview">
        <div class="preview-frame-wrap">
            <div class="preview-toolbar">
                <span class="preview-dot" style="background:#f05252"></span>
                <span class="preview-dot" style="background:#f59e0b"></span>
                <span class="preview-dot" style="background:#3ecf8e"></span>
                <span style="color:var(--muted);margin-left:.3rem;">index.html — Live-Vorschau</span>
                <button class="btn btn-ghost btn-sm" style="margin-left:auto;" onclick="refreshPreview()">
                    <i class="fas fa-sync-alt"></i> Reload
                </button>
            </div>
            <iframe id="preview-iframe" src="index.html"></iframe>
        </div>
    </div>

    <!-- ══ JSON PANE ══ -->
    <div class="pane" id="pane-json">
        <div class="section-head">
            <h2>JSON Export / Import</h2>
            <div style="display:flex;gap:.6rem;">
                <button class="btn btn-ghost btn-sm" onclick="copyJSON()"><i class="fas fa-copy"></i> Kopieren</button>
                <button class="btn btn-primary btn-sm" onclick="downloadJSON()"><i class="fas fa-download"></i> Download</button>
                <label class="btn btn-ghost btn-sm" style="cursor:pointer;">
                    <i class="fas fa-upload"></i> Import
                    <input type="file" accept=".json" style="display:none" onchange="importJSON(this)">
                </label>
            </div>
        </div>
        <div class="json-box" id="json-box">Lade...</div>
    </div>

</main>

<!-- ─── Modal ─────────────────────────────────────────────────────────────── -->
<div class="modal-backdrop" id="modal-backdrop" onclick="if(event.target===this)closeModal()">
<div class="modal">
    <div class="modal-header">
        <h2 id="modal-h">Neuer Eintrag</h2>
        <button class="modal-close" onclick="closeModal()"><i class="fas fa-times"></i></button>
    </div>
    <div class="modal-body">
        <input type="hidden" id="e-id">

        <div class="form-row">
            <div class="form-group">
                <label>Titel *</label>
                <input type="text" id="e-title" placeholder="z.B. Unsere Gründung">
            </div>
            <div class="form-group">
                <label>Tag / Datum</label>
                <input type="text" id="e-tag" placeholder="z.B. 2018 oder März">
            </div>
        </div>

        <div class="form-row">
            <div class="form-group icon-picker-wrap">
                <label>Icon</label>
                <input type="hidden" id="e-icon" value="fas fa-star">
                <!-- Vorschau des gewählten Icons -->
                <div class="icon-selected-preview" onclick="toggleIconPanel()">
                    <div class="prev-icon"><i id="prev-icon-i" class="fas fa-star"></i></div>
                    <span class="prev-label" id="prev-icon-label">fas fa-star</span>
                    <i class="fas fa-chevron-down prev-arrow" id="prev-arrow"></i>
                </div>
                <!-- Icon Panel -->
                <div class="icon-panel" id="icon-panel">
                    <!-- Tabs -->
                    <div class="icon-tabs">
                        <button class="icon-tab active" id="tab-fa" onclick="switchIconTab('fa')">
                            <i class="fas fa-icons"></i> Font Awesome
                        </button>
                        <button class="icon-tab" id="tab-svg" onclick="switchIconTab('svg')">
                            <i class="fas fa-file-code"></i> Eigenes SVG
                        </button>
                    </div>
                    <!-- FA Tab -->
                    <div id="icon-tab-fa">
                        <div class="icon-panel-head">
                            <i class="fas fa-search" style="color:var(--muted);"></i>
                            <input type="text" id="icon-search-inp" placeholder="Icon suchen… z.B. star, mail, rocket"
                                   oninput="filterIcons(this.value)">
                        </div>
                        <div class="icon-cats" id="icon-cats"></div>
                        <div class="icon-grid" id="icon-grid"></div>
                    </div>
                    <!-- SVG Tab -->
                    <div id="icon-tab-svg" style="display:none; padding:.8rem;">
                        <div class="svg-upload-zone" id="svg-upload-zone" onclick="document.getElementById('svg-file-inp').click()">
                            <i class="fas fa-file-code svg-upload-icon"></i>
                            <div class="svg-upload-label">SVG-Datei vom Computer wählen</div>
                            <input type="file" id="svg-file-inp" accept=".svg,image/svg+xml" style="display:none" onchange="handleSVGFile(this)">
                        </div>
                        <div id="svg-preview-wrap" style="display:none; margin-top:.8rem;">
                            <div style="font-size:.72rem;color:var(--muted);margin-bottom:.4rem;text-transform:uppercase;font-weight:600;letter-spacing:.04em;">Vorschau</div>
                            <div style="display:flex;align-items:center;gap:1rem;">
                                <div id="svg-preview-icon" style="width:52px;height:52px;background:var(--accent);border-radius:12px;display:flex;align-items:center;justify-content:center;padding:10px;flex-shrink:0;color:#fff;"></div>
                                <div style="flex:1;">
                                    <div id="svg-preview-name" style="font-size:.82rem;color:#ccc;margin-bottom:.4rem;"></div>
                                    <button class="btn btn-primary btn-sm" onclick="applySVGIcon()">
                                        <i class="fas fa-check"></i> Dieses SVG verwenden
                                    </button>
                                </div>
                            </div>
                        </div>
                        <div style="margin-top:.8rem;padding:.6rem;background:rgba(255,255,255,.03);border-radius:8px;font-size:.72rem;color:var(--muted);line-height:1.6;">
                            <i class="fas fa-info-circle" style="color:var(--accent);"></i>
                            SVG wird inline gespeichert und direkt im Timeline-Punkt angezeigt. Am besten SVGs ohne hardcodierte Farben verwenden.
                        </div>
                    </div>
                </div>
            </div>
            <div class="form-group">
                <label>Positionierung</label>
                <div style="display:flex;gap:1.2rem;align-items:center;padding:.4rem 0;">
                    <label class="switch-row">
                        <label class="switch"><input type="checkbox" id="e-reverse"><span class="slider"></span></label>
                        Links (reverse)
                    </label>
                    <label class="switch-row">
                        <label class="switch"><input type="checkbox" id="e-active" checked><span class="slider"></span></label>
                        Aktiv
                    </label>
                </div>
            </div>
        </div>

        <!-- TinyMCE -->
        <div class="form-group tinymce-wrap" style="margin-bottom:1rem;">
            <label>Inhalt (HTML)</label>
            <textarea id="e-content" style="height:200px;background:var(--ink3);color:#fff;border:1.5px solid var(--border);border-radius:var(--radius);padding:.8rem;font-family:monospace;font-size:.85rem;"></textarea>
        </div>

        <!-- Bildupload -->
        <div class="form-group">
            <label>Bild (optional)</label>
            <div class="upload-zone" id="upload-zone"
                 ondragover="event.preventDefault();this.classList.add('over')"
                 ondragleave="this.classList.remove('over')"
                 ondrop="handleDrop(event)">
                <input type="file" accept="image/*" onchange="handleFileSelect(this)">
                <div class="upload-icon"><i class="fas fa-cloud-upload-alt"></i></div>
                <div class="upload-label">
                    <strong>Klicken oder Bild hierher ziehen</strong><br>
                    JPG, PNG, WebP, GIF · max. 8 MB
                </div>
                <img class="img-preview" id="img-preview" src="" alt="">
            </div>
            <button class="img-remove" id="img-remove" onclick="removeImage()">
                <i class="fas fa-trash"></i> Bild entfernen
            </button>
            <input type="hidden" id="e-image-url">
        </div>
    </div>
    <div class="modal-footer">
        <button class="btn btn-ghost" onclick="closeModal()">Abbrechen</button>
        <button class="btn btn-primary" onclick="saveEntry()">
            <i class="fas fa-save"></i> Speichern
        </button>
    </div>
</div>
</div>

<!-- Toast container -->
<div class="toast-stack" id="toast-stack"></div>

<!-- Close icon dropdown on outside click -->
<!-- Close icon panel on outside click -->
<script>document.addEventListener('click', e => { if(!e.target.closest('.icon-picker-wrap')) { document.getElementById('icon-panel').classList.remove('open'); document.getElementById('prev-arrow').style.transform=''; } });</script>

<script>
/* ════════════════════════════════════════════════════════════════════════════
   Timeline CMS – Admin JavaScript
════════════════════════════════════════════════════════════════════════════ */
const API = 'timeline-api.php';
let allEntries = [];
let dragSrcId  = null;

// ─── TinyMCE Init ────────────────────────────────────────────────────────
tinymce.init({
    selector: '#e-content',
    skin: 'oxide-dark', content_css: 'dark',
    height: 220,
    menubar: false,
    toolbar_mode: 'sliding',
    plugins: 'lists link image code emoticons',
    toolbar: 'bold italic underline | bullist numlist | link | forecolor | emoticons | code',
    content_style: `
        body { font-family: DM Sans, sans-serif; font-size:14px;
               background:#1c2030; color:#e0e4f0; padding:8px 12px; }
        p { margin:0 0 .5rem; }
    `,
    setup(ed) {
        ed.on('change', () => ed.save());
    }
});

// ─── Icons ───────────────────────────────────────────────────────────────
// ─── Icons mit Kategorien ────────────────────────────────────────────────
const FA_ICONS = {
    'Allgemein':  [
        ['fas fa-star','Star'],['fas fa-heart','Heart'],['fas fa-bolt','Bolt'],
        ['fas fa-fire','Fire'],['fas fa-rocket','Rocket'],['fas fa-flag','Flag'],
        ['fas fa-thumbs-up','Like'],['fas fa-lightbulb','Idee'],['fas fa-crown','Crown'],
        ['fas fa-gem','Gem'],['fas fa-award','Award'],['fas fa-trophy','Trophy'],
    ],
    'Tech': [
        ['fas fa-laptop','Laptop'],['fas fa-mobile-alt','Mobil'],['fas fa-desktop','Desktop'],
        ['fas fa-server','Server'],['fas fa-database','Database'],['fas fa-code','Code'],
        ['fas fa-terminal','Terminal'],['fas fa-microchip','Chip'],['fas fa-wifi','Wifi'],
        ['fas fa-cloud','Cloud'],['fas fa-robot','Robot'],['fas fa-satellite','Satellite'],
        ['fas fa-tv','TV'],['fas fa-keyboard','Keyboard'],['fas fa-mouse','Mouse'],
        ['fas fa-hdd','HDD'],['fas fa-memory','RAM'],['fas fa-network-wired','Netzwerk'],
    ],
    'Business': [
        ['fas fa-chart-bar','Chart'],['fas fa-chart-line','Trend'],['fas fa-briefcase','Koffer'],
        ['fas fa-handshake','Deal'],['fas fa-dollar-sign','Dollar'],['fas fa-coins','Coins'],
        ['fas fa-piggy-bank','Sparen'],['fas fa-cash-register','Kasse'],['fas fa-receipt','Beleg'],
        ['fas fa-file-contract','Vertrag'],['fas fa-balance-scale','Waage'],['fas fa-building','Firma'],
    ],
    'Menschen': [
        ['fas fa-users','Team'],['fas fa-user-tie','Manager'],['fas fa-user-graduate','Abschluss'],
        ['fas fa-user-md','Arzt'],['fas fa-comments','Chat'],['fas fa-envelope','Mail'],
        ['fas fa-phone','Phone'],['fas fa-globe','Globe'],['fas fa-map-marker-alt','Ort'],
        ['fas fa-hands-helping','Helfen'],['fas fa-baby','Baby'],['fas fa-child','Kind'],
    ],
    'Medien': [
        ['fas fa-camera','Kamera'],['fas fa-film','Film'],['fas fa-music','Musik'],
        ['fas fa-palette','Design'],['fas fa-pen-nib','Schreiben'],['fas fa-book','Buch'],
        ['fas fa-newspaper','News'],['fas fa-photo-video','Foto/Video'],['fas fa-microphone','Mikrofon'],
        ['fas fa-headphones','Headphones'],['fas fa-podcast','Podcast'],['fas fa-broadcast-tower','Radio'],
    ],
    'Natur & Leben': [
        ['fas fa-leaf','Natur'],['fas fa-tree','Baum'],['fas fa-sun','Sonne'],
        ['fas fa-moon','Mond'],['fas fa-snowflake','Winter'],['fas fa-water','Wasser'],
        ['fas fa-mountain','Berg'],['fas fa-globe-europe','Erde'],['fas fa-car','Auto'],
        ['fas fa-plane','Flug'],['fas fa-ship','Schiff'],['fas fa-bicycle','Fahrrad'],
    ],
};

let currentCategory = 'Allgemein';
let currentIcon = 'fas fa-star';

function buildCategoryTabs() {
    const cats = document.getElementById('icon-cats');
    cats.innerHTML = Object.keys(FA_ICONS).map(cat =>
        `<button class="icon-cat-btn ${cat === currentCategory ? 'active' : ''}"
                 onclick="switchCategory('${cat}')">${cat}</button>`
    ).join('');
}

function switchCategory(cat) {
    currentCategory = cat;
    document.querySelectorAll('.icon-cat-btn').forEach(b =>
        b.classList.toggle('active', b.textContent === cat)
    );
    buildIconGrid('');
    document.getElementById('icon-search-inp').value = '';
}

function buildIconGrid(filter) {
    const grid = document.getElementById('icon-grid');
    let icons;
    if (filter && filter.trim()) {
        // Suche über alle Kategorien
        icons = Object.values(FA_ICONS).flat()
            .filter(([cls, lbl]) =>
                cls.toLowerCase().includes(filter.toLowerCase()) ||
                lbl.toLowerCase().includes(filter.toLowerCase())
            );
    } else {
        icons = FA_ICONS[currentCategory] || [];
    }
    if (!icons.length) {
        grid.innerHTML = '<div class="icon-empty"><i class="fas fa-search"></i><br>Kein Icon gefunden</div>';
        return;
    }
    grid.innerHTML = icons.map(([cls, lbl]) =>
        `<div class="icon-opt ${cls === currentIcon ? 'sel' : ''}" onclick="selectIcon('${cls}','${lbl}')">
            <i class="${cls}"></i>
            <span>${lbl}</span>
        </div>`
    ).join('');
}

function filterIcons(v) { buildIconGrid(v); }

function toggleIconPanel() {
    const panel = document.getElementById('icon-panel');
    const arrow = document.getElementById('prev-arrow');
    const isOpen = panel.classList.toggle('open');
    arrow.style.transform = isOpen ? 'rotate(180deg)' : '';
    if (isOpen) {
        switchIconTab('fa');
        buildCategoryTabs();
        buildIconGrid('');
        setTimeout(() => document.getElementById('icon-search-inp').focus(), 50);
    }
}

function selectIcon(cls, lbl) {
    currentIcon = cls;
    document.getElementById('e-icon').value = cls;
    document.getElementById('prev-icon-i').className = cls;
    document.getElementById('prev-icon-label').textContent = cls;
    document.getElementById('icon-panel').classList.remove('open');
    document.getElementById('prev-arrow').style.transform = '';
    buildIconGrid(document.getElementById('icon-search-inp').value);
}

function setIconPickerValue(cls) {
    currentIcon = cls || 'fas fa-star';
    document.getElementById('e-icon').value = currentIcon;
    if (currentIcon.trim().startsWith('<svg')) {
        // SVG – direkt ins prev-icon rendern
        document.querySelector('.prev-icon').innerHTML = currentIcon;
        document.querySelector('.prev-icon').style.color = '#fff';
        document.getElementById('prev-icon-label').textContent = 'Eigenes SVG';
    } else {
        document.querySelector('.prev-icon').innerHTML = `<i id="prev-icon-i" class="${currentIcon}"></i>`;
        document.getElementById('prev-icon-label').textContent = currentIcon;
    }
}

// ─── Icon Tab Switcher ────────────────────────────────────────────────────
function switchIconTab(tab) {
    document.getElementById('icon-tab-fa').style.display  = tab === 'fa'  ? 'block' : 'none';
    document.getElementById('icon-tab-svg').style.display = tab === 'svg' ? 'block' : 'none';
    document.getElementById('tab-fa').classList.toggle('active',  tab === 'fa');
    document.getElementById('tab-svg').classList.toggle('active', tab === 'svg');
}

// ─── SVG Upload ───────────────────────────────────────────────────────────
let pendingSVG = null;

function handleSVGFile(input) {
    const file = input.files[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = function(e) {
        let svg = e.target.result.trim();
        svg = svg.replace(/<\?xml[^>]*\?>/gi, '').trim();
        const match = svg.match(/<svg[\s\S]*<\/svg>/i);
        if (!match) { toast('Ungültige SVG-Datei!', 'error'); return; }
        svg = match[0].replace(/<svg/, '<svg style="width:100%;height:100%;fill:currentColor"');
        pendingSVG = svg;
        document.getElementById('svg-preview-icon').innerHTML = svg;
        document.getElementById('svg-preview-name').textContent = file.name;
        document.getElementById('svg-preview-wrap').style.display = 'block';
    };
    reader.readAsText(file);
}

function applySVGIcon() {
    if (!pendingSVG) return;
    currentIcon = pendingSVG;
    document.getElementById('e-icon').value = pendingSVG;
    document.querySelector('.prev-icon').innerHTML = pendingSVG;
    document.querySelector('.prev-icon').style.color = '#fff';
    document.getElementById('prev-icon-label').textContent = 'Eigenes SVG';
    document.getElementById('icon-panel').classList.remove('open');
    document.getElementById('prev-arrow').style.transform = '';
    document.getElementById('svg-file-inp').value = '';
    document.getElementById('svg-preview-wrap').style.display = 'none';
    pendingSVG = null;
    toast('SVG Icon gesetzt ✓');
}

// ─── Pane navigation ─────────────────────────────────────────────────────
const PANES = { entries:'Einträge verwalten', preview:'Live-Vorschau', json:'JSON Export' };
function switchPane(name) {
    Object.keys(PANES).forEach(p => {
        document.getElementById('pane-'+p).classList.toggle('active', p === name);
        document.getElementById('nav-'+p).classList.toggle('active', p === name);
    });
    document.getElementById('pane-title').textContent = PANES[name];
    if (name === 'preview') refreshPreview();
    if (name === 'json')    refreshJSON();
}

// ─── Toast ────────────────────────────────────────────────────────────────
function toast(msg, type = 'success') {
    const icons = { success:'fas fa-check-circle', error:'fas fa-exclamation-circle', info:'fas fa-info-circle' };
    const el = document.createElement('div');
    el.className = `toast ${type}`;
    el.innerHTML = `<i class="${icons[type] || icons.info} t-icon"></i> ${msg}`;
    document.getElementById('toast-stack').appendChild(el);
    setTimeout(() => {
        el.classList.add('out');
        setTimeout(() => el.remove(), 280);
    }, 3000);
}

// ─── Load entries ─────────────────────────────────────────────────────────
async function loadEntries() {
    const res = await fetch(`${API}?action=entries`);
    allEntries = await res.json();
    renderStats();
    renderList();
    document.getElementById('nav-badge').textContent = allEntries.length;
}

function renderStats() {
    document.getElementById('st-total').textContent  = allEntries.length;
    document.getElementById('st-active').textContent = allEntries.filter(e=>e.active).length;
    document.getElementById('st-imgs').textContent   = allEntries.filter(e=>e.image_url).length;
    document.getElementById('st-rev').textContent    = allEntries.filter(e=>e.is_reverse).length;
}

function renderList() {
    const list = document.getElementById('entry-list');
    if (!allEntries.length) {
        list.innerHTML = `<div class="empty-state"><i class="fas fa-stream"></i>Noch keine Einträge.<br>Leg deinen ersten Meilenstein an!</div>`;
        return;
    }
    list.innerHTML = allEntries.map(e => {
        const thumb = e.image_url
            ? `<div class="entry-thumb"><img src="${escAttr(e.image_url)}" alt=""></div>`
            : `<div class="entry-thumb" style="background:var(--accent)"><i class="${esc(e.icon)}"></i></div>`;
        const preview = (e.content || '').replace(/<[^>]+>/g,'').slice(0, 80) || '—';
        return `
        <div class="entry-card ${e.active?'':'inactive'}"
             draggable="true" data-id="${e.id}"
             ondragstart="dndStart(event,${e.id})"
             ondragover="dndOver(event)"
             ondrop="dndDrop(event,${e.id})"
             ondragleave="this.classList.remove('over')">
            <span class="drag-handle" title="Verschieben">⠿</span>
            ${thumb}
            <div class="entry-meta">
                <h3>${esc(e.title)} ${e.tag?`<span style="font-size:.72rem;color:var(--muted);font-weight:400;">${esc(e.tag)}</span>`:''}
                </h3>
                <div class="preview">${esc(preview)}</div>
                <div class="chips">
                    ${e.is_reverse?'<span class="chip rev"><i class="fas fa-exchange-alt"></i>Links</span>':''}
                    ${e.image_url ?'<span class="chip img"><i class="fas fa-image"></i>Bild</span>':''}
                    ${!e.active   ?'<span class="chip off"><i class="fas fa-eye-slash"></i>Versteckt</span>':''}
                    <span class="chip">#${e.sort_order}</span>
                </div>
            </div>
            <div class="entry-actions">
                <button class="btn btn-ghost btn-icon btn-sm" title="Bearbeiten" onclick="editEntry(${e.id})"><i class="fas fa-pen"></i></button>
                <button class="btn btn-ghost btn-icon btn-sm" title="${e.active?'Verbergen':'Einblenden'}" onclick="toggleActive(${e.id},${e.active?1:0})">
                    <i class="fas fa-${e.active?'eye-slash':'eye'}"></i>
                </button>
                <button class="btn btn-danger btn-icon btn-sm" title="Löschen" onclick="deleteEntry(${e.id})"><i class="fas fa-trash"></i></button>
            </div>
        </div>`;
    }).join('');
}

// ─── DnD Reorder ─────────────────────────────────────────────────────────
function dndStart(e, id) {
    dragSrcId = id;
    e.currentTarget.style.opacity = '.4';
    e.dataTransfer.effectAllowed = 'move';
}
function dndOver(e) {
    e.preventDefault();
    e.currentTarget.classList.add('over');
    e.dataTransfer.dropEffect = 'move';
}
async function dndDrop(e, targetId) {
    e.preventDefault();
    document.querySelectorAll('.entry-card').forEach(c => { c.classList.remove('over'); c.style.opacity=''; });
    if (dragSrcId === targetId) return;
    const si = allEntries.findIndex(x=>x.id==dragSrcId);
    const ti = allEntries.findIndex(x=>x.id==targetId);
    const [moved] = allEntries.splice(si, 1);
    allEntries.splice(ti, 0, moved);
    const payload = allEntries.map((x,i) => ({id:x.id, sort_order:i+1}));
    await fetch(`${API}?action=reorder`, { method:'PUT', headers:{'Content-Type':'application/json'}, body:JSON.stringify(payload) });
    toast('Reihenfolge gespeichert ✓');
    loadEntries();
}

// ─── Toggle active ────────────────────────────────────────────────────────
async function toggleActive(id, current) {
    await put(`entry&id=${id}`, { active: current ? 0 : 1 });
    loadEntries();
}

// ─── Delete ───────────────────────────────────────────────────────────────
async function deleteEntry(id) {
    if (!confirm('Eintrag wirklich löschen?')) return;
    await fetch(`${API}?action=entry&id=${id}`, { method:'DELETE' });
    toast('Gelöscht', 'info');
    loadEntries();
}

// ─── Modal ────────────────────────────────────────────────────────────────
function openModal(entry = null) {
    document.getElementById('modal-h').textContent  = entry ? 'Eintrag bearbeiten' : 'Neuer Eintrag';
    document.getElementById('e-id').value           = entry?.id ?? '';
    document.getElementById('e-title').value        = entry?.title ?? '';
    document.getElementById('e-tag').value          = entry?.tag   ?? '';
    document.getElementById('e-reverse').checked    = entry ? !!entry.is_reverse : false;
    document.getElementById('e-active').checked     = entry ? !!entry.active    : true;
    document.getElementById('e-image-url').value    = entry?.image_url ?? '';

    // Icon Picker
    setIconPickerValue(entry?.icon ?? 'fas fa-star');
    // Panel schliessen beim Öffnen
    document.getElementById('icon-panel').classList.remove('open');

    // TinyMCE content
    const ed = tinymce.get('e-content');
    if (ed) ed.setContent(entry?.content ?? '<p></p>');
    else document.getElementById('e-content').value = entry?.content ?? '';

    // Image preview
    const prev = document.getElementById('img-preview');
    const rem  = document.getElementById('img-remove');
    if (entry?.image_url) {
        prev.src = entry.image_url; prev.classList.add('show');
        rem.classList.add('show');
    } else {
        prev.src = ''; prev.classList.remove('show');
        rem.classList.remove('show');
    }

    document.getElementById('modal-backdrop').classList.add('open');
    setTimeout(() => document.getElementById('e-title').focus(), 50);
}
function closeModal() { document.getElementById('modal-backdrop').classList.remove('open'); }

function editEntry(id) { openModal(allEntries.find(e=>e.id==id)); }

async function saveEntry() {
    const id = document.getElementById('e-id').value;
    const ed = tinymce.get('e-content');
    const content = ed ? ed.getContent() : document.getElementById('e-content').value;
    const body = {
        title:      document.getElementById('e-title').value.trim(),
        tag:        document.getElementById('e-tag').value.trim(),
        icon:       document.getElementById('e-icon').value.trim() || 'fas fa-star',
        content,
        image_url:  document.getElementById('e-image-url').value || null,
        is_reverse: document.getElementById('e-reverse').checked ? 1 : 0,
        active:     document.getElementById('e-active').checked  ? 1 : 0,
    };
    if (!body.title) { toast('Titel ist Pflichtfeld!', 'error'); return; }
    if (id) { await put(`entry&id=${id}`, body); toast('Gespeichert ✓'); }
    else    { await post('entry', body);          toast('Erstellt ✓');   }
    closeModal();
    loadEntries();
}

// ─── Image Upload ─────────────────────────────────────────────────────────
function handleFileSelect(input) { uploadFile(input.files[0]); }
function handleDrop(e) {
    e.preventDefault();
    document.getElementById('upload-zone').classList.remove('over');
    uploadFile(e.dataTransfer.files[0]);
}
async function uploadFile(file) {
    if (!file) return;
    const fd = new FormData();
    fd.append('image', file);
    toast('Bild wird hochgeladen…', 'info');
    try {
        const res  = await fetch(`${API}?action=upload`, { method:'POST', body: fd });
        const data = await res.json();
        if (data.error) { toast(data.error, 'error'); return; }
        document.getElementById('e-image-url').value = data.url;
        const prev = document.getElementById('img-preview');
        prev.src = data.url; prev.classList.add('show');
        document.getElementById('img-remove').classList.add('show');
        toast('Bild hochgeladen ✓');
    } catch(e) { toast('Upload fehlgeschlagen', 'error'); }
}
function removeImage() {
    document.getElementById('e-image-url').value = '';
    const prev = document.getElementById('img-preview');
    prev.src = ''; prev.classList.remove('show');
    document.getElementById('img-remove').classList.remove('show');
}

// ─── Config ───────────────────────────────────────────────────────────────
// ─── Preview ──────────────────────────────────────────────────────────────
function refreshPreview() {
    document.getElementById('preview-iframe').src = 'index.html?t=' + Date.now();
}
function openPreviewTab() { window.open('index.html', '_blank'); }

// ─── JSON ─────────────────────────────────────────────────────────────────
async function refreshJSON() {
    const [cfgR, entR] = await Promise.all([
        fetch(`${API}?action=config`),
        fetch(`${API}?action=entries`)
    ]);
    const data = { config: await cfgR.json(), entries: await entR.json() };
    document.getElementById('json-box').textContent = JSON.stringify(data, null, 2);
}
function copyJSON() {
    navigator.clipboard.writeText(document.getElementById('json-box').textContent);
    toast('JSON kopiert ✓', 'info');
}
function downloadJSON() {
    const blob = new Blob([document.getElementById('json-box').textContent], {type:'application/json'});
    const a = Object.assign(document.createElement('a'), {href:URL.createObjectURL(blob), download:'timeline-export.json'});
    a.click();
}
async function importJSON(input) {
    const file = input.files[0]; if (!file) return;
    let data; try { data = JSON.parse(await file.text()); } catch { toast('Ungültiges JSON!','error'); return; }
    if (data.config) await put('config', data.config);
    if (data.entries) for (const e of data.entries) await post('entry', e);
    toast(`Import: ${data.entries?.length ?? 0} Einträge ✓`);
    loadEntries(); input.value='';
}

// ─── HTTP helpers ─────────────────────────────────────────────────────────
const hdrs = {'Content-Type':'application/json'};
async function put(act, body)  { return fetch(`${API}?action=${act}`, {method:'PUT',  headers:hdrs, body:JSON.stringify(body)}); }
async function post(act, body) { return fetch(`${API}?action=${act}`, {method:'POST', headers:hdrs, body:JSON.stringify(body)}); }

// ─── Helpers ──────────────────────────────────────────────────────────────
function esc(s)     { const d=document.createElement('div');d.textContent=s||'';return d.innerHTML; }
function escAttr(s) { return String(s||'').replace(/"/g,'&quot;'); }

// ─── Boot ─────────────────────────────────────────────────────────────────
loadEntries();
</script>
</body>
</html>