<?php
$dbPath = __DIR__ . '/../database/tennis_club.sqlite';
$pdo = null;
try {
    $pdo = new PDO('sqlite:' . $dbPath);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->exec("CREATE TABLE IF NOT EXISTS messages (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, body TEXT, created_at INTEGER)");
    $pdo->exec("CREATE TABLE IF NOT EXISTS bookings (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, court TEXT, slot_date TEXT, slot_time TEXT, created_at INTEGER, UNIQUE(court, slot_date, slot_time))");
} catch (Exception $e) { $pdo = null; }

$name = isset($_COOKIE['tennis_name']) ? substr(trim($_COOKIE['tennis_name']), 0, 30) : '';
$ADMIN_PASSWORD = '123456';
$ADMIN_TOKEN = hash('sha256', 'baseline-admin-' . $ADMIN_PASSWORD);
$isAdmin = isset($_COOKIE['tennis_admin']) && hash_equals($ADMIN_TOKEN, $_COOKIE['tennis_admin']);

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (isset($_POST['set_name'])) {
        $n = trim($_POST['set_name']);
        if ($n !== '') {
            $n = substr($n, 0, 30);
            setcookie('tennis_name', $n, ['expires' => time() + 86400 * 60, 'path' => '/', 'secure' => true, 'samesite' => 'None']);
            $_COOKIE['tennis_name'] = $n;
            $name = $n;
        }
    }
    if (isset($_POST['logout'])) {
        setcookie('tennis_name', '', ['expires' => time() - 3600, 'path' => '/', 'secure' => true, 'samesite' => 'None']);
        unset($_COOKIE['tennis_name']);
        $name = '';
    }

    if (isset($_POST['admin_login'])) {
        $pw = $_POST['admin_password'] ?? '';
        if ($pw === $ADMIN_PASSWORD) {
            setcookie('tennis_admin', $ADMIN_TOKEN, ['expires' => time() + 86400, 'path' => '/', 'secure' => true, 'samesite' => 'None', 'httponly' => true]);
            $_COOKIE['tennis_admin'] = $ADMIN_TOKEN;
            $isAdmin = true;
            header("Location: ?page=admin");
            exit;
        } else {
            header("Location: ?page=admin&err=1");
            exit;
        }
    }
    if (isset($_POST['admin_logout'])) {
        setcookie('tennis_admin', '', ['expires' => time() - 3600, 'path' => '/', 'secure' => true, 'samesite' => 'None']);
        unset($_COOKIE['tennis_admin']);
        $isAdmin = false;
        header("Location: ?page=admin");
        exit;
    }

    if ($isAdmin && $pdo) {
        if (isset($_POST['admin_edit_msg_id'])) {
            try {
                $stmt = $pdo->prepare("UPDATE messages SET body = ? WHERE id = ?");
                $stmt->execute([substr(trim($_POST['admin_edit_msg_body'] ?? ''), 0, 500), (int)$_POST['admin_edit_msg_id']]);
            } catch (Exception $e) {}
            header("Location: ?page=admin#chats");
            exit;
        }
        if (isset($_POST['admin_delete_msg_id'])) {
            try {
                $stmt = $pdo->prepare("DELETE FROM messages WHERE id = ?");
                $stmt->execute([(int)$_POST['admin_delete_msg_id']]);
            } catch (Exception $e) {}
            header("Location: ?page=admin#chats");
            exit;
        }
        if (isset($_POST['admin_delete_booking_id'])) {
            try {
                $stmt = $pdo->prepare("DELETE FROM bookings WHERE id = ?");
                $stmt->execute([(int)$_POST['admin_delete_booking_id']]);
            } catch (Exception $e) {}
            header("Location: ?page=admin#bookings");
            exit;
        }
        if (isset($_POST['admin_rename_user'])) {
            $from = trim($_POST['admin_rename_from'] ?? '');
            $to = substr(trim($_POST['admin_rename_to'] ?? ''), 0, 30);
            if ($from !== '' && $to !== '') {
                try {
                    $s1 = $pdo->prepare("UPDATE messages SET name = ? WHERE name = ?");
                    $s1->execute([$to, $from]);
                    $s2 = $pdo->prepare("UPDATE bookings SET name = ? WHERE name = ?");
                    $s2->execute([$to, $from]);
                } catch (Exception $e) {}
            }
            header("Location: ?page=admin#users");
            exit;
        }
        if (isset($_POST['admin_purge_user'])) {
            $u = trim($_POST['admin_purge_user']);
            if ($u !== '') {
                try {
                    $pdo->prepare("DELETE FROM messages WHERE name = ?")->execute([$u]);
                    $pdo->prepare("DELETE FROM bookings WHERE name = ?")->execute([$u]);
                } catch (Exception $e) {}
            }
            header("Location: ?page=admin#users");
            exit;
        }
    }

    if ($pdo) {
        if (isset($_POST['message']) && $name !== '') {
            $msg = trim($_POST['message']);
            if ($msg !== '') {
                try {
                    $stmt = $pdo->prepare("INSERT INTO messages (name, body, created_at) VALUES (?, ?, ?)");
                    $stmt->execute([$name, substr($msg, 0, 500), time()]);
                } catch (Exception $e) {}
            }
        }
        if (isset($_POST['book']) && $name !== '' && !empty($_POST['court']) && !empty($_POST['slot_date']) && !empty($_POST['slot_time'])) {
            try {
                $stmt = $pdo->prepare("INSERT INTO bookings (name, court, slot_date, slot_time, created_at) VALUES (?, ?, ?, ?, ?)");
                $stmt->execute([$name, $_POST['court'], $_POST['slot_date'], $_POST['slot_time'], time()]);
            } catch (Exception $e) {}
        }
        if (isset($_POST['cancel_id']) && $name !== '') {
            try {
                $stmt = $pdo->prepare("DELETE FROM bookings WHERE id = ? AND name = ?");
                $stmt->execute([$_POST['cancel_id'], $name]);
            } catch (Exception $e) {}
        }
    }
    $anchor = isset($_POST['anchor']) ? '#' . $_POST['anchor'] : '';
    $redirect = $_SERVER['PHP_SELF'] . $anchor;
    header("Location: " . $redirect);
    exit;
}

if (isset($_GET['action']) && $_GET['action'] === 'messages') {
    header('Content-Type: application/json');
    if ($pdo) {
        try {
            $rows = $pdo->query("SELECT name, body, created_at FROM messages ORDER BY id DESC LIMIT 80")->fetchAll(PDO::FETCH_ASSOC);
            echo json_encode(array_reverse($rows));
        } catch (Exception $e) { echo json_encode([]); }
    } else {
        echo json_encode([]);
    }
    exit;
}

function e($s){ return htmlspecialchars($s ?? '', ENT_QUOTES, 'UTF-8'); }

function human_size($bytes){
    if ($bytes < 1024) return $bytes . ' B';
    $units = ['KB','MB','GB','TB'];
    $i = -1;
    do { $bytes /= 1024; $i++; } while ($bytes >= 1024 && $i < count($units)-1);
    return number_format($bytes, $bytes < 10 ? 2 : 1) . ' ' . $units[$i];
}

$page = $_GET['page'] ?? 'home';

$projectRoot = realpath(__DIR__ . '/..');
$webRoot = realpath(__DIR__);
$target = $projectRoot;

