<?php
session_start();
$page_title = 'Scan & Order';
$active_nav = 'scan';
include("includes/header.php"); // Must define $conn and validate session

// ── Auth guard ──────────────────────────────────────────────────────────────
// After header.php runs, ensure we have a logged-in customer
$uid = isset($_SESSION['user_id']) ? (int)$_SESSION['user_id'] : 0;
if (!$uid) {
    // Redirect to login, preserving the QR URL so they return after login
    $return = urlencode($_SERVER['REQUEST_URI']);
    header("Location: signin.php?redirect=$return");
    exit;
}

// ── HELPER: render a single menu item card ──────────────────────────────────
// FIXED: Defined BEFORE it is called below (was previously defined after use)
// Horizontal card: thumbnail left, name/price/description right. The action
// slot bottom-right starts as a "+" button and is swapped in-place (by JS,
// see syncItemUI) for a qty stepper once the item has been added — cart
// state lives client-side, so both controls are always rendered and
// toggled rather than decided here on the server.
function render_menu_item(array $item, int $rid): string {
    $has_image = $item['image'] && file_exists("../restaurantadmin/uploads/menu/" . $item['image']);
    $img_url   = $has_image ? '../restaurantadmin/uploads/menu/' . $item['image'] : '';
    if ($has_image) {
        $img_html = '<img src="' . htmlspecialchars($img_url) . '" alt="">';
    } else {
        $img_html = '<div class="mi-thumb-fallback"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--primary)" stroke-width="1.5" stroke-linecap="round" opacity=".5"><path d="M3 11l19-9-9 19-2-8-8-2z"/></svg></div>';
    }
    $desc        = $item['description'] ? htmlspecialchars($item['description']) : '';
    $name        = htmlspecialchars($item['name']);
    $price       = number_format($item['price'], 0);
    $id          = (int)$item['id'];
    $js_name     = addslashes($item['name']);
    $js_price    = (float)$item['price'];
    $js_img      = addslashes($img_url);
    $name_attr   = htmlspecialchars($item['name'], ENT_QUOTES);

    $action = $item['is_available']
        ? <<<HTML
        <div class="mi-action" id="action-{$id}">
          <button type="button" class="mi-add" onclick="addToCart({$id},'{$js_name}',{$js_price},'{$js_img}')" aria-label="Add {$name_attr}">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2.5" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
          </button>
          <div class="mi-stepper">
            <button type="button" class="mi-step-btn mi-step-minus" onclick="decrementItem({$id})" aria-label="Remove one {$name_attr}">
              <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="5" y1="12" x2="19" y2="12"/></svg>
            </button>
            <span class="mi-qty">0</span>
            <button type="button" class="mi-step-btn mi-step-plus" onclick="incrementItem({$id})" aria-label="Add one more {$name_attr}">
              <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
            </button>
          </div>
        </div>
        HTML
        : '<span class="mi-unavailable">Sold out</span>';

    return <<<HTML
<div class="menu-item-card" id="item-{$id}">
  <div class="mi-thumb">{$img_html}</div>
  <div class="mi-body" id="body-{$id}">
    <div class="mi-top">
      <span class="mi-name">{$name}</span>
      <span class="mi-price">₦{$price}</span>
    </div>
    <p class="mi-desc">{$desc}</p>
  </div>
  {$action}
</div>
HTML;
}

// ── Restaurant from QR param ────────────────────────────────────────────────
$rid        = isset($_GET['rid']) ? (int)$_GET['rid'] : 0;
$restaurant = null;

if ($rid) {
    $rs = $conn->prepare("SELECT * FROM restaurants WHERE id=? AND status=1");
    $rs->bind_param("i", $rid);
    $rs->execute();
    $restaurant = $rs->get_result()->fetch_assoc();

    if ($restaurant) {
        // Log the QR scan
        $ip = $_SERVER['REMOTE_ADDR'];
        $ls = $conn->prepare("INSERT INTO qr_scans (restaurant_id, user_id, ip_address) VALUES (?,?,?)");
        $ls->bind_param("iis", $rid, $uid, $ip);
        $ls->execute();
    }
}
?>

<?php if (!$rid || !$restaurant): ?>
<!-- ══ Pay / Scan View ═══════════════════════════════════════════════════════ -->
<?php
// A code was supplied but didn't resolve to a live restaurant
$invalid_code = (bool)$rid && !$restaurant;

// Last few distinct restaurants this user has scanned, for the "Recent" quick action
$recent_restaurants = [];
$rec_q = $conn->prepare(
    "SELECT r.id, r.name, r.logo, MAX(q.scanned_at) AS last_scanned
     FROM qr_scans q
     JOIN restaurants r ON r.id = q.restaurant_id AND r.status = 1
     WHERE q.user_id = ?
     GROUP BY r.id
     ORDER BY last_scanned DESC
     LIMIT 6"
);
if ($rec_q) {
    $rec_q->bind_param("i", $uid);
    $rec_q->execute();
    $recent_restaurants = $rec_q->get_result()->fetch_all(MYSQLI_ASSOC);
}
?>

<style>
/* This screen is a focused, full-attention task (camera permission + scanning),
   so it intentionally suspends the normal app chrome — same pattern as the
   checkout flow — rather than competing with the Dabil topbar and tab bar. */
.app-topbar, .app-bottomnav { display: none; }
.main-content { padding-top: env(safe-area-inset-top); padding-bottom: 24px; }

/* ── Pay screen topbar ───────────────────────────────────────────────── */
.pay-topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 2px 22px;
}
.pay-topbar .pay-back {
  width: 34px; height: 34px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  color: var(--text); background: var(--bg); flex-shrink: 0; touch-action: manipulation;
}
.pay-topbar .pay-title { font-size: 1.05rem; font-weight: 800; letter-spacing: -.02em; }
.pay-topbar-right { display: flex; align-items: center; gap: 12px; }

