<?php
// ==================== CONFIG ====================
$ROOT = realpath($_SERVER['DOCUMENT_ROOT'] ?? __DIR__);

// ==================== HELPERS ====================
function safe_path($p) {
    global $ROOT;
    $p = str_replace(["\0", '\\'], ['', '/'], $p);
    $p = preg_replace('#/+#', '/', $p);
    if ($p === '' || $p[0] !== '/') $p = '/' . $p;
    $full = $ROOT . $p;
    $real = realpath($full);
    if ($real === false) {
        $parent = realpath(dirname($full));
        if ($parent === false || strpos($parent, $ROOT) !== 0) return false;
        return rtrim($parent, '/') . '/' . basename($full);
    }
    if (strpos($real, $ROOT) !== 0) return false;
    return $real;
}

function rel_path($abs) {
    global $ROOT;
    $rel = ltrim(str_replace($ROOT, '', str_replace('\\', '/', $abs)), '/');
    return $rel === '' ? '/' : '/' . $rel;
}

function fmt_size($b) {
    $b = max(0, $b);
    $u = ['B','KB','MB','GB','TB'];
    $p = $b ? floor(log($b) / log(1024)) : 0;
    return round($b / pow(1024, $p), 2) . ' ' . $u[min($p, 4)];
}

function perms_oct($p) {
    return substr(sprintf('%o', fileperms($p)), -4);
}

function ext_class($name) {
    $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
    $map = [
        'php'=>'php','js'=>'js','css'=>'css','html'=>'html','json'=>'json','xml'=>'xml',
        'md'=>'md','txt'=>'txt','log'=>'log','csv'=>'csv','sql'=>'sql',
        'jpg'=>'img','jpeg'=>'img','png'=>'img','gif'=>'img','svg'=>'img','webp'=>'img',
        'pdf'=>'pdf','zip'=>'arc','rar'=>'arc','tar'=>'arc','gz'=>'arc','7z'=>'arc',
        'mp4'=>'vid','webm'=>'vid','avi'=>'vid','mkv'=>'vid',
        'mp3'=>'aud','wav'=>'aud','ogg'=>'aud',
    ];
    return $map[$ext] ?? 'file';
}

function del_tree($d) {
    if (!file_exists($d)) return false;
    if (!is_dir($d)) return @unlink($d);
    foreach (scandir($d) as $f) {
        if ($f === '.' || $f === '..') continue;
        if (!del_tree($d . DIRECTORY_SEPARATOR . $f)) return false;
    }
    return @rmdir($d);
}

function msg($t, $m) { $_SESSION['msg'] = ['t' => $t, 'm' => $m]; }

// ==================== SESSION ====================
if (session_status() === PHP_SESSION_NONE) session_start();

// ==================== DOWNLOAD HANDLER ====================
if (isset($_GET['download'])) {
    $df = safe_path($_GET['download']);
    if ($df && is_file($df)) {
        $name = basename($df);
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . $name . '"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($df));
        readfile($df);
        exit;
    }
    http_response_code(404);
    die('File not found');
}

// ==================== CURRENT DIR ====================
$req_path = $_GET['p'] ?? '/';
$current = safe_path($req_path);
if ($current === false || !is_dir($current)) $current = $ROOT;
$current_rel = rel_path($current);