if ($page === 'files') {
    $reqPath = isset($_GET['path']) && $_GET['path'] !== '' ? $_GET['path'] : $projectRoot;
    $reqPath = str_replace('\\', '/', $reqPath);
    $resolved = realpath($reqPath);
    if ($resolved === false || !is_readable($resolved)) {
        $target = $projectRoot;
    } else {
        $target = $resolved;
    }
    if (isset($_GET['dl']) && is_file($target)) {
        $size = filesize($target);
        if ($size <= 50 * 1024 * 1024) {
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="' . basename($target) . '"');
            header('Content-Length: ' . $size);
            readfile($target);
            exit;
        }
    }
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= $page === 'files' ? 'Files / ' : ($page === 'admin' ? 'Admin / ' : '') ?>Baseline — A Tennis Club</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Bricolage+Grotesque:opsz,wght@12..96,300;12..96,400;12..96,500;12..96,600;12..96,700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
:root{
  --bg:#0b0c0a;
  --bg-2:#111210;
  --surface:#161815;
  --surface-2:#1d201c;
  --surface-3:#252925;
  --line:rgba(255,255,255,.07);
  --line-2:rgba(255,255,255,.13);
  --text:#eceae3;
  --dim:#9a9890;
  --dimmer:#5e5d56;
  --lime:#d4ff3a;
  --lime-2:#b6dd24;
  --lime-soft:rgba(212,255,58,.12);
  --clay:#f06a3a;
  --grass:#74c354;
  --hard:#5cb6d6;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{background:var(--bg);color:var(--text);font-family:'Bricolage Grotesque',sans-serif;font-size:16px;line-height:1.5;-webkit-font-smoothing:antialiased;font-feature-settings:"ss01","ss02"}
body{overflow-x:hidden;min-height:100vh}
.serif{font-family:'Instrument Serif',serif;letter-spacing:-.01em}
.mono{font-family:'JetBrains Mono',monospace}
::selection{background:var(--lime);color:#000}

body::before{
  content:'';position:fixed;inset:0;pointer-events:none;z-index:0;
  background:
    radial-gradient(800px 500px at 85% -5%, rgba(212,255,58,.06), transparent 60%),
    radial-gradient(700px 400px at -5% 100%, rgba(240,106,58,.04), transparent 60%);
}
body::after{
  content:'';position:fixed;inset:0;pointer-events:none;z-index:0;opacity:.4;
  background-image:radial-gradient(circle at 1px 1px, rgba(255,255,255,.025) 1px, transparent 0);
  background-size:24px 24px;
}

.container{max-width:1320px;margin:0 auto;padding:0 32px;position:relative;z-index:1}

nav.top{
  position:sticky;top:0;z-index:50;
  backdrop-filter:blur(20px) saturate(180%);
  background:rgba(11,12,10,.72);
  border-bottom:1px solid var(--line);
}
.nav-inner{display:flex;align-items:center;justify-content:space-between;padding:18px 0;gap:24px}
.brand{display:flex;align-items:center;gap:12px;text-decoration:none;color:var(--text)}
.brand-mark{
  width:36px;height:36px;border-radius:50%;
  background:radial-gradient(circle at 32% 30%, #e8ff5a, var(--lime) 55%, #95b81d 100%);
  position:relative;flex-shrink:0;
  box-shadow:0 0 0 1px rgba(212,255,58,.4), 0 8px 20px rgba(212,255,58,.25);
}
.brand-mark::before,.brand-mark::after{
  content:'';position:absolute;inset:0;border-radius:50%;
  border:1px solid rgba(255,255,255,.6);
  clip-path:polygon(0 30%, 100% 70%, 100% 75%, 0 35%);
}
.brand-mark::after{clip-path:polygon(0 25%, 100% 65%, 100% 60%, 0 20%);transform:rotate(180deg)}
.brand-text{display:flex;flex-direction:column;line-height:1}
.brand-name{font-family:'Instrument Serif',serif;font-size:22px;letter-spacing:-.01em}
.brand-sub{font-family:'JetBrains Mono',monospace;font-size:9.5px;text-transform:uppercase;letter-spacing:.22em;color:var(--dim);margin-top:3px}

.nav-links{display:flex;align-items:center;gap:4px}
.nav-links a{
  color:var(--dim);text-decoration:none;font-weight:500;font-size:13.5px;
  padding:8px 14px;border-radius:999px;transition:all .2s;
  display:inline-flex;align-items:center;gap:6px;
}
.nav-links a:hover{color:var(--text);background:var(--surface)}
.nav-links a.active{color:var(--lime);background:var(--lime-soft)}

.user-pill{
  display:inline-flex;align-items:center;gap:8px;
  background:var(--surface-2);border:1px solid var(--line-2);
  padding:6px 14px 6px 8px;border-radius:999px;font-size:13px;font-weight:500;
  color:var(--text);
}
.user-pill .av{
  width:22px;height:22px;border-radius:50%;font-size:11px;font-weight:600;
  display:flex;align-items:center;justify-content:center;color:#000;
  font-family:'Instrument Serif',serif;
}
.live-dot{width:7px;height:7px;border-radius:50%;background:var(--lime);box-shadow:0 0 8px var(--lime)}

.hero{padding:80px 0 60px;position:relative}
.hero-grid{display:grid;grid-template-columns:1.5fr 1fr;gap:60px;align-items:center}
.eyebrow{
  display:inline-flex;align-items:center;gap:10px;
  font-family:'JetBrains Mono',monospace;font-size:11.5px;text-transform:uppercase;
  letter-spacing:.18em;color:var(--lime);margin-bottom:32px;
  padding:6px 14px;border:1px solid rgba(212,255,58,.25);border-radius:999px;
  background:var(--lime-soft);
}
.eyebrow .pulse{width:6px;height:6px;border-radius:50%;background:var(--lime);box-shadow:0 0 10px var(--lime);animation:pulse 1.8s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.7)}}

.hero h1{
  font-family:'Instrument Serif',serif;font-weight:400;
  font-size:clamp(54px, 8.5vw, 120px);line-height:.92;
  letter-spacing:-.03em;margin-bottom:32px;
}
.hero h1 em{font-style:italic;color:var(--lime)}
.hero h1 .strike{position:relative;display:inline-block}
.hero h1 .strike::after{
  content:'';position:absolute;left:-2%;right:-2%;top:53%;height:3px;
  background:var(--clay);transform:rotate(-3deg);
}
.hero p.lead{font-size:18px;color:var(--dim);max-width:520px;margin-bottom:40px;line-height:1.55}

.hero-cta{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.btn{
  display:inline-flex;align-items:center;gap:10px;padding:14px 24px;
  border-radius:999px;font-weight:600;font-size:14.5px;text-decoration:none;
  border:none;cursor:pointer;transition:all .2s;font-family:inherit;
  white-space:nowrap;
}
.btn-primary{background:var(--lime);color:#0b0c0a;box-shadow:0 0 0 1px var(--lime), 0 12px 32px rgba(212,255,58,.25)}
.btn-primary:hover{background:#e1ff5a;transform:translateY(-2px);box-shadow:0 0 0 1px var(--lime), 0 16px 38px rgba(212,255,58,.35)}
.btn-ghost{background:transparent;color:var(--text);border:1px solid var(--line-2)}
.btn-ghost:hover{background:var(--surface);border-color:var(--text)}
.btn-arrow{display:inline-flex;width:24px;height:24px;border-radius:50%;background:rgba(0,0,0,.12);align-items:center;justify-content:center;transition:transform .2s}
.btn-primary:hover .btn-arrow{transform:translateX(4px)}

.court-illus{position:relative;aspect-ratio:3/4;max-width:380px;margin-left:auto}
.court-illus svg{width:100%;height:100%;filter:drop-shadow(0 30px 60px rgba(212,255,58,.15))}

.marquee{
  margin-top:60px;padding:24px 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  overflow:hidden;white-space:nowrap;
}
.marquee-track{display:inline-flex;gap:48px;animation:scroll 40s linear infinite}
.marquee-item{display:inline-flex;align-items:center;gap:14px;font-family:'Instrument Serif',serif;font-size:24px;color:var(--dim);font-style:italic}
.marquee-item::before{content:'●';color:var(--lime);font-size:10px;font-style:normal}
@keyframes scroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}

.bento{
  display:grid;grid-template-columns:repeat(4,1fr);gap:1px;
  background:var(--line);border-radius:24px;overflow:hidden;
  margin-top:60px;border:1px solid var(--line);
}
.bento-cell{background:var(--bg-2);padding:28px;position:relative}
.bento-cell .num{font-family:'Instrument Serif',serif;font-size:64px;line-height:1;letter-spacing:-.03em;color:var(--text);font-weight:400}
.bento-cell .num em{color:var(--lime);font-style:italic}
.bento-cell .lab{font-family:'JetBrains Mono',monospace;font-size:10.5px;text-transform:uppercase;letter-spacing:.14em;color:var(--dim);margin-top:12px;max-width:160px}
.bento-cell .corner{position:absolute;top:16px;right:16px;font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--dimmer)}

section{padding:120px 0;position:relative}
.section-head{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:48px;flex-wrap:wrap;gap:24px}
.section-head .tag{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--lime);letter-spacing:.18em;text-transform:uppercase;margin-bottom:14px;display:block}
.section-head h2{font-family:'Instrument Serif',serif;font-weight:400;font-size:clamp(40px,5.5vw,76px);line-height:1;letter-spacing:-.025em}
.section-head h2 em{color:var(--lime);font-style:italic}
.section-head p{color:var(--dim);max-width:380px;font-size:15px}

.name-gate{
  background:linear-gradient(135deg, var(--surface-2) 0%, var(--surface) 100%);
  border:1px solid var(--line-2);
  padding:36px 40px;border-radius:24px;margin-bottom:32px;
  display:flex;align-items:center;justify-content:space-between;gap:30px;flex-wrap:wrap;
  position:relative;overflow:hidden;
}
.name-gate::before{
  content:'';position:absolute;right:-80px;top:-80px;width:280px;height:280px;border-radius:50%;
  background:radial-gradient(circle at 35% 35%, var(--lime), transparent 70%);opacity:.08;
}
.name-gate > *{position:relative;z-index:1}
.name-gate h3{font-family:'Instrument Serif',serif;font-weight:400;font-size:30px;margin-bottom:6px}
.name-gate h3 em{color:var(--lime);font-style:italic}
.name-gate p{color:var(--dim);font-size:14px}
.name-gate form{display:flex;gap:8px;flex-wrap:wrap}
.name-gate input{
  padding:13px 20px;border-radius:999px;border:1px solid var(--line-2);
  font-family:inherit;font-size:14.5px;min-width:240px;
  background:var(--bg);color:var(--text);
}
.name-gate input:focus{outline:none;border-color:var(--lime);box-shadow:0 0 0 3px var(--lime-soft)}
.name-gate button{
  background:var(--lime);color:#000;padding:13px 26px;border-radius:999px;
  border:none;font-weight:600;font-family:inherit;cursor:pointer;transition:transform .15s;font-size:14.5px;
}
.name-gate button:hover{transform:translateY(-2px)}

.booking-wrap{
  background:var(--surface);border:1px solid var(--line);border-radius:28px;padding:36px;
  position:relative;overflow:hidden;
}
.day-tabs{display:flex;gap:6px;margin-bottom:28px;overflow-x:auto;padding-bottom:6px}
.day-tab{
  flex-shrink:0;background:var(--surface-2);border:1px solid var(--line);
  border-radius:14px;padding:14px 18px;cursor:pointer;text-align:left;
  min-width:90px;transition:all .2s;font-family:inherit;color:var(--text);
}
.day-tab:hover{border-color:var(--line-2);background:var(--surface-3)}
.day-tab.active{background:var(--lime);color:#000;border-color:var(--lime)}
.day-tab .lab{font-family:'JetBrains Mono',monospace;font-size:9.5px;text-transform:uppercase;letter-spacing:.12em;opacity:.6}
.day-tab .num{font-family:'Instrument Serif',serif;font-size:30px;font-weight:400;line-height:1.05;margin-top:2px}
.day-tab .mon{font-size:11px;opacity:.6;font-family:'JetBrains Mono',monospace}

.court-legend{display:flex;gap:20px;margin-bottom:16px;flex-wrap:wrap;font-size:12px;color:var(--dim);font-family:'JetBrains Mono',monospace;text-transform:uppercase;letter-spacing:.1em}
.swatch{display:inline-flex;align-items:center;gap:8px}
.swatch i{width:10px;height:10px;border-radius:3px;display:inline-block}
.sw-clay{background:var(--clay)}
.sw-grass{background:var(--grass)}
.sw-hard{background:var(--hard)}
.sw-mine{background:var(--lime)}

.slots-grid{display:grid;grid-template-columns:84px repeat(3,1fr);gap:6px}
.slots-grid .header-cell{
  padding:14px 10px;text-align:center;font-family:'JetBrains Mono',monospace;
  font-size:10.5px;text-transform:uppercase;letter-spacing:.14em;color:var(--dim);
}
.slots-grid .time-label{
  padding:18px 8px;font-family:'Instrument Serif',serif;font-size:20px;
  display:flex;align-items:center;justify-content:center;color:var(--dim);
}
.slot{
  background:var(--surface-2);border:1px solid var(--line);border-radius:14px;
  padding:14px 14px;min-height:68px;display:flex;flex-direction:column;justify-content:center;gap:3px;
  transition:all .15s;cursor:pointer;font-family:inherit;color:var(--text);text-align:left;position:relative;overflow:hidden;
}
.slot:hover{transform:translateY(-1px);border-color:var(--line-2)}
.slot.available{border-style:dashed;background:transparent;border-color:rgba(255,255,255,.08)}
.slot.available:hover{border-style:solid;border-color:var(--lime);background:var(--lime-soft)}
.slot.available .lab-book{font-size:12px;color:var(--lime);font-weight:600;font-family:'JetBrains Mono',monospace;text-transform:uppercase;letter-spacing:.1em}
.slot.available .ct{font-family:'JetBrains Mono',monospace;font-size:10px;text-transform:uppercase;letter-spacing:.1em;color:var(--dimmer)}
.slot.booked{cursor:default}
.slot.booked .who{font-weight:600;font-size:14px;color:var(--text)}
.slot.booked .ct{font-family:'JetBrains Mono',monospace;font-size:10px;text-transform:uppercase;letter-spacing:.1em;color:var(--dim)}
.slot.mine{background:linear-gradient(135deg, rgba(212,255,58,.18), rgba(212,255,58,.06));border-color:rgba(212,255,58,.4)}
.slot.mine .who{color:var(--lime)}
.slot.mine .who::after{content:' (you)';color:var(--dim);font-weight:400;font-size:11.5px}
.slot.mine::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--lime)}
.slot .cancel{font-size:11px;color:var(--clay);text-decoration:underline;background:none;border:none;cursor:pointer;padding:0;font-family:'JetBrains Mono',monospace;align-self:flex-start;margin-top:2px;text-transform:uppercase;letter-spacing:.08em}

.modal-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.7);backdrop-filter:blur(10px);z-index:100;display:none;align-items:center;justify-content:center;padding:20px}
.modal-backdrop.open{display:flex;animation:fade .2s}
@keyframes fade{from{opacity:0}to{opacity:1}}
.modal{background:var(--surface);border:1px solid var(--line-2);border-radius:24px;padding:36px;max-width:460px;width:100%;position:relative;animation:pop .25s}
@keyframes pop{from{transform:scale(.94) translateY(10px);opacity:0}to{transform:scale(1) translateY(0);opacity:1}}
.modal h3{font-family:'Instrument Serif',serif;font-weight:400;font-size:32px;letter-spacing:-.02em;margin-bottom:8px}
.modal h3 em{color:var(--lime);font-style:italic}
.modal .sub{color:var(--dim);margin-bottom:28px;font-family:'JetBrains Mono',monospace;font-size:12px;text-transform:uppercase;letter-spacing:.12em}
.modal label{display:block;font-family:'JetBrains Mono',monospace;font-size:10.5px;text-transform:uppercase;letter-spacing:.14em;color:var(--dim);margin-bottom:10px}
.court-picker{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:28px}
.court-opt{padding:18px 10px;border:1px solid var(--line-2);border-radius:14px;cursor:pointer;text-align:center;transition:all .2s;background:var(--surface-2);color:var(--text)}
.court-opt:hover{border-color:var(--text)}
.court-opt.selected{background:var(--lime);color:#000;border-color:var(--lime)}
.court-opt .nm{font-family:'Instrument Serif',serif;font-size:18px}
.modal-actions{display:flex;gap:10px;justify-content:flex-end}
.modal .close{position:absolute;right:18px;top:18px;background:none;border:none;cursor:pointer;font-size:18px;color:var(--dim);width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;transition:background .2s}
.modal .close:hover{background:var(--surface-2);color:var(--text)}

.chat-wrap{
  background:var(--surface);border:1px solid var(--line);border-radius:28px;overflow:hidden;
}
.chat-header{padding:24px 30px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:center}
.chat-header h3{font-family:'Instrument Serif',serif;font-weight:400;font-size:24px}
.chat-header h3 em{color:var(--lime);font-style:italic}
.chat-header .live{display:flex;align-items:center;gap:8px;font-family:'JetBrains Mono',monospace;font-size:10.5px;text-transform:uppercase;letter-spacing:.14em;color:var(--lime)}
.chat-body{height:480px;overflow-y:auto;padding:28px 30px;display:flex;flex-direction:column;gap:20px}
.chat-body::-webkit-scrollbar{width:6px}
.chat-body::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:3px}
.msg{display:flex;gap:14px;align-items:flex-start;max-width:78%}
.msg.mine{flex-direction:row-reverse;align-self:flex-end}
.avatar{width:38px;height:38px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:600;font-size:14px;color:#000;flex-shrink:0;font-family:'Instrument Serif',serif}
.msg-bubble{background:var(--surface-2);border:1px solid var(--line);padding:12px 18px;border-radius:18px;border-top-left-radius:4px;font-size:14.5px;color:var(--text)}
.msg.mine .msg-bubble{background:var(--lime);color:#000;border-color:var(--lime);border-top-left-radius:18px;border-top-right-radius:4px}
.msg-meta{font-family:'JetBrains Mono',monospace;font-size:10px;text-transform:uppercase;letter-spacing:.12em;color:var(--dim);margin-bottom:6px}
.msg.mine .msg-meta{text-align:right}
.msg-body{word-break:break-word;line-height:1.5}
.chat-empty{text-align:center;padding:50px 20px;color:var(--dim);font-family:'Instrument Serif',serif;font-style:italic;font-size:20px}
.chat-form{display:flex;gap:10px;padding:18px 22px;border-top:1px solid var(--line);background:var(--bg-2)}
.chat-form input{flex:1;border:1px solid var(--line-2);background:var(--surface);padding:14px 20px;border-radius:999px;font-family:inherit;font-size:14.5px;color:var(--text)}
.chat-form input:focus{outline:none;border-color:var(--lime);box-shadow:0 0 0 3px var(--lime-soft)}
.chat-form button{background:var(--lime);color:#000;border:none;padding:0 26px;border-radius:999px;font-weight:600;cursor:pointer;font-family:inherit;font-size:14px;transition:transform .15s}
.chat-form button:hover{transform:translateY(-1px)}
.chat-form.locked input{opacity:.5}

.rules-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}
.rule-card{background:var(--surface);border:1px solid var(--line);border-radius:20px;padding:28px;position:relative;overflow:hidden;transition:all .25s}
.rule-card:hover{border-color:var(--line-2);transform:translateY(-3px)}
.rule-card .ix{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--lime);letter-spacing:.16em;margin-bottom:14px;display:block}
.rule-card h4{font-family:'Instrument Serif',serif;font-weight:400;font-size:24px;letter-spacing:-.01em;margin-bottom:10px}
.rule-card p{color:var(--dim);font-size:14.5px;line-height:1.55}

footer{padding:80px 0 50px;border-top:1px solid var(--line);margin-top:80px;color:var(--dim);font-size:13.5px}
.foot-grid{display:flex;justify-content:space-between;align-items:flex-end;gap:30px;flex-wrap:wrap}
.foot-grid h4{font-family:'Instrument Serif',serif;font-weight:400;font-size:48px;color:var(--text);letter-spacing:-.02em;margin-bottom:14px;line-height:1}
.foot-grid h4 em{color:var(--lime);font-style:italic}
.foot-right{text-align:right;font-family:'JetBrains Mono',monospace;font-size:11.5px;text-transform:uppercase;letter-spacing:.12em}
.foot-right .signout{background:none;border:none;color:var(--clay);cursor:pointer;font-family:inherit;font-size:11.5px;text-transform:uppercase;letter-spacing:.12em;text-decoration:underline}

.subpage-hero{padding:80px 0 40px}
.subpage-hero h1{font-family:'Instrument Serif',serif;font-weight:400;font-size:clamp(48px,7vw,96px);letter-spacing:-.03em;line-height:.95;margin-bottom:18px}
.subpage-hero h1 em{color:var(--lime);font-style:italic}
.subpage-hero p{color:var(--dim);font-size:17px;max-width:580px;line-height:1.55}

.crumbs{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin:36px 0 22px;font-family:'JetBrains Mono',monospace;font-size:12.5px}
.crumbs a{color:var(--dim);text-decoration:none;padding:7px 12px;border-radius:8px;background:var(--surface);border:1px solid var(--line);transition:all .15s}
.crumbs a:hover{color:var(--text);border-color:var(--line-2)}
.crumbs a.up{background:var(--lime);color:#000;border-color:var(--lime)}
.crumbs a.up:hover{background:#e1ff5a}
.crumbs a.project{background:var(--surface-2);color:var(--lime);border-color:var(--line-2)}
.crumbs .sep{color:var(--dimmer)}
.crumbs .here{color:var(--text);padding:7px 12px;background:var(--surface-2);border:1px solid var(--line-2);border-radius:8px}

.file-panel{background:var(--surface);border:1px solid var(--line);border-radius:20px;overflow:hidden}
.file-panel-head{padding:20px 28px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:12px;background:var(--bg-2)}
.file-panel-head h3{font-family:'Instrument Serif',serif;font-weight:400;font-size:22px}
.file-panel-head .meta{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--dim);text-transform:uppercase;letter-spacing:.12em}
.file-list{list-style:none}
.file-row{display:grid;grid-template-columns:24px 1fr 110px 180px;align-items:center;gap:16px;padding:14px 28px;border-bottom:1px solid var(--line);transition:background .12s;text-decoration:none;color:var(--text)}
.file-row:last-child{border-bottom:none}
.file-row:hover{background:var(--surface-2)}
.file-row .ico{font-family:'JetBrains Mono',monospace;color:var(--lime);text-align:center;font-size:14px}
.file-row .nm{font-weight:500;word-break:break-all;font-size:14.5px}
.file-row .nm.dir{color:var(--lime)}
.file-row .sz{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--dim);text-align:right}
.file-row .mt{font-family:'JetBrains Mono',monospace;font-size:11.5px;color:var(--dimmer);text-align:right}
.parent-row{background:var(--surface-2)}
.parent-row .nm{color:var(--lime);font-weight:600}
.empty-dir{padding:60px 26px;text-align:center;color:var(--dim);font-family:'Instrument Serif',serif;font-style:italic;font-size:19px}
.file-view{background:var(--surface);border:1px solid var(--line);border-radius:20px;overflow:hidden}
.file-view-head{padding:20px 28px;background:var(--bg-2);border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:14px}
.file-view-head .nm{font-family:'JetBrains Mono',monospace;font-size:14px;word-break:break-all;color:var(--text)}
.file-view-head .actions{display:flex;gap:8px}
.file-view-head .actions a{background:var(--lime);color:#000;padding:8px 16px;border-radius:999px;text-decoration:none;font-size:12.5px;font-weight:600;transition:transform .15s}
.file-view-head .actions a:hover{transform:translateY(-1px)}
.file-view-head .actions a.ghost{background:var(--surface-2);color:var(--text);border:1px solid var(--line-2)}
.file-view pre{margin:0;padding:28px;font-family:'JetBrains Mono',monospace;font-size:12.5px;line-height:1.65;color:var(--text);overflow:auto;max-height:75vh;background:var(--bg);white-space:pre;tab-size:4}
.file-view .img-wrap{padding:40px;text-align:center;background:repeating-conic-gradient(var(--bg-2) 0% 25%, var(--surface) 0% 50%) 50%/24px 24px}
.file-view .img-wrap img{max-width:100%;max-height:75vh;border-radius:8px;box-shadow:0 10px 40px rgba(0,0,0,.5)}
.file-view .binary-note{padding:60px 26px;text-align:center;color:var(--dim)}
.file-view .binary-note .big{font-size:36px;margin-bottom:14px;color:var(--lime)}

.admin-hero{padding:80px 0 30px;position:relative}
.admin-hero .badge{display:inline-flex;align-items:center;gap:8px;background:var(--lime);color:#000;padding:8px 16px;border-radius:999px;font-family:'JetBrains Mono',monospace;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.16em;margin-bottom:24px}
.admin-hero h1{font-family:'Instrument Serif',serif;font-weight:400;font-size:clamp(48px,7vw,96px);letter-spacing:-.03em;line-height:.95;margin-bottom:18px}
.admin-hero h1 em{color:var(--lime);font-style:italic}
.admin-hero p{color:var(--dim);font-size:17px;max-width:580px}

.login-card{max-width:460px;margin:50px auto 0;background:var(--surface);border:1px solid var(--line-2);border-radius:20px;padding:40px;box-shadow:0 40px 80px -30px rgba(0,0,0,.6)}
.login-card h3{font-family:'Instrument Serif',serif;font-weight:400;font-size:30px;letter-spacing:-.02em;margin-bottom:8px}
.login-card h3 em{color:var(--lime);font-style:italic}
.login-card .sub{color:var(--dim);font-size:14px;margin-bottom:26px}
.login-card label{display:block;font-family:'JetBrains Mono',monospace;font-size:10.5px;text-transform:uppercase;letter-spacing:.14em;color:var(--dim);margin-bottom:10px}
.login-card input{width:100%;padding:14px 18px;border:1px solid var(--line-2);border-radius:12px;font-family:inherit;font-size:15px;color:var(--text);background:var(--bg);margin-bottom:18px}
.login-card input:focus{outline:none;border-color:var(--lime);box-shadow:0 0 0 3px var(--lime-soft)}
.login-card button{width:100%;background:var(--lime);color:#000;border:none;padding:15px;border-radius:12px;font-weight:600;cursor:pointer;font-family:inherit;font-size:15px;transition:transform .15s}
.login-card button:hover{transform:translateY(-1px)}
.login-err{background:rgba(240,106,58,.12);color:var(--clay);padding:12px 16px;border-radius:10px;font-size:13.5px;margin-bottom:18px;border-left:3px solid var(--clay)}
.login-hint{font-size:11px;color:var(--dimmer);text-align:center;margin-top:14px;font-family:'JetBrains Mono',monospace;letter-spacing:.12em;text-transform:uppercase}

.admin-toolbar{display:flex;gap:4px;flex-wrap:wrap;margin-bottom:30px;padding:8px;background:var(--surface);border:1px solid var(--line);border-radius:16px;align-items:center}
.admin-toolbar a{padding:10px 18px;border-radius:10px;text-decoration:none;color:var(--dim);font-weight:500;font-size:13.5px;transition:all .15s}
.admin-toolbar a:hover{background:var(--surface-2);color:var(--text)}
.admin-toolbar a.active{background:var(--lime);color:#000}
.admin-toolbar .spacer{flex:1}
.admin-toolbar form{margin:0}
.admin-toolbar button.logout{background:transparent;color:var(--clay);border:1px solid var(--line-2);padding:9px 16px;border-radius:10px;font-weight:500;cursor:pointer;font-family:inherit;font-size:12.5px;transition:all .15s}
.admin-toolbar button.logout:hover{background:var(--clay);color:#fff;border-color:var(--clay)}

.admin-section{background:var(--surface);border:1px solid var(--line);border-radius:20px;overflow:hidden;margin-bottom:24px}
.admin-section-head{padding:22px 30px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:12px;background:var(--bg-2)}
.admin-section-head h3{font-family:'Instrument Serif',serif;font-weight:400;font-size:24px;letter-spacing:-.01em}
.admin-section-head h3 em{color:var(--lime);font-style:italic}
.admin-section-head .meta{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--dim);text-transform:uppercase;letter-spacing:.12em}

.admin-overview-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line)}
.admin-overview-cell{background:var(--surface);padding:28px}
.admin-overview-cell .num{font-family:'Instrument Serif',serif;font-size:52px;line-height:1;letter-spacing:-.02em}
.admin-overview-cell .num em{color:var(--lime);font-style:italic}
.admin-overview-cell .lab{font-family:'JetBrains Mono',monospace;font-size:10.5px;text-transform:uppercase;letter-spacing:.14em;color:var(--dim);margin-top:12px}

.admin-table{width:100%;border-collapse:collapse}
.admin-table th{text-align:left;padding:14px 22px;font-family:'JetBrains Mono',monospace;font-size:10.5px;text-transform:uppercase;letter-spacing:.14em;color:var(--dim);background:var(--bg-2);border-bottom:1px solid var(--line)}
.admin-table td{padding:16px 22px;border-bottom:1px solid var(--line);vertical-align:top;font-size:14px;color:var(--text)}
.admin-table tr:last-child td{border-bottom:none}
.admin-table tr:hover td{background:var(--surface-2)}
.admin-table .num-cell{font-family:'JetBrains Mono',monospace;color:var(--dim);font-size:12px}
.admin-table .name-cell{font-weight:600}
.admin-table .body-cell{color:var(--text);word-break:break-word;max-width:420px}
.admin-table .actions-cell{white-space:nowrap;text-align:right}
.admin-btn{display:inline-block;padding:6px 12px;border-radius:8px;font-family:inherit;font-size:11.5px;font-weight:500;cursor:pointer;border:1px solid var(--line-2);background:var(--surface-2);color:var(--text);text-decoration:none;margin-left:4px;transition:all .15s}
.admin-btn:hover{background:var(--surface-3);border-color:var(--text)}
.admin-btn.danger{color:var(--clay);border-color:rgba(240,106,58,.3)}
.admin-btn.danger:hover{background:var(--clay);color:#fff;border-color:var(--clay)}
.admin-btn.primary{background:var(--lime);color:#000;border-color:var(--lime)}
.admin-btn.primary:hover{background:#e1ff5a;border-color:#e1ff5a}
.admin-empty{padding:50px 20px;text-align:center;color:var(--dim);font-family:'Instrument Serif',serif;font-style:italic;font-size:19px}
.edit-form{display:flex;gap:6px;align-items:center}
.edit-form input{flex:1;padding:8px 12px;border:1px solid var(--line-2);border-radius:8px;font-family:inherit;font-size:13px;background:var(--bg);color:var(--text)}
.edit-form input:focus{outline:none;border-color:var(--lime)}

.user-card{display:flex;align-items:center;gap:16px;padding:18px 24px;border-bottom:1px solid var(--line);flex-wrap:wrap}
.user-card:last-child{border-bottom:none}
.user-card:hover{background:var(--surface-2)}
.user-card .av{width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:600;color:#000;font-family:'Instrument Serif',serif;font-size:17px;flex-shrink:0}
.user-card .uinfo{flex:1;min-width:180px}
.user-card .uinfo .nm{font-weight:600;font-size:15.5px;color:var(--text)}
.user-card .uinfo .st{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--dim);text-transform:uppercase;letter-spacing:.1em;margin-top:4px}
.user-card .uactions{display:flex;gap:6px;flex-wrap:wrap}
.user-card .uactions form{display:flex;gap:6px;align-items:center;margin:0}
.user-card .uactions input{padding:8px 12px;border:1px solid var(--line-2);border-radius:8px;font-family:inherit;font-size:13px;background:var(--bg);color:var(--text);width:140px}
.user-card .uactions input:focus{outline:none;border-color:var(--lime)}

@media (max-width: 900px){
  .hero-grid{grid-template-columns:1fr;gap:40px}
  .court-illus{max-width:300px;margin:0 auto}
  .bento{grid-template-columns:repeat(2,1fr)}
  .slots-grid{grid-template-columns:60px repeat(3,1fr);gap:5px}
  .slot{padding:10px 8px;min-height:62px}
  .slots-grid .time-label{font-size:16px;padding:14px 4px}
  .nav-links a:not(.user-pill){font-size:12.5px;padding:7px 10px}
  .name-gate{padding:28px}
  .file-row{grid-template-columns:24px 1fr 80px;gap:10px;padding:12px 18px}
  .file-row .mt{display:none}
  .admin-table th:nth-child(1),.admin-table td:nth-child(1){display:none}
  .admin-table td,.admin-table th{padding:10px 14px}
  .admin-overview-grid{grid-template-columns:repeat(2,1fr)}
}
@media (max-width: 560px){
  .container{padding:0 20px}
  section{padding:70px 0}
  .hero{padding:50px 0 30px}
  .slot .ct{display:none}
  .slot.booked .who{font-size:12.5px}
  .nav-links{gap:2px}
  .brand-sub{display:none}
}
</style>
</head>
<body>

<nav class="top">
  <div class="container nav-inner">
    <a href="/" class="brand">
      <span class="brand-mark"></span>
      <span class="brand-text">
        <span class="brand-name">Baseline</span>
        <span class="brand-sub">Tennis · Est. 1998</span>
      </span>
    </a>
    <div class="nav-links">
      <a href="/#courts" class="<?= $page==='home'?'active':'' ?>">Courts</a>
      <a href="/#clubhouse">Lounge</a>
      <a href="?page=files" class="<?= $page==='files'?'active':'' ?>">Files</a>
      <a href="?page=admin" class="<?= $page==='admin'?'active':'' ?>">Admin</a>
      <?php if ($name):
        $hue = crc32($name) % 360;
        $initial = strtoupper(mb_substr($name, 0, 1));
      ?>
        <div class="user-pill"><span class="av" style="background:hsl(<?= $hue ?>,70%,60%)"><?= e($initial) ?></span><?= e($name) ?></div>
      <?php endif; ?>
    </div>
  </div>
</nav>

<?php if ($page === 'admin'): ?>

<header class="admin-hero">
  <div class="container">
    <div class="badge">● Restricted · Staff Only</div>
    <h1>Club <em>Control</em></h1>
    <p>Backstage at Baseline. Manage members, moderate the lounge, and tidy up the booking ledger.</p>
  </div>
</header>

<section style="padding:20px 0 90px">
  <div class="container">

    <?php if (!$isAdmin): ?>
      <div class="login-card">
        <h3>Admin <em>sign in</em></h3>
        <div class="sub">Enter the admin password to continue.</div>
        <?php if (isset($_GET['err'])): ?>
          <div class="login-err">Incorrect password. Try again.</div>
        <?php endif; ?>
        <form method="post">
          <label>Password</label>
          <input type="password" name="admin_password" placeholder="••••••" required autofocus>
          <button type="submit" name="admin_login" value="1">Unlock Admin</button>
        </form>
        <div class="login-hint">authorized personnel only</div>
      </div>
    <?php else:
      $allMessages = [];
      $allBookings = [];
      $userStats = [];
      if ($pdo) {
          try {
              $allMessages = $pdo->query("SELECT * FROM messages ORDER BY id DESC")->fetchAll(PDO::FETCH_ASSOC);
          } catch (Exception $e) {}
          try {
              $allBookings = $pdo->query("SELECT * FROM bookings ORDER BY slot_date DESC, slot_time DESC")->fetchAll(PDO::FETCH_ASSOC);
          } catch (Exception $e) {}
      }
      foreach ($allMessages as $m) {
          $n = $m['name'];
          if (!isset($userStats[$n])) $userStats[$n] = ['msgs'=>0,'books'=>0,'last'=>0];
          $userStats[$n]['msgs']++;
          if ((int)$m['created_at'] > $userStats[$n]['last']) $userStats[$n]['last'] = (int)$m['created_at'];
      }
      foreach ($allBookings as $b) {
          $n = $b['name'];
          if (!isset($userStats[$n])) $userStats[$n] = ['msgs'=>0,'books'=>0,'last'=>0];
          $userStats[$n]['books']++;
          if ((int)$b['created_at'] > $userStats[$n]['last']) $userStats[$n]['last'] = (int)$b['created_at'];
      }
      uksort($userStats, 'strcasecmp');
      $editId = isset($_GET['edit']) ? (int)$_GET['edit'] : 0;
    ?>

      <div class="admin-toolbar">
        <a href="#overview" class="active">Overview</a>
        <a href="#users">Users · <?= count($userStats) ?></a>
        <a href="#chats">Chats · <?= count($allMessages) ?></a>
        <a href="#bookings">Bookings · <?= count($allBookings) ?></a>
        <div class="spacer"></div>
        <form method="post"><button class="logout" name="admin_logout" value="1">Sign out admin</button></form>
      </div>

      <div class="admin-section" id="overview">
        <div class="admin-section-head">
          <h3>At a <em>glance</em></h3>
          <div class="meta">Welcome back, admin</div>
        </div>
        <div class="admin-overview-grid">
          <div class="admin-overview-cell"><div class="num"><em><?= count($userStats) ?></em></div><div class="lab">Members on file</div></div>
          <div class="admin-overview-cell"><div class="num"><?= count($allMessages) ?></div><div class="lab">Messages posted</div></div>
          <div class="admin-overview-cell"><div class="num"><?= count($allBookings) ?></div><div class="lab">Court bookings</div></div>
          <div class="admin-overview-cell"><div class="num">
            <?php
              $upcoming = 0; $today = date('Y-m-d');
              foreach ($allBookings as $b) if ($b['slot_date'] >= $today) $upcoming++;
              echo $upcoming;
            ?>
          </div><div class="lab">Upcoming slots</div></div>
        </div>
      </div>

      <div class="admin-section" id="users">
        <div class="admin-section-head">
          <h3><em>Members</em></h3>
          <div class="meta"><?= count($userStats) ?> on file</div>
        </div>
        <?php if (empty($userStats)): ?>
          <div class="admin-empty">No members have signed in yet.</div>
        <?php else: foreach ($userStats as $uname => $st):
          $hue = crc32($uname) % 360;
          $initial = strtoupper(mb_substr($uname, 0, 1));
        ?>
          <div class="user-card">
            <div class="av" style="background:hsl(<?= $hue ?>,70%,60%)"><?= e($initial) ?></div>
            <div class="uinfo">
              <div class="nm"><?= e($uname) ?></div>
              <div class="st"><?= $st['msgs'] ?> msg<?= $st['msgs']===1?'':'s' ?> · <?= $st['books'] ?> booking<?= $st['books']===1?'':'s' ?><?= $st['last'] ? ' · last seen ' . date('M j, Y g:ia', $st['last']) : '' ?></div>
            </div>
            <div class="uactions">
              <form method="post" onsubmit="return confirm('Rename this user — this updates all their messages and bookings.');">
                <input type="hidden" name="admin_rename_from" value="<?= e($uname) ?>">
                <input type="text" name="admin_rename_to" placeholder="New name" maxlength="30" required>
                <button class="admin-btn" name="admin_rename_user" value="1">Rename</button>
              </form>
              <form method="post" onsubmit="return confirm('Purge all data for this user?');">
                <button class="admin-btn danger" name="admin_purge_user" value="<?= e($uname) ?>">Purge</button>
              </form>
            </div>
          </div>
        <?php endforeach; endif; ?>
      </div>

      <div class="admin-section" id="chats">
        <div class="admin-section-head">
          <h3>Chat <em>messages</em></h3>
          <div class="meta"><?= count($allMessages) ?> total</div>
        </div>
        <?php if (empty($allMessages)): ?>
          <div class="admin-empty">No chat messages yet.</div>
        <?php else: ?>
          <table class="admin-table">
            <thead>
              <tr>
                <th style="width:60px">#</th>
                <th style="width:140px">Member</th>
                <th>Message</th>
                <th style="width:140px">When</th>
                <th style="width:200px;text-align:right">Actions</th>
              </tr>
            </thead>
            <tbody>
              <?php foreach ($allMessages as $m): ?>
                <tr>
                  <td class="num-cell">#<?= (int)$m['id'] ?></td>
                  <td class="name-cell"><?= e($m['name']) ?></td>
                  <td class="body-cell">
                    <?php if ($editId === (int)$m['id']): ?>
                      <form method="post" class="edit-form">
                        <input type="hidden" name="admin_edit_msg_id" value="<?= (int)$m['id'] ?>">
                        <input type="text" name="admin_edit_msg_body" value="<?= e($m['body']) ?>" maxlength="500" autofocus>
                        <button class="admin-btn primary" type="submit">Save</button>
                        <a class="admin-btn" href="?page=admin#chats">Cancel</a>
                      </form>
                    <?php else: ?>
                      <?= e($m['body']) ?>
                    <?php endif; ?>
                  </td>
                  <td class="num-cell"><?= date('M j · g:ia', (int)$m['created_at']) ?></td>
                  <td class="actions-cell">
                    <?php if ($editId !== (int)$m['id']): ?>
                      <a class="admin-btn" href="?page=admin&edit=<?= (int)$m['id'] ?>#chats">Edit</a>
                    <?php endif; ?>
                    <form method="post" style="display:inline" onsubmit="return confirm('Delete this message?');">
                      <input type="hidden" name="admin_delete_msg_id" value="<?= (int)$m['id'] ?>">
                      <button class="admin-btn danger" type="submit">Delete</button>
                    </form>
                  </td>
                </tr>
              <?php endforeach; ?>
            </tbody>
          </table>
        <?php endif; ?>
      </div>

      <div class="admin-section" id="bookings">
        <div class="admin-section-head">
          <h3>Court <em>bookings</em></h3>
          <div class="meta"><?= count($allBookings) ?> total</div>
        </div>
        <?php if (empty($allBookings)): ?>
          <div class="admin-empty">No bookings on the ledger.</div>
        <?php else: ?>
          <table class="admin-table">
            <thead>
              <tr>
                <th style="width:60px">#</th>
                <th style="width:140px">Member</th>
                <th style="width:110px">Court</th>
                <th style="width:130px">Date</th>
                <th style="width:90px">Time</th>
                <th style="width:140px">Booked</th>
                <th style="width:120px;text-align:right">Actions</th>
              </tr>
            </thead>
            <tbody>
              <?php foreach ($allBookings as $b):
                $past = $b['slot_date'] < date('Y-m-d');
              ?>
                <tr style="<?= $past?'opacity:.45':'' ?>">
                  <td class="num-cell">#<?= (int)$b['id'] ?></td>
                  <td class="name-cell"><?= e($b['name']) ?></td>
                  <td><?= e($b['court']) ?></td>
                  <td class="num-cell"><?= e($b['slot_date']) ?></td>
                  <td class="num-cell"><?= e($b['slot_time']) ?></td>
                  <td class="num-cell"><?= date('M j · g:ia', (int)$b['created_at']) ?></td>
                  <td class="actions-cell">
                    <form method="post" style="display:inline" onsubmit="return confirm('Cancel this booking?');">
                      <input type="hidden" name="admin_delete_booking_id" value="<?= (int)$b['id'] ?>">
                      <button class="admin-btn danger" type="submit">Cancel</button>
                    </form>
                  </td>
                </tr>
              <?php endforeach; ?>
            </tbody>
          </table>
        <?php endif; ?>
      </div>

    <?php endif; ?>

  </div>
</section>

<?php elseif ($page === 'files'): ?>

<header class="subpage-hero">
  <div class="container">
    <div class="eyebrow"><span class="pulse"></span>Server / File Browser</div>
    <h1><em>Files</em></h1>
    <p>A peek behind the curtain — every file the club keeps on the server, from the front-of-house code to the trophy ledger in the database.</p>
  </div>
</header>

<section style="padding:20px 0 90px">
  <div class="container">

    <?php
    $parentPath = dirname($target);
    $hasParent = ($parentPath !== $target);
    $segments = array_values(array_filter(explode('/', $target), function($s){ return $s !== ''; }));
    ?>
    <div class="crumbs">
      <?php if ($hasParent): ?>
        <a class="up" href="?page=files&amp;path=<?= e(urlencode($parentPath)) ?>" title="Go to parent directory">↑ Up</a>
        <span class="sep">/</span>
      <?php endif; ?>
      <a class="project" href="?page=files" title="Project root">◆ project</a>
      <span class="sep">/</span>
      <a href="?page=files&amp;path=<?= e(urlencode('/')) ?>" title="Filesystem root">/</a>
      <?php
      $accum = '';
      foreach ($segments as $i => $part):
        $accum .= '/' . $part;
        $isLast = ($i === count($segments) - 1);
      ?>
        <span class="sep">/</span>
        <?php if ($isLast): ?>
          <span class="here"><?= e($part) ?></span>
        <?php else: ?>
          <a href="?page=files&amp;path=<?= e(urlencode($accum)) ?>"><?= e($part) ?></a>
        <?php endif; ?>
      <?php endforeach; ?>
    </div>

    <?php if (is_file($target)):
        $ext = strtolower(pathinfo($target, PATHINFO_EXTENSION));
        $size = filesize($target);
        $imgExt = ['png','jpg','jpeg','gif','svg','webp','ico'];
        $textExt = ['php','html','htm','css','js','json','md','txt','log','xml','yml','yaml','ini','env','sql','sh','conf','gitignore','lock'];
        $basename = basename($target);
        $treatAsText = in_array($ext, $textExt) || ($ext === '' && $size < 200000);
        $backDir = dirname($target);
    ?>
      <div class="file-view">
        <div class="file-view-head">
          <div>
            <div class="nm"><?= e($basename) ?></div>
            <div style="font-size:11px;color:var(--dim);margin-top:6px;font-family:'JetBrains Mono',monospace;letter-spacing:.06em"><?= e(human_size($size)) ?> · modified <?= date('M j, Y g:ia', filemtime($target)) ?></div>
          </div>
          <div class="actions">
            <?php if ($size <= 50*1024*1024): ?>
              <a href="?page=files&amp;path=<?= e(urlencode($target)) ?>&amp;dl=1">↓ Download</a>
            <?php endif; ?>
            <a class="ghost" href="?page=files&amp;path=<?= e(urlencode($backDir)) ?>">← Back</a>
          </div>
        </div>
        <?php if (in_array($ext, $imgExt) && $size <= 5*1024*1024):
            $absTarget = realpath($target);
            $isWebFile = $webRoot && strpos($absTarget, $webRoot) === 0;
        ?>
          <?php if ($isWebFile):
            $webRel = ltrim(substr($absTarget, strlen($webRoot)), '/\\');
          ?>
            <div class="img-wrap"><img src="/<?= e($webRel) ?>" alt=""></div>
          <?php else: ?>
            <div class="binary-note"><div class="big">◇</div>Image preview is only available for files inside the web root. Use download to view.</div>
          <?php endif; ?>
        <?php elseif ($treatAsText && $size <= 1024*1024):
          $content = @file_get_contents($target);
          $isBinary = false;
          if ($content !== false && $content !== '') {
              $sample = substr($content, 0, 8000);
              if (strpos($sample, "\0") !== false) $isBinary = true;
          }
        ?>
          <?php if ($isBinary): ?>
            <div class="binary-note"><div class="big">◇</div>Binary file — preview not available. Use download to grab it.</div>
          <?php else: ?>
            <pre><?= e($content) ?></pre>
          <?php endif; ?>
        <?php else: ?>
          <div class="binary-note"><div class="big">◇</div>
            <?= $size > 1024*1024 ? 'File is too large to preview here.' : 'No preview available for this file type.' ?>
          </div>
        <?php endif; ?>
      </div>

    <?php elseif (is_dir($target)):
        $items = [];
        $handle = @opendir($target);
        if ($handle) {
            while (($entry = readdir($handle)) !== false) {
                if ($entry === '.' || $entry === '..') continue;
                $full = $target . '/' . $entry;
                $items[] = [
                    'name' => $entry,
                    'full' => $full,
                    'is_dir' => is_dir($full),
                    'size' => is_file($full) ? @filesize($full) : 0,
                    'mtime' => @filemtime($full) ?: 0,
                ];
            }
            closedir($handle);
            usort($items, function($a, $b){
                if ($a['is_dir'] !== $b['is_dir']) return $a['is_dir'] ? -1 : 1;
                return strcasecmp($a['name'], $b['name']);
            });
        }
        $dirCount = count(array_filter($items, function($i){ return $i['is_dir']; }));
        $fileCount = count($items) - $dirCount;
        $isProjectRoot = ($target === $projectRoot);
        $headerLabel = $isProjectRoot ? 'Project Root' : ($target === '/' ? 'Filesystem Root' : basename($target));
    ?>
      <div class="file-panel">
        <div class="file-panel-head">
          <h3><?= e($headerLabel) ?></h3>
          <div class="meta"><?= $dirCount ?> folder<?= $dirCount===1?'':'s' ?> · <?= $fileCount ?> file<?= $fileCount===1?'':'s' ?></div>
        </div>
        <ul class="file-list">
          <?php if ($hasParent): ?>
            <li>
              <a class="file-row parent-row" href="?page=files&amp;path=<?= e(urlencode($parentPath)) ?>">
                <div class="ico">↑</div>
                <div class="nm">.. (parent directory)</div>
                <div class="sz">—</div>
                <div class="mt"><?= e($parentPath) ?></div>
              </a>
            </li>
          <?php endif; ?>
          <?php if (empty($items) && !$hasParent): ?>
            <li><div class="empty-dir">Nothing in here but tumbleweed.</div></li>
          <?php elseif (empty($items)): ?>
            <li><div class="empty-dir">Nothing in here but tumbleweed.</div></li>
          <?php else: foreach ($items as $it): ?>
              <li>
                <a class="file-row" href="?page=files&amp;path=<?= e(urlencode($it['full'])) ?>">
                  <div class="ico"><?= $it['is_dir'] ? '▸' : '·' ?></div>
                  <div class="nm <?= $it['is_dir']?'dir':'' ?>"><?= e($it['name']) ?><?= $it['is_dir']?'/':'' ?></div>
                  <div class="sz"><?= $it['is_dir'] ? '—' : e(human_size($it['size'])) ?></div>
                  <div class="mt"><?= $it['mtime'] ? date('M j, Y · g:ia', $it['mtime']) : '' ?></div>
                </a>
              </li>
          <?php endforeach; endif; ?>
        </ul>
      </div>
    <?php else: ?>
      <div class="file-panel">
        <div class="empty-dir">Path not found. The ball's out of bounds.</div>
      </div>
    <?php endif; ?>

  </div>
</section>

<?php else:
$bookings = [];
if ($pdo) {
    try {
        $today = date('Y-m-d');
        $week = date('Y-m-d', strtotime('+6 days'));
        $stmt = $pdo->prepare("SELECT * FROM bookings WHERE slot_date >= ? AND slot_date <= ? ORDER BY slot_date, slot_time");
        $stmt->execute([$today, $week]);
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $b) {
            $bookings[$b['slot_date'] . '|' . $b['slot_time'] . '|' . $b['court']] = $b;
        }
    } catch (Exception $e) {}
}

$messages = [];
if ($pdo) {
    try {
        $rows = $pdo->query("SELECT * FROM messages ORDER BY id DESC LIMIT 80")->fetchAll(PDO::FETCH_ASSOC);
        $messages = array_reverse($rows);
    } catch (Exception $e) {}
}

$courts = ['Clay', 'Grass', 'Hard'];
$times = ['08:00','10:00','12:00','14:00','16:00','18:00'];
$days = [];
for ($i = 0; $i < 7; $i++) {
    $d = strtotime("+$i days");
    $days[] = ['date' => date('Y-m-d', $d), 'label' => date('D', $d), 'day' => date('j', $d), 'mon' => date('M', $d)];
}
?>

<header class="hero">
  <div class="container hero-grid">
    <div>
      <div class="eyebrow"><span class="pulse"></span>Est. 1998 · Members Society</div>
      <h1>Love means <em>nothing</em>. The <span class="strike">match</span> game means <em>everything</em>.</h1>
      <p class="lead">A neighborhood tennis club for early birds, weekend warriors, and anyone who's ever yelled at a net cord. Book a court. Find a hit. Talk smack in the lounge.</p>
      <div class="hero-cta">
        <a href="#courts" class="btn btn-primary">
          Reserve a Court
          <span class="btn-arrow">
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
          </span>
        </a>
        <a href="#clubhouse" class="btn btn-ghost">Visit the Lounge</a>
      </div>
    </div>
    <div class="court-illus" aria-hidden="true">
      <svg viewBox="0 0 300 400">
        <defs>
          <linearGradient id="courtg" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stop-color="#1d201c"/>
            <stop offset="100%" stop-color="#0b0c0a"/>
          </linearGradient>
          <radialGradient id="ballg" cx="35%" cy="30%">
            <stop offset="0%" stop-color="#eaff5a"/>
            <stop offset="60%" stop-color="#d4ff3a"/>
            <stop offset="100%" stop-color="#95b81d"/>
          </radialGradient>
        </defs>
        <rect x="20" y="20" width="260" height="360" rx="8" fill="url(#courtg)" stroke="rgba(255,255,255,.08)"/>
        <g stroke="rgba(212,255,58,.35)" stroke-width="1.5" fill="none">
          <rect x="50" y="50" width="200" height="300"/>
          <line x1="50" y1="200" x2="250" y2="200" stroke="rgba(212,255,58,.6)"/>
          <line x1="150" y1="50" x2="150" y2="350"/>
          <rect x="90" y="130" width="120" height="140"/>
          <line x1="90" y1="200" x2="210" y2="200"/>
        </g>
        <g>
          <line x1="50" y1="200" x2="250" y2="200" stroke="rgba(255,255,255,.5)" stroke-width="2"/>
          <pattern id="netp" x="0" y="0" width="5" height="5" patternUnits="userSpaceOnUse">
            <path d="M0 0 L5 5 M5 0 L0 5" stroke="rgba(255,255,255,.18)" stroke-width=".5"/>
          </pattern>
          <rect x="50" y="194" width="200" height="14" fill="url(#netp)"/>
        </g>
        <g transform="translate(195,105)">
          <circle r="28" fill="url(#ballg)"/>
          <path d="M-28 0 Q-10 10 0 -28" stroke="rgba(255,255,255,.6)" stroke-width="1.5" fill="none"/>
          <path d="M28 0 Q10 -10 0 28" stroke="rgba(255,255,255,.6)" stroke-width="1.5" fill="none"/>
        </g>
        <g transform="translate(95,290) rotate(-20)">
          <ellipse cx="0" cy="0" rx="30" ry="38" fill="none" stroke="rgba(255,255,255,.7)" stroke-width="2"/>
          <ellipse cx="0" cy="0" rx="26" ry="34" fill="rgba(212,255,58,.05)"/>
          <g stroke="rgba(255,255,255,.4)" stroke-width=".7">
            <line x1="-24" y1="-14" x2="24" y2="-14"/>
            <line x1="-26" y1="-4" x2="26" y2="-4"/>
            <line x1="-26" y1="6" x2="26" y2="6"/>
            <line x1="-24" y1="16" x2="24" y2="16"/>
            <line x1="-10" y1="-32" x2="-10" y2="32"/>
            <line x1="0" y1="-34" x2="0" y2="34"/>
            <line x1="10" y1="-32" x2="10" y2="32"/>
          </g>
          <rect x="-3" y="36" width="6" height="38" fill="rgba(255,255,255,.7)" rx="2"/>
          <rect x="-4" y="56" width="8" height="20" fill="var(--lime)"/>
        </g>
      </svg>
    </div>
  </div>

  <div class="container">
    <div class="marquee">
      <div class="marquee-track">
        <span class="marquee-item">Clay</span>
        <span class="marquee-item">Grass</span>
        <span class="marquee-item">Hard</span>
        <span class="marquee-item">Singles</span>
        <span class="marquee-item">Doubles</span>
        <span class="marquee-item">Dawn till Dusk</span>
        <span class="marquee-item">Whites preferred</span>
        <span class="marquee-item">No double faults</span>
        <span class="marquee-item">Clay</span>
        <span class="marquee-item">Grass</span>
        <span class="marquee-item">Hard</span>
        <span class="marquee-item">Singles</span>
        <span class="marquee-item">Doubles</span>
        <span class="marquee-item">Dawn till Dusk</span>
        <span class="marquee-item">Whites preferred</span>
        <span class="marquee-item">No double faults</span>
      </div>
    </div>

    <div class="bento">
      <div class="bento-cell"><div class="corner">01</div><div class="num"><em>3</em></div><div class="lab">Surfaces — Clay, Grass, Hard</div></div>
      <div class="bento-cell"><div class="corner">02</div><div class="num">214</div><div class="lab">Active members</div></div>
      <div class="bento-cell"><div class="corner">03</div><div class="num">26<em>y</em></div><div class="lab">Since founding</div></div>
      <div class="bento-cell"><div class="corner">04</div><div class="num">7<em>am</em></div><div class="lab">Earliest slot</div></div>
    </div>
  </div>
</header>

<section id="courts">
  <div class="container">

    <?php if (!$name): ?>
    <div class="name-gate">
      <div>
        <h3>Sign in to the <em>club</em></h3>
        <p>Just your name — no passwords, no fuss. We trust you.</p>
      </div>
      <form method="post" action="">
        <input type="text" name="set_name" placeholder="Your name (e.g. Serena W.)" required maxlength="30" autocomplete="off">
        <input type="hidden" name="anchor" value="courts">
        <button type="submit">Enter Court →</button>
      </form>
    </div>
    <?php endif; ?>

    <div class="section-head">
      <div>
        <span class="tag">/ 01 — Reserve</span>
        <h2>Court <em>bookings</em></h2>
      </div>
      <p>Reserve a one-hour slot. Three surfaces, six daily windows, seven days out. Members only — be kind, cancel early.</p>
    </div>

    <div class="booking-wrap">
      <div class="day-tabs" id="day-tabs">
        <?php foreach($days as $i => $d): ?>
          <button class="day-tab <?= $i===0?'active':'' ?>" data-day="<?= $d['date'] ?>">
            <div class="lab"><?= $d['label'] ?></div>
            <div class="num"><?= $d['day'] ?></div>
            <div class="mon"><?= $d['mon'] ?></div>
          </button>
        <?php endforeach; ?>
      </div>

      <div class="court-legend">
        <span class="swatch"><i class="sw-clay"></i> Clay</span>
        <span class="swatch"><i class="sw-grass"></i> Grass</span>
        <span class="swatch"><i class="sw-hard"></i> Hard</span>
        <span class="swatch" style="margin-left:auto"><i class="sw-mine"></i> Your booking</span>
      </div>

      <?php foreach($days as $i => $d): ?>
        <div class="day-panel" data-panel="<?= $d['date'] ?>" style="<?= $i===0?'':'display:none' ?>">
          <div class="slots-grid">
            <div class="header-cell">Time</div>
            <?php foreach($courts as $c): ?>
              <div class="header-cell"><?= $c ?></div>
            <?php endforeach; ?>

            <?php foreach($times as $t): ?>
              <div class="time-label"><?= $t ?></div>
              <?php foreach($courts as $c):
                $key = $d['date'].'|'.$t.'|'.$c;
                $b = $bookings[$key] ?? null;
                if ($b):
                  $mine = ($name !== '' && $b['name'] === $name);
              ?>
                <div class="slot booked <?= $mine?'mine':'' ?>">
                  <div class="who"><?= e($b['name']) ?></div>
                  <div class="ct"><?= e($c) ?></div>
                  <?php if ($mine): ?>
                    <form method="post" style="margin:0">
                      <input type="hidden" name="cancel_id" value="<?= (int)$b['id'] ?>">
                      <input type="hidden" name="anchor" value="courts">
                      <button class="cancel" type="submit">cancel</button>
                    </form>
                  <?php endif; ?>
                </div>
              <?php else: ?>
                <button class="slot available"
                        data-date="<?= $d['date'] ?>"
                        data-time="<?= $t ?>"
                        data-court="<?= $c ?>"
                        <?= $name?'':'disabled style="opacity:.4;cursor:not-allowed"' ?>>
                  <div class="lab-book">+ Book</div>
                  <div class="ct"><?= $c ?></div>
                </button>
              <?php endif; endforeach; ?>
            <?php endforeach; ?>
          </div>
        </div>
      <?php endforeach; ?>
    </div>
  </div>
</section>

<section id="clubhouse">
  <div class="container">
    <div class="section-head">
      <div>
        <span class="tag">/ 02 — Talk</span>
        <h2>Members' <em>lounge</em></h2>
      </div>
      <p>The watercooler between sets. Brag, complain, find a doubles partner, debate the GOAT (it's Federer).</p>
    </div>

    <div class="chat-wrap">
      <div class="chat-header">
        <h3>The <em>lounge</em></h3>
        <div class="live"><span class="live-dot"></span>Live</div>
      </div>
      <div class="chat-body" id="chat-body">
        <?php if (empty($messages)): ?>
          <div class="chat-empty">Quiet courts today — be the first to break the silence.</div>
        <?php else: foreach($messages as $m):
          $mine = ($name !== '' && $m['name'] === $name);
          $initial = strtoupper(mb_substr($m['name'], 0, 1));
          $hue = crc32($m['name']) % 360;
        ?>
          <div class="msg <?= $mine?'mine':'' ?>">
            <div class="avatar" style="background:hsl(<?= $hue ?>,70%,60%)"><?= e($initial) ?></div>
            <div>
              <div class="msg-meta"><?= e($m['name']) ?> · <?= date('g:ia', (int)$m['created_at']) ?></div>
              <div class="msg-bubble"><div class="msg-body"><?= e($m['body']) ?></div></div>
            </div>
          </div>
        <?php endforeach; endif; ?>
      </div>
      <form class="chat-form <?= $name?'':'locked' ?>" method="post">
        <input type="text" name="message" placeholder="<?= $name?'Say something to the club…':'Sign in above to chat' ?>" maxlength="500" <?= $name?'':'disabled' ?> required>
        <input type="hidden" name="anchor" value="clubhouse">
        <button type="submit" <?= $name?'':'disabled' ?>>Send</button>
      </form>
    </div>
  </div>
</section>

<section id="about" style="padding-top:30px">
  <div class="container">
    <div class="section-head">
      <div>
        <span class="tag">/ 03 — Etiquette</span>
        <h2>House <em>rules</em></h2>
      </div>
      <p>A few traditions that keep us honest.</p>
    </div>
    <div class="rules-grid">
      <?php
      $rules = [
        ['Whites preferred', 'Clay stains everything. Wear what you don\'t mind retiring.'],
        ['Cancel early', 'No-shows steal courts. Free your slot if you can\'t make it.'],
        ['Net cord apologies', 'Raise the hand. It\'s tradition, even on match point.'],
        ['Quiet on serve', 'Hold conversations between points, not during the toss.'],
        ['Sweep your clay', 'Brush the lines and drag the surface after every match.'],
        ['Be a good loser', 'Shake hands at the net. Mean it.'],
      ];
      foreach ($rules as $i => $r): ?>
        <div class="rule-card">
          <span class="ix">RULE / <?= str_pad($i+1, 2, '0', STR_PAD_LEFT) ?></span>
          <h4><?= e($r[0]) ?></h4>
          <p><?= e($r[1]) ?></p>
        </div>
      <?php endforeach; ?>
    </div>
  </div>
</section>

<!-- Booking modal -->
<div class="modal-backdrop" id="modal">
  <div class="modal">
    <button class="close" id="modal-close" aria-label="Close">✕</button>
    <h3>Confirm your <em>booking</em></h3>
    <div class="sub" id="modal-sub">—</div>
    <form method="post" id="book-form">
      <label>Court Surface</label>
      <div class="court-picker" id="court-picker">
        <div class="court-opt" data-court="Clay"><div class="nm">Clay</div></div>
        <div class="court-opt" data-court="Grass"><div class="nm">Grass</div></div>
        <div class="court-opt" data-court="Hard"><div class="nm">Hard</div></div>
      </div>
      <input type="hidden" name="slot_date" id="f-date">
      <input type="hidden" name="slot_time" id="f-time">
      <input type="hidden" name="court" id="f-court">
      <input type="hidden" name="book" value="1">
      <input type="hidden" name="anchor" value="courts">
      <div class="modal-actions">
        <button type="button" class="btn btn-ghost" id="modal-cancel">Cancel</button>
        <button type="submit" class="btn btn-primary">Confirm Booking</button>
      </div>
    </form>
  </div>
</div>

<footer>
  <div class="container foot-grid">
    <div>
      <h4>See you on <em>court</em>.</h4>
      <div>Baseline Tennis Club · 14 Racquet Lane · Open dawn to dusk · Members only</div>
    </div>
    <div class="foot-right">
      © <?= date('Y') ?> Baseline TC<br>
      <?php if ($name): ?>
        Signed in as <?= e($name) ?> ·
        <form method="post" style="display:inline">
          <button type="submit" name="logout" value="1" class="signout">sign out</button>
        </form>
      <?php else: ?>
        not signed in
      <?php endif; ?>
    </div>
  </div>
</footer>

<?php endif; ?>

<script>
(function(){
  // Day tabs
  var tabs = document.querySelectorAll('.day-tab');
  var panels = document.querySelectorAll('.day-panel');
  tabs.forEach(function(t){
    t.addEventListener('click', function(){
      tabs.forEach(function(x){ x.classList.remove('active'); });
      t.classList.add('active');
      var d = t.getAttribute('data-day');
      panels.forEach(function(p){
        p.style.display = (p.getAttribute('data-panel') === d) ? '' : 'none';
      });
    });
  });

  // Booking modal
  var modal = document.getElementById('modal');
  if (modal) {
    var fDate = document.getElementById('f-date');
    var fTime = document.getElementById('f-time');
    var fCourt = document.getElementById('f-court');
    var sub = document.getElementById('modal-sub');
    var picker = document.getElementById('court-picker');

    document.querySelectorAll('.slot.available').forEach(function(s){
      s.addEventListener('click', function(e){
        if (s.hasAttribute('disabled')) return;
        e.preventDefault();
        var date = s.getAttribute('data-date');
        var time = s.getAttribute('data-time');
        var court = s.getAttribute('data-court');
        fDate.value = date;
        fTime.value = time;
        fCourt.value = court;
        sub.textContent = date + ' · ' + time + ' · ' + court + ' Court';
        picker.querySelectorAll('.court-opt').forEach(function(o){
          o.classList.toggle('selected', o.getAttribute('data-court') === court);
        });
        modal.classList.add('open');
      });
    });

    picker && picker.querySelectorAll('.court-opt').forEach(function(o){
      o.addEventListener('click', function(){
        picker.querySelectorAll('.court-opt').forEach(function(x){ x.classList.remove('selected'); });
        o.classList.add('selected');
        fCour