The checkout combines everything above in one <form id="checkout-form" class="form-store-data" novalidate> that ends with a total and a submit button. It keeps no copy of the cart. It reads the Store's cart getter, and the steppers write back through the setQty action, so the Cart tab's badge follows:
$el.value.on('stepper:change', '.stepper', (e) => {
const id = Number(e.target.dataset.book);
console.log(`book ${id}: qty ${e.detail}`);
$store.dispatch('setQty', { id, qty: e.detail });
});The stepper inputs carry no-store-data, so a stored draft can never contradict the Store. Everything else is read by recalc(), bound as @change on the <form>, which calls convertToData() and $update(); the total adds the delivery cost, plus $2.50 when data.gift is not empty. With one copy of book 1 and two of book 5, one tap on the first plus logged book 1: qty 2, and the total read "Items $62.38 + extras $3.99, Total $66.37". Shared state goes in the Store (Dom7, App API and Store); values only this form needs stay in the form.