// ==================== POST ACTIONS ====================
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = $_POST['action'] ?? '';
    $target = isset($_POST['target']) ? safe_path($_POST['target']) : false;

    if ($action === 'upload' && $target && is_dir($target)) {
        $ok = 0; $fail = 0; $names = [];
        if (!empty($_FILES['files']['name'][0])) {
            foreach ($_FILES['files']['name'] as $i => $name) {
                if ($_FILES['files']['error'][$i] !== UPLOAD_ERR_OK) { $fail++; continue; }
                $dest = $target . '/' . basename($name);
                if (move_uploaded_file($_FILES['files']['tmp_name'][$i], $dest)) {
                    $ok++;
                    $names[] = $target . '/' . basename($name);
                } else {
                    $fail++;
                }
            }
        }
        // Build a full path message and redirect to the TARGET folder
        if ($ok > 0) {
            $target_rel = rel_path($target);
            $list = array_map('basename', $names);
            $details = "Uploaded to: " . $names[0] . (count($names) > 1 ? " (+" . (count($names)-1) . " more)" : "");
            msg($fail ? 'warn' : 'ok', $details);
        } else {
            msg('err', 'Upload failed');
        }
        // Always redirect to the target folder
        header('Location: ?p=' . urlencode(rel_path($target)));
        exit;
    }

    elseif ($action === 'mkdir' && $target && is_dir($target)) {
        $n = trim($_POST['name'] ?? '');
        if ($n === '' || $n === '.' || $n === '..') msg('err', 'Invalid name');
        elseif (file_exists($target . '/' . $n)) msg('err', 'Already exists');
        elseif (@mkdir($target . '/' . $n, 0755)) msg('ok', "Folder '$n' created");
        else msg('err', "Failed to create folder");
    }

    elseif ($action === 'touch' && $target && is_dir($target)) {
        $n = trim($_POST['name'] ?? '');
        if ($n === '') msg('err', 'Invalid name');
        elseif (file_exists($target . '/' . $n)) msg('err', 'Already exists');
        elseif (@file_put_contents($target . '/' . $n, '') !== false) msg('ok', "File '$n' created");
        else msg('err', 'Failed to create file');
    }

    elseif ($action === 'rename' && $target) {
        $nn = trim($_POST['new_name'] ?? '');
        $parent = dirname($target);
        if ($nn === '' || $nn === '.' || $nn === '..') msg('err', 'Invalid name');
        elseif (file_exists($parent . '/' . $nn)) msg('err', 'Name already exists');
        elseif (@rename($target, $parent . '/' . $nn)) msg('ok', 'Renamed');
        else msg('err', 'Rename failed');
    }

    elseif ($action === 'delete' && $target && $target !== $ROOT) {
        $name = basename($target);
        if (del_tree($target)) msg('ok', "Deleted '$name'");
        else msg('err', "Failed to delete '$name'");
    }

    elseif ($action === 'save' && $target && is_file($target)) {
        if (@file_put_contents($target, $_POST['content'] ?? '') !== false) msg('ok', 'Saved');
        else msg('err', 'Save failed');
    }

    $back = '?p=' . urlencode($current_rel);
    header('Location: ' . $back);
    exit;
}

// ==================== VIEW / EDIT MODE ====================
$editing = null;
$editing_content = '';
if (isset($_GET['view'])) {
    $vf = safe_path($_GET['view']);
    if ($vf && is_file($vf)) { $editing = $vf; $editing_content = file_get_contents($vf); }
}
if (isset($_GET['edit'])) {
    $ef = safe_path($_GET['edit']);
    if ($ef && is_file($ef)) { $editing = $ef; $editing_content = file_get_contents($ef); }
}

// ==================== FILE LIST ====================
$items = [];
foreach (scandir($current) as $e) {
    if ($e === '.' || $e === '..') continue;
    $full = $current . '/' . $e;
    $isDir = is_dir($full);
    $items[] = [
        'name' => $e,
        'abs'  => $full,
        'rel'  => rel_path($full),
        'is_dir' => $isDir,
        'size' => $isDir ? 0 : @filesize($full),
        'mtime' => @filemtime($full),
        'writable' => is_writable($full),
        'perms' => perms_oct($full),
    ];
}
usort($items, function($a, $b) {
    if ($a['is_dir'] !== $b['is_dir']) return $a['is_dir'] ? -1 : 1;
    return strcasecmp($a['name'], $b['name']);
});

