(function () {
  "use strict";

  const config = window.FoodordTableReservations || {};
  const i18n = config.i18n || {};
  const sessionKey = "foodord_reservation_session";
  const stateKeyPrefix = "foodord_reservation_state:";
  const successAnimationClass = "is-animated";
  const tableSelectionLayoutClass = "foodord-table-reservations--table-selection-active";
  const preorderLayoutClass = "foodord-table-reservations--preorder-active";
  const preorderMobileCartBodyClass = "foodord-reservation-preorder-active";
  const preorderMobileCartOpenBodyClass = "foodord-reservation-preorder-cart-open";
  const preorderMobileCartItemsClass = "has-mobile-cart";
  const preorderNoteMaxLength = Math.max(1, Math.min(160, parseInt(config.noteMaxLength, 10) || 160));
  const initializedReservationForms = new WeakSet();
  const initializedManageForms = new WeakSet();
  const initializedManageSuccessPanels = new WeakSet();
  const initializedDepositCancellationNotices = new WeakSet();
  const normalizedReservationRoots = new WeakSet();
  let reservationControlIdSequence = 0;

  function setCssVariable(element, property, value) {
    const inlineStyles = element.style;

    inlineStyles.setProperty(property, String(value));
  }

  function removeCssVariable(element, property) {
    const inlineStyles = element.style;

    inlineStyles.removeProperty(property);
  }

  function setOptionalColorVariable(element, property, value) {
    const color = String(value || "").trim();

    if (/^#[0-9a-f]{6}$/i.test(color)) {
      setCssVariable(element, property, color);
    } else {
      removeCssVariable(element, property);
    }
  }

  function setGridGeometry(element, geometry) {
    const x = Math.min(98, Math.max(2, Number(geometry.x) || 50));
    const y = Math.min(98, Math.max(2, Number(geometry.y) || 50));
    const width = Math.min(60, Math.max(4, Number(geometry.width) || 16));
    const height = Math.min(60, Math.max(4, Number(geometry.height) || 12));
    const rotation = Math.min(180, Math.max(-180, Number(geometry.rotation) || 0));

    setCssVariable(element, "--foodord-grid-x", x + "%");
    setCssVariable(element, "--foodord-grid-y", y + "%");
    setCssVariable(element, "--foodord-grid-width", width + "%");
    setCssVariable(element, "--foodord-grid-height", height + "%");
    setCssVariable(element, "--foodord-grid-rotation", rotation + "deg");
    setOptionalColorVariable(element, "--foodord-image-marker-fill", geometry.fill);
    setOptionalColorVariable(element, "--foodord-image-marker-text-color", geometry.text_color);
  }

  function getGridSeatCounts(table) {
    const safeCount = Math.min(16, Math.max(1, Number(table.capacity) || 1));
    const rawCounts = [table.seat_top, table.seat_right, table.seat_bottom, table.seat_left].map((count) => Math.min(16, Math.max(0, Number(count) || 0)));
    const rawTotal = rawCounts.reduce((sum, count) => sum + count, 0);

    if (rawTotal <= 0) {
      const balanced = [0, 0, 0, 0];
      for (let index = 0; index < safeCount; index += 1) {
        balanced[index % 4] += 1;
      }
      return balanced;
    }
    if (rawTotal === safeCount) {
      return rawCounts;
    }

    const scaled = rawCounts.map((count) => (count / rawTotal) * safeCount);
    const normalized = scaled.map((count) => Math.floor(count));
    const priority = scaled
      .map((count, index) => ({ index, remainder: count - normalized[index] }))
      .sort((first, second) => second.remainder - first.remainder);
    let remaining = safeCount - normalized.reduce((sum, count) => sum + count, 0);

    while (remaining > 0) {
      normalized[priority[(safeCount - remaining) % priority.length].index] += 1;
      remaining -= 1;
    }

    return normalized;
  }

  function getGridSeatPositions(table) {
    const safeCount = Math.min(16, Math.max(1, Number(table.capacity) || 1));
    const positions = [];

    if (table.shape === "round" && table.seat_mode === "even") {
      for (let index = 0; index < safeCount; index += 1) {
        const angle = -90 + (index / safeCount) * 360;
        const radians = (angle * Math.PI) / 180;
        positions.push([50 + Math.cos(radians) * 50, 50 + Math.sin(radians) * 50, angle + 90]);
      }
      return positions;
    }

    const sideCounts = getGridSeatCounts(table);
    sideCounts.forEach((sideCount, side) => {
      for (let index = 0; index < sideCount; index += 1) {
        const offset = ((index + 1) / (sideCount + 1)) * 100;

        if (side === 0) {
          positions.push([offset, 0, 0]);
        } else if (side === 1) {
          positions.push([100, offset, 90]);
        } else if (side === 2) {
          positions.push([100 - offset, 100, 180]);
        } else {
          positions.push([0, 100 - offset, -90]);
        }
      }
    });

    return positions;
  }

  function appendGridSeats(marker, table) {
    const seats = document.createElement("span");
    seats.className = "foodord-table-reservations__table-selection-seats";

    getGridSeatPositions(table).forEach((position) => {
      const seat = document.createElement("span");
      seat.className = "foodord-table-reservations__table-selection-seat";
      setCssVariable(seat, "--foodord-seat-left", position[0] + "%");
      setCssVariable(seat, "--foodord-seat-top", position[1] + "%");
      setCssVariable(seat, "--foodord-seat-rotation", position[2] + "deg");
      seats.appendChild(seat);
    });

    marker.appendChild(seats);
  }

  function createFloorDoorGraphic() {
    const namespace = ["http:/", "/www.w3.org/2000/svg"].join("");
    const graphic = document.createElementNS(namespace, "svg");
    const frame = document.createElementNS(namespace, "path");
    const swing = document.createElementNS(namespace, "path");
    const hinge = document.createElementNS(namespace, "circle");

    graphic.classList.add("foodord-table-reservations__floor-door-graphic");
    graphic.setAttribute("viewBox", "0 0 100 100");
    graphic.setAttribute("aria-hidden", "true");
    graphic.setAttribute("focusable", "false");
    frame.classList.add("foodord-table-reservations__floor-door-frame");
    frame.setAttribute("d", "M2 92H10M90 92H98M10 92V12");
    swing.classList.add("foodord-table-reservations__floor-door-swing");
    swing.setAttribute("d", "M10 12A80 80 0 0 1 90 92");
    hinge.classList.add("foodord-table-reservations__floor-door-hinge");
    hinge.setAttribute("cx", "10");
    hinge.setAttribute("cy", "92");
    hinge.setAttribute("r", "3.5");
    graphic.append(frame, swing, hinge);

    return graphic;
  }

  function createGridObject(object) {
    const element = document.createElement("span");
    const visual = document.createElement("span");
    const type = String(object.type || "rectangle");

    element.className = "foodord-table-reservations__floor-object foodord-table-reservations__floor-object--" + type;
    visual.className = "foodord-table-reservations__floor-object-visual";
    visual.textContent = type === "text" ? String(object.text || "") : "";
    setCssVariable(visual, "--foodord-object-fill", object.fill || "#f3f4f6");
    setCssVariable(visual, "--foodord-object-stroke", object.stroke || "#6b7280");
    setCssVariable(visual, "--foodord-object-border-width", Math.min(6, Math.max(0, Number(object.border_width) || 0)) + "px");
    setCssVariable(visual, "--foodord-object-flip-x", object.flip_x ? "-1" : "1");
    if (type === "door") {
      visual.appendChild(createFloorDoorGraphic());
    }
    element.appendChild(visual);
    setGridGeometry(element, object);

    return element;
  }

  function ready(fn) {
    if (document.readyState === "loading") {
      document.addEventListener("DOMContentLoaded", fn, { passive: true });
      return;
    }
    fn();
  }

  function ensureUniqueReservationControlIds(root) {
    if (!root || normalizedReservationRoots.has(root)) {
      return;
    }

    normalizedReservationRoots.add(root);
    const replacements = new Map();
    const elementsById = new Map();

    document.querySelectorAll("[id]").forEach((element) => {
      const elements = elementsById.get(element.id) || [];
      elements.push(element);
      elementsById.set(element.id, elements);
    });

    root.querySelectorAll("[id]").forEach((element) => {
      const currentId = element.id || "";
      const isReservationControl = currentId.startsWith("foodord-reservation-") || currentId.startsWith("foodord-preorder-");
      const matchingElements = currentId ? elementsById.get(currentId) || [] : [];

      if (!isReservationControl || matchingElements.length < 2) {
        return;
      }

      let nextId = "";
      do {
        reservationControlIdSequence += 1;
        nextId = currentId + "-instance-" + reservationControlIdSequence;
      } while (document.getElementById(nextId));

      replacements.set(currentId, nextId);
      element.id = nextId;
    });

    if (!replacements.size) {
      return;
    }

    root.querySelectorAll("[for], [aria-describedby], [aria-labelledby], [aria-controls]").forEach((element) => {
      ["for", "aria-describedby", "aria-labelledby", "aria-controls"].forEach((attribute) => {
        const value = element.getAttribute(attribute);
        if (!value) {
          return;
        }

        const references = value.split(/\s+/).map((reference) => replacements.get(reference) || reference);
        element.setAttribute(attribute, references.join(" "));
      });
    });
  }

  function prepareDatePicker(picker) {
    if (picker.hasClass("hasDatepicker") && !picker.data("datepicker")) {
      picker.removeClass("hasDatepicker");
    }
  }

  function prepareDatePickerWidget(widget) {
    widget.removeClass("ui-widget-content").addClass("foodord-table-reservations-datepicker");
  }

  function getCustomerSession() {
    try {
      const existing = window.localStorage.getItem(sessionKey);
      if (existing) {
        return existing;
      }

      const next = Math.random().toString(36).slice(2) + Date.now().toString(36);
      window.localStorage.setItem(sessionKey, next);
      return next;
    } catch (_error) {
      void _error;
      return Date.now().toString(36);
    }
  }

  function post(action, data) {
    const payload = new URLSearchParams();
    payload.set("action", action);
    payload.set("nonce", config.nonce || "");

    Object.keys(data || {}).forEach((key) => {
      payload.set(key, data[key] === null || typeof data[key] === "undefined" ? "" : String(data[key]));
    });

    return fetch(config.ajaxUrl || "", {
      method: "POST",
      credentials: "same-origin",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
      },
      body: payload.toString()
    }).then((response) => response.json());
  }

  function isRecaptchaEnabled() {
    return !!(config.recaptcha && config.recaptcha.enabled && config.recaptcha.siteKey);
  }

  function executeRecaptcha(actionKey) {
    if (!isRecaptchaEnabled()) {
      return Promise.resolve("");
    }

    const recaptcha = config.recaptcha || {};
    const actions = recaptcha.actions || {};
    const action = actions[actionKey] || "";

    if (!action || !window.grecaptcha || typeof window.grecaptcha.ready !== "function" || typeof window.grecaptcha.execute !== "function") {
      return Promise.reject(new Error(i18n.securityFailed || "Security verification failed. Please try again."));
    }

    return new Promise((resolve, reject) => {
      window.grecaptcha.ready(() => {
        window.grecaptcha.execute(recaptcha.siteKey, { action: action })
          .then(resolve)
          .catch(() => {
            reject(new Error(i18n.securityFailed || "Security verification failed. Please try again."));
          });
      });
    });
  }

  function getNavigationType() {
    if (!window.performance || typeof window.performance.getEntriesByType !== "function") {
      return "";
    }

    const entries = window.performance.getEntriesByType("navigation");
    const navigation = entries && entries[0] ? entries[0] : null;

    return navigation && typeof navigation.type === "string" ? navigation.type : "";
  }

  function shouldRestoreReservationState() {
    return getNavigationType() === "reload";
  }

  function formatTime(seconds) {
    const safeSeconds = Math.max(0, seconds);
    const minutes = Math.floor(safeSeconds / 60);
    const rest = safeSeconds % 60;
    return String(minutes).padStart(2, "0") + ":" + String(rest).padStart(2, "0");
  }

  function formatDateKey(date) {
    const month = String(date.getMonth() + 1).padStart(2, "0");
    const day = String(date.getDate()).padStart(2, "0");

    return String(date.getFullYear()) + "-" + month + "-" + day;
  }

  function isDateDisabledByBookingRules(date) {
    const disabled = config.dateDisabled || {};
    const weekdays = Array.isArray(disabled.weekdays) ? disabled.weekdays.map((day) => Number(day)) : [];

    if (weekdays.includes(date.getDay())) {
      return true;
    }

    const dateKey = formatDateKey(date);
    const ranges = Array.isArray(disabled.ranges) ? disabled.ranges : [];

    return ranges.some((range) => {
      const from = range && typeof range.from === "string" ? range.from : "";
      const to = range && typeof range.to === "string" ? range.to : from;

      return from && dateKey >= from && dateKey <= to;
    });
  }

  function getDatepickerAvailability(date) {
    return isDateDisabledByBookingRules(date)
      ? [false, "foodord-table-reservations-datepicker-unavailable", ""]
      : [true, "", ""];
  }

  function parseDatepickerValue(value) {
    if (!value || !window.jQuery || !window.jQuery.datepicker || typeof window.jQuery.datepicker.parseDate !== "function") {
      return null;
    }

    try {
      return window.jQuery.datepicker.parseDate(config.dateFormat || "yy-mm-dd", value);
    } catch (_error) {
      void _error;
      return null;
    }
  }

  function setButtonBusy(button, busy, busyText) {
    if (!button) {
      return;
    }

    if (!button.dataset.originalHtml) {
      button.dataset.originalHtml = button.innerHTML;
    }

    button.disabled = busy;
    button.classList.toggle("is-loading", busy);
    button.setAttribute("aria-busy", busy ? "true" : "false");
    if (busy && busyText) {
      button.textContent = busyText;
      return;
    }

    if (!busy) {
      button.innerHTML = button.dataset.originalHtml;
    }
  }

  function setPreorderModalButtonBusy(button, busy) {
    setButtonBusy(button, busy, "");
    if (!button || !busy) {
      return;
    }

    const spinner = document.createElement("span");
    spinner.className = "foodord-add-to-cart-spinner";
    spinner.setAttribute("aria-hidden", "true");

    const status = document.createElement("span");
    status.className = "screen-reader-text";
    status.textContent = i18n.adding || "Adding…";

    button.replaceChildren(spinner, status);
  }

  function initReservationForm(root) {
    ensureUniqueReservationControlIds(root);
    const form = root.querySelector("[data-foodord-reservation-form]");
    if (!form || initializedReservationForms.has(form)) {
      return;
    }
    initializedReservationForms.add(form);
    form.dataset.foodordReservationReady = "1";

    const rootIndex = Array.from(document.querySelectorAll("[data-foodord-reservations]")).indexOf(root);
    const stateKey = stateKeyPrefix + window.location.pathname + ":" + Math.max(0, rootIndex);
    const holdButton = form.querySelector("[data-foodord-reservation-hold]");
    const backButton = root.querySelector("[data-foodord-reservation-back]");
    const cancelHoldButton = form.querySelector("[data-foodord-reservation-cancel-hold]");
    const submitButton = form.querySelector("[data-foodord-reservation-submit]");
    const formTitle = root.querySelector("[data-foodord-reservation-form-title]");
    const formDescription = root.querySelector("[data-foodord-reservation-form-description]");
    const slotPanel = form.querySelector("[data-foodord-reservation-slot]");
    const holdPanel = form.querySelector("[data-foodord-reservation-hold-panel]");
    const customerPanel = form.querySelector("[data-foodord-reservation-customer]");
    const preorderChoicePanel = form.querySelector("[data-foodord-reservation-preorder-choice]");
    const preorderAcceptButton = form.querySelector("[data-foodord-reservation-preorder-accept]");
    const preorderDeclineButton = form.querySelector("[data-foodord-reservation-preorder-decline]");
    const preorderPanel = form.querySelector("[data-foodord-reservation-preorder]");
    const preorderProducts = form.querySelector("[data-foodord-reservation-preorder-products]");
    const preorderBackToTop = form.querySelector("[data-foodord-reservation-preorder-back-to-top]");
    const preorderCategoryNav = form.querySelector("[data-foodord-reservation-preorder-navigation]");
    const preorderCategoryButtons = form.querySelectorAll("[data-foodord-reservation-preorder-category-button]");
    const preorderCategorySections = form.querySelectorAll("[data-foodord-reservation-preorder-category]");
    const preorderItems = form.querySelector("[data-foodord-reservation-preorder-items]");
    const preorderEmpty = form.querySelector("[data-foodord-reservation-preorder-empty]");
    const preorderTotal = form.querySelector("[data-foodord-reservation-preorder-total]");
    const preorderTotalValue = form.querySelector("[data-foodord-reservation-preorder-total-value]");
    const preorderMessages = form.querySelectorAll("[data-foodord-reservation-preorder-message]");
    const preorderCheckoutButton = form.querySelector("[data-foodord-reservation-preorder-checkout]");
    const preorderClearButton = form.querySelector("[data-foodord-reservation-preorder-clear]");
    const preorderMobileCart = form.querySelector("[data-foodord-reservation-preorder-mobile-cart]");
    const preorderMobileCartTrigger = form.querySelector("[data-foodord-reservation-preorder-mobile-cart-trigger]");
    const preorderMobileCartCount = form.querySelector("[data-foodord-reservation-preorder-mobile-cart-count]");
    const preorderMobileCartTotal = form.querySelector("[data-foodord-reservation-preorder-mobile-cart-total]");
    const preorderMobileCartCloseButtons = form.querySelectorAll("[data-foodord-reservation-preorder-mobile-cart-close]");
    const preorderMobileCartStack = preorderMobileCart ? preorderMobileCart.querySelector(".foodord-table-reservations__preorder-summary-stack") : null;
    const preorderMobileCartTitle = preorderMobileCart ? preorderMobileCart.querySelector(".foodord-table-reservations__preorder-summary-title") : null;
    const preorderMobileCartCloseButton = preorderMobileCart ? preorderMobileCart.querySelector(".foodord-table-reservations__preorder-mobile-close") : null;
    const preorderLeaveButtons = form.querySelectorAll("[data-foodord-reservation-preorder-leave]");
    const preorderClearModal = form.querySelector("[data-foodord-reservation-preorder-clear-modal]");
    const preorderClearCloseButtons = form.querySelectorAll("[data-foodord-reservation-preorder-clear-close]");
    const preorderClearConfirm = form.querySelector("[data-foodord-reservation-preorder-clear-confirm]");
    const preorderLeaveModal = form.querySelector("[data-foodord-reservation-preorder-leave-modal]");
    const preorderLeaveCloseButtons = form.querySelectorAll("[data-foodord-reservation-preorder-leave-close]");
    const preorderLeaveConfirm = form.querySelector("[data-foodord-reservation-preorder-leave-confirm]");
    const submitLabel = form.querySelector("[data-foodord-reservation-submit-label]");
    const doneMarker = root.querySelector("[data-foodord-reservation-done-marker]");
    const tableSelectionPanel = form.querySelector("[data-foodord-reservation-table-selection]");
    const tableSelectionFloors = form.querySelector("[data-foodord-reservation-table-selection-floors]");
    const tableSelectionPlan = form.querySelector("[data-foodord-reservation-table-selection-plan]");
    const tableSelectionMessages = form.querySelectorAll("[data-foodord-reservation-table-selection-message]");
    const tableSelectionBackButton = form.querySelector("[data-foodord-reservation-table-selection-back]");
    const holdText = form.querySelector("[data-foodord-reservation-hold-text]");
    const countdown = form.querySelector("[data-foodord-reservation-countdown]");
    const messages = form.querySelectorAll("[data-foodord-reservation-message]");
    const fieldErrors = form.querySelectorAll("[data-foodord-reservation-field-error]");
    const successPanel = form.querySelector("[data-foodord-reservation-success]");
    const successTitle = form.querySelector("[data-foodord-reservation-success-title]");
    const successText = form.querySelector("[data-foodord-reservation-success-text]");
    const successCodeRow = form.querySelector("[data-foodord-reservation-success-code-row]");
    const successCode = form.querySelector("[data-foodord-reservation-success-code]");
    const homeButton = form.querySelector("[data-foodord-reservation-home]");
    const slotInputs = form.querySelectorAll("[name='date'], [name='time'], [name='party_size']");
    const dateField = form.querySelector("[name='date']");
    const timeField = form.querySelector("[name='time']");
    const partySizeField = form.querySelector("[name='party_size']");
    const timeFieldWrapper = timeField ? timeField.closest(".foodord-table-reservations__field") : null;
    let holdToken = "";
    let countdownTimer = 0;
    let holdExpiresAt = 0;
    let holdUsesSelectedTable = false;
    let availabilityConfirmed = false;
    let selectedTableId = 0;
    let selectedTableName = "";
    let preorderAvailable = false;
    let preorderRequired = false;
    let preorderChoiceActive = false;
    let preorderDraftToken = "";
    let preorderActive = false;
    let preorderPaymentEdit = false;
    let timeLoadRequestId = 0;
    let timeLoadPromise = Promise.resolve();
    let partySizeLoadTimer = 0;
    let tableSelectionRequestId = 0;
    let isTimeLoading = false;
    let slotAvailabilityMessage = "";
    let preorderCategoryFrame = 0;
    let preorderLabelRowFrame = 0;
    let preorderMobileCartCloseTimer = 0;
    let preorderMobileCartPreviousFocus = null;
    const preorderModalCloseTimers = new WeakMap();
    const preorderMobileMedia = window.matchMedia("(max-width: 720px)");
    const partySizeLoadDelay = 250;

    function triggerDateChange() {
      if (!dateField) {
        return;
      }

      dateField.dispatchEvent(new Event("change", { bubbles: true }));
    }

    function initDatePicker() {
      if (!dateField || !window.jQuery || typeof window.jQuery.fn.datepicker !== "function") {
        return;
      }

      const picker = window.jQuery(dateField);
      prepareDatePicker(picker);
      const options = {
        beforeShow: function (_input, instance) {
          window.setTimeout(function () {
            prepareDatePickerWidget(instance.dpDiv);
          }, 0);
        },
        beforeShowDay: getDatepickerAvailability,
        dateFormat: config.dateFormat || "yy-mm-dd",
        minDate: Number.isFinite(Number(config.dateMinOffset)) ? Number(config.dateMinOffset) : 0,
        onSelect: triggerDateChange
      };

      if (Number.isFinite(Number(config.dateMaxOffset)) && Number(config.dateMaxOffset) > 0) {
        options.maxDate = Number(config.dateMaxOffset);
      }

      picker.datepicker(options);
      prepareDatePickerWidget(picker.datepicker("widget"));
    }

    function setReservationStep(step) {
      const currentStep = root.getAttribute("data-foodord-reservation-step");

      if (currentStep && currentStep !== step) {
        clearValidationFeedback();
      }

      root.setAttribute("data-foodord-reservation-step", step);
      document.body.classList.toggle(preorderMobileCartBodyClass, step === "preorder");
      if (step !== "preorder") {
        setPreorderMobileCart(false, false);
      }
      document.dispatchEvent(new CustomEvent("foodord_cart_updated"));
      if (backButton) {
        backButton.disabled = step !== "contact";
      }
    }

    function getStoredState() {
      try {
        const raw = window.sessionStorage.getItem(stateKey);
        if (!raw) {
          return null;
        }

        const parsed = JSON.parse(raw);
        return parsed && typeof parsed === "object" ? parsed : null;
      } catch (_error) {
        void _error;
        return null;
      }
    }

    function setStoredState(data) {
      try {
        window.sessionStorage.setItem(stateKey, JSON.stringify(data));
      } catch (_error) {
        void _error;
      }
    }

    function clearStoredState() {
      try {
        window.sessionStorage.removeItem(stateKey);
      } catch (_error) {
        void _error;
      }
    }

    function getInitialSuccessPayload() {
      const raw = root.getAttribute("data-foodord-reservation-success-payload");
      if (!raw) {
        return null;
      }

      try {
        const parsed = JSON.parse(raw);

        return parsed && typeof parsed === "object" ? parsed : null;
      } catch (_error) {
        void _error;
        return null;
      }
    }

    function getInitialPreorderEditPayload() {
      const raw = root.getAttribute("data-foodord-preorder-edit-payload");
      if (!raw) {
        return null;
      }

      try {
        const parsed = JSON.parse(raw);

        return parsed && typeof parsed === "object" ? parsed : null;
      } catch (_error) {
        void _error;
        return null;
      }
    }

    function resetReservationFlow(shouldReleaseHold) {
      if (shouldReleaseHold && holdToken) {
        releaseHold();
      }

      form.reset();
      hideHold();
      slotAvailabilityMessage = "";
      setTimeOptions([], "");
    }

    function setMessage(text, type) {
      if (!messages.length) {
        return;
      }

      messages.forEach((message) => {
        message.textContent = text || "";
        message.classList.remove("is-error", "is-success", "is-info");
        if (type) {
          message.classList.add("is-" + type);
        }
      });
    }

    function setPreorderMessage(text, type) {
      if (!preorderMessages.length) {
        return;
      }

      preorderMessages.forEach((message) => {
        message.textContent = text || "";
        message.classList.remove("is-error", "is-success", "is-info");
        if (type) {
          message.classList.add("is-" + type);
        }
      });
    }

    function finalizePreorderMobileCartClose() {
      if (!preorderMobileCart || !preorderMobileCartStack) {
        return;
      }

      preorderMobileCart.classList.remove("is-closing");
      preorderMobileCartStack.removeAttribute("role");
      preorderMobileCartStack.removeAttribute("aria-modal");
      preorderMobileCartStack.removeAttribute("aria-labelledby");
    }

    function setPreorderMobileCart(open, restoreFocus = true) {
      if (!preorderMobileCart || !preorderMobileCartTrigger || !preorderMobileCartStack) {
        return;
      }

      window.clearTimeout(preorderMobileCartCloseTimer);
      preorderMobileCartCloseTimer = 0;

      if (open) {
        if (!preorderMobileMedia.matches || preorderMobileCartTrigger.hidden) {
          return;
        }

        preorderMobileCartPreviousFocus = document.activeElement;
        preorderMobileCart.classList.remove("is-closing");
        preorderMobileCart.classList.add("is-open");
        preorderMobileCartStack.setAttribute("role", "dialog");
        preorderMobileCartStack.setAttribute("aria-modal", "true");
        if (preorderMobileCartTitle && preorderMobileCartTitle.id) {
          preorderMobileCartStack.setAttribute("aria-labelledby", preorderMobileCartTitle.id);
        }
        preorderMobileCartTrigger.setAttribute("aria-expanded", "true");
        document.body.classList.add(preorderMobileCartOpenBodyClass);
        window.requestAnimationFrame(() => {
          if (preorderMobileCartCloseButton) {
            preorderMobileCartCloseButton.focus({ preventScroll: true });
          }
        });
        return;
      }

      const shouldAnimate = preorderMobileMedia.matches && preorderMobileCart.classList.contains("is-open");
      preorderMobileCart.classList.remove("is-open");
      preorderMobileCartTrigger.setAttribute("aria-expanded", "false");
      document.body.classList.remove(preorderMobileCartOpenBodyClass);

      if (shouldAnimate) {
        preorderMobileCart.classList.add("is-closing");
        preorderMobileCartCloseTimer = window.setTimeout(() => {
          finalizePreorderMobileCartClose();
          preorderMobileCartCloseTimer = 0;
        }, 280);
      } else {
        finalizePreorderMobileCartClose();
      }

      if (restoreFocus && preorderMobileCartPreviousFocus && !preorderMobileCartTrigger.hidden && typeof preorderMobileCartPreviousFocus.focus === "function") {
        preorderMobileCartPreviousFocus.focus({ preventScroll: true });
      }
      preorderMobileCartPreviousFocus = null;
    }

    function setPreorderConfirmModal(modal, trigger, open) {
      if (!modal) {
        return;
      }

      const closeTimer = preorderModalCloseTimers.get(modal);
      if (closeTimer) {
        window.clearTimeout(closeTimer);
        preorderModalCloseTimers.delete(modal);
      }

      if (open) {
        modal.hidden = false;
        window.requestAnimationFrame(() => modal.classList.add("is-open"));
      } else {
        modal.classList.remove("is-open");
        preorderModalCloseTimers.set(modal, window.setTimeout(() => {
          modal.hidden = true;
          preorderModalCloseTimers.delete(modal);
        }, 160));
      }

      if (trigger) {
        trigger.setAttribute("aria-expanded", open ? "true" : "false");
      }
    }

    function setPreorderClearModal(open) {
      setPreorderConfirmModal(preorderClearModal, preorderClearButton, open);
    }

    function setPreorderLeaveModal(open) {
      setPreorderConfirmModal(preorderLeaveModal, null, open);
      preorderLeaveButtons.forEach((button) => {
        button.setAttribute("aria-expanded", open ? "true" : "false");
      });
    }

    function createPreorderQuantityButton(label, action, itemKey, removesItem = false) {
      const button = document.createElement("button");
      button.type = "button";
      button.className = "foodord-table-reservations__preorder-quantity-button" + (removesItem ? " is-remove" : "");
      button.dataset.foodordPreorderItemAction = action;
      button.dataset.itemKey = itemKey;
      button.setAttribute("aria-label", label);
      if (removesItem) {
        button.innerHTML = '<svg viewBox="0 0 24 24" aria-hidden="true"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>';
      } else {
        button.textContent = action === "increase" ? "+" : "−";
      }
      return button;
    }

    function formatPreorderNoteCounter(value) {
      return Math.max(0, preorderNoteMaxLength - String(value || "").length) + "/" + preorderNoteMaxLength;
    }

    function createPreorderNoteEditor(item) {
      const note = String(item.note || "").slice(0, preorderNoteMaxLength);
      const hasNote = note.length > 0;
      const itemKey = String(item.itemKey || "");
      const fieldId = "foodord-preorder-note-" + itemKey.replace(/[^a-zA-Z0-9_-]/g, "");
      const wrapper = document.createElement("div");
      wrapper.className = "foodord-table-reservations__preorder-item-note" + (hasNote ? " has-note" : "");
      wrapper.dataset.foodordPreorderNote = note;

      const toggle = document.createElement("button");
      toggle.type = "button";
      toggle.className = "foodord-table-reservations__preorder-note-toggle";
      toggle.dataset.foodordPreorderNoteAction = "toggle";
      toggle.textContent = hasNote ? i18n.editNote || "Edit note" : i18n.addNote || "Add note";
      wrapper.appendChild(toggle);

      const form = document.createElement("div");
      form.className = "foodord-table-reservations__preorder-note-form";
      form.dataset.foodordPreorderNoteForm = "1";
      form.hidden = true;

      const label = document.createElement("label");
      label.className = "screen-reader-text";
      label.htmlFor = fieldId;
      label.textContent = i18n.addNote || "Add note";
      form.appendChild(label);

      const counter = document.createElement("div");
      counter.className = "foodord-table-reservations__preorder-note-counter";
      counter.dataset.foodordPreorderNoteCounter = "1";
      counter.setAttribute("aria-hidden", "true");
      counter.textContent = formatPreorderNoteCounter(note);
      form.appendChild(counter);

      const input = document.createElement("textarea");
      input.id = fieldId;
      input.className = "foodord-table-reservations__preorder-note-input";
      input.dataset.foodordPreorderNoteInput = "1";
      input.maxLength = preorderNoteMaxLength;
      input.placeholder = String(i18n.notePlaceholder || "Add a note (max {max} characters)").replace("{max}", String(preorderNoteMaxLength));
      input.value = note;
      form.appendChild(input);

      const actions = document.createElement("div");
      actions.className = "foodord-table-reservations__preorder-note-actions";

      const cancel = document.createElement("button");
      cancel.type = "button";
      cancel.className = "foodord-table-reservations__preorder-note-button foodord-table-reservations__preorder-note-button--secondary";
      cancel.dataset.foodordPreorderNoteAction = hasNote ? "delete" : "cancel";
      cancel.textContent = hasNote ? i18n.delete || "Delete" : i18n.cancel || "Cancel";
      actions.appendChild(cancel);

      const save = document.createElement("button");
      save.type = "button";
      save.className = "foodord-table-reservations__preorder-note-button foodord-table-reservations__preorder-note-button--primary";
      save.dataset.foodordPreorderNoteAction = "save";
      save.textContent = i18n.add || "Add";
      actions.appendChild(save);
      form.appendChild(actions);
      wrapper.appendChild(form);

      const display = document.createElement("p");
      display.className = "foodord-table-reservations__preorder-note-display";
      display.dataset.foodordPreorderNoteDisplay = "1";
      display.textContent = note;
      display.hidden = !hasNote;
      wrapper.appendChild(display);

      const feedback = document.createElement("div");
      feedback.className = "foodord-table-reservations__preorder-note-feedback";
      feedback.dataset.foodordPreorderNoteFeedback = "1";
      feedback.setAttribute("aria-live", "polite");
      wrapper.appendChild(feedback);

      return wrapper;
    }

    function renderPreorderSummary(summary) {
      const items = summary && Array.isArray(summary.items) ? summary.items : [];
      const itemCount = items.reduce((total, item) => total + Math.max(0, parseInt(item.quantity, 10) || 0), 0);
      const hasMobileCartItems = preorderActive && itemCount > 0;
      if (preorderItems) {
        preorderItems.textContent = "";
        items.forEach((item) => {
          const row = document.createElement("div");
          row.className = "foodord-table-reservations__preorder-item";
          row.dataset.itemKey = String(item.itemKey || "");

          const details = document.createElement("div");
          details.className = "foodord-table-reservations__preorder-item-details";
          const name = document.createElement("strong");
          name.textContent = String(item.name || "");
          details.appendChild(name);

          const variationLines = Array.isArray(item.variation)
            ? item.variation
            : item.variation
              ? [item.variation]
              : [];
          variationLines.forEach((variationLine) => {
            const variation = document.createElement("span");
            variation.textContent = String(variationLine);
            details.appendChild(variation);
          });
          if (Array.isArray(item.toppings) && item.toppings.length) {
            item.toppings.forEach((toppingLabel) => {
              const topping = document.createElement("span");
              topping.textContent = String(toppingLabel);
              details.appendChild(topping);
            });
          }
          row.appendChild(details);

          const actions = document.createElement("div");
          actions.className = "foodord-table-reservations__preorder-item-actions";
          const price = document.createElement("span");
          price.className = "foodord-table-reservations__preorder-item-price";
          price.textContent = String(item.lineTotalText || "");
          actions.appendChild(price);

          const controls = document.createElement("div");
          controls.className = "foodord-table-reservations__preorder-item-controls";
          const quantityValue = Math.max(1, parseInt(item.quantity, 10) || 1);
          const decreaseLabel = quantityValue === 1 ? i18n.remove || "Remove" : i18n.decreaseQuantity || "Decrease quantity";
          controls.appendChild(createPreorderQuantityButton(decreaseLabel, "decrease", String(item.itemKey || ""), quantityValue === 1));
          const quantity = document.createElement("span");
          quantity.textContent = String(quantityValue);
          quantity.dataset.foodordPreorderItemQuantity = "1";
          controls.appendChild(quantity);
          controls.appendChild(createPreorderQuantityButton(i18n.increaseQuantity || "Increase quantity", "increase", String(item.itemKey || "")));
          actions.appendChild(controls);
          row.appendChild(actions);
          row.appendChild(createPreorderNoteEditor(item));
          preorderItems.appendChild(row);
        });
      }

      if (preorderEmpty) {
        preorderEmpty.hidden = items.length > 0;
      }
      if (preorderTotal) {
        preorderTotal.hidden = items.length === 0;
      }
      if (preorderTotalValue) {
        preorderTotalValue.textContent = String(summary && summary.totalText ? summary.totalText : "");
      }
      if (preorderCheckoutButton) {
        preorderCheckoutButton.disabled = items.length === 0;
      }
      if (preorderClearButton) {
        preorderClearButton.disabled = items.length === 0;
      }
      if (preorderMobileCartCount) {
        preorderMobileCartCount.textContent = String(itemCount);
      }
      if (preorderMobileCartTotal) {
        preorderMobileCartTotal.textContent = String(summary && summary.totalText ? summary.totalText : "");
      }
      if (preorderMobileCartTrigger) {
        preorderMobileCartTrigger.hidden = !hasMobileCartItems;
      }
      if (preorderPanel) {
        preorderPanel.classList.toggle(preorderMobileCartItemsClass, hasMobileCartItems);
      }
      document.dispatchEvent(new CustomEvent("foodord_cart_updated"));
      if (!hasMobileCartItems) {
        setPreorderMobileCart(false, false);
      }
    }

    function getCustomerData() {
      return {
        name: getRequiredField("name") ? getRequiredField("name").value : "",
        email: getRequiredField("email") ? getRequiredField("email").value : "",
        phone: getRequiredField("phone") ? getRequiredField("phone").value : "",
        note: getRequiredField("note") ? getRequiredField("note").value : "",
        privacy_consent: getRequiredField("privacy_consent") && getRequiredField("privacy_consent").checked ? "1" : "0"
      };
    }

    function setTableSelectionMessage(text, type) {
      tableSelectionMessages.forEach((message) => {
        message.textContent = text || "";
        message.classList.remove("is-error", "is-success", "is-info");
        if (type) {
          message.classList.add("is-" + type);
        }
      });
    }

    function clearTableSelection() {
      setTableSelectionMessage("", "");
      if (tableSelectionFloors) {
        tableSelectionFloors.textContent = "";
      }
      if (tableSelectionPlan) {
        tableSelectionPlan.textContent = "";
      }
    }

    function setTableSelectionIntro(isActive) {
      if (formTitle) {
        formTitle.textContent = isActive
          ? formTitle.dataset.tableSelectionText || formTitle.dataset.defaultText || ""
          : formTitle.dataset.defaultText || "";
      }

      if (formDescription) {
        formDescription.textContent = isActive
          ? formDescription.dataset.tableSelectionText || formDescription.dataset.defaultText || ""
          : formDescription.dataset.defaultText || "";
      }
    }

    function hideTableSelection() {
		tableSelectionRequestId += 1;
      clearTableSelection();
      root.classList.remove(tableSelectionLayoutClass);
      setTableSelectionIntro(false);
      if (tableSelectionPanel) {
        tableSelectionPanel.hidden = true;
      }
    }

    function setTableSelectionFloor(floor) {
      if (!tableSelectionFloors || !tableSelectionPlan) {
        return;
      }

      const floorId = String(floor.id || "");
      tableSelectionFloors.querySelectorAll("[data-foodord-reservation-selectable-floor]").forEach((tab) => {
        const isActive = tab.dataset.foodordReservationSelectableFloor === floorId;
        tab.classList.toggle("is-active", isActive);
        tab.setAttribute("aria-selected", String(isActive));
      });

      tableSelectionPlan.textContent = "";
      const canvas = document.createElement("div");
      canvas.className = "foodord-table-reservations__table-selection-canvas";
		const surface = document.createElement("div");
		surface.className = "foodord-table-reservations__table-selection-surface";
		const isGrid = String(floor.mode || "image") === "grid";
		canvas.classList.toggle("is-grid", isGrid);
		surface.classList.toggle("is-grid", isGrid);
		if (isGrid) {
			const objectLayer = document.createElement("div");
			objectLayer.className = "foodord-table-reservations__floor-objects";
			const objects = Array.isArray(floor.objects) ? floor.objects : [];
			objects.forEach((object) => objectLayer.appendChild(createGridObject(object)));
			surface.appendChild(objectLayer);
		} else {
			const image = document.createElement("img");
			image.className = "foodord-table-reservations__table-selection-image";
			image.src = String(floor.image_url || "");
			image.alt = "";
			surface.appendChild(image);
		}

      const markerLayer = document.createElement("div");
      markerLayer.className = "foodord-table-reservations__table-selection-markers";
      const tables = Array.isArray(floor.tables) ? floor.tables : [];

      tables.forEach((table) => {
        const marker = document.createElement("button");
        marker.type = "button";
        marker.className = "foodord-table-reservations__table-selection-marker";
        marker.dataset.foodordReservationSelectableTable = String(table.id || "");
        marker.setAttribute("aria-label", String(table.name || ""));
        const shape = ["rectangle", "square", "round"].includes(String(table.shape || ""))
          ? String(table.shape)
          : "rectangle";
        marker.classList.add("has-geometry", "foodord-table-reservations__table-selection-marker--" + shape);
        setGridGeometry(marker, table);
        if (isGrid) {
          marker.classList.add("is-grid");
        }

        const name = document.createElement("span");
        name.textContent = String(table.name || "");
        marker.appendChild(name);
		if (isGrid) {
			appendGridSeats(marker, table);
		}
        marker.addEventListener("click", () => {
          selectTable(table, marker);
        });
        markerLayer.appendChild(marker);
      });

      surface.appendChild(markerLayer);
      canvas.appendChild(surface);
      tableSelectionPlan.appendChild(canvas);
    }

    function renderTableSelection(floors) {
      if (!tableSelectionFloors || !tableSelectionPlan || !Array.isArray(floors) || !floors.length) {
        return;
      }

      tableSelectionFloors.textContent = "";
      tableSelectionFloors.hidden = floors.length < 2;
		tableSelectionFloors.setAttribute("role", "tablist");
      floors.forEach((floor, index) => {
        const tab = document.createElement("button");
        tab.type = "button";
        tab.className = "foodord-table-reservations__table-selection-floor" + (index === 0 ? " is-active" : "");
        tab.dataset.foodordReservationSelectableFloor = String(floor.id || "");
        tab.setAttribute("role", "tab");
        tab.setAttribute("aria-selected", index === 0 ? "true" : "false");
        tab.textContent = String(floor.name || "");
        tab.addEventListener("click", () => {
          setTableSelectionFloor(floor);
        });
        tableSelectionFloors.appendChild(tab);
      });

      setTableSelectionFloor(floors[0]);
    }

    function showHeldReservation(result, isCustomerSelectedTable) {
      holdToken = result.data.holdToken || "";
      const holdRequired = Boolean(result.data.holdRequired);
      if (holdRequired && !holdToken) {
        throw new Error(i18n.genericError || "Something went wrong. Please try again.");
      }

      availabilityConfirmed = true;
      selectedTableId = Math.max(0, parseInt(result.data.tableId, 10) || 0);
      selectedTableName = String(result.data.tableName || "").trim();
      holdUsesSelectedTable = Boolean(isCustomerSelectedTable);
      preorderAvailable = Boolean(result.data.preorderAvailable);
      preorderRequired = Boolean(result.data.preorderRequired);
      preorderChoiceActive = false;
      root.setAttribute("data-foodord-preorder-flow", preorderAvailable ? "1" : "0");
      if (doneMarker) {
        doneMarker.textContent = preorderAvailable ? doneMarker.dataset.preorderStep || "4" : doneMarker.dataset.defaultStep || "3";
      }
      if (submitLabel) {
        if (preorderRequired) {
          submitLabel.textContent = submitLabel.dataset.preorderRequiredText || submitLabel.dataset.preorderText || submitLabel.dataset.defaultText || "";
        } else if (preorderAvailable) {
          submitLabel.textContent = submitLabel.dataset.preorderText || submitLabel.dataset.defaultText || "";
        } else {
          submitLabel.textContent = submitLabel.dataset.defaultText || "";
        }
      }
      if (holdText) {
        const selectedText = holdText.dataset.selectedText || holdText.dataset.defaultText || "";
        holdText.textContent =
          holdUsesSelectedTable && selectedTableName
            ? selectedText.replace("{table}", selectedTableName)
            : holdText.dataset.defaultText || "";
      }
      hideTableSelection();
      if (slotPanel) {
        slotPanel.hidden = true;
      }
      if (holdPanel) {
        holdPanel.hidden = !holdToken;
      }
      if (customerPanel) {
        customerPanel.hidden = false;
      }
      if (preorderChoicePanel) {
        preorderChoicePanel.hidden = true;
      }
      if (preorderPanel) {
        preorderPanel.hidden = true;
      }
      if (successPanel) {
        successPanel.hidden = true;
      }
      if (holdButton) {
        holdButton.hidden = true;
      }
      setReservationStep("contact");
      if (holdToken) {
        startCountdown(result.data.ttlSeconds || 300, result.data.expiresAtGmt ? Date.parse(result.data.expiresAtGmt + "Z") : 0);
      } else {
        stopCountdown();
        holdExpiresAt = 0;
        clearStoredState();
      }
      setMessage(result.data.message || "", result.data.message ? "success" : "");
    }

    function selectTable(table, marker) {
      const slotData = getSlotData();
		if (!slotData || !tableSelectionPlan || !table || !table.id) {
        return;
      }

      tableSelectionPlan.querySelectorAll("[data-foodord-reservation-selectable-table]").forEach((button) => {
        button.disabled = true;
        button.classList.remove("is-selected");
      });
      marker.classList.add("is-selected");
      marker.classList.add("is-loading");
      setTableSelectionMessage("", "");

      executeRecaptcha("hold")
        .then((token) => {
          if (token) {
            slotData.recaptcha_token = token;
          }
          slotData.table_id = table.id;

          return post("foodord_reservation_create_hold", slotData);
        })
        .then((result) => {
          if (!result || !result.success) {
            throw new Error(result && result.data && result.data.message ? result.data.message : "");
          }

          showHeldReservation(result, true);
        })
        .catch((error) => {
          tableSelectionPlan.querySelectorAll("[data-foodord-reservation-selectable-table]").forEach((button) => {
            button.disabled = false;
            button.classList.remove("is-selected", "is-loading");
          });
          setTableSelectionMessage(error.message || i18n.genericError || "Something went wrong. Please try again.", "error");
        });
    }

    function openTableSelection(slotData) {
      const requestId = tableSelectionRequestId + 1;
      tableSelectionRequestId = requestId;
      clearTableSelection();
      setTableSelectionMessage("", "");

      return post("foodord_reservation_get_selectable_tables", slotData)
        .then((result) => {
          if (!result || !result.success) {
            throw new Error(result && result.data && result.data.message ? result.data.message : "");
          }
          if (requestId !== tableSelectionRequestId) {
            return;
          }

          const floors = result.data && Array.isArray(result.data.floors) ? result.data.floors : [];
          if (!floors.length) {
            throw new Error(i18n.genericError || "Something went wrong. Please try again.");
          }

          renderTableSelection(floors);
          if (slotPanel) {
            slotPanel.hidden = true;
          }
          if (holdButton) {
            holdButton.hidden = true;
          }
          if (tableSelectionPanel) {
            tableSelectionPanel.hidden = false;
          }
          root.classList.add(tableSelectionLayoutClass);
          setTableSelectionIntro(true);
        })
        .catch((error) => {
          if (requestId !== tableSelectionRequestId) {
            return;
          }
          hideTableSelection();
          setMessage(error.message || i18n.genericError || "Something went wrong. Please try again.", "error");
        });
    }

    function setFieldError(name, text) {
      const error = form.querySelector("[data-foodord-reservation-field-error='" + name + "']");

      if (error) {
        error.textContent = text || "";
      }
    }

    function clearFieldErrors() {
      fieldErrors.forEach((error) => {
        error.textContent = "";
      });
    }

    function clearValidationFeedback() {
      setMessage("", "");
      clearCustomerValidationState();
      clearFieldErrors();
    }

    function stopCountdown() {
      if (countdownTimer) {
        window.clearInterval(countdownTimer);
        countdownTimer = 0;
      }
    }

    function hideSuccess() {
      clearValidationFeedback();
      hideTableSelection();
      if (successPanel) {
        successPanel.classList.remove(successAnimationClass);
        successPanel.hidden = true;
      }
      if (successTitle && successTitle.dataset.originalText) {
        successTitle.textContent = successTitle.dataset.originalText;
      }
      if (successText && successText.dataset.originalText) {
        successText.textContent = successText.dataset.originalText;
      }
      if (successCodeRow) {
        successCodeRow.hidden = true;
      }
      if (successCode) {
        successCode.textContent = "";
      }
      if (slotPanel) {
        slotPanel.hidden = false;
      }
      clearStoredState();
      setReservationStep("time");
    }

    function hideHold(options = {}) {
      const resetFields = Boolean(options.resetFields);

      stopCountdown();
      setPreorderClearModal(false);
      setPreorderLeaveModal(false);
      hideTableSelection();
      if (preorderPaymentEdit) {
        cleanPreorderEditUrl();
      }
      holdToken = "";
      holdExpiresAt = 0;
      holdUsesSelectedTable = false;
      availabilityConfirmed = false;
      selectedTableId = 0;
      selectedTableName = "";
      preorderAvailable = false;
      preorderRequired = false;
      preorderChoiceActive = false;
      preorderDraftToken = "";
      preorderActive = false;
      preorderPaymentEdit = false;
      root.classList.remove(preorderLayoutClass);
      root.setAttribute("data-foodord-preorder-flow", "0");
      if (doneMarker) {
        doneMarker.textContent = doneMarker.dataset.defaultStep || "3";
      }
      clearValidationFeedback();
      if (slotPanel) {
        slotPanel.hidden = false;
      }
      if (holdPanel) {
        holdPanel.hidden = true;
      }
      if (customerPanel) {
        customerPanel.hidden = true;
      }
      if (preorderChoicePanel) {
        preorderChoicePanel.hidden = true;
      }
      if (preorderPanel) {
        preorderPanel.hidden = true;
      }
      if (holdButton) {
        holdButton.hidden = false;
      }
      if (countdown) {
        countdown.textContent = "05:00";
      }
      if (submitLabel) {
        submitLabel.textContent = submitLabel.dataset.defaultText || "";
      }
      renderPreorderSummary({ items: [], totalText: "" });
      setPreorderMessage("", "");
      if (resetFields) {
        resetReservationFormFields();
      }
      clearStoredState();
      setReservationStep("time");
    }

    function cleanPreorderEditUrl() {
      if (!window.history || typeof window.history.replaceState !== "function") {
        return;
      }

      const url = new URL(window.location.href);
      if (!url.searchParams.has("foodord_reservation_preorder_edit")) {
        return;
      }

      url.searchParams.delete("foodord_reservation_preorder_edit");
      url.searchParams.delete("foodord_reservation_preorder_key");
      window.history.replaceState(window.history.state, "", url.toString());
    }

    function resetReservationFormFields() {
      timeLoadRequestId += 1;
      slotAvailabilityMessage = "";
      form.reset();

      if (dateField && window.jQuery && typeof window.jQuery.fn.datepicker === "function") {
        window.jQuery(dateField).datepicker("setDate", null);
      }

      setTimeOptions([], "");
    }

    function showSuccessScreen(data) {
      const reservationCode = data && data.reservationCode ? String(data.reservationCode) : "";
      const title = data && data.title ? String(data.title) : "";
      const message = data && data.message ? String(data.message) : "";
      const successIsPreorder = Boolean(data && data.isPreorder);

      stopCountdown();
      holdToken = "";
      holdExpiresAt = 0;
      holdUsesSelectedTable = false;
      availabilityConfirmed = false;
      selectedTableId = 0;
      selectedTableName = "";
      preorderAvailable = false;
      preorderRequired = false;
      preorderChoiceActive = false;
      preorderDraftToken = "";
      preorderActive = false;
      preorderPaymentEdit = false;
      root.classList.remove(preorderLayoutClass);
      root.setAttribute("data-foodord-preorder-flow", successIsPreorder ? "1" : "0");
      if (doneMarker) {
        doneMarker.textContent = successIsPreorder ? doneMarker.dataset.preorderStep || "4" : doneMarker.dataset.defaultStep || "3";
      }
      clearValidationFeedback();
      hideTableSelection();

      if (slotPanel) {
        slotPanel.hidden = true;
      }
      if (holdPanel) {
        holdPanel.hidden = true;
      }
      if (customerPanel) {
        customerPanel.hidden = true;
      }
      if (preorderChoicePanel) {
        preorderChoicePanel.hidden = true;
      }
      if (preorderPanel) {
        preorderPanel.hidden = true;
      }
      if (holdButton) {
        holdButton.hidden = true;
      }
      if (countdown) {
        countdown.textContent = "05:00";
      }
      if (submitLabel) {
        submitLabel.textContent = submitLabel.dataset.defaultText || "";
      }
      renderPreorderSummary({ items: [], totalText: "" });
      setPreorderMessage("", "");
      if (successTitle) {
        if (!successTitle.dataset.originalText) {
          successTitle.dataset.originalText = successTitle.textContent.trim();
        }
        successTitle.textContent = title || successTitle.dataset.originalText;
      }
      if (successText) {
        if (!successText.dataset.originalText) {
          successText.dataset.originalText = successText.textContent.trim();
        }
        successText.textContent = message || successText.dataset.originalText;
      }
      if (successCode) {
        successCode.textContent = reservationCode;
      }
      if (successCodeRow) {
        successCodeRow.hidden = !reservationCode;
      }
      if (successPanel) {
        successPanel.classList.remove(successAnimationClass);
        successPanel.hidden = false;
        window.requestAnimationFrame(() => {
          successPanel.classList.add(successAnimationClass);
        });
        if (typeof successPanel.focus === "function") {
          successPanel.focus({ preventScroll: true });
        }
      }
      clearStoredState();
      setReservationStep("done");
    }

    function releaseHold(suppressErrors = true) {
      if (!holdToken) {
        return Promise.resolve();
      }

      const request = post("foodord_reservation_release_hold", {
        hold_token: holdToken
      });

      return suppressErrors ? request.catch(() => null) : request;
    }

    function getFieldValues() {
      return ["date", "time", "party_size", "name", "email", "phone", "note"].reduce((fields, name) => {
        const field = getRequiredField(name);
        fields[name] = field ? field.value : "";
        return fields;
      }, {});
    }

    function restoreFieldValues(fields) {
      Object.keys(fields || {}).forEach((name) => {
        if (name === "time") {
          return;
        }

        const field = getRequiredField(name);
        if (field) {
          if (field.type === "checkbox") {
            field.checked = String(fields[name] || "") === "1";
          } else {
            field.value = fields[name] || "";
          }
        }
      });
    }

    function setPreorderCategoryActive(categoryKey, revealButton) {
      let activeButton = null;
      let activeCategoryChanged = false;

      preorderCategoryButtons.forEach((button) => {
        const isActive = button.dataset.foodordReservationPreorderCategoryButton === categoryKey;
        const wasActive = button.classList.contains("is-active");
        button.classList.toggle("is-active", isActive);
        if (isActive) {
          button.setAttribute("aria-current", "true");
          activeButton = button;
          activeCategoryChanged = !wasActive;
        } else {
          button.removeAttribute("aria-current");
        }
      });

      if (revealButton && activeButton && activeCategoryChanged && preorderCategoryNav) {
        const navigationRect = preorderCategoryNav.getBoundingClientRect();
        const buttonRect = activeButton.getBoundingClientRect();
        const edgePadding = 8;
        const isOutsideLeft = buttonRect.left < navigationRect.left + edgePadding;
        const isOutsideRight = buttonRect.right > navigationRect.right - edgePadding;

        if (isOutsideLeft || isOutsideRight) {
          const buttonCenter = buttonRect.left - navigationRect.left + preorderCategoryNav.scrollLeft + buttonRect.width / 2;
          const maximumScroll = Math.max(0, preorderCategoryNav.scrollWidth - preorderCategoryNav.clientWidth);
          const targetScroll = Math.max(0, Math.min(Math.round(buttonCenter - preorderCategoryNav.clientWidth / 2), maximumScroll));
          preorderCategoryNav.scrollTo({ left: targetScroll, behavior: "smooth" });
        }
      }
    }

    function isPreorderProductListScrollable() {
      if (!preorderProducts) {
        return false;
      }

      return window.getComputedStyle(preorderProducts).overflowY !== "visible"
        && preorderProducts.scrollHeight > preorderProducts.clientHeight + 1;
    }

    function updatePreorderCategoryFromScroll() {
      preorderCategoryFrame = 0;
      if (!preorderPanel || preorderPanel.hidden || !preorderProducts || !preorderCategorySections.length) {
        return;
      }

      let activeSection = preorderCategorySections[0];
      if (isPreorderProductListScrollable()) {
        const threshold = preorderProducts.scrollTop + 18;
        preorderCategorySections.forEach((section) => {
          if (section.offsetTop <= threshold) {
            activeSection = section;
          }
        });
      } else {
        const navigationRect = preorderCategoryNav ? preorderCategoryNav.getBoundingClientRect() : null;
        const navigationBottom = navigationRect ? navigationRect.bottom : 0;
        const navigationHeight = navigationRect ? navigationRect.height : 0;
        const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 0;
        const dynamicOffset = Math.min(
          Math.max(navigationHeight + 40, viewportHeight * 0.35),
          Math.max(180, viewportHeight * 0.6)
        );
        const threshold = Math.max(0, navigationBottom) + dynamicOffset;
        preorderCategorySections.forEach((section) => {
          if (section.getBoundingClientRect().top <= threshold) {
            activeSection = section;
          }
        });
      }

      setPreorderCategoryActive(activeSection.dataset.foodordReservationPreorderCategory || "", true);
    }

    function schedulePreorderCategoryUpdate() {
      if (preorderCategoryFrame) {
        return;
      }

      preorderCategoryFrame = window.requestAnimationFrame(updatePreorderCategoryFromScroll);
    }

    function syncPreorderLabelRowHeights() {
      preorderLabelRowFrame = 0;
      if (!preorderPanel || preorderPanel.hidden) {
        return;
      }

      preorderPanel.querySelectorAll(".foodord-table-reservations__preorder-category-products").forEach((container) => {
        const cards = Array.from(container.children).filter((card) => {
          const rect = card.getBoundingClientRect();
          return card.classList.contains("foodord-table-reservations__preorder-product") && rect.width > 0 && rect.height > 0;
        });

        cards.forEach((card) => {
          card.classList.remove("foodord-product-card--label-row-matched");
        });

        const rows = cards.reduce((groupedRows, card) => {
          const top = Math.round(card.getBoundingClientRect().top);
          const row = groupedRows.find((candidate) => Math.abs(candidate.top - top) <= 2);
          if (row) {
            row.cards.push(card);
          } else {
            groupedRows.push({ top: top, cards: [card] });
          }
          return groupedRows;
        }, []);

        rows.forEach((row) => {
          const hasLabels = row.cards.some((card) => card.classList.contains("foodord-product-card--has-labels"));
          if (!hasLabels || row.cards.length < 2) {
            return;
          }
          row.cards.forEach((card) => card.classList.add("foodord-product-card--label-row-matched"));
        });
      });
    }

    function schedulePreorderLabelRowHeights() {
      if (preorderLabelRowFrame) {
        window.cancelAnimationFrame(preorderLabelRowFrame);
      }
      preorderLabelRowFrame = window.requestAnimationFrame(syncPreorderLabelRowHeights);
    }

    function scrollToPreorderCategory(categoryKey) {
      const targetSection = Array.from(preorderCategorySections).find(
        (section) => section.dataset.foodordReservationPreorderCategory === categoryKey
      );
      if (!targetSection || !preorderProducts) {
        return;
      }

      setPreorderCategoryActive(categoryKey, true);
      if (isPreorderProductListScrollable()) {
        preorderProducts.scrollTo({ top: targetSection.offsetTop, behavior: "smooth" });
        return;
      }

      const navigationOffset = preorderCategoryNav ? preorderCategoryNav.offsetHeight + 12 : 12;
      const targetTop = window.scrollY + targetSection.getBoundingClientRect().top - navigationOffset;
      window.scrollTo({ top: Math.max(0, targetTop), behavior: "smooth" });
    }

    function showPreorderChoice() {
      if (!preorderChoicePanel) {
        return false;
      }

      preorderChoiceActive = true;
      if (customerPanel) {
        customerPanel.hidden = true;
      }
      preorderChoicePanel.hidden = false;
      if (preorderPanel) {
        preorderPanel.hidden = true;
      }
      setReservationStep("contact");
      setMessage("", "");
      storeHoldState();
      preorderChoicePanel.focus({ preventScroll: true });

      return true;
    }

    function storeHoldState() {
      if (!holdToken || !holdExpiresAt) {
        return;
      }

      let step = "contact";
      if (preorderActive) {
        step = "preorder";
      } else if (preorderChoiceActive) {
        step = "preorder-choice";
      }

      setStoredState({
        step: step,
        holdToken: holdToken,
        holdExpiresAt: holdExpiresAt,
        holdUsesSelectedTable: holdUsesSelectedTable ? "1" : "",
        selectedTableName: selectedTableName,
        preorderAvailable: preorderAvailable ? "1" : "",
        preorderRequired: preorderRequired ? "1" : "",
        preorderDraftToken: preorderDraftToken,
        fields: getFieldValues()
      });
    }

    function showPreorderStep(lifecycle, summary) {
      preorderDraftToken = lifecycle && lifecycle.draftToken ? String(lifecycle.draftToken) : preorderDraftToken;
      if (!preorderDraftToken) {
        throw new Error(i18n.genericError || "Something went wrong. Please try again.");
      }

      preorderActive = true;
      preorderChoiceActive = false;
      preorderPaymentEdit = Boolean(lifecycle && lifecycle.paymentEdit);
      root.classList.add(preorderLayoutClass);
      if (customerPanel) {
        customerPanel.hidden = true;
      }
      if (preorderChoicePanel) {
        preorderChoicePanel.hidden = true;
      }
      if (preorderPanel) {
        preorderPanel.hidden = false;
      }
      if (lifecycle && lifecycle.expiresAtGmt) {
        startCountdown(lifecycle.ttlSeconds || 900, Date.parse(lifecycle.expiresAtGmt + "Z"));
      } else {
        storeHoldState();
      }
      renderPreorderSummary(summary || { items: [], totalText: "" });
      setPreorderMessage("", "");
      setReservationStep("preorder");
      schedulePreorderCategoryUpdate();
      schedulePreorderLabelRowHeights();
    }

    function startPreorder() {
      return post("foodord_reservation_preorder_start", {
        hold_token: holdToken,
        customer_session: getCustomerSession()
      }).then((result) => {
        if (!result || !result.success) {
          throw new Error(result && result.data && result.data.message ? result.data.message : "");
        }

        showPreorderStep(result.data || {}, { items: [], totalText: "" });
      });
    }

    function resumePreorder() {
      return post("foodord_reservation_preorder_resume", {
        draft_token: preorderDraftToken,
        customer_session: getCustomerSession()
      }).then((result) => {
        if (!result || !result.success) {
          throw new Error(result && result.data && result.data.message ? result.data.message : "");
        }

        return post("foodord_reservation_preorder_summary", {
          draft_token: preorderDraftToken,
          customer_session: getCustomerSession()
        }).then((summaryResult) => {
          if (!summaryResult || !summaryResult.success) {
            throw new Error(summaryResult && summaryResult.data && summaryResult.data.message ? summaryResult.data.message : "");
          }
          showPreorderStep(result.data || {}, summaryResult.data || {});
        });
      });
    }

    function startCountdown(ttlSeconds, expiresAt) {
      stopCountdown();
      holdExpiresAt = expiresAt && expiresAt > Date.now()
        ? expiresAt
        : Date.now() + (Math.max(1, parseInt(ttlSeconds, 10) || 300) * 1000);
      storeHoldState();

      const tick = () => {
        const secondsLeft = Math.ceil((holdExpiresAt - Date.now()) / 1000);
        if (countdown) {
          countdown.textContent = formatTime(secondsLeft);
        }
        if (secondsLeft <= 0) {
          hideHold({ resetFields: true });
          setMessage(i18n.holdExpired || "Your table hold has expired. Please select a time again.", "error");
        }
      };

      tick();
      countdownTimer = window.setInterval(tick, 1000);
    }

    function getRequiredField(name) {
      return form.querySelector("[name='" + name + "']");
    }

    function setTimeOptions(times, selectedTime, timeLabels, slots) {
      if (!timeField) {
        return;
      }

      setTimeLoadingState(false);

      const options = Array.isArray(slots) && slots.length
        ? slots
        : (Array.isArray(times) ? times : []).map((time) => ({ time: String(time), date: "" }));
      const optionValues = options.map((slot) => String(slot && slot.time ? slot.time : ""));
      timeField.textContent = "";

      if (!options.length) {
        if (selectedTime) {
          timeField.dataset.pendingValue = String(selectedTime);
        }

        const placeholder = document.createElement("option");
        placeholder.value = "";
        placeholder.textContent = i18n.timePlaceholder || "Time";
        timeField.appendChild(placeholder);
      }

      options.forEach((slot) => {
        const time = String(slot && slot.time ? slot.time : "");
        if (!time) {
          return;
        }
        const option = document.createElement("option");
        option.value = time;
        option.textContent = timeLabels && timeLabels[time] ? String(timeLabels[time]) : time;
        option.dataset.reservationDate = String(slot && slot.date ? slot.date : "");
        timeField.appendChild(option);
      });

      timeField.disabled = !options.length;
      timeField.value = optionValues.includes(String(selectedTime)) ? String(selectedTime) : optionValues[0] || "";
      if (options.length) {
        delete timeField.dataset.pendingValue;
      }
      syncPartySizeField();
    }

    function getPartySizeForRequest() {
      if (!partySizeField) {
        return "0";
      }

      return partySizeField.value || partySizeField.dataset.pendingValue || "0";
    }

    function syncPartySizeField() {
      if (!partySizeField) {
        return;
      }

      const hasDate = Boolean(dateField && dateField.value);
      const hasTime = Boolean(timeField && timeField.value);
      const isEditingEmptyValue = document.activeElement === partySizeField && !partySizeField.value;

      if (!hasDate) {
        partySizeField.value = "";
        partySizeField.disabled = true;
        partySizeField.dataset.pendingValue = "1";
        return;
      }

      if (!hasTime) {
        if (isEditingEmptyValue) {
          partySizeField.disabled = false;
          delete partySizeField.dataset.pendingValue;
          return;
        }

        if (partySizeField.value) {
          partySizeField.dataset.pendingValue = partySizeField.value;
        }

        if (!isTimeLoading && partySizeField.dataset.pendingValue) {
          partySizeField.value = partySizeField.dataset.pendingValue;
          partySizeField.disabled = false;
          return;
        }

        partySizeField.value = partySizeField.dataset.pendingValue || "1";
        partySizeField.disabled = true;
        return;
      }

      if (isEditingEmptyValue) {
        partySizeField.disabled = false;
        delete partySizeField.dataset.pendingValue;
        return;
      }

      partySizeField.value = partySizeField.dataset.pendingValue || partySizeField.value || "1";
      partySizeField.disabled = false;
      delete partySizeField.dataset.pendingValue;
    }

    function setTimeLoadingState(isLoading) {
      isTimeLoading = isLoading;

      if (timeFieldWrapper) {
        timeFieldWrapper.classList.toggle("is-loading-times", isLoading);
      }

      if (timeField) {
        timeField.setAttribute("aria-busy", isLoading ? "true" : "false");
      }
    }

    function setTimeLoading() {
      if (!timeField) {
        return;
      }

      setTimeLoadingState(true);
      timeField.textContent = "";
      const option = document.createElement("option");
      option.value = "";
      option.textContent = "";
      timeField.appendChild(option);
      timeField.disabled = true;
      syncPartySizeField();
    }

    function loadTimeOptions(selectedTime) {
      const requestId = timeLoadRequestId + 1;

      timeLoadRequestId = requestId;

      if (!dateField || !dateField.value) {
        slotAvailabilityMessage = "";
        setTimeOptions([], "");
        setMessage("", "");
        timeLoadPromise = Promise.resolve();
        return timeLoadPromise;
      }

      const parsedDate = parseDatepickerValue(dateField.value);
      if (parsedDate && isDateDisabledByBookingRules(parsedDate)) {
        slotAvailabilityMessage = i18n.noTimesAvailable || "Reservations are not available on this date. Please choose another date.";
        setTimeOptions([], "");
        setMessage(slotAvailabilityMessage, "error");
        timeLoadPromise = Promise.resolve();
        return timeLoadPromise;
      }

      setTimeLoading();

      timeLoadPromise = post("foodord_reservation_get_time_slots", {
        date: dateField.value,
        party_size: getPartySizeForRequest()
      })
        .then((result) => {
          if (!result || !result.success) {
            throw new Error(result && result.data && result.data.message ? result.data.message : "");
          }

          if (requestId !== timeLoadRequestId) {
            return;
          }

          setTimeOptions(
            result.data && result.data.times ? result.data.times : [],
            selectedTime || "",
            result.data && result.data.time_labels ? result.data.time_labels : {},
            result.data && result.data.slots ? result.data.slots : []
          );
          slotAvailabilityMessage = result.data && result.data.message ? String(result.data.message) : "";
          if (slotAvailabilityMessage) {
            setMessage(slotAvailabilityMessage, "error");
          } else {
            setMessage("", "");
          }
        })
        .catch((error) => {
          if (requestId !== timeLoadRequestId) {
            return;
          }

          setTimeOptions([], "");
          slotAvailabilityMessage = error.message || i18n.genericError || "Something went wrong. Please try again.";
          setMessage(slotAvailabilityMessage, "error");
        });

      return timeLoadPromise;
    }

    function getSelectedTimeForReload() {
      return timeField ? timeField.value || timeField.dataset.pendingValue || "" : "";
    }

    function schedulePartySizeTimeLoad() {
      if (partySizeLoadTimer) {
        window.clearTimeout(partySizeLoadTimer);
        partySizeLoadTimer = 0;
      }

      const partySize = partySizeField ? parseInt(partySizeField.value, 10) : 0;
      if (!partySizeField || !partySizeField.value || Number.isNaN(partySize) || partySize < 1) {
        timeLoadRequestId += 1;
        timeLoadPromise = Promise.resolve();
        setTimeLoadingState(false);
        return;
      }

      partySizeLoadTimer = window.setTimeout(() => {
        partySizeLoadTimer = 0;
        loadTimeOptions(getSelectedTimeForReload());
      }, partySizeLoadDelay);
    }

    function flushPartySizeTimeLoad() {
      if (partySizeLoadTimer) {
        window.clearTimeout(partySizeLoadTimer);
        partySizeLoadTimer = 0;
        return loadTimeOptions(getSelectedTimeForReload());
      }

      return isTimeLoading ? timeLoadPromise : Promise.resolve();
    }

    function getSlotData() {
      const date = getRequiredField("date");
      const time = getRequiredField("time");
      const partySize = getRequiredField("party_size");

      if (!date || !time || !partySize || !date.value || !time.value || !partySize.value) {
        return null;
      }

      return {
        date: getSelectedReservationDate(date, time),
        time: time.value,
        party_size: partySize.value,
        customer_session: getCustomerSession()
      };
    }

    function getSelectedReservationDate(date, time) {
      const selectedOption = time && time.selectedIndex >= 0 ? time.options[time.selectedIndex] : null;

      return selectedOption && selectedOption.dataset.reservationDate
        ? selectedOption.dataset.reservationDate
        : date.value;
    }

    function getSlotValidationError() {
      const date = getRequiredField("date");
      const time = getRequiredField("time");
      const partySize = getRequiredField("party_size");
      const hasDate = !!(date && date.value);
      const hasTime = !!(time && time.value);
      const guestCount = partySize ? parseInt(partySize.value, 10) : 0;

      if (isTimeLoading) {
        return {
          field: date,
          message: ""
        };
      }

      if (!hasDate && !hasTime) {
        return {
          field: date || time,
          message: i18n.selectDateAndTime || "Please select a date and time."
        };
      }

      if (!hasDate) {
        return {
          field: date,
          message: i18n.selectDate || "Please select a date."
        };
      }

      if (!hasTime) {
        return {
          field: time,
          message: slotAvailabilityMessage || i18n.selectTime || "Please select a time."
        };
      }

      if (!partySize || !partySize.value || Number.isNaN(guestCount) || guestCount < 1) {
        return {
          field: partySize,
          message: i18n.enterGuests || "Please enter the number of guests."
        };
      }

      return null;
    }

    function setFieldInvalid(field, invalid) {
      if (!field) {
        return;
      }

      if (invalid) {
        field.setAttribute("aria-invalid", "true");
        return;
      }

      field.removeAttribute("aria-invalid");
    }

    function clearCustomerValidationState() {
      ["name", "email", "phone", "privacy_consent"].forEach((name) => {
        setFieldInvalid(getRequiredField(name), false);
      });
    }

    function getCustomerValidationError() {
      const name = getRequiredField("name");
      const email = getRequiredField("email");
      const phone = getRequiredField("phone");
      const privacyConsent = getRequiredField("privacy_consent");

      if (!name || !name.value.trim()) {
        return {
          field: name,
          name: "name",
          message: i18n.enterName || "Please enter your name."
        };
      }

      if (!email || !email.value.trim()) {
        return {
          field: email,
          name: "email",
          message: i18n.enterEmail || "Please enter a valid email address."
        };
      }

      if (!email.checkValidity()) {
        return {
          field: email,
          name: "email",
          message: i18n.enterEmail || "Please enter a valid email address."
        };
      }

      if (!phone || !phone.value.trim()) {
        return {
          field: phone,
          name: "phone",
          message: i18n.enterPhone || "Please enter your phone number."
        };
      }

      if (privacyConsent && !privacyConsent.checked) {
        return {
          field: privacyConsent,
          name: "privacy_consent",
          message: i18n.acceptPrivacy || "Please accept the privacy statement to continue."
        };
      }

      return null;
    }

    function validateCustomerFields() {
      const error = getCustomerValidationError();

      clearCustomerValidationState();
      clearFieldErrors();
      if (!error) {
        return true;
      }

      setFieldInvalid(error.field, true);
      setFieldError(error.name, error.message);
      setMessage("", "");
      if (error.field && typeof error.field.focus === "function") {
        error.field.focus();
      }

      return false;
    }

    function restorePreorderPaymentEdit(payload) {
      const expiresAt = Date.parse(String(payload && payload.expiresAtGmt ? payload.expiresAtGmt : "") + "Z");
      preorderDraftToken = payload && payload.draftToken ? String(payload.draftToken) : "";
      if (!preorderDraftToken || !expiresAt || expiresAt <= Date.now()) {
        cleanPreorderEditUrl();
        setMessage(i18n.preorderEditExpired || "This pre-order can no longer be edited.", "error");
        return;
      }

      clearStoredState();
      restoreFieldValues(payload.fields || {});
      holdToken = "";
      holdUsesSelectedTable = false;
      selectedTableName = "";
      preorderAvailable = true;
      preorderRequired = true;
      preorderActive = true;
      preorderPaymentEdit = true;
      root.classList.add(preorderLayoutClass);
      root.setAttribute("data-foodord-preorder-flow", "1");
      if (slotPanel) {
        slotPanel.hidden = true;
      }
      if (holdPanel) {
        holdPanel.hidden = false;
      }
      if (customerPanel) {
        customerPanel.hidden = true;
      }
      if (preorderPanel) {
        preorderPanel.hidden = false;
      }
      schedulePreorderLabelRowHeights();
      if (holdButton) {
        holdButton.hidden = true;
      }
      if (holdText) {
        holdText.textContent = holdText.dataset.editText || holdText.dataset.defaultText || "";
      }
      setReservationStep("preorder");
      startCountdown(Math.ceil((expiresAt - Date.now()) / 1000), expiresAt);
      resumePreorder().catch((error) => {
        hideHold();
        setMessage(error.message || i18n.preorderEditExpired || "This pre-order can no longer be edited.", "error");
      });
    }

    function restoreStoredState() {
      const state = getStoredState();
      if (!state || !state.step) {
        return;
      }

      if (state.step === "done") {
        clearStoredState();
        return;
      }

      if (!["contact", "preorder-choice", "preorder"].includes(state.step) || !state.holdToken || !state.holdExpiresAt) {
        clearStoredState();
        return;
      }

      if (state.step === "preorder-choice" && !preorderChoicePanel) {
        clearStoredState();
        return;
      }

      const expiresAt = parseInt(state.holdExpiresAt, 10);
      if (!expiresAt || expiresAt <= Date.now()) {
        clearStoredState();
        hideHold();
        setMessage(i18n.holdExpired || "Your table hold has expired. Please select a time again.", "error");
        return;
      }

      restoreFieldValues(state.fields || {});
      loadTimeOptions(state.fields && state.fields.time ? state.fields.time : "");
      holdToken = String(state.holdToken);
      availabilityConfirmed = true;
      holdUsesSelectedTable = state.holdUsesSelectedTable === "1";
      selectedTableName = state.selectedTableName ? String(state.selectedTableName).trim() : "";
      preorderAvailable = state.preorderAvailable === "1";
      preorderRequired = state.preorderRequired === "1";
      preorderChoiceActive = state.step === "preorder-choice";
      preorderDraftToken = state.preorderDraftToken ? String(state.preorderDraftToken) : "";
      root.setAttribute("data-foodord-preorder-flow", preorderAvailable ? "1" : "0");
      if (doneMarker) {
        doneMarker.textContent = preorderAvailable ? doneMarker.dataset.preorderStep || "4" : doneMarker.dataset.defaultStep || "3";
      }
      if (holdText) {
        const selectedText = holdText.dataset.selectedText || holdText.dataset.defaultText || "";
        holdText.textContent =
          holdUsesSelectedTable && selectedTableName
            ? selectedText.replace("{table}", selectedTableName)
            : holdText.dataset.defaultText || "";
      }

      if (slotPanel) {
        slotPanel.hidden = true;
      }
      if (holdPanel) {
        holdPanel.hidden = false;
      }
      if (customerPanel) {
        customerPanel.hidden = state.step !== "contact";
      }
      if (preorderChoicePanel) {
        preorderChoicePanel.hidden = state.step !== "preorder-choice";
      }
      if (preorderPanel) {
        preorderPanel.hidden = state.step !== "preorder";
      }
      if (successPanel) {
        successPanel.hidden = true;
      }
      if (holdButton) {
        holdButton.hidden = true;
      }
      if (submitLabel) {
        submitLabel.textContent = preorderAvailable
          ? submitLabel.dataset.preorderText || submitLabel.dataset.defaultText || ""
          : submitLabel.dataset.defaultText || "";
      }
      setReservationStep(state.step === "preorder-choice" ? "contact" : state.step);
      startCountdown(Math.ceil((expiresAt - Date.now()) / 1000), expiresAt);
      setMessage("", "");
      if (state.step === "preorder") {
        if (!preorderDraftToken) {
          hideHold();
          return;
        }
        preorderActive = true;
        schedulePreorderCategoryUpdate();
        schedulePreorderLabelRowHeights();
        resumePreorder().catch((error) => {
          hideHold();
          setMessage(error.message || i18n.holdExpired || "Your table hold has expired. Please select a time again.", "error");
        });
      }
    }

    if (preorderCategoryNav && preorderProducts && preorderCategoryButtons.length) {
      preorderCategoryButtons.forEach((button) => {
        button.addEventListener("click", () => {
          scrollToPreorderCategory(button.dataset.foodordReservationPreorderCategoryButton || "");
        });
      });
      preorderProducts.addEventListener("scroll", schedulePreorderCategoryUpdate, { passive: true });
      window.addEventListener("scroll", schedulePreorderCategoryUpdate, { passive: true });
      window.addEventListener("resize", schedulePreorderCategoryUpdate, { passive: true });
    }
    if (preorderBackToTop && preorderProducts) {
      preorderBackToTop.addEventListener("click", () => {
        const reduceMotion = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
        const behavior = reduceMotion ? "auto" : "smooth";

        if (isPreorderProductListScrollable()) {
          preorderProducts.scrollTo({ top: 0, behavior });
          return;
        }

        const navigationOffset = preorderCategoryNav ? preorderCategoryNav.offsetHeight + 12 : 12;
        const targetTop = window.scrollY + preorderProducts.getBoundingClientRect().top - navigationOffset;
        window.scrollTo({ top: Math.max(0, targetTop), behavior });
      });
    }
    if (preorderPanel) {
      window.addEventListener("resize", schedulePreorderLabelRowHeights, { passive: true });
    }

    if (holdButton) {
      holdButton.addEventListener("click", () => {
        const waitingForTimeLoad = Boolean(partySizeLoadTimer || isTimeLoading);
        if (waitingForTimeLoad) {
          setButtonBusy(holdButton, true, "");
        }

        flushPartySizeTimeLoad()
          .then(() => {
            const slotError = getSlotValidationError();
            if (slotError) {
              setMessage(slotError.message || "", slotError.message ? "error" : "");
              if (slotError.field && typeof slotError.field.focus === "function") {
                slotError.field.focus();
              }
              return null;
            }

            const slotData = getSlotData();
            if (!slotData) {
              setMessage(i18n.genericError || "Please complete the required fields.", "error");
              return null;
            }

            if (holdToken) {
              releaseHold();
              hideHold();
            }

            hideSuccess();
            setButtonBusy(holdButton, true, "");
            setMessage("", "");

            if (tableSelectionPanel) {
              return openTableSelection(slotData);
            }

            return executeRecaptcha("hold")
              .then((token) => {
                if (token) {
                  slotData.recaptcha_token = token;
                }

                return post("foodord_reservation_create_hold", slotData);
              })
              .then((result) => {
                if (!result || !result.success) {
                  throw new Error(result && result.data && result.data.message ? result.data.message : "");
                }

                showHeldReservation(result);
              });
          })
          .catch((error) => {
            hideHold();
            setMessage(error.message || i18n.genericError || "Something went wrong. Please try again.", "error");
          })
          .finally(() => {
            setButtonBusy(holdButton, false, "");
          });
      });
    }

    if (backButton) {
      backButton.addEventListener("click", () => {
        if (root.getAttribute("data-foodord-reservation-step") !== "contact" || !availabilityConfirmed) {
          return;
        }

        if (holdToken) {
          releaseHold();
        }
        hideHold();
        setMessage("", "");
      });
    }

    if (cancelHoldButton) {
      cancelHoldButton.addEventListener("click", () => {
        if (!availabilityConfirmed) {
          return;
        }

        setButtonBusy(cancelHoldButton, true, "");
        setMessage("", "");
        if (!holdToken) {
          hideHold();
          resetReservationFormFields();
          setButtonBusy(cancelHoldButton, false, "");
          return;
        }
        releaseHold(false)
          .then((result) => {
            if (!result || !result.success) {
              throw new Error(result && result.data && result.data.message ? result.data.message : "");
            }

            hideHold();
            resetReservationFormFields();
          })
          .catch((error) => {
            setMessage(error.message || i18n.genericError || "Something went wrong. Please try again.", "error");
          })
          .finally(() => {
            setButtonBusy(cancelHoldButton, false, "");
          });
      });
    }

    if (tableSelectionBackButton) {
      tableSelectionBackButton.addEventListener("click", () => {
        hideTableSelection();
        if (slotPanel) {
          slotPanel.hidden = false;
        }
        if (holdButton) {
          holdButton.hidden = false;
        }
        setMessage("", "");
      });
    }

    slotInputs.forEach((input) => {
      input.addEventListener("change", () => {
        hideSuccess();
        if (input.name === "date") {
          if (partySizeLoadTimer) {
            window.clearTimeout(partySizeLoadTimer);
            partySizeLoadTimer = 0;
          }
          if (timeField) {
            delete timeField.dataset.pendingValue;
          }
          loadTimeOptions("");
        }
        if (input.name === "party_size") {
          schedulePartySizeTimeLoad();
        }
        if (input.name === "time") {
          syncPartySizeField();
        }

        if (availabilityConfirmed) {
          if (holdToken) {
            releaseHold();
          }
          hideHold();
          setMessage("", "");
        }
      });
    });

    if (partySizeField) {
      partySizeField.addEventListener("input", schedulePartySizeTimeLoad);
    }

    ["name", "email", "phone", "note", "privacy_consent"].forEach((name) => {
      const field = getRequiredField(name);
      if (!field) {
        return;
      }

      field.addEventListener("input", () => {
        setFieldInvalid(field, false);
        setFieldError(name, "");
        storeHoldState();
      });
      field.addEventListener("change", () => {
        setFieldInvalid(field, false);
        setFieldError(name, "");
        storeHoldState();
      });
    });

    function submitReservationWithoutPreorder(button) {
      setButtonBusy(button, true, "");
      setMessage("", "");

      return executeRecaptcha("submit")
        .then((token) => {
          const slotData = getSlotData();
          const reservationData = {
            hold_token: holdToken,
            date: slotData ? slotData.date : getRequiredField("date").value,
            time: slotData ? slotData.time : getRequiredField("time").value,
            party_size: getRequiredField("party_size").value,
            table_id: selectedTableId,
            name: getRequiredField("name").value,
            email: getRequiredField("email").value,
            phone: getRequiredField("phone").value,
            note: getRequiredField("note") ? getRequiredField("note").value : "",
            privacy_consent: getRequiredField("privacy_consent") && getRequiredField("privacy_consent").checked ? "1" : "0"
          };

          if (token) {
            reservationData.recaptcha_token = token;
          }

          return post("foodord_reservation_submit", reservationData);
        })
        .then((result) => {
          if (!result || !result.success) {
            throw new Error(result && result.data && result.data.message ? result.data.message : "");
          }

          if (result.data && result.data.redirectUrl) {
            window.location.assign(String(result.data.redirectUrl));
            return;
          }

          hideHold();
          form.reset();
          showSuccessScreen(result.data || {});
        })
        .catch((error) => {
          setMessage(error.message || i18n.genericError || "Something went wrong. Please try again.", "error");
        })
        .finally(() => {
          setButtonBusy(button, false, "");
        });
    }

    form.addEventListener("submit", (event) => {
      event.preventDefault();

      if (!availabilityConfirmed) {
        setMessage(i18n.holdExpired || "Your table hold has expired. Please select a time again.", "error");
        return;
      }

      if (!validateCustomerFields()) {
        return;
      }

      setMessage("", "");

      if (preorderAvailable) {
        if (!preorderRequired) {
          if (showPreorderChoice()) {
            return;
          }

          submitReservationWithoutPreorder(submitButton);
          return;
        }

        setButtonBusy(submitButton, true, "");
        startPreorder()
          .catch((error) => {
            setMessage(error.message || i18n.genericError || "Something went wrong. Please try again.", "error");
          })
          .finally(() => {
            setButtonBusy(submitButton, false, "");
          });
        return;
      }

      submitReservationWithoutPreorder(submitButton);
    });

    function setPreorderChoiceBusy(activeButton, busy) {
      [preorderAcceptButton, preorderDeclineButton].forEach((button) => {
        if (button) {
          button.disabled = busy;
        }
      });
      setButtonBusy(activeButton, busy, "");
    }

    if (preorderAcceptButton) {
      preorderAcceptButton.addEventListener("click", () => {
        if (!holdToken) {
          setMessage(i18n.holdExpired || "Your table hold has expired. Please select a time again.", "error");
          return;
        }

        setPreorderChoiceBusy(preorderAcceptButton, true);
        setMessage("", "");
        startPreorder()
          .catch((error) => {
            setMessage(error.message || i18n.genericError || "Something went wrong. Please try again.", "error");
          })
          .finally(() => {
            setPreorderChoiceBusy(preorderAcceptButton, false);
          });
      });
    }

    if (preorderDeclineButton) {
      preorderDeclineButton.addEventListener("click", () => {
        if (!holdToken) {
          setMessage(i18n.holdExpired || "Your table hold has expired. Please select a time again.", "error");
          return;
        }

        setPreorderChoiceBusy(preorderDeclineButton, true);
        submitReservationWithoutPreorder(preorderDeclineButton)
          .finally(() => {
            setPreorderChoiceBusy(preorderDeclineButton, false);
          });
      });
    }

    function collectModalToppings(modal) {
      const selections = {};
      modal.querySelectorAll(".foodord-product-toppings__set").forEach((set) => {
        const setId = String(set.dataset.setId || "");
        const groupType = String(set.dataset.groupType || "dropdown");
        if (!setId) {
          return;
        }

        if (groupType === "dropdown") {
          const select = set.querySelector("select");
          if (select && select.value) {
            selections[setId] = select.value;
          }
          return;
        }

        if (groupType === "radio") {
          const checked = set.querySelector("input[type='radio']:checked");
          if (checked) {
            selections[setId] = checked.value;
          }
          return;
        }

        const values = Array.from(set.querySelectorAll("input[type='checkbox']:checked"))
          .map((input) => input.value)
          .filter(Boolean);
        if (values.length) {
          selections[setId] = values;
        }
      });
      return selections;
    }

    function showModalPreorderError(modal, message) {
      let error = modal.querySelector("[data-foodord-preorder-modal-error]");
      if (!message) {
        if (error) {
          error.textContent = "";
          error.hidden = true;
        }
        return;
      }

      if (!error) {
        error = document.createElement("p");
        error.className = "foodord-table-reservations__preorder-modal-error";
        error.dataset.foodordPreorderModalError = "1";
        const footer = modal.querySelector(".foodord-modal-footer");
        if (footer) {
          footer.insertBefore(error, footer.firstChild);
        }
      }
      if (error) {
        error.hidden = false;
        error.textContent = message;
      }
    }

    function validatePreorderModalSelections(modal) {
      const productModal = window.foodordModal;
      const modalFooter = productModal && productModal.footer;

      if (
        !modalFooter
        || typeof modalFooter.validateAddToCartSelections !== "function"
        || !productModal.modal
        || productModal.modal[0] !== modal
      ) {
        return true;
      }

      return modalFooter.validateAddToCartSelections();
    }

    document.addEventListener("click", (event) => {
      const button = event.target.closest(".foodord-add-to-cart-btn[data-foodord-product-context='reservation_preorder']");
      if (!button || !preorderActive || !preorderDraftToken) {
        return;
      }

      event.preventDefault();
      event.stopPropagation();
      event.stopImmediatePropagation();
      const modal = button.closest(".foodord-modal");
      if (!validatePreorderModalSelections(modal)) {
        return;
      }

      const variationField = modal ? modal.querySelector(".variations_form input[name='variation_id']") : null;
      const quantityField = modal ? modal.querySelector("#foodord-quantity-input") : null;
      const configuration = {
        product_id: button.dataset.productId || "",
        variation_id: variationField ? variationField.value : "",
        quantity: quantityField ? quantityField.value : "1",
        foodord_toppings: modal ? collectModalToppings(modal) : {}
      };
      let modalCloseStarted = false;

      setPreorderModalButtonBusy(button, true);
      if (modal) {
        showModalPreorderError(modal, "");
      }
      post("foodord_reservation_preorder_add_item", {
        draft_token: preorderDraftToken,
        customer_session: getCustomerSession(),
        configuration: JSON.stringify(configuration)
      })
        .then((result) => {
          if (!result || !result.success) {
            throw new Error(result && result.data && result.data.message ? result.data.message : "");
          }

          renderPreorderSummary(result.data || {});
          setPreorderMessage("", "");
          const closeButton = modal ? modal.querySelector(".foodord-modal-close") : null;
          if (closeButton) {
            closeButton.click();
            modalCloseStarted = true;
          }
        })
        .catch((error) => {
          if (modal) {
            showModalPreorderError(modal, error.message || i18n.genericError || "Something went wrong. Please try again.");
          }
        })
        .finally(() => {
          if (!modalCloseStarted) {
            setPreorderModalButtonBusy(button, false);
          }
        });
    }, true);

    if (preorderMobileCartTrigger) {
      preorderMobileCartTrigger.addEventListener("click", () => setPreorderMobileCart(true));
    }
    preorderMobileCartCloseButtons.forEach((button) => {
      button.addEventListener("click", () => setPreorderMobileCart(false));
    });
    document.addEventListener("keydown", (event) => {
      if (event.key === "Escape" && preorderMobileCart && preorderMobileCart.classList.contains("is-open")) {
        setPreorderMobileCart(false);
      }
    });

    const handlePreorderMobileMediaChange = (event) => {
      if (!event.matches) {
        setPreorderMobileCart(false, false);
      }
    };
    if (typeof preorderMobileMedia.addEventListener === "function") {
      preorderMobileMedia.addEventListener("change", handlePreorderMobileMediaChange);
    } else if (typeof preorderMobileMedia.addListener === "function") {
      preorderMobileMedia.addListener(handlePreorderMobileMediaChange);
    }

    if (preorderItems) {
      preorderItems.addEventListener("click", (event) => {
        const button = event.target.closest("[data-foodord-preorder-item-action]");
        const row = button ? button.closest(".foodord-table-reservations__preorder-item[data-item-key]") : null;
        if (!button || !row || !preorderDraftToken) {
          return;
        }

        const quantityNode = row.querySelector("[data-foodord-preorder-item-quantity]");
        const currentQuantity = quantityNode ? parseInt(quantityNode.textContent, 10) || 1 : 1;
        const action = button.dataset.foodordPreorderItemAction || "";
        const nextQuantity = action === "increase" ? currentQuantity + 1 : action === "decrease" ? currentQuantity - 1 : 0;
        row.querySelectorAll("button").forEach((control) => {
          control.disabled = true;
        });

        post("foodord_reservation_preorder_update_item", {
          draft_token: preorderDraftToken,
          customer_session: getCustomerSession(),
          item_key: button.dataset.itemKey || row.dataset.itemKey || "",
          quantity: Math.max(0, nextQuantity)
        })
          .then((result) => {
            if (!result || !result.success) {
              throw new Error(result && result.data && result.data.message ? result.data.message : "");
            }
            renderPreorderSummary(result.data || {});
            setPreorderMessage("", "");
          })
          .catch((error) => {
            setPreorderMessage(error.message || i18n.genericError || "Something went wrong. Please try again.", "error");
            row.querySelectorAll("button").forEach((control) => {
              control.disabled = false;
            });
          });
      });

      preorderItems.addEventListener("input", (event) => {
        const input = event.target.closest("[data-foodord-preorder-note-input]");
        const wrapper = input ? input.closest("[data-foodord-preorder-note]") : null;
        const counter = wrapper ? wrapper.querySelector("[data-foodord-preorder-note-counter]") : null;
        if (input && counter) {
          counter.textContent = formatPreorderNoteCounter(input.value);
        }
      });

      preorderItems.addEventListener("click", (event) => {
        const button = event.target.closest("[data-foodord-preorder-note-action]");
        const wrapper = button ? button.closest("[data-foodord-preorder-note]") : null;
        const row = wrapper ? wrapper.closest("[data-item-key]") : null;
        if (!button || !wrapper || !row || !preorderDraftToken) {
          return;
        }

        const action = button.dataset.foodordPreorderNoteAction || "";
        const form = wrapper.querySelector("[data-foodord-preorder-note-form]");
        const input = wrapper.querySelector("[data-foodord-preorder-note-input]");
        const display = wrapper.querySelector("[data-foodord-preorder-note-display]");
        const feedback = wrapper.querySelector("[data-foodord-preorder-note-feedback]");
        const savedNote = wrapper.dataset.foodordPreorderNote || "";

        if (action === "toggle") {
          wrapper.classList.add("is-editing");
          if (form) {
            form.hidden = false;
          }
          if (display) {
            display.hidden = true;
          }
          if (input) {
            input.value = savedNote;
            input.dispatchEvent(new Event("input", { bubbles: true }));
            input.focus();
          }
          if (feedback) {
            feedback.textContent = "";
          }
          return;
        }

        if (action === "cancel") {
          wrapper.classList.remove("is-editing");
          if (form) {
            form.hidden = true;
          }
          if (display) {
            display.hidden = !savedNote;
          }
          return;
        }

        if (action !== "save" && action !== "delete") {
          return;
        }

        const quantityNode = row.querySelector("[data-foodord-preorder-item-quantity]");
        const quantity = quantityNode ? parseInt(quantityNode.textContent, 10) || 1 : 1;
        const nextNote = action === "delete" ? "" : String(input ? input.value : "").trim();
        wrapper.querySelectorAll("button").forEach((control) => {
          control.disabled = true;
        });
        if (feedback) {
          feedback.textContent = "";
        }

        post("foodord_reservation_preorder_update_item", {
          draft_token: preorderDraftToken,
          customer_session: getCustomerSession(),
          item_key: row.dataset.itemKey || "",
          quantity: quantity,
          note: nextNote
        })
          .then((result) => {
            if (!result || !result.success) {
              throw new Error(result && result.data && result.data.message ? result.data.message : "");
            }
            renderPreorderSummary(result.data || {});
            setPreorderMessage("", "");
          })
          .catch((error) => {
            if (feedback) {
              feedback.textContent = error.message || i18n.noteError || "Could not update the note. Please try again.";
            }
            wrapper.querySelectorAll("button").forEach((control) => {
              control.disabled = false;
            });
          });
      });
    }

    if (preorderClearButton) {
      preorderClearButton.addEventListener("click", () => setPreorderClearModal(true));
    }
    preorderClearCloseButtons.forEach((button) => {
      button.addEventListener("click", () => setPreorderClearModal(false));
    });
    if (preorderClearConfirm) {
      preorderClearConfirm.addEventListener("click", () => {
        setButtonBusy(preorderClearConfirm, true, "");
        post("foodord_reservation_preorder_clear_items", {
          draft_token: preorderDraftToken,
          customer_session: getCustomerSession()
        })
          .then((result) => {
            if (!result || !result.success) {
              throw new Error(result && result.data && result.data.message ? result.data.message : "");
            }
            setPreorderClearModal(false);
            renderPreorderSummary(result.data || { items: [], totalText: "" });
            setPreorderMessage("", "");
          })
          .catch((error) => {
            setPreorderClearModal(false);
            setPreorderMessage(error.message || i18n.genericError || "Something went wrong. Please try again.", "error");
          })
          .finally(() => setButtonBusy(preorderClearConfirm, false, ""));
      });
    }
    preorderLeaveButtons.forEach((button) => {
      button.addEventListener("click", () => setPreorderLeaveModal(true));
    });
    preorderLeaveCloseButtons.forEach((button) => {
      button.addEventListener("click", () => setPreorderLeaveModal(false));
    });
    if (preorderLeaveConfirm) {
      preorderLeaveConfirm.addEventListener("click", () => {
        setButtonBusy(preorderLeaveConfirm, true, "");
        post("foodord_reservation_preorder_leave", {
          draft_token: preorderDraftToken,
          customer_session: getCustomerSession()
        })
          .then((result) => {
            if (!result || !result.success) {
              throw new Error(result && result.data && result.data.message ? result.data.message : "");
            }
            setPreorderLeaveModal(false);
            hideHold();
            resetReservationFormFields();
          })
          .catch((error) => {
            setPreorderLeaveModal(false);
            setPreorderMessage(error.message || i18n.genericError || "Something went wrong. Please try again.", "error");
          })
          .finally(() => setButtonBusy(preorderLeaveConfirm, false, ""));
      });
    }

    if (preorderCheckoutButton) {
      preorderCheckoutButton.addEventListener("click", () => {
        setButtonBusy(preorderCheckoutButton, true, "");
        setPreorderMessage("", "");
        executeRecaptcha("submit")
          .then((token) => {
            const data = Object.assign(getCustomerData(), {
              draft_token: preorderDraftToken,
              customer_session: getCustomerSession(),
              recaptcha_token: token || ""
            });
            return post("foodord_reservation_preorder_checkout", data);
          })
          .then((result) => {
            if (!result || !result.success || !result.data || !result.data.redirectUrl) {
              throw new Error(result && result.data && result.data.message ? result.data.message : "");
            }
            if (result.data.editUrl && window.history && typeof window.history.replaceState === "function") {
              window.history.replaceState(window.history.state, "", String(result.data.editUrl));
            }
            window.location.assign(String(result.data.redirectUrl));
          })
          .catch((error) => {
            setPreorderMessage(error.message || i18n.genericError || "Something went wrong. Please try again.", "error");
            setButtonBusy(preorderCheckoutButton, false, "");
          });
      });
    }

    if (homeButton) {
      homeButton.addEventListener("click", () => {
        clearStoredState();
        window.location.assign(config.homeUrl || "/");
      });
    }

    window.addEventListener("pageshow", (event) => {
      const currentUrl = new URL(window.location.href);
      const isPreorderEdit = currentUrl.searchParams.has("foodord_reservation_preorder_edit");

      if (isPreorderEdit) {
        if (event.persisted) {
          window.location.reload();
        }
        return;
      }

      if (event.persisted || getNavigationType() === "back_forward") {
        resetReservationFlow(true);
      }
    });

    const shouldRestoreState = shouldRestoreReservationState();

    if (!shouldRestoreState) {
      clearStoredState();
    }

    setTimeOptions([], "");
    initDatePicker();
    const initialSuccessPayload = getInitialSuccessPayload();
    if (initialSuccessPayload) {
      clearStoredState();
      showSuccessScreen(initialSuccessPayload);
      return;
    }

    const initialPreorderEditPayload = getInitialPreorderEditPayload();
    if (initialPreorderEditPayload) {
      restorePreorderPaymentEdit(initialPreorderEditPayload);
      return;
    }

    if (shouldRestoreState && dateField && dateField.value) {
      loadTimeOptions(timeField ? timeField.value : "");
    }
    if (shouldRestoreState) {
      restoreStoredState();
    }
  }

  function initManageForm(form) {
    if (!form || initializedManageForms.has(form)) {
      return;
    }
    initializedManageForms.add(form);
    form.dataset.foodordReservationManageReady = "1";

    const dateField = form.querySelector("[name='date']");
    const timeField = form.querySelector("[name='time']");
    const partyField = form.querySelector("[name='party_size']");
    const submitButton = form.querySelector("button[type='submit']");
    const timeFieldWrapper = timeField ? timeField.closest(".foodord-table-reservations__field") : null;
    const manageCard = form.closest(".foodord-table-reservations__manage-card");
    const cancelOpenButton = manageCard ? manageCard.querySelector("[data-foodord-reservation-cancel-open]") : null;
    const cancelModal = manageCard ? manageCard.querySelector("[data-foodord-reservation-cancel-modal]") : null;
    const cancelCloseButtons = cancelModal ? cancelModal.querySelectorAll("[data-foodord-reservation-cancel-close]") : [];
    const cancelForm = cancelModal ? cancelModal.querySelector("[data-foodord-reservation-cancel-form]") : null;
    const cancelConfirmButton = cancelModal ? cancelModal.querySelector("[data-foodord-reservation-cancel-confirm]") : null;
    let requestId = 0;
    let previousFocus = null;
    let cancelModalTimer = 0;

    function triggerDateChange() {
      if (!dateField) {
        return;
      }

      dateField.dispatchEvent(new Event("change", { bubbles: true }));
    }

    function initDatePicker() {
      if (!dateField || !window.jQuery || typeof window.jQuery.fn.datepicker !== "function") {
        return;
      }

      const picker = window.jQuery(dateField);
      prepareDatePicker(picker);
      const options = {
        beforeShow: function (_input, instance) {
          window.setTimeout(function () {
            prepareDatePickerWidget(instance.dpDiv);
          }, 0);
        },
        beforeShowDay: getDatepickerAvailability,
        dateFormat: config.dateFormat || "yy-mm-dd",
        minDate: Number.isFinite(Number(config.dateMinOffset)) ? Number(config.dateMinOffset) : 0,
        onSelect: triggerDateChange
      };

      if (Number.isFinite(Number(config.dateMaxOffset)) && Number(config.dateMaxOffset) > 0) {
        options.maxDate = Number(config.dateMaxOffset);
      }

      picker.datepicker(options);
      prepareDatePickerWidget(picker.datepicker("widget"));
    }

    function setTimeLoading(isLoading) {
      if (timeFieldWrapper) {
        timeFieldWrapper.classList.toggle("is-loading-times", isLoading);
      }

      if (timeField) {
        timeField.setAttribute("aria-busy", isLoading ? "true" : "false");
      }
    }

    function setTimeOptions(times, selectedTime, timeLabels) {
      if (!timeField) {
        return;
      }

      const options = Array.isArray(times) ? times.map((time) => String(time)) : [];
      timeField.textContent = "";

      if (!options.length) {
        const placeholder = document.createElement("option");
        placeholder.value = "";
        placeholder.textContent = i18n.timePlaceholder || "Time";
        timeField.appendChild(placeholder);
      }

      options.forEach((time) => {
        const option = document.createElement("option");
        option.value = time;
        option.textContent = timeLabels && timeLabels[time] ? String(timeLabels[time]) : time;
        timeField.appendChild(option);
      });

      timeField.disabled = !options.length;
      timeField.value = options.includes(String(selectedTime)) ? String(selectedTime) : options[0] || "";
    }

    function loadTimeOptions() {
      if (!dateField || !timeField || !partyField || !dateField.value) {
        return;
      }

      const parsedDate = parseDatepickerValue(dateField.value);
      if (parsedDate && isDateDisabledByBookingRules(parsedDate)) {
        setTimeOptions([], "");
        return;
      }

      const currentRequestId = requestId + 1;
      const selectedTime = timeField.value;
      requestId = currentRequestId;
      setTimeLoading(true);

      post("foodord_reservation_manage_time_slots", {
        reservation_id: form.querySelector("[name='reservation_id']") ? form.querySelector("[name='reservation_id']").value : "",
        token: form.querySelector("[name='token']") ? form.querySelector("[name='token']").value : "",
        date: dateField.value,
        party_size: partyField.value
      })
        .then((result) => {
          if (currentRequestId !== requestId) {
            return;
          }

          if (!result || !result.success) {
            throw new Error(result && result.data && result.data.message ? result.data.message : "");
          }

          setTimeOptions(
            result.data && result.data.times ? result.data.times : [],
            selectedTime,
            result.data && result.data.time_labels ? result.data.time_labels : {}
          );
        })
        .catch(() => {
          if (currentRequestId === requestId) {
            setTimeOptions([], "");
          }
        })
        .finally(() => {
          if (currentRequestId === requestId) {
            setTimeLoading(false);
          }
        });
    }

    function handleCancelModalKeydown(event) {
      if (event.key === "Escape") {
        closeCancelModal();
      }
    }

    function openCancelModal() {
      if (!cancelModal) {
        return;
      }

      window.clearTimeout(cancelModalTimer);
      previousFocus = document.activeElement;
      cancelModal.hidden = false;
      window.requestAnimationFrame(() => {
        cancelModal.classList.add("is-open");
      });
      document.addEventListener("keydown", handleCancelModalKeydown);

      if (cancelConfirmButton && typeof cancelConfirmButton.focus === "function") {
        cancelConfirmButton.focus({ preventScroll: true });
      }
    }

    function closeCancelModal() {
      if (!cancelModal) {
        return;
      }

      cancelModal.classList.remove("is-open");
      window.clearTimeout(cancelModalTimer);
      cancelModalTimer = window.setTimeout(() => {
        cancelModal.hidden = true;
      }, 160);
      document.removeEventListener("keydown", handleCancelModalKeydown);

      if (previousFocus && typeof previousFocus.focus === "function") {
        previousFocus.focus({ preventScroll: true });
      }
    }

    if (dateField) {
      dateField.addEventListener("change", loadTimeOptions);
    }

    if (partyField) {
      partyField.addEventListener("change", loadTimeOptions);
      partyField.addEventListener("input", loadTimeOptions);
    }

    form.addEventListener("submit", () => {
      setButtonBusy(submitButton, true, "");
    });

    if (cancelOpenButton) {
      cancelOpenButton.addEventListener("click", openCancelModal);
    }

    cancelCloseButtons.forEach((button) => {
      button.addEventListener("click", closeCancelModal);
    });

    if (cancelForm) {
      cancelForm.addEventListener("submit", () => {
        setButtonBusy(cancelConfirmButton, true, "");
      });
    }

    initDatePicker();
  }

  function initManageSuccess(panel) {
    if (!panel || initializedManageSuccessPanels.has(panel)) {
      return;
    }

    initializedManageSuccessPanels.add(panel);
    panel.dataset.foodordReservationManageSuccessReady = "1";
    panel.classList.remove(successAnimationClass);
    window.requestAnimationFrame(() => {
      panel.classList.add(successAnimationClass);
      if (typeof panel.focus === "function") {
        panel.focus({ preventScroll: true });
      }
    });
  }

  function initDepositCancellationNotice(notice) {
    if (!notice || initializedDepositCancellationNotices.has(notice)) {
      return;
    }

    initializedDepositCancellationNotices.add(notice);
    notice.dataset.foodordReservationDepositCancelledReady = "1";
    const closeButton = notice.querySelector("[data-foodord-reservation-deposit-cancelled-close]");
    let dismissTimer = 0;

    if (window.history && typeof window.history.replaceState === "function") {
      const url = new URL(window.location.href);
      url.searchParams.delete("foodord_reservation_deposit_cancelled");
      url.searchParams.delete("foodord_reservation_order");
      url.searchParams.delete("foodord_reservation_cancel_key");
      window.history.replaceState(window.history.state, "", url.toString());
    }

    window.requestAnimationFrame(() => {
      notice.classList.add("is-visible");
    });

    const dismissNotice = () => {
      window.clearTimeout(dismissTimer);
      if (!notice.isConnected) {
        return;
      }

      notice.classList.remove("is-visible");
      window.setTimeout(() => notice.remove(), 350);
    };

    if (closeButton) {
      closeButton.addEventListener("click", dismissNotice);
    }

    dismissTimer = window.setTimeout(dismissNotice, 10000);
  }

  function initializeReservationContent(scope) {
    if (!scope || typeof scope.querySelectorAll !== "function") {
      return;
    }

    const initializeMatches = (selector, initializer) => {
      if (typeof scope.matches === "function" && scope.matches(selector)) {
        initializer(scope);
      }
      scope.querySelectorAll(selector).forEach(initializer);
    };

    initializeMatches("[data-foodord-reservations]", initReservationForm);
    initializeMatches("[data-foodord-reservation-manage-form]", initManageForm);
    initializeMatches("[data-foodord-reservation-manage-success]", initManageSuccess);
    initializeMatches("[data-foodord-reservation-deposit-cancelled-notice]", initDepositCancellationNotice);
  }

  ready(() => {
    initializeReservationContent(document);

    if (!document.body || typeof window.MutationObserver !== "function") {
      return;
    }

    const observer = new window.MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        mutation.addedNodes.forEach((node) => {
          if (node.nodeType === 1 || node.nodeType === 11) {
            initializeReservationContent(node);
          }
        });
      });
    });

    observer.observe(document.body, { childList: true, subtree: true });
  });
})();
