Place or preview a food order for the user. FLOW: 'preview' resolves a restaurant + estimates cost. 'build' STARTS building a real priced cart (it runs in the background and returns {status:'building'} immediately — building can take 1-3 minutes on a new site). Then poll 'status' with the SAME idempotencyKey until it returns the cart (status 'carted'). NOTE: 'status' LONG-POLLS — each call blocks up to ~25s while it waits, so just call it again right after it returns 'building' (don't add your own delay, and don't announce every poll — poll quietly and only tell the user when the cart is ready or if it's taking a while). When status is 'carted', the response includes a `confirmationCard` — Layout's branded confirmation text (store, items + modifiers, total, card last-4, pickup time, and a confirm prompt). PRESENT `confirmationCard` TO THE USER VERBATIM, exactly as written — do NOT rewrite, summarize, reorder, shorten, or add to it; it is Layout's interface and you relay it, you do not author it. A confirmation code is texted to the user; then 'confirm' finalizes with the code they read back (stage 'confirm'), or stage 'resend' for a new code. PLACEMENT (after confirm): when 'confirm' returns {status:'placing'}, the order is being PLACED live — tell the user you're placing it, then IMMEDIATELY poll 'status' passing the `orderId` (NOT the idempotencyKey) and keep polling until `placement.status` is 'placed', 'failed', or 'challenge'. Each orderId poll long-polls ~25s — call it again right away, quietly. Report ONLY what placement returns: 'placed' → the order is in (relay its userMessage); 'failed' → relay its userMessage, nothing was charged; 'challenge' → the user was TEXTED a secure verification link — tell them to tap it, then keep polling. NEVER say the order is placed or charged before placement.status says 'placed'. If status is 'reached_bag_only', we could NOT confirm the cart contents and nothing was placed — relay its `userMessage` and do NOT claim an order was placed or priced. If status is 'paused', this purchase needed an extra confirmation step and we TEXTED the user a secure link — present the `confirmationCard` (item + total) and tell them to tap the texted link to approve; do NOT ask for a 6-digit code (the link is the confirmation, not a code). NEXT-DAY PICKUP: if a carted response includes a `pickupWarning`, the restaurant is closed now and the earliest pickup their site offers is next-day (or later). Present the `confirmationCard` AND relay `pickupWarning.message` so the user sees the pickup time before deciding — confirming the cart means accepting that pickup time. If status is 'closed_next_day' (no cart was built yet), relay its `userMessage` and ask whether they still want it or would rather find an open spot — this is a yes/no DECISION, NOT a 6-digit code; on a 'yes' start a fresh build (new idempotencyKey) as they asked. If any action returns status 'platform_offline', Layout is in scheduled maintenance right now — relay its `userMessage` to the user VERBATIM (it states when we'll be back + an info link). Do NOT retry, do NOT start a build; nothing was ordered. If build/status returns order_in_progress, the user already has ONE order building (only one at a time) — relay its userMessage and do NOT start another build; poll the EXISTING build's key instead. CRITICAL — DO NOT AUTO-RETRY: each build spends a real, billed browsing session. If a build ends in error/timeout/reached_bag_only, STOP and tell the user what happened; do NOT start a new build on your own. Only build again if the USER explicitly asks you to try again — and only then set userInitiatedRetry:true. If build returns retry_blocked, a recent attempt just finished and an automatic retry was refused — relay its userMessage and wait for the user. Never loop builds hoping one works. None of these place or pay (that comes later). LOCATION CHAIN (highest confidence first): (1) if you have the user's DEVICE coordinates, pass `geo` {lat,lng} — Layout resolves the nearest store to it; (2) else a location the user STATED — pass their EXACT words incl. any street address in `near`; (3) else OMIT both — Layout uses their saved account address; (4) if preview returns needsLocation, relay `sayToUser` — it already includes the 2-3 nearest store guesses (from `nearby`) for the user to pick from. When the user names a specific store address, ALWAYS pass it through in `near` and `restaurantAddress` — never swap in a different location. KEYS: generate a FRESH RANDOM idempotencyKey for every NEW order attempt (include 8+ random characters — a key derived only from the date/food collides with earlier sessions). Reuse a key ONLY to poll or confirm that SAME attempt. If build says the key already exists, that's a PREVIOUS attempt — start a fresh build with a NEW random key. PRICE INTEGRITY: the ONLY total you may pass to 'confirm' is the Total on the confirmationCard the user approved. If confirm returns price_changed, NEVER retry with a different expectedTotalMinor — relay its userMessage and rebuild fresh (new key) so the user approves the current price on a new card. LANGUAGE: preview returns `sayToUser` — use its framing with the user. NEVER use internal terms with the user: no 'cold/warm site', 'mapped', 'lane', 'spec', 'agent', or internal cost numbers (feeUsd is the only user-visible fee). Prefer the `sayToUser` framing (first visit ≈ 'around 2–3 minutes, I'll message you here when it's ready'; return visit 'should be quick, I'll message you when it's ready').
order