$flash = $_SESSION['msg'] ?? null;
if ($flash) unset($_SESSION['msg']);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex,nofollow,noarchive">
<title>File Manager</title>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300..700&display=swap" rel="stylesheet">
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
:root {
    --bg: #000;
    --panel: #141414;
    --panel-2: #1a1a1a;
    --panel-3: #232323;
    --border: #2a2a2a;
    --text: #fff;
    --text-dim: #9a9a9a;
    --text-mute: #666;
    --accent: #00ff88;
    --accent-dim: #00cc6a;
    --danger: #ff4444;
    --warn: #ffaa00;
    --info: #4aa8ff;
}
body {
    font-family: "Space Grotesk", -apple-system, sans-serif;
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
    line-height: 1.5;
    font-size: 14px;
}
.wrap { max-width: 1400px; margin: 0 auto; padding: 20px; }

.topbar {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 16px;
    padding: 20px 28px;
    margin-bottom: 16px;
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: 12px;
}
.brand { display: flex; align-items: center; gap: 12px; }
.brand-logo {
    width: 40px; height: 40px;
    background: linear-gradient(135deg, var(--accent), #00ccff);
    border-radius: 10px;
    display: grid; place-items: center;
    font-size: 20px; color: #000;
}
.brand h1 { font-size: 20px; font-weight: 600; letter-spacing: -0.5px; }
.brand .sub { color: var(--text-dim); font-size: 12px; }
.stats { display: flex; gap: 20px; color: var(--text-dim); font-size: 13px; }
.stats span b { color: var(--text); font-weight: 500; }

.crumbs {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 12px 18px;
    margin-bottom: 16px;
    display: flex; align-items: center; flex-wrap: wrap; gap: 4px;
    font-size: 13px; overflow-x: auto;
}
.crumbs a, .crumbs .crumb {
    color: var(--text-dim);
    text-decoration: none;
    padding: 4px 10px;
    border-radius: 6px;
    transition: all .15s;
    white-space: nowrap;
}
.crumbs a:hover { background: var(--panel-3); color: var(--text); }
.crumbs .sep { color: var(--text-mute); }
.crumbs .current { color: var(--accent); font-weight: 500; }

.toolbar {
    display: flex; gap: 8px; flex-wrap: wrap;
    margin-bottom: 16px;
}
.btn {
    background: var(--panel-2);
    color: var(--text);
    border: 1px solid var(--border);
    padding: 9px 16px;
    border-radius: 10px;
    cursor: pointer;
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    transition: all .15s;
    display: inline-flex; align-items: center; gap: 6px;
    text-decoration: none;
}
.btn:hover { border-color: var(--accent); background: var(--panel-3); }
.btn-primary { background: var(--accent); color: #000; border-color: var(--accent); }
.btn-primary:hover { background: var(--accent-dim); }
.btn-danger { color: var(--danger); }
.btn-danger:hover { background: var(--danger); color: #fff; border-color: var(--danger); }
.btn-sm { padding: 5px 10px; font-size: 12px; border-radius: 6px; }

.flash {
    padding: 14px 18px;
    border-radius: 10px;
    margin-bottom: 16px;
    display: flex; align-items: flex-start; gap: 10px;
    font-size: 13px;
    animation: slide .25s ease;
}
.flash .path {
    font-family: ui-monospace, monospace;
    background: rgba(0,0,0,0.4);
    padding: 2px 8px;
    border-radius: 4px;
    color: var(--accent);
    word-break: break-all;
    margin-left: 4px;
}
@keyframes slide { from { opacity:0; transform: translateY(-6px); } to { opacity:1; transform:none; } }
.flash-ok { background: rgba(0,255,136,0.08); border: 1px solid rgba(0,255,136,0.3); color: var(--accent); }
.flash-err { background: rgba(255,68,68,0.08); border: 1px solid rgba(255,68,68,0.3); color: var(--danger); }
.flash-warn { background: rgba(255,170,0,0.08); border: 1px solid rgba(255,170,0,0.3); color: var(--warn); }

.card {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 16px;
    overflow: hidden;
}
table { width: 100%; border-collapse: collapse; }
th, td { padding: 12px 16px; text-align: left; }
th {
    background: var(--panel-2);
    color: var(--text-dim);
    font-weight: 500;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-bottom: 1px solid var(--border);
}
tbody tr { border-bottom: 1px solid var(--border); transition: background .12s; }
tbody tr:last-child { border-bottom: none; }
tbody tr:hover { background: var(--panel-2); }
td { font-size: 13px; color: var(--text-dim); }
td.name { color: var(--text); font-weight: 500; }
td.name a { color: inherit; text-decoration: none; display: flex; align-items: center; gap: 10px; }
td.name a:hover { color: var(--accent); }
td.actions { white-space: nowrap; text-align: right; }
td.actions form { display: inline-block; margin: 0 1px; }
.icon {
    display: inline-grid; place-items: center;
    width: 28px; height: 28px;
    background: var(--panel-3);
    border-radius: 6px;
    font-size: 14px;
    flex-shrink: 0;
}
.icon.dir { background: rgba(0,255,136,0.1); }
.icon.php { background: rgba(139,92,246,0.15); color: #b794f4; }
.icon.img { background: rgba(74,168,255,0.15); color: var(--info); }
.icon.pdf { background: rgba(255,68,68,0.15); color: var(--danger); }
.icon.arc { background: rgba(255,170,0,0.15); color: var(--warn); }
.icon.vid, .icon.aud { background: rgba(236,72,153,0.15); color: #f472b6; }
.icon.txt, .icon.md, .icon.log, .icon.csv, .icon.sql { background: rgba(255,255,255,0.05); }
.icon.json, .icon.xml { background: rgba(74,168,255,0.15); color: var(--info); }
.icon.html, .icon.css, .icon.js { background: rgba(0,255,136,0.1); }
.size { font-variant-numeric: tabular-nums; }
.perm { font-family: ui-monospace, monospace; font-size: 12px; }
.perm-r { color: var(--accent); }
.perm-ro { color: var(--warn); }

.empty { text-align: center; padding: 80px 20px; color: var(--text-mute); }
.empty .icon-lg { font-size: 48px; opacity: 0.3; margin-bottom: 12px; }

.modal-bg {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.75);
    backdrop-filter: blur(6px);
    z-index: 100;
    display: none;
    align-items: center; justify-content: center;
    padding: 20px;
}
.modal-bg.open { display: flex; }
.modal {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 16px;
    width: 100%; max-width: 480px;
    overflow: hidden;
    animation: pop .2s ease;
}
@keyframes pop { from { transform: scale(0.95); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.modal-head { padding: 18px 22px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 10px; font-weight: 600; }
.modal-body { padding: 20px 22px; }
.modal-foot { padding: 14px 22px; border-top: 1px solid var(--border); display: flex; gap: 8px; justify-content: flex-end; background: var(--panel-2); }
.modal label { display: block; font-size: 12px; color: var(--text-dim); margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.5px; }
.modal input[type="text"] {
    width: 100%;
    background: var(--bg);
    border: 1px solid var(--border);
    color: var(--text);
    padding: 10px 14px;
    border-radius: 8px;
    font-family: inherit;
    font-size: 14px;
}
.modal input[type="text"]:focus { outline: none; border-color: var(--accent); }
.modal textarea {
    width: 100%;
    min-height: 60vh;
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 14px;
    font-family: ui-monospace, "SF Mono", Monaco, monospace;
    font-size: 13px;
    line-height: 1.6;
    resize: vertical;
}
.modal textarea:focus { outline: none; border-color: var(--accent); }
.modal.lg { max-width: 900px; }
.dropzone {
    border: 2px dashed var(--border);
    border-radius: 12px;
    padding: 32px 20px;
    text-align: center;
    cursor: pointer;
    transition: all .15s;
    background: var(--bg);
}
.dropzone:hover, .dropzone.over { border-color: var(--accent); background: rgba(0,255,136,0.03); }
.dropzone .icon-lg { font-size: 40px; margin-bottom: 8px; opacity: 0.7; }
.dropzone input { display: none; }
.file-list { margin-top: 12px; max-height: 180px; overflow-y: auto; }
.file-item { display: flex; justify-content: space-between; padding: 8px 12px; background: var(--bg); border-radius: 6px; margin-bottom: 4px; font-size: 12px; }

.editor-head { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; }

@media (max-width: 768px) {
    .wrap { padding: 12px; }
    .topbar { padding: 16px 20px; }
    th, td { padding: 10px 12px; }
    .col-date, .col-perm { display: none; }
    td.name a { gap: 8px; }
}

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--panel-3); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--border); }
</style>
</head>
<body>
<div class="wrap">

<div class="topbar">
    <div class="brand">
        <div class="brand-logo">📂</div>
        <div>
            <h1>File Manager</h1>
            <div class="sub"><?= count($items) ?> item<?= count($items)!==1?'s':'' ?> • <?= fmt_size(disk_free_space($ROOT)) ?> free</div>
        </div>
    </div>
    <div class="stats">
        <span><b><?= php_sapi_name() ?></b></span>
        <span><b>PHP <?= PHP_VERSION ?></b></span>
    </div>
</div>

<?php if ($flash): ?>
<div class="flash flash-<?= htmlspecialchars($flash['t']) ?>">
    <span style="flex-shrink:0; margin-top:2px;"><?= $flash['t']==='ok'?'✓':($flash['t']==='err'?'✕':'⚠') ?></span>
    <div style="flex:1;"><?= htmlspecialchars($flash['m']) ?></div>
</div>
<?php endif; ?>

<div class="crumbs">
    <?php
    $parts = array_filter(explode('/', $current_rel));
    $acc = '';
    $first = true;
    foreach ($parts as $p):
        $acc .= '/' . $p;
        $isLast = ($acc === $current_rel);
        if (!$first) echo '<span class="sep">/</span>';
        $first = false;
        if ($isLast): ?>
            <span class="crumb current"><?= htmlspecialchars($p) ?></span>
        <?php else: ?>
            <a href="?p=<?= urlencode($acc) ?>"><?= htmlspecialchars($p) ?></a>
        <?php endif;
    endforeach;
    if (empty($parts)) echo '<span class="crumb current">/</span>';
    ?>
</div>

<div class="toolbar">
    <?php if ($current !== $ROOT):
        $parent_rel = dirname($current_rel);
        $parent_link = ($parent_rel === '.' || $parent_rel === '/' || $parent_rel === '\\') ? '/' : $parent_rel;
    ?>
        <a class="btn" href="?p=<?= urlencode($parent_link) ?>">⬆ Back</a>
    <?php endif; ?>
    <button class="btn btn-primary" onclick="openModal('m-mkdir')">📁 New Folder</button>
    <button class="btn btn-primary" onclick="openModal('m-touch')">📄 New File</button>
    <button class="btn btn-primary" onclick="openModal('m-upload')">⬆ Upload</button>
</div>

<div class="card">
<?php if (empty($items)): ?>
    <div class="empty">
        <div class="icon-lg">📂</div>
        <h3>This folder is empty</h3>
        <p>Create a new file or folder to get started</p>
    </div>
<?php else: ?>
<table>
<thead>
<tr>
    <th style="width: 50%;">Name</th>
    <th class="col-size">Size</th>
    <th class="col-date">Modified</th>
    <th class="col-perm">Perms</th>
    <th style="text-align: right;">Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($items as $it):
    $ext = ext_class($it['name']);
    $icon = $it['is_dir'] ? '📁' : (
        in_array($ext, ['img'])?'🖼':(in_array($ext,['pdf'])?'📕':(in_array($ext,['arc'])?'📦':(in_array($ext,['vid'])?'🎬':(in_array($ext,['aud'])?'🎵':(in_array($ext,['php'])?'🐘':(in_array($ext,['js','css','html'])?'🌐':(in_array($ext,['json','xml'])?'📋':'📄'))))))));
    $href = $it['is_dir'] ? '?p=' . urlencode($it['rel']) : '?p=' . urlencode($current_rel) . '&view=' . urlencode($it['rel']);
    $permClass = $it['writable'] ? 'perm-r' : 'perm-ro';
?>
<tr>
    <td class="name">
        <a href="<?= htmlspecialchars($href) ?>">
            <span class="icon <?= $it['is_dir']?'dir':htmlspecialchars($ext) ?>"><?= $icon ?></span>
            <span><?= htmlspecialchars($it['name']) ?><?= $it['is_dir'] ? '/' : '' ?></span>
        </a>
    </td>
    <td class="col-size size"><?= $it['is_dir'] ? '—' : fmt_size($it['size']) ?></td>
    <td class="col-date"><?= date('M j, Y H:i', $it['mtime']) ?></td>
    <td class="col-perm perm <?= $permClass ?>"><?= $it['perms'] ?></td>
    <td class="actions">
        <?php if (!$it['is_dir']): ?>
            <a class="btn btn-sm" href="?p=<?= urlencode($current_rel) ?>&edit=<?= urlencode($it['rel']) ?>">Edit</a>
            <a class="btn btn-sm" href="?p=<?= urlencode($current_rel) ?>&download=<?= urlencode($it['rel']) ?>">⬇ Download</a>
        <?php endif; ?>
        <button class="btn btn-sm" onclick="openRename('<?= htmlspecialchars(addslashes($it['name']), ENT_QUOTES) ?>', '<?= htmlspecialchars(addslashes($it['rel']), ENT_QUOTES) ?>')">Rename</button>
        <form method="post" style="display:inline" onsubmit="return confirm('Delete <?= htmlspecialchars(addslashes($it['name']), ENT_QUOTES) ?>? This cannot be undone.')">
            <input type="hidden" name="action" value="delete">
            <input type="hidden" name="target" value="<?= htmlspecialchars($it['rel']) ?>">
            <button class="btn btn-sm btn-danger" type="submit">Delete</button>
        </form>
    </td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>

</div><!-- /wrap -->

<!-- Modals -->
<div class="modal-bg" id="m-mkdir">
    <div class="modal">
        <div class="modal-head">📁 New Folder</div>
        <form method="post">
            <div class="modal-body">
                <input type="hidden" name="action" value="mkdir">
                <input type="hidden" name="target" value="<?= htmlspecialchars($current_rel) ?>">
                <label>Folder Name</label>
                <input type="text" name="name" required autofocus>
            </div>
            <div class="modal-foot">
                <button type="button" class="btn" onclick="closeModal('m-mkdir')">Cancel</button>
                <button type="submit" class="btn btn-primary">Create</button>
            </div>
        </form>
    </div>
</div>

<div class="modal-bg" id="m-touch">
    <div class="modal">
        <div class="modal-head">📄 New File</div>
        <form method="post">
            <div class="modal-body">
                <input type="hidden" name="action" value="touch">
                <input type="hidden" name="target" value="<?= htmlspecialchars($current_rel) ?>">
                <label>File Name</label>
                <input type="text" name="name" required autofocus placeholder="example.txt">
            </div>
            <div class="modal-foot">
                <button type="button" class="btn" onclick="closeModal('m-touch')">Cancel</button>
                <button type="submit" class="btn btn-primary">Create</button>
            </div>
        </form>
    </div>
</div>

<div class="modal-bg" id="m-rename">
    <div class="modal">
        <div class="modal-head">✏️ Rename</div>
        <form method="post">
            <div class="modal-body">
                <input type="hidden" name="action" value="rename">
                <input type="hidden" name="target" id="rename-target">
                <label>New Name</label>
                <input type="text" name="new_name" id="rename-input" required autofocus>
            </div>
            <div class="modal-foot">
                <button type="button" class="btn" onclick="closeModal('m-rename')">Cancel</button>
                <button type="submit" class="btn btn-primary">Rename</button>
            </div>
        </form>
    </div>
</div>

<div class="modal-bg" id="m-upload">
    <div class="modal">
        <div class="modal-head">⬆ Upload Files</div>
        <form method="post" enctype="multipart/form-data" id="upload-form">
            <div class="modal-body">
                <input type="hidden" name="action" value="upload">
                <input type="hidden" name="target" value="<?= htmlspecialchars($current_rel) ?>">
                <div class="dropzone" id="drop">
                    <div class="icon-lg">📤</div>
                    <p><b>Click to browse</b> or drag &amp; drop files</p>
                    <p style="color:var(--text-dim); font-size:12px; margin-top:6px;">Will be uploaded to: <code style="color:var(--accent);"><?= htmlspecialchars($current_rel) ?></code></p>
                    <input type="file" name="files[]" id="file-input" multiple>
                </div>
                <div class="file-list" id="file-list"></div>
            </div>
            <div class="modal-foot">
                <button type="button" class="btn" onclick="closeModal('m-upload')">Cancel</button>
                <button type="submit" class="btn btn-primary">Upload</button>
            </div>
        </form>
    </div>
</div>

<?php if ($editing): $isEdit = isset($_GET['edit']); ?>
<div class="modal-bg open" id="m-editor">
    <div class="modal lg">
        <div class="modal-head editor-head">
            <div>
                <?= $isEdit ? '✏️ Edit' : '👁 View' ?>: <?= htmlspecialchars(basename($editing)) ?>
                <small style="color:var(--text-dim); font-weight:400; margin-left:6px;"><?= fmt_size(filesize($editing)) ?></small>
            </div>
            <a class="btn btn-sm" href="?p=<?= urlencode($current_rel) ?>">✕ Close</a>
        </div>
        <form method="post">
            <div class="modal-body">
                <input type="hidden" name="action" value="save">
                <input type="hidden" name="target" value="<?= htmlspecialchars(rel_path($editing)) ?>">
                <textarea name="content" <?= $isEdit ? '' : 'readonly' ?> spellcheck="false"><?= htmlspecialchars($editing_content) ?></textarea>
            </div>
            <?php if ($isEdit): ?>
            <div class="modal-foot">
                <a class="btn" href="?p=<?= urlencode($current_rel) ?>">Cancel</a>
                <button type="submit" class="btn btn-primary">💾 Save</button>
            </div>
            <?php endif; ?>
        </form>
    </div>
</div>
<?php endif; ?>

<script>
function openModal(id) { document.getElementById(id).classList.add('open'); }
function closeModal(id) { document.getElementById(id).classList.remove('open'); }
function openRename(name, path) {
    document.getElementById('rename-target').value = path;
    document.getElementById('rename-input').value = name;
    openModal('m-rename');
    setTimeout(() => document.getElementById('rename-input').focus(), 50);
}
document.querySelectorAll('.modal-bg').forEach(m => {
    m.addEventListener('click', e => {
        if (e.target === m && m.id !== 'm-editor') m.classList.remove('open');
    });
});
document.addEventListener('keydown', e => {
    if (e.key === 'Escape') {
        document.querySelectorAll('.modal-bg.open').forEach(m => {
            if (m.id !== 'm-editor') m.classList.remove('open');
        });
    }
});

const drop = document.getElementById('drop');
const fi = document.getElementById('file-input');
const fl = document.getElementById('file-list');
if (drop) {
    drop.addEventListener('click', () => fi.click());
    ['dragover','dragenter'].forEach(ev => drop.addEventListener(ev, e => { e.preventDefault(); drop.classList.add('over'); }));
    ['dragleave','drop'].forEach(ev => drop.addEventListener(ev, () => drop.classList.remove('over')));
    drop.addEventListener('drop', e => {
        e.preventDefault();
        fi.files = e.dataTransfer.files;
        updateFiles();
    });
    fi.addEventListener('change', updateFiles);
}
function updateFiles() {
    fl.innerHTML = '';
    Array.from(fi.files).forEach(f => {
        const d = document.createElement('div');
        d.className = 'file-item';
        d.innerHTML = `<span>📄 ${f.name}</span><span style="color:var(--text-dim)">${(f.size/1024).toFixed(1)} KB</span>`;
        fl.appendChild(d);
    });
}
</script>
</body>
</html>
