$sizeLimit) jsonResponse(['error' => 'payload too large'], 413); // Each route file contains its handlers as if-blocks that exit on // match. Order matters: public.php sets up $sessionTenant which // admin.php and messages.php use later in the chain. require __DIR__ . '/inc/routes/public.php'; require __DIR__ . '/inc/routes/account.php'; require __DIR__ . '/inc/routes/admin.php'; require __DIR__ . '/inc/routes/messages.php'; require __DIR__ . '/inc/routes/chat.php'; require __DIR__ . '/inc/routes/collab-buckets.php'; require __DIR__ . '/inc/routes/collab-cards.php'; require __DIR__ . '/inc/routes/collab-locks.php'; require __DIR__ . '/inc/routes/shopping.php'; jsonResponse(['error' => 'not found'], 404); } // ── UI ───────────────────────────────────────────────────────────── // Shopping UI lives outside /api/ so phones can bookmark a clean URL. // File has both /api/shopping* and /shopping handlers; they short- // circuit on match, so loading it here for the non-API path is safe. require __DIR__ . '/inc/routes/shopping.php'; require __DIR__ . '/ui/layout.php';