/* ── Decorative scan preview ─────────────────────────────────────────── */
.scan-hero {
  position: relative;
  border-radius: 22px;
  background: linear-gradient(160deg, #1B2333 0%, #0D1117 100%);
  height: clamp(220px, 62vw, 300px);
  overflow: hidden;
  margin-bottom: 18px;
  display: flex; align-items: center; justify-content: center;
}
.scan-hero .scan-frame {
  position: relative;
  width: 150px; height: 150px;
}
.scan-hero .scan-frame i {
  position: absolute; width: 28px; height: 28px;
  border: 3px solid rgba(255,255,255,.85);
}
.scan-hero .scan-frame i:nth-child(1) { top: 0; left: 0; border-right: none; border-bottom: none; border-radius: 8px 0 0 0; }
.scan-hero .scan-frame i:nth-child(2) { top: 0; right: 0; border-left: none; border-bottom: none; border-radius: 0 8px 0 0; }
.scan-hero .scan-frame i:nth-child(3) { bottom: 0; left: 0; border-right: none; border-top: none; border-radius: 0 0 0 8px; }
.scan-hero .scan-frame i:nth-child(4) { bottom: 0; right: 0; border-left: none; border-top: none; border-radius: 0 0 8px 0; }
.scan-hero .scan-glyph { color: rgba(255,255,255,.5); }
.scan-hero .scan-line {
  position: absolute; left: 6px; right: 6px; top: 6px; height: 2px;
  background: linear-gradient(90deg, transparent, #5B9BFF, transparent);
  box-shadow: 0 0 8px 1px rgba(91,155,255,.8);
  animation: scanSweep 2.2s ease-in-out infinite;
}
@keyframes scanSweep {
  0%, 100% { top: 6px; opacity: .9; }
  50% { top: calc(100% - 8px); opacity: .9; }
}

/* ── Buttons & quick actions ──────────────────────────────────────────── */
.btn-start-camera {
  width: 100%; display: flex; align-items: center; justify-content: center; gap: 9px;
  background: var(--primary); color: #fff; border: none; border-radius: 14px;
  padding: 15px; font-size: .95rem; font-weight: 700; cursor: pointer;
  font-family: var(--font); margin-bottom: 10px; box-shadow: var(--shadow-lg);
  touch-action: manipulation;
}
.btn-start-camera:active { background: var(--primary-dark); }
.btn-manual {
  width: 100%; display: flex; align-items: center; justify-content: center; gap: 9px;
  background: var(--primary-bg); color: var(--primary); border: none; border-radius: 14px;
  padding: 14px; font-size: .9rem; font-weight: 700; cursor: pointer;
  font-family: var(--font); margin-bottom: 22px; touch-action: manipulation;
}
.btn-manual:active { background: #dce8fb; }
.pay-quick-actions { display: flex; gap: 28px; justify-content: center; }
.pay-quick-actions button {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  background: none; border: none; cursor: pointer; font-family: var(--font); touch-action: manipulation;
}
.pay-quick-actions .qa-circle {
  width: 50px; height: 50px; border-radius: 50%; background: var(--bg);
  display: flex; align-items: center; justify-content: center; color: var(--text-muted);
}
.pay-quick-actions button:active .qa-circle { background: var(--border); }
.pay-quick-actions span.qa-text { font-size: .74rem; font-weight: 700; color: var(--text-muted); }

/* ── Recent restaurants sheet ────────────────────────────────────────── */
.sheet-overlay {
  position: fixed; inset: 0; background: rgba(15,23,42,.45); z-index: 600;
  display: none; align-items: flex-end; justify-content: center;
}
.sheet-overlay.open { display: flex; }
.sheet-panel {
  width: 100%; max-width: var(--app-max-w); background: #fff; border-radius: 22px 22px 0 0;
  padding: 10px 18px calc(env(safe-area-inset-bottom) + 22px); max-height: 70vh; overflow-y: auto;
  animation: sheetUp .25s ease both;
}
@keyframes sheetUp { from { transform: translateY(24px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
.sheet-handle { width: 36px; height: 4px; border-radius: 4px; background: var(--border); margin: 8px auto 14px; }
.sheet-panel h3 { font-size: .95rem; font-weight: 800; margin-bottom: 12px; }

/* ── Manual entry modal ──────────────────────────────────────────────── */
.modal-overlay {
  position: fixed; inset: 0; background: rgba(15,23,42,.45); z-index: 600;
  display: none; align-items: center; justify-content: center; padding: 24px;
}
.modal-overlay.open { display: flex; }
.modal-card {
  width: 100%; max-width: 360px; background: #fff; border-radius: 18px; padding: 22px;
  animation: sheetUp .2s ease both;
}
.modal-card h3 { font-size: 1rem; font-weight: 800; margin-bottom: 6px; }
.modal-card p { font-size: .82rem; color: var(--text-muted); margin-bottom: 16px; }
.modal-card .modal-actions { display: flex; gap: 10px; margin-top: 16px; }
.modal-card .modal-actions button { flex: 1; }

/* ── Full-screen camera overlay ───────────────────────────────────────── */
.camera-overlay {
  position: fixed; inset: 0; max-width: var(--app-max-w); margin: 0 auto;
  background: #000; z-index: 500; display: none; flex-direction: column;
}
.camera-overlay.open { display: flex; }
#qrReaderEl {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  width: 100%; height: 100%;
  overflow: hidden;
}
#qrReaderEl video {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}

.camera-topbar {
  position: relative; z-index: 2; display: flex; align-items: center; justify-content: space-between;
  padding: calc(env(safe-area-inset-top) + 14px) 16px 16px;
  background: linear-gradient(180deg, rgba(0,0,0,.55), transparent);
}
.camera-topbar .cam-icon-btn {
  width: 38px; height: 38px; border-radius: 50%; border: none; display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.16); color: #fff; cursor: pointer; touch-action: manipulation;
}
.camera-topbar .cam-torch { background: var(--primary); }
.camera-topbar .cam-title { color: #fff; font-weight: 700; font-size: .95rem; }

.camera-frame-wrap {
  position: relative; z-index: 1; flex: 1; display: flex; align-items: center; justify-content: center;
}
.camera-frame {
  position: relative; width: 230px; height: 230px;
  box-shadow: 0 0 0 2000px rgba(0,0,0,.5);
  border-radius: 18px;
}
.camera-frame i {
  position: absolute; width: 30px; height: 30px; border: 3px solid #fff;
}
.camera-frame i:nth-child(1) { top: -2px; left: -2px; border-right: none; border-bottom: none; border-radius: 14px 0 0 0; }
.camera-frame i:nth-child(2) { top: -2px; right: -2px; border-left: none; border-bottom: none; border-radius: 0 14px 0 0; }
.camera-frame i:nth-child(3) { bottom: -2px; left: -2px; border-right: none; border-top: none; border-radius: 0 0 0 14px; }
.camera-frame i:nth-child(4) { bottom: -2px; right: -2px; border-left: none; border-top: none; border-radius: 0 0 14px 0; }
.camera-frame .cam-scan-line {
  position: absolute; left: 4px; right: 4px; top: 4px; height: 2px;
  background: linear-gradient(90deg, transparent, #5B9BFF, transparent);
  box-shadow: 0 0 10px 1px rgba(91,155,255,.9);
  animation: scanSweep 2.2s ease-in-out infinite;
}

.camera-bottom {
  position: relative; z-index: 2; text-align: center; padding: 0 24px calc(env(safe-area-inset-bottom) + 28px);
}
.camera-bottom .cam-instruction { color: rgba(255,255,255,.85); font-size: .85rem; line-height: 1.5; margin-bottom: 18px; }
.btn-manual-dark {
  display: inline-flex; align-items: center; gap: 8px; background: rgba(255,255,255,.16);
  color: #fff; border: none; border-radius: 30px; padding: 12px 22px; font-size: .85rem; font-weight: 700;
  font-family: var(--font); cursor: pointer; margin-bottom: 14px; touch-action: manipulation;
}
.btn-manual-dark:active { background: rgba(255,255,255,.28); }
.cam-help { display: block; color: rgba(255,255,255,.65); font-size: .78rem; }
.cam-help u { color: #fff; }
.camera-permission-msg {
  position: relative; z-index: 2; margin: auto 24px; text-align: center; color: #fff;
  display: none;
}
.camera-permission-msg.show { display: block; }
.camera-permission-msg svg { margin: 0 auto 14px; display: block; opacity: .7; }
.camera-permission-msg p { font-size: .85rem; color: rgba(255,255,255,.8); margin-bottom: 18px; line-height: 1.5; }

/* ── Toast ─────────────────────────────────────────────────────────────── */
.scan-toast {
  position: fixed; bottom: calc(env(safe-area-inset-bottom) + 24px); left: 50%; transform: translateX(-50%);
  background: #0F172A; color: #fff; padding: 11px 20px; border-radius: 30px; font-size: .8rem; font-weight: 600;
  box-shadow: 0 6px 20px rgba(0,0,0,.25); z-index: 700; opacity: 0; pointer-events: none; transition: opacity .25s;
  max-width: 86%; text-align: center;
}
.scan-toast.show { opacity: 1; }
</style>

<div id="payView">
  <!-- Custom topbar (replaces the global Dabil topbar for this focused flow) -->
  <div class="pay-topbar">
    <a href="dashboard.php" id="payBackLink" onclick="return goBackFromPay(event)" class="pay-back">
      <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5m0 0l7 7M5 12l7-7"/></svg>
    </a>
    <span class="pay-title">Pay</span>
    <div class="pay-topbar-right">
      <a href="notifications.php" class="icon-btn" title="Notifications">
        <svg viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8a6 6 0 10-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 01-3.46 0"/></svg>
        <?php if ($__unread > 0): ?><span class="notif-dot"></span><?php endif; ?>
      </a>
      <a href="profile.php" class="topbar-avatar" style="width:32px;height:32px;font-size:.65rem" title="<?php echo htmlspecialchars($__name); ?>"><?php echo $__avatar_url ? '<img src="' . htmlspecialchars($__avatar_url) . '" alt="">' : $__initials; ?></a>
    </div>
  </div>

  <p style="color:var(--text-muted);font-size:.875rem;line-height:1.5;margin-bottom:22px">
    Quickly pay at your favorite spots or scan a new QR code.
  </p>

  <?php if ($invalid_code): ?>
  <div class="alert alert-error">
    <svg viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="10"/><path d="M12 8v4M12 16h.01"/></svg>
    <span>We couldn't find a restaurant for that code. Try scanning again or enter it manually.</span>
  </div>
  <?php endif; ?>

  <h2 style="font-size:.95rem;font-weight:800;letter-spacing:-.02em;margin-bottom:12px">Scan QR code</h2>

  <div class="scan-hero">
    <div class="scan-frame">
      <i></i><i></i><i></i><i></i>
      <div class="scan-line"></div>
      <svg class="scan-glyph" width="56" height="56" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)">
        <path d="M3 7V5a2 2 0 012-2h2M17 3h2a2 2 0 012 2v2M21 17v2a2 2 0 01-2 2h-2M7 21H5a2 2 0 01-2-2v-2"/>
        <rect x="7" y="7" width="10" height="10" rx="1"/>
      </svg>
    </div>
  </div>

  <button type="button" class="btn-start-camera" onclick="startCamera()">
    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z"/><circle cx="12" cy="13" r="4"/></svg>
    Start Camera
  </button>
  <button type="button" class="btn-manual" onclick="openManualModal()">
    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="6" width="20" height="12" rx="2"/><line x1="6" y1="10" x2="6" y2="10"/><line x1="10" y1="10" x2="10" y2="10"/><line x1="14" y1="10" x2="14" y2="10"/><line x1="18" y1="10" x2="18" y2="10"/><line x1="6" y1="14" x2="18" y2="14"/></svg>
    Enter ID Manually
  </button>

  <div class="pay-quick-actions">
    <button type="button" onclick="document.getElementById('qrFileInput').click()">
      <span class="qa-circle">
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="M21 15l-5-5L5 21"/></svg>
      </span>
      <span class="qa-text">Photos</span>
    </button>
    <button type="button" onclick="openRecentSheet()">
      <span class="qa-circle">
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 16 14"/></svg>
      </span>
      <span class="qa-text">Recent</span>
    </button>
  </div>
  <input type="file" id="qrFileInput" accept="image/*" style="display:none">
</div>

<!-- ── Full-screen camera scanning view ──────────────────────────────────── -->
<div class="camera-overlay" id="cameraView">
  <div id="qrReaderEl">
    <video id="qrVideo" playsinline muted autoplay></video>
  </div>
  <canvas id="qrCanvas" style="display:none"></canvas>

  <div class="camera-topbar">
    <button type="button" class="cam-icon-btn" onclick="closeCamera()" title="Close">
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </button>
    <span class="cam-title">Scan QR Code</span>
    <button type="button" class="cam-icon-btn cam-torch" id="torchBtn" onclick="toggleTorch()" title="Flashlight">
      <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2L3 14h8l-1 8 10-12h-8l1-8z"/></svg>
    </button>
  </div>

  <div class="camera-frame-wrap">
    <div class="camera-frame" id="cameraFrame">
      <i></i><i></i><i></i><i></i>
      <div class="cam-scan-line"></div>
    </div>
    <div class="camera-permission-msg" id="permissionMsg">
      <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="1.5" stroke-linecap="round"><path d="M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z"/><circle cx="12" cy="13" r="4"/><line x1="2" y1="2" x2="22" y2="22"/></svg>
      <p id="permissionMsgText">We need camera access to scan QR codes.<br>Check your browser permissions and try again.</p>
      <button type="button" class="btn-manual-dark" onclick="startCamera()">Try Again</button>
    </div>
  </div>

  <div class="camera-bottom">
    <p class="cam-instruction">Align the QR code within the frame to pay or scan items.</p>
    <button type="button" class="btn-manual-dark" onclick="openManualModal()">
      <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="6" width="20" height="12" rx="2"/><line x1="6" y1="14" x2="18" y2="14"/></svg>
      Enter ID Manually
    </button>
    <a href="help_center.php" class="cam-help">Having trouble? <u>Visit Help Center</u></a>
  </div>
</div>

<!-- ── Manual entry modal ────────────────────────────────────────────────── -->
<div class="modal-overlay" id="manualModal">
  <div class="modal-card">
    <h3>Enter restaurant code</h3>
    <p>Ask your server for the numeric code shown on their QR stand.</p>
    <div class="form-group" style="margin-bottom:6px">
      <input type="text" id="manualCodeInput" class="form-control" placeholder="e.g. 104" inputmode="numeric" autocomplete="off">
    </div>
    <div class="modal-actions">
      <button type="button" class="btn btn-secondary btn-md" onclick="closeManualModal()">Cancel</button>
      <button type="button" class="btn btn-primary btn-md" onclick="submitManual()">Continue</button>
    </div>
  </div>
</div>

<!-- ── Recent restaurants sheet ──────────────────────────────────────────── -->
<div class="sheet-overlay" id="recentSheet" onclick="if(event.target===this) closeRecentSheet()">
  <div class="sheet-panel">
    <div class="sheet-handle"></div>
    <h3>Recently scanned</h3>
    <?php if (empty($recent_restaurants)): ?>
    <p style="font-size:.84rem;color:var(--text-muted);padding-bottom:8px">You haven't scanned any restaurants yet.</p>
    <?php else: ?>
    <?php foreach ($recent_restaurants as $r):
      $logo_path = $r['logo'] ? '../restaurantadmin/uploads/logos/' . $r['logo'] : null;
      $has_logo  = $logo_path && file_exists(dirname(__FILE__) . '/' . $logo_path);
      $initials  = strtoupper(substr($r['name'], 0, 2));
    ?>
    <a href="scan.php?rid=<?php echo $r['id']; ?>" class="rest-list-item">
      <div class="rest-logo">
        <?php if ($has_logo): ?><img src="<?php echo htmlspecialchars($logo_path); ?>" alt=""><?php else: ?><?php echo $initials; ?><?php endif; ?>
      </div>
      <div class="rest-info">
        <div class="rest-name"><?php echo htmlspecialchars($r['name']); ?></div>
        <div class="rest-meta">Last scanned <?php echo date('M j, g:i A', strtotime($r['last_scanned'])); ?></div>
      </div>
      <div class="rest-chevron">
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="9 18 15 12 9 6"/></svg>
      </div>
    </a>
    <?php endforeach; ?>
    <?php endif; ?>
  </div>
</div>

<div class="scan-toast" id="scanToast"></div>

<!-- jsQR: a small, low-level QR decoder with no opinions about cameras or
     UI. After repeated cross-device failures with a higher-level scanner
     library managing the camera lifecycle for us, we now drive
     getUserMedia and the decode loop ourselves — fewer moving parts,
     and every failure point is something we can see and control. -->
<script src="https://unpkg.com/jsqr@1.4.0/dist/jsQR.js"></script>
<script>
let mediaStream = null;
let scanRAF = null;
let torchOn = false;
let cameraRunning = false;
let cameraStarting = false;
let lastBadCodeToast = 0;

// Safari is aggressive about restoring pages from the back/forward cache
// (e.g. the customer taps a code, the menu loads, they tap the browser's
// Back button to scan something else). When that happens this script's
// variables come back exactly as they were even though the OS already
// tore the actual camera stream down. Force a clean slate whenever the
// page is restored this way.
window.addEventListener('pageshow', (event) => {
  if (!event.persisted) return;
  stopCamera();
  document.getElementById('cameraView').classList.remove('open');
  document.getElementById('payView').style.display = '';
});

// "Back" on the Pay screen should return wherever the user came from,
// same convention used on the menu screen's back link.
function goBackFromPay(e) {
  const cameFromApp = document.referrer && document.referrer.indexOf(window.location.origin) === 0;
  if (cameFromApp && window.history.length > 1) {
    e.preventDefault();
    window.history.back();
    return false;
  }
  return true;
}

function showToast(msg) {
  const t = document.getElementById('scanToast');
  t.textContent = msg;
  t.classList.add('show');
  clearTimeout(window._scanToastTimer);
  window._scanToastTimer = setTimeout(() => t.classList.remove('show'), 2600);
}

// We deliberately never navigate to the raw decoded text. A physical QR
// sign can encode a full absolute URL, and blindly doing
// window.location.href = decodedText would carry the browser off to
// whatever domain/path is printed on it — if that doesn't share this
// session's cookie scope, the next page load looks "logged out" even
// though the customer never asked to leave the app. Instead we pull out
// only the restaurant id (and item/cat if present) and always build our
// own same-origin, same-folder link.
function extractScanTarget(decoded) {
  decoded = (decoded || '').trim();
  if (!decoded) return null;

  // Case 1: a full/partial URL like https://dabil.com.ng/customer/scan.php?rid=12&item=5
  // We don't require the rid value to be purely numeric here — the PHP
  // side already safely casts it with (int) and shows a friendly "code
  // not found" message for anything invalid, so the JS layer only needs
  // to decide whether something *looks* like a code worth forwarding.
  try {
    const url = new URL(decoded, window.location.href);
    const rid = url.searchParams.get('rid');
    if (rid) {
      let target = 'scan.php?rid=' + encodeURIComponent(rid);
      const item  = url.searchParams.get('item');
      const cat   = url.searchParams.get('cat');
      const table = url.searchParams.get('table');
      const tt    = url.searchParams.get('tt'); // 'loc' = Location/Office QR
      if (item)  target += '&item=' + encodeURIComponent(item);
      if (cat)   target += '&cat=' + encodeURIComponent(cat);
      if (table) target += '&table=' + encodeURIComponent(table);
      if (tt)    target += '&tt=' + encodeURIComponent(tt);
      return target;
    }
    // It parsed as a URL but had no rid param at all (e.g. someone scanned
    // an unrelated link) — nothing useful to do with it.
    if (url.search || url.pathname.length > 1) return null;
  } catch (e) { /* not a parseable URL — fall through to the bare-code case */ }

  // Case 2: the QR just encodes a bare restaurant code, e.g. "12" or "RT-12"
  if (/^[A-Za-z0-9_-]{1,24}$/.test(decoded)) {
    return 'scan.php?rid=' + encodeURIComponent(decoded);
  }

  return null;
}

function describeUnrecognized(decoded) {
  const preview = (decoded || '').slice(0, 40);
  return preview ? 'Unrecognized code: "' + preview + '"' : "That doesn't look like a Dabil QR code.";
}

function routeToCode(decoded) {
  const target = extractScanTarget(decoded);
  if (!target) {
    showToast(describeUnrecognized(decoded));
    return;
  }
  window.location.href = target;
}

// ── Camera ───────────────────────────────────────────────────────────────
// We drive getUserMedia and the decode loop directly rather than handing
// the camera lifecycle to a wrapper library — this is the third rewrite of
// this section after a string of cross-device failures we couldn't see
// inside that library's internals. Every step here is plain, inspectable
// browser API, so when something fails we know exactly which call failed.

function handleDecodedText(decodedText) {
  // Defensive try/catch: this runs once per scanned frame, so an uncaught
  // error here would just die silently frame after frame — i.e. exactly a
  // "nothing happens" bug with no clue why. Surface anything unexpected
  // as a toast instead.
  try {
    const target = extractScanTarget(decodedText);
    if (!target) {
      // Likely a misread or a non-Dabil code — nudge the user but keep
      // scanning rather than killing the camera over a bad read. Throttled
      // so a static unrecognized code sitting in frame doesn't spam toasts.
      const now = Date.now();
      if (now - lastBadCodeToast > 2500) {
        lastBadCodeToast = now;
        showToast(describeUnrecognized(decodedText));
      }
      return;
    }
    stopCamera();
    window.location.href = target;
  } catch (err) {
    showToast('Scan error: ' + (err && err.message ? err.message : err));
  }
}

function scanLoop() {
  if (!cameraRunning) return;
  const video = document.getElementById('qrVideo');
  if (video.readyState === video.HAVE_ENOUGH_DATA && video.videoWidth > 0) {
    const canvas = document.getElementById('qrCanvas');
    canvas.width = video.videoWidth;
    canvas.height = video.videoHeight;
    const ctx = canvas.getContext('2d', { willReadFrequently: true });
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
    try {
      const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
      const result = jsQR(imageData.data, imageData.width, imageData.height);
      if (result && result.data) {
        handleDecodedText(result.data);
        if (!cameraRunning) return; // handleDecodedText stopped the camera on a valid code
      }
    } catch (e) { /* a dropped frame here and there is fine — keep scanning */ }
  }
  scanRAF = requestAnimationFrame(scanLoop);
}

async function startCamera() {
  if (cameraRunning || cameraStarting) return;
  cameraStarting = true;

  document.getElementById('permissionMsg').classList.remove('show');
  document.getElementById('cameraFrame').style.display = '';
  document.getElementById('payView').style.display = 'none';
  document.getElementById('cameraView').classList.add('open');

  // Always tear down anything left over from a previous attempt first.
  stopCamera();

  try {
    // "ideal" hints (non-mandatory) keep this to one clean request — no
    // separate device-enumeration call beforehand, which on iOS Safari was
    // leaving a stream open that made the real request fail outright.
    // Lower resolution also negotiates faster, which matters more on iOS
    // than Android to begin with, and a QR decoder doesn't need full-res.
    mediaStream = await navigator.mediaDevices.getUserMedia({
      video: { facingMode: 'environment', width: { ideal: 640 }, height: { ideal: 480 } },
      audio: false
    });
  } catch (err) {
    cameraStarting = false;
    document.getElementById('cameraFrame').style.display = 'none';
    const deniedNames = ['NotAllowedError', 'PermissionDeniedError', 'SecurityError'];
    const isDenied = err && deniedNames.includes(err.name);
    document.getElementById('permissionMsgText').innerHTML = isDenied
      ? 'We need camera access to scan QR codes.<br>Check your browser permissions and try again.'
      : "Couldn't start the camera on this device.<br>Try again, or enter the code manually below.";
    document.getElementById('permissionMsg').classList.add('show');
    return;
  }

  const video = document.getElementById('qrVideo');
  // playsinline/muted must be set before play() is called — iOS Safari
  // will otherwise hijack the feed into its own native fullscreen player
  // instead of staying inside our custom overlay UI.
  video.setAttribute('playsinline', 'true');
  video.setAttribute('webkit-playsinline', 'true');
  video.muted = true;
  video.srcObject = mediaStream;
  try { await video.play(); } catch (e) { /* some browsers start playing on their own anyway */ }

  cameraRunning = true;
  cameraStarting = false;
  lastBadCodeToast = 0;
  scanRAF = requestAnimationFrame(scanLoop);
}

function stopCamera() {
  cameraRunning = false;
  cameraStarting = false;
  torchOn = false;
  if (scanRAF) { cancelAnimationFrame(scanRAF); scanRAF = null; }
  const video = document.getElementById('qrVideo');
  if (video) { video.pause(); video.srcObject = null; }
  if (mediaStream) {
    mediaStream.getTracks().forEach(t => t.stop());
    mediaStream = null;
  }
}

function closeCamera() {
  stopCamera();
  document.getElementById('cameraView').classList.remove('open');
  document.getElementById('payView').style.display = '';
}

function toggleTorch() {
  const track = mediaStream && mediaStream.getVideoTracks()[0];
  if (!cameraRunning || !track) { showToast('Start the camera first.'); return; }
  const caps = track.getCapabilities ? track.getCapabilities() : {};
  if (!caps.torch) {
    showToast("Flashlight isn't supported on this device.");
    return;
  }
  const next = !torchOn;
  track.applyConstraints({ advanced: [{ torch: next }] })
    .then(() => { torchOn = next; })
    .catch(() => showToast("Couldn't toggle the flashlight."));
}

// ── Manual entry ─────────────────────────────────────────────────────────
function openManualModal() {
  document.getElementById('manualModal').classList.add('open');
  setTimeout(() => document.getElementById('manualCodeInput').focus(), 50);
}
function closeManualModal() {
  document.getElementById('manualModal').classList.remove('open');
}
function submitManual() {
  const val = document.getElementById('manualCodeInput').value.trim();
  if (!val) { showToast('Please enter a code.'); return; }
  window.location.href = 'scan.php?rid=' + encodeURIComponent(val);
}

// ── Photos (decode QR from an uploaded image) ──────────────────────────
document.getElementById('qrFileInput').addEventListener('change', function(e) {
  const file = e.target.files[0];
  if (!file) return;
  const objectUrl = URL.createObjectURL(file);
  const img = new Image();
  img.onload = function() {
    try {
      const canvas = document.getElementById('qrCanvas');
      canvas.width = img.naturalWidth;
      canvas.height = img.naturalHeight;
      const ctx = canvas.getContext('2d');
      ctx.drawImage(img, 0, 0);
      const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
      const result = jsQR(imageData.data, imageData.width, imageData.height);
      if (result && result.data) {
        routeToCode(result.data);
      } else {
        showToast("Couldn't find a QR code in that image.");
      }
    } catch (err) {
      showToast("Couldn't read that image.");
    } finally {
      URL.revokeObjectURL(objectUrl);
      e.target.value = '';
    }
  };
  img.onerror = function() {
    URL.revokeObjectURL(objectUrl);
    e.target.value = '';
    showToast("Couldn't read that image.");
  };
  img.src = objectUrl;
});

// ── Recent restaurants sheet ─────────────────────────────────────────────
function openRecentSheet() { document.getElementById('recentSheet').classList.add('open'); }
function closeRecentSheet() { document.getElementById('recentSheet').classList.remove('open'); }
</script>

<?php else: ?>
<!-- ══ Menu View ═════════════════════════════════════════════════════════════ -->
<?php
// Optional per-item or per-category focus from QR
$focus_item_id = isset($_GET['item']) ? (int)$_GET['item'] : 0;
$focus_cat_id  = isset($_GET['cat'])  ? (int)$_GET['cat']  : 0;

// Table number — present when a table-specific QR was scanned (see
// restaurantadmin/tables.php, which encodes &table= alongside &rid=).
// Carried through category links and into checkout below.
$table_num  = isset($_GET['table']) ? trim((string)$_GET['table']) : '';
// &tt=loc marks a Location/Office QR (organizations) — the label shown is then
// the location name itself ("ICT Office") rather than "Table <n>".
$table_type = (($_GET['tt'] ?? '') === 'loc') ? 'loc' : '';
$table_qs   = $table_num !== '' ? '&table=' . urlencode($table_num) . ($table_type === 'loc' ? '&tt=loc' : '') : '';

// Fetch categories for this restaurant
$cats = $conn->prepare("SELECT * FROM categories WHERE restaurant_id=? ORDER BY sort_order, name");
$cats->bind_param("i", $rid);
$cats->execute();
$categories = $cats->get_result()->fetch_all(MYSQLI_ASSOC) ?: [];

// Fetch available menu items (filtered by category if requested). Items
// render as one flat, ordered list — category_id, name keeps everything
// grouped without needing a separate header per category.
if ($focus_cat_id) {
    $items_stmt = $conn->prepare(
        "SELECT * FROM menu_items WHERE restaurant_id=? AND category_id=? AND is_available=1 ORDER BY name"
    );
    $items_stmt->bind_param("ii", $rid, $focus_cat_id);
} else {
    $items_stmt = $conn->prepare(
        "SELECT * FROM menu_items WHERE restaurant_id=? AND is_available=1 ORDER BY category_id, name"
    );
    $items_stmt->bind_param("i", $rid);
}
$items_stmt->execute();
$menu_items = $items_stmt->get_result()->fetch_all(MYSQLI_ASSOC) ?: [];

// Resolve focused item (from per-item QR scan)
$focused_item = null;
if ($focus_item_id) {
    foreach ($menu_items as $mi) {
        if ($mi['id'] == $focus_item_id) { $focused_item = $mi; break; }
    }
    // Item may be unavailable — still show it so user knows
    if (!$focused_item) {
        $fi = $conn->prepare("SELECT * FROM menu_items WHERE id=? AND restaurant_id=?");
        $fi->bind_param("ii", $focus_item_id, $rid);
        $fi->execute();
        $focused_item = $fi->get_result()->fetch_assoc();
    }
}

?>

<style>
/* The menu is a focused, in-restaurant ordering flow — same reasoning as
   the Pay/scan screen: suspend the normal Dabil topbar and tab bar rather
   than compete with them. */
.app-topbar, .app-bottomnav { display: none; }
.main-content { padding-top: env(safe-area-inset-top); padding-bottom: 24px; }

.menu-topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 2px 18px;
}
.menu-topbar-left { display: flex; align-items: center; gap: 12px; min-width: 0; }
.menu-topbar .menu-back {
  width: 34px; height: 34px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  color: var(--text); background: var(--bg); flex-shrink: 0; touch-action: manipulation;
}
.menu-topbar .menu-title { font-size: 1.05rem; font-weight: 800; letter-spacing: -.02em; }
.menu-topbar-right { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }

.menu-hero { margin-bottom: 18px; }
.menu-hero h1 {
  font-size: clamp(1.35rem, 6vw, 1.6rem); font-weight: 800; letter-spacing: -.03em;
  color: var(--primary); line-height: 1.15; margin-bottom: 3px;
}
.menu-hero p { font-size: .85rem; color: var(--text-muted); font-weight: 600; }

.menu-cat-pills {
  display: flex; gap: 10px; margin-bottom: 22px;
  overflow-x: auto; padding-bottom: 4px;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.menu-cat-pills::-webkit-scrollbar { display: none; }
.menu-cat-pill {
  flex-shrink: 0; padding: 10px 20px; border-radius: 30px;
  font-size: .85rem; font-weight: 700; white-space: nowrap;
  background: var(--bg); color: var(--text-muted); text-decoration: none;
  transition: all .15s; touch-action: manipulation;
}
.menu-cat-pill.active { background: var(--primary); color: #fff; box-shadow: 0 4px 12px rgba(34,90,227,.3); }

.menu-item-card {
  position: relative; display: flex; gap: 14px;
  background: #fff; border-radius: 18px; padding: 14px;
  box-shadow: 0 2px 10px rgba(15,23,42,.06);
  margin-bottom: 14px;
}
.menu-item-card .mi-thumb {
  width: 76px; height: 76px; border-radius: 14px; overflow: hidden; flex-shrink: 0; background: #0F172A;
}
.menu-item-card .mi-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.menu-item-card .mi-thumb-fallback {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: var(--primary-bg);
}
.menu-item-card .mi-body { flex: 1; min-width: 0; padding-right: 42px; transition: padding-right .15s; }
.menu-item-card .mi-body.has-stepper { padding-right: 96px; }
.menu-item-card .mi-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; margin-bottom: 4px; }
.menu-item-card .mi-name { font-weight: 700; font-size: .92rem; line-height: 1.3; }
.menu-item-card .mi-price { font-weight: 800; font-size: .88rem; color: var(--primary); white-space: nowrap; flex-shrink: 0; }
.menu-item-card .mi-desc {
  font-size: .78rem; color: var(--text-muted); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.menu-item-card .mi-action { position: absolute; right: 14px; bottom: 14px; }
.menu-item-card .mi-add {
  width: 36px; height: 36px; border-radius: 50%; border: none;
  background: var(--primary); color: #fff; display: flex; align-items: center; justify-content: center;
  cursor: pointer; box-shadow: 0 4px 12px rgba(34,90,227,.35); touch-action: manipulation;
}
.menu-item-card .mi-add:active { background: var(--primary-dark); transform: scale(.94); }
.menu-item-card .mi-stepper {
  display: none; align-items: center; gap: 7px;
  background: var(--primary-bg); border-radius: 30px; padding: 5px;
  box-shadow: 0 4px 12px rgba(34,90,227,.18);
}
.menu-item-card .mi-step-btn {
  width: 26px; height: 26px; border-radius: 50%; border: none; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; cursor: pointer; touch-action: manipulation;
}
.menu-item-card .mi-step-btn.mi-step-plus { background: var(--primary); color: #fff; }
.menu-item-card .mi-step-btn.mi-step-plus:active { background: var(--primary-dark); }
.menu-item-card .mi-step-btn.mi-step-minus { background: #fff; color: var(--primary); border: 1.5px solid rgba(34,90,227,.25); }
.menu-item-card .mi-step-btn.mi-step-minus:active { background: var(--bg); }
.menu-item-card .mi-qty { font-weight: 800; font-size: .85rem; min-width: 16px; text-align: center; color: var(--text); }
.menu-item-card .mi-unavailable {
  position: absolute; right: 14px; bottom: 14px; font-size: .68rem; font-weight: 700; color: var(--error);
  background: var(--error-bg); padding: 5px 9px; border-radius: 8px;
}

/* ── Floating "View Cart" bar ─────────────────────────────────────────── */
.cart-fab-bar {
  display: none;
  position: fixed; left: 18px; right: 18px; bottom: calc(env(safe-area-inset-bottom) + 18px);
  max-width: calc(var(--app-max-w) - 36px); margin: 0 auto;
  background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
  color: #fff; border-radius: 18px; padding: 15px 20px;
  align-items: center; justify-content: space-between; gap: 14px;
  box-shadow: 0 10px 30px rgba(34,90,227,.4); cursor: pointer; z-index: 300;
  touch-action: manipulation; transition: transform .15s;
}
.cart-fab-bar:active { transform: scale(.98); }
.cart-fab-bar .cfb-left { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cart-fab-bar .cfb-count { font-size: .72rem; font-weight: 600; opacity: .85; }
.cart-fab-bar .cfb-total { font-size: 1.1rem; font-weight: 800; letter-spacing: -.02em; }
.cart-fab-bar .cfb-right { display: flex; align-items: center; gap: 6px; font-weight: 700; font-size: .9rem; flex-shrink: 0; }
</style>

<!-- Topbar -->
<div class="menu-topbar">
  <div class="menu-topbar-left">
    <a href="dashboard.php" id="menuBackLink" onclick="return goBackFromMenu(event)" class="menu-back">
      <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5m0 0l7 7M5 12l7-7"/></svg>
    </a>
    <span class="menu-title">Menu</span>
  </div>
  <div class="menu-topbar-right">
    <a href="notifications.php" class="icon-btn" title="Notifications">
      <svg viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8a6 6 0 10-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 01-3.46 0"/></svg>
      <?php if ($__unread > 0): ?><span class="notif-dot"></span><?php endif; ?>
    </a>
    <a href="profile.php" class="topbar-avatar" style="width:32px;height:32px;font-size:.65rem" title="<?php echo htmlspecialchars($__name); ?>"><?php echo $__avatar_url ? '<img src="' . htmlspecialchars($__avatar_url) . '" alt="">' : $__initials; ?></a>
  </div>
</div>

<!-- Restaurant hero -->
<div class="menu-hero">
  <h1><?php echo htmlspecialchars($restaurant['name']); ?></h1>
  <?php if ($table_num !== ''): ?>
  <p><?php echo $table_type === 'loc' ? htmlspecialchars($table_num) : 'Table ' . htmlspecialchars($table_num); ?></p>
  <?php elseif ($restaurant['address']): ?>
  <p><?php echo htmlspecialchars($restaurant['address']); ?></p>
  <?php endif; ?>
</div>

<!-- Category filter pills -->
<?php if (!$focus_item_id && count($categories) > 0): ?>
<div class="menu-cat-pills">
  <a href="scan.php?rid=<?php echo $rid; ?><?php echo $table_qs; ?>" class="menu-cat-pill<?php echo !$focus_cat_id ? ' active' : ''; ?>">All</a>
  <?php foreach ($categories as $c): ?>
  <a href="scan.php?rid=<?php echo $rid; ?>&cat=<?php echo $c['id']; ?><?php echo $table_qs; ?>" class="menu-cat-pill<?php echo $focus_cat_id == $c['id'] ? ' active' : ''; ?>">
    <?php echo htmlspecialchars($c['name']); ?>
  </a>
  <?php endforeach; ?>
</div>
<?php endif; ?>

<!-- Focused item highlight (from per-item QR) -->
<?php if ($focused_item): ?>
<div style="margin-bottom:24px">
  <div style="font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--primary);margin-bottom:10px;display:flex;align-items:center;gap:8px">
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
      <path d="M3 7V5a2 2 0 012-2h2M17 3h2a2 2 0 012 2v2M21 17v2a2 2 0 01-2 2h-2M7 21H5a2 2 0 01-2-2v-2"/>
      <rect x="7" y="7" width="10" height="10" rx="1"/>
    </svg>
    You scanned this item
  </div>
  <div style="border:2.5px solid var(--primary);border-radius:16px;overflow:hidden;box-shadow:0 8px 28px rgba(34,90,227,.15);max-width:400px">
    <?php if ($focused_item['image'] && file_exists("../restaurantadmin/uploads/menu/" . $focused_item['image'])): ?>
    <img src="../restaurantadmin/uploads/menu/<?php echo htmlspecialchars($focused_item['image']); ?>"
         alt="<?php echo htmlspecialchars($focused_item['name']); ?>"
         style="width:100%;height:200px;object-fit:cover">
    <?php else: ?>
    <div style="height:120px;background:var(--primary-bg);display:flex;align-items:center;justify-content:center">
      <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="var(--primary)" stroke-width="1.5" stroke-linecap="round" opacity=".4">
        <path d="M3 11l19-9-9 19-2-8-8-2z"/>
      </svg>
    </div>
    <?php endif; ?>
    <div style="padding:18px">
      <div style="font-weight:800;font-size:1.05rem;margin-bottom:6px"><?php echo htmlspecialchars($focused_item['name']); ?></div>
      <?php if ($focused_item['description']): ?>
      <div style="font-size:.82rem;color:var(--text-muted);margin-bottom:12px;line-height:1.6"><?php echo htmlspecialchars($focused_item['description']); ?></div>
      <?php endif; ?>
      <div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px">
        <div style="font-size:1.25rem;font-weight:800;color:var(--primary)">₦<?php echo number_format($focused_item['price'], 0); ?></div>
        <?php if ($focused_item['is_available']): ?>
        <?php
          $focused_has_image = $focused_item['image'] && file_exists("../restaurantadmin/uploads/menu/" . $focused_item['image']);
          $focused_img_js    = $focused_has_image ? addslashes('../restaurantadmin/uploads/menu/' . $focused_item['image']) : '';
          $fid               = (int)$focused_item['id'];
          $fname_js          = addslashes($focused_item['name']);
          $fname_attr        = htmlspecialchars($focused_item['name'], ENT_QUOTES);
        ?>
        <div class="mi-action" id="action-<?php echo $fid; ?>" style="position:static">
          <button type="button" class="mi-add" style="width:auto;height:auto;border-radius:10px;padding:11px 24px;gap:8px;display:inline-flex;align-items:center;box-shadow:0 4px 14px rgba(34,90,227,.3)"
                  onclick="addToCart(<?php echo $fid; ?>,'<?php echo $fname_js; ?>',<?php echo $focused_item['price']; ?>,'<?php echo $focused_img_js; ?>')" aria-label="Add <?php echo $fname_attr; ?>">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2.5" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
            Add to Cart
          </button>
          <div class="mi-stepper" style="padding:7px 9px;gap:10px">
            <button type="button" class="mi-step-btn mi-step-minus" style="width:32px;height:32px" onclick="decrementItem(<?php echo $fid; ?>)" aria-label="Remove one <?php echo $fname_attr; ?>">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="5" y1="12" x2="19" y2="12"/></svg>
            </button>
            <span class="mi-qty" style="font-size:1rem">0</span>
            <button type="button" class="mi-step-btn mi-step-plus" style="width:32px;height:32px" onclick="incrementItem(<?php echo $fid; ?>)" aria-label="Add one more <?php echo $fname_attr; ?>">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
            </button>
          </div>
        </div>
        <?php else: ?>
        <span style="font-size:.8rem;color:var(--error);font-weight:600;background:var(--error-bg);padding:8px 16px;border-radius:10px">Currently unavailable</span>
        <?php endif; ?>
      </div>
    </div>
  </div>
  <a href="scan.php?rid=<?php echo $rid; ?><?php echo $table_qs; ?>" style="display:inline-flex;align-items:center;gap:6px;font-size:.8rem;color:var(--primary);font-weight:600;margin-top:12px">
    View full menu →
  </a>
</div>
<?php endif; ?>

<!-- Cart Bar (fixed bottom) -->
<div id="cartBar" class="cart-fab-bar" onclick="goCheckout()">
  <div class="cfb-left">
    <span class="cfb-count" id="cartCount">0 items</span>
    <span class="cfb-total" id="cartTotal">₦0</span>
  </div>
  <div class="cfb-right">
    View Cart
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
  </div>
</div>

<?php if (empty($menu_items) && !$focused_item): ?>
<!-- Empty menu state -->
<div class="card" style="padding:60px;text-align:center;color:var(--text-muted)">
  <svg width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="var(--border)" stroke-width="1.5" stroke-linecap="round" style="margin:0 auto 14px;display:block">
    <path d="M4 6h16M4 10h16M4 14h16M4 18h7"/>
  </svg>
  <p style="font-size:1rem;font-weight:700;margin-bottom:6px">No items available<?php echo $focus_cat_id ? ' in this category' : ''; ?></p>
  <?php if ($focus_cat_id): ?>
  <a href="scan.php?rid=<?php echo $rid; ?><?php echo $table_qs; ?>" style="font-size:.85rem;color:var(--primary);font-weight:600">View full menu →</a>
  <?php else: ?>
  <p style="font-size:.85rem">Check back later or ask the restaurant.</p>
  <?php endif; ?>
</div>

<?php elseif (!$focus_item_id): ?>
<!-- Menu items — one flat, ordered list (category_id, name from the
     query above already keeps things grouped without needing a
     separate header per category; the active pill already says which
     category you're looking at). -->
<div>
  <?php foreach ($menu_items as $item): ?>
    <?php echo render_menu_item($item, $rid); ?>
  <?php endforeach; ?>
</div>
<?php endif; ?>

<script>
// ── "Back" on the menu screen should return to wherever the user came
// from (dashboard, the partner restaurants list, etc.) instead of always
// landing on the QR scanner. We only trust browser history when the
// previous page was actually part of this app; a direct/QR-camera visit
// (no in-app referrer) falls back to the dashboard via the href above.
function goBackFromMenu(e) {
  const cameFromApp = document.referrer && document.referrer.indexOf(window.location.origin) === 0;
  if (cameFromApp && window.history.length > 1) {
    e.preventDefault();
    window.history.back();
    return false;
  }
  return true;
}

let cart = {};

// Restore cart from sessionStorage for this restaurant
try {
  const saved = sessionStorage.getItem('dabil_cart');
  if (saved) {
    const data = JSON.parse(saved);
    if (data.rid === <?php echo $rid; ?>) {
      cart = data.cart || {};
      updateCartBar();
      Object.keys(cart).forEach(syncItemUI);
    }
  }
} catch(e) {}

// ── Per-item add/remove ──────────────────────────────────────────────────
// The "+" button and the (− qty +) stepper are both always present in the
// markup for each item (see render_menu_item in PHP) — this just toggles
// which one is visible, rather than a toast telling you it happened.
function syncItemUI(id) {
  const action = document.getElementById('action-' + id);
  if (!action) return;
  const addBtn  = action.querySelector('.mi-add');
  const stepper = action.querySelector('.mi-stepper');
  const qtyEl   = action.querySelector('.mi-qty');
  const body    = document.getElementById('body-' + id);
  const qty = (cart[id] && cart[id].qty) || 0;
  if (qty > 0) {
    if (addBtn) addBtn.style.display = 'none';
    if (stepper) stepper.style.display = 'flex';
    if (qtyEl) qtyEl.textContent = qty;
    if (body) body.classList.add('has-stepper');
  } else {
    if (addBtn) addBtn.style.display = 'flex';
    if (stepper) stepper.style.display = 'none';
    if (body) body.classList.remove('has-stepper');
  }
}

function addToCart(id, name, price, img) {
  if (!cart[id]) cart[id] = {name, price, qty: 0, img: img || ''};
  cart[id].qty++;
  updateCartBar();
  syncItemUI(id);
}

function incrementItem(id) {
  if (!cart[id]) return;
  cart[id].qty++;
  updateCartBar();
  syncItemUI(id);
}

function decrementItem(id) {
  if (!cart[id]) return;
  cart[id].qty = Math.max(0, cart[id].qty - 1);
  if (cart[id].qty === 0) delete cart[id];
  updateCartBar();
  syncItemUI(id);
}

function updateCartBar() {
  const items      = Object.values(cart);
  const total_qty  = items.reduce((s, i) => s + i.qty, 0);
  const total_price = items.reduce((s, i) => s + (i.price * i.qty), 0);
  const bar = document.getElementById('cartBar');
  if (total_qty > 0) {
    bar.style.display = 'flex';
    document.getElementById('cartCount').textContent = total_qty + ' item' + (total_qty > 1 ? 's' : '');
    document.getElementById('cartTotal').textContent  = '₦' + total_price.toLocaleString('en-NG', {minimumFractionDigits: 0});
  } else {
    bar.style.display = 'none';
  }
  sessionStorage.setItem('dabil_cart', JSON.stringify({cart, rid: <?php echo $rid; ?>}));
}

function goCheckout() {
  const tableQs = <?php echo json_encode($table_qs); ?>;
  window.location.href = 'checkout.php?rid=<?php echo $rid; ?>' + tableQs;
}

<?php if ($focus_item_id): ?>
window.addEventListener('load', () => {
  const el = document.getElementById('item-<?php echo $focus_item_id; ?>');
  if (el) {
    el.style.borderColor = 'var(--primary)';
    el.style.boxShadow   = '0 0 0 3px rgba(34,90,227,.2)';
    el.scrollIntoView({behavior: 'smooth', block: 'center'});
  }
});
<?php endif; ?>
</script>

<?php endif; ?>

<?php include("includes/footer.php"); ?>
