diff --git a/PLAN.md b/PLAN.md
index f33456c..97be652 100644
--- a/PLAN.md
+++ b/PLAN.md
@@ -573,30 +573,30 @@ Track completion per file. Mark with `[x]` when done.
### Phase 4 -- Cart
-- [ ] `cart/cart.html.twig`
-- [ ] `cart/cart-empty.html.twig`
-- [ ] `cart/cart-item-data.html.twig`
-- [ ] `cart/cart-totals.html.twig`
-- [ ] `cart/cart-shipping.html.twig`
-- [ ] `cart/cross-sells.html.twig`
-- [ ] `cart/mini-cart.html.twig`
-- [ ] `cart/proceed-to-checkout-button.html.twig`
-- [ ] `cart/shipping-calculator.html.twig`
+- [x] `cart/cart.html.twig`
+- [x] `cart/cart-empty.html.twig`
+- [x] `cart/cart-item-data.html.twig`
+- [x] `cart/cart-totals.html.twig`
+- [x] `cart/cart-shipping.html.twig`
+- [x] `cart/cross-sells.html.twig`
+- [x] `cart/mini-cart.html.twig`
+- [x] `cart/proceed-to-checkout-button.html.twig`
+- [x] `cart/shipping-calculator.html.twig`
### Phase 5 -- Checkout
-- [ ] `checkout/form-checkout.html.twig`
-- [ ] `checkout/form-billing.html.twig`
-- [ ] `checkout/form-shipping.html.twig`
-- [ ] `checkout/form-coupon.html.twig`
-- [ ] `checkout/form-login.html.twig`
-- [ ] `checkout/review-order.html.twig`
-- [ ] `checkout/payment.html.twig`
-- [ ] `checkout/payment-method.html.twig`
-- [ ] `checkout/terms.html.twig`
-- [ ] `checkout/thankyou.html.twig`
-- [ ] `checkout/order-received.html.twig`
-- [ ] `checkout/cart-errors.html.twig`
+- [x] `checkout/form-checkout.html.twig`
+- [x] `checkout/form-billing.html.twig`
+- [x] `checkout/form-shipping.html.twig`
+- [x] `checkout/form-coupon.html.twig`
+- [x] `checkout/form-login.html.twig`
+- [x] `checkout/review-order.html.twig`
+- [x] `checkout/payment.html.twig`
+- [x] `checkout/payment-method.html.twig`
+- [x] `checkout/terms.html.twig`
+- [x] `checkout/thankyou.html.twig`
+- [x] `checkout/order-received.html.twig`
+- [x] `checkout/cart-errors.html.twig`
### Phase 6 -- My Account
diff --git a/assets/css/wc-bootstrap.css b/assets/css/wc-bootstrap.css
index da10b58..b5fd3d4 100644
--- a/assets/css/wc-bootstrap.css
+++ b/assets/css/wc-bootstrap.css
@@ -187,6 +187,56 @@
display: contents;
}
+/* ==========================================================================
+ Cart Table
+ Responsive cart item layout and thumbnail sizing.
+ ========================================================================== */
+
+.woocommerce-cart-form .product-thumbnail img {
+ width: 60px;
+ height: 60px;
+ object-fit: cover;
+ border-radius: var(--bs-border-radius);
+}
+
+/* ==========================================================================
+ Checkout
+ Sticky order review sidebar and payment method toggle.
+ ========================================================================== */
+
+.payment_box {
+ transition: all 0.2s ease;
+}
+
+.woocommerce-checkout .form-row label {
+ font-weight: 500;
+}
+
+/* Override WooCommerce form fields to use Bootstrap styles */
+.woocommerce-checkout .form-row input.input-text,
+.woocommerce-checkout .form-row textarea,
+.woocommerce-checkout .form-row select {
+ display: block;
+ width: 100%;
+ padding: 0.375rem 0.75rem;
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: var(--bs-body-color);
+ background-color: var(--bs-body-bg);
+ border: var(--bs-border-width) solid var(--bs-border-color);
+ border-radius: var(--bs-border-radius);
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+
+.woocommerce-checkout .form-row input.input-text:focus,
+.woocommerce-checkout .form-row textarea:focus,
+.woocommerce-checkout .form-row select:focus {
+ border-color: #86b7fe;
+ outline: 0;
+ box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
+}
+
/* ==========================================================================
Dark Mode Overrides
Fix any plugin elements that don't adapt to Bootstrap's dark mode.
@@ -194,7 +244,14 @@
/* Bootstrap 5 dark mode uses data-bs-theme="dark" attribute on */
[data-bs-theme="dark"] {
- /* Example overrides for dark mode compatibility */
+ /* Checkout form focus color for dark mode */
+}
+
+[data-bs-theme="dark"] .woocommerce-checkout .form-row input.input-text:focus,
+[data-bs-theme="dark"] .woocommerce-checkout .form-row textarea:focus,
+[data-bs-theme="dark"] .woocommerce-checkout .form-row select:focus {
+ border-color: #6ea8fe;
+ box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
}
/* ==========================================================================
diff --git a/templates/cart/cart-empty.html.twig b/templates/cart/cart-empty.html.twig
new file mode 100644
index 0000000..477055f
--- /dev/null
+++ b/templates/cart/cart-empty.html.twig
@@ -0,0 +1,23 @@
+{#
+ # Empty Cart (Bootstrap 5 Override)
+ #
+ # Displayed when the cart has no items.
+ #
+ # WooCommerce PHP equivalent: cart/cart-empty.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+{{ do_action('woocommerce_cart_is_empty') }}
+
+
+
+
{{ __('Your cart is currently empty.') }}
+
+ {% if wc_get_page_id('shop') > 0 %}
+
+ {{ __('Return to shop') }}
+
+ {% endif %}
+
diff --git a/templates/cart/cart-item-data.html.twig b/templates/cart/cart-item-data.html.twig
new file mode 100644
index 0000000..1e17583
--- /dev/null
+++ b/templates/cart/cart-item-data.html.twig
@@ -0,0 +1,24 @@
+{#
+ # Cart Item Data / Variation Details (Bootstrap 5 Override)
+ #
+ # Renders variation/custom data for a cart item.
+ #
+ # Expected context:
+ # item_data - Array of variation data, each with:
+ # .key - Attribute label
+ # .value - Attribute value (HTML)
+ #
+ # WooCommerce PHP equivalent: cart/cart-item-data.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+{% if item_data is defined and item_data|length > 0 %}
+
+ {% for data in item_data %}
+ {{ data.key|raw }}:
+ {{ data.value|raw }}
+ {% endfor %}
+
+{% endif %}
diff --git a/templates/cart/cart-shipping.html.twig b/templates/cart/cart-shipping.html.twig
new file mode 100644
index 0000000..dc16981
--- /dev/null
+++ b/templates/cart/cart-shipping.html.twig
@@ -0,0 +1,69 @@
+{#
+ # Cart Shipping Methods (Bootstrap 5 Override)
+ #
+ # Renders available shipping methods as Bootstrap form-check radios.
+ #
+ # Expected context:
+ # available_methods - Array of shipping method objects
+ # chosen_method - Currently chosen method ID
+ # formatted_destination - Formatted shipping address
+ # has_calculated_shipping - Whether shipping has been calculated
+ # show_shipping_calculator - Whether to show the calculator
+ # package_name - Package name/label
+ # index - Package index
+ #
+ # WooCommerce PHP equivalent: cart/cart-shipping.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+
+
{{ package_name|default(__('Shipping'))|esc_html }}
+
+ {% if available_methods is defined and available_methods|length > 0 %}
+
+
+ {% if formatted_destination is defined and formatted_destination %}
+
+ {{ formatted_destination|raw }}
+
+ {% endif %}
+ {% elseif not has_calculated_shipping|default(false) %}
+
+ {{ __('Shipping costs are calculated during checkout.') }}
+
+ {% else %}
+
+ {{ __('No shipping options were found.') }}
+
+ {% endif %}
+
+ {% if show_shipping_calculator|default(false) %}
+ {% include 'cart/shipping-calculator.html.twig' %}
+ {% endif %}
+
diff --git a/templates/cart/cart-totals.html.twig b/templates/cart/cart-totals.html.twig
new file mode 100644
index 0000000..74fae2e
--- /dev/null
+++ b/templates/cart/cart-totals.html.twig
@@ -0,0 +1,82 @@
+{#
+ # Cart Totals (Bootstrap 5 Override)
+ #
+ # Renders the cart totals as a Bootstrap card with list-group rows.
+ #
+ # Expected context:
+ # cart - WC()->cart object (subtotal, fees, coupons, shipping, total)
+ # cart_subtotal - Pre-rendered subtotal HTML
+ # cart_total - Pre-rendered total HTML
+ # coupons - Array of applied coupon objects
+ # fees - Array of fee objects
+ #
+ # WooCommerce PHP equivalent: cart/cart-totals.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+
+ {{ do_action('woocommerce_before_cart_totals') }}
+
+
+
+
+
+ {# Subtotal #}
+
+ {{ __('Subtotal') }}
+ {{ cart_subtotal|default(cart.get_cart_subtotal())|raw }}
+
+
+ {# Coupons #}
+ {% if coupons is defined %}
+ {% for coupon in coupons %}
+
+ {{ __('Coupon:') }} {{ coupon.code|esc_html }}
+ {{ coupon.discount_html|raw }}
+
+ {% endfor %}
+ {% endif %}
+
+ {# Shipping #}
+ {{ do_action('woocommerce_cart_totals_before_shipping') }}
+
+ {% if wc_shipping_enabled() is defined and wc_shipping_enabled() %}
+
+ {{ do_action('woocommerce_cart_totals_shipping') }}
+
+ {% endif %}
+
+ {{ do_action('woocommerce_cart_totals_after_shipping') }}
+
+ {# Fees #}
+ {% if fees is defined %}
+ {% for fee in fees %}
+
+ {{ fee.name|esc_html }}
+ {{ fee.total_html|raw }}
+
+ {% endfor %}
+ {% endif %}
+
+ {{ do_action('woocommerce_cart_totals_before_order_total') }}
+
+ {# Order total #}
+
+ {{ __('Total') }}
+ {{ cart_total|default(cart.get_total())|raw }}
+
+
+ {{ do_action('woocommerce_cart_totals_after_order_total') }}
+
+
+
+ {{ do_action('woocommerce_proceed_to_checkout') }}
+
+
+
+ {{ do_action('woocommerce_after_cart_totals') }}
+
diff --git a/templates/cart/cart.html.twig b/templates/cart/cart.html.twig
new file mode 100644
index 0000000..4bcdec2
--- /dev/null
+++ b/templates/cart/cart.html.twig
@@ -0,0 +1,171 @@
+{#
+ # Cart Page (Bootstrap 5 Override)
+ #
+ # Main cart page with items table and totals sidebar.
+ # Layout: col-lg-8 (items) + col-lg-4 (totals).
+ #
+ # Expected context:
+ # cart_items - Array from WC()->cart->get_cart(), each with:
+ # .key - Cart item key
+ # .product - WC_Product object
+ # .product_id - Product ID
+ # .product_name - Filtered product name
+ # .permalink - Product URL
+ # .quantity - Quantity
+ # .subtotal - Line subtotal HTML
+ # .price - Unit price HTML
+ # .thumbnail - Product thumbnail HTML
+ # .item_data_html - Variation data HTML
+ # .remove_url - Remove item URL
+ # .visible - Whether item is visible
+ # .css_class - Item CSS class
+ #
+ # WooCommerce PHP equivalent: cart/cart.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+{{ do_action('woocommerce_before_cart') }}
+
+
+ {# Cart items table #}
+
+
+ {# Cart totals sidebar #}
+
+
+ {{ do_action('woocommerce_cart_collaterals') }}
+
+
+
+
+{{ do_action('woocommerce_after_cart') }}
diff --git a/templates/cart/cross-sells.html.twig b/templates/cart/cross-sells.html.twig
new file mode 100644
index 0000000..390d431
--- /dev/null
+++ b/templates/cart/cross-sells.html.twig
@@ -0,0 +1,32 @@
+{#
+ # Cross-sell Products (Bootstrap 5 Override)
+ #
+ # Renders cross-sell product recommendations below the cart.
+ #
+ # Expected context:
+ # cross_sells - Array of WC_Product objects
+ # columns - Number of columns
+ # heading - Section heading (filtered)
+ #
+ # WooCommerce PHP equivalent: cart/cross-sells.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+{% if cross_sells is defined and cross_sells|length > 0 %}
+
+ {% set heading = heading|default(__('You may be interested in…')) %}
+ {% if heading %}
+ {{ heading }}
+ {% endif %}
+
+ {{ woocommerce_product_loop_start() }}
+
+ {% for product in cross_sells %}
+ {% include 'content-product.html.twig' with { product: product } %}
+ {% endfor %}
+
+ {{ woocommerce_product_loop_end() }}
+
+{% endif %}
diff --git a/templates/cart/mini-cart.html.twig b/templates/cart/mini-cart.html.twig
new file mode 100644
index 0000000..a5629bf
--- /dev/null
+++ b/templates/cart/mini-cart.html.twig
@@ -0,0 +1,87 @@
+{#
+ # Mini Cart / Cart Widget (Bootstrap 5 Override)
+ #
+ # Renders the mini cart as an offcanvas slide-in panel.
+ #
+ # Expected context:
+ # cart_items - Array from WC()->cart->get_cart()
+ # cart_is_empty - Whether cart is empty
+ # cart_subtotal - Cart subtotal HTML
+ # args - Widget arguments (list_class)
+ #
+ # WooCommerce PHP equivalent: cart/mini-cart.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+{{ do_action('woocommerce_before_mini_cart') }}
+
+{% if not cart_is_empty|default(true) %}
+
+ {{ do_action('woocommerce_before_mini_cart_contents') }}
+
+ {% if cart_items is defined %}
+ {% for item in cart_items %}
+
+ {# Remove link #}
+
+
+
+
+ {# Thumbnail #}
+ {% if item.permalink %}
+
+ {{ item.thumbnail|raw }}
+
+ {% endif %}
+
+ {# Product info #}
+
+ {% if item.permalink %}
+
+ {{ item.product_name }}
+
+ {% else %}
+
{{ item.product_name }}
+ {% endif %}
+
+ {{ item.item_data_html|default('')|raw }}
+
+
+ {{ item.quantity }} × {{ item.price|raw }}
+
+
+
+ {% endfor %}
+ {% endif %}
+
+ {{ do_action('woocommerce_mini_cart_contents') }}
+
+
+
+ {{ do_action('woocommerce_widget_shopping_cart_total') }}
+
+ {{ __('Subtotal:') }}
+ {{ cart_subtotal|raw }}
+
+
+
+ {{ do_action('woocommerce_widget_shopping_cart_before_buttons') }}
+
+
+ {{ do_action('woocommerce_widget_shopping_cart_buttons') }}
+
+
+ {{ do_action('woocommerce_widget_shopping_cart_after_buttons') }}
+{% else %}
+
+ {{ __('No products in the cart.') }}
+
+{% endif %}
+
+{{ do_action('woocommerce_after_mini_cart') }}
diff --git a/templates/cart/proceed-to-checkout-button.html.twig b/templates/cart/proceed-to-checkout-button.html.twig
new file mode 100644
index 0000000..7197c8e
--- /dev/null
+++ b/templates/cart/proceed-to-checkout-button.html.twig
@@ -0,0 +1,12 @@
+{#
+ # Proceed to Checkout Button (Bootstrap 5 Override)
+ #
+ # WooCommerce PHP equivalent: cart/proceed-to-checkout-button.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+
+ {{ __('Proceed to checkout') }}
+
diff --git a/templates/cart/shipping-calculator.html.twig b/templates/cart/shipping-calculator.html.twig
new file mode 100644
index 0000000..3f3e44b
--- /dev/null
+++ b/templates/cart/shipping-calculator.html.twig
@@ -0,0 +1,109 @@
+{#
+ # Shipping Calculator (Bootstrap 5 Override)
+ #
+ # Collapsible form to estimate shipping costs.
+ #
+ # Expected context:
+ # button_text - Submit button text
+ # customer_country - Selected country code
+ # customer_state - Selected state code
+ # customer_city - City value
+ # customer_postcode - Postcode value
+ # countries - Array of country options
+ # states - Array of state options for selected country
+ # show_country - Whether to show country field
+ # show_state - Whether to show state field
+ # show_city - Whether to show city field
+ # show_postcode - Whether to show postcode field
+ #
+ # WooCommerce PHP equivalent: cart/shipping-calculator.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+{{ do_action('woocommerce_before_shipping_calculator') }}
+
+
+
+{{ do_action('woocommerce_after_shipping_calculator') }}
diff --git a/templates/checkout/cart-errors.html.twig b/templates/checkout/cart-errors.html.twig
new file mode 100644
index 0000000..abf5717
--- /dev/null
+++ b/templates/checkout/cart-errors.html.twig
@@ -0,0 +1,24 @@
+{#
+ # Cart Errors on Checkout (Bootstrap 5 Override)
+ #
+ # Displayed when checkout cannot proceed due to cart validation errors.
+ #
+ # WooCommerce PHP equivalent: checkout/cart-errors.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+{{ do_action('woocommerce_cart_has_errors') }}
+
+
+
+ {{ __('There are some issues with the items in your cart. Please go back to your cart and resolve these issues before checking out.') }}
+
+
+
+
+
+ {{ __('Return to cart') }}
+
+
diff --git a/templates/checkout/form-billing.html.twig b/templates/checkout/form-billing.html.twig
new file mode 100644
index 0000000..49e5b1f
--- /dev/null
+++ b/templates/checkout/form-billing.html.twig
@@ -0,0 +1,66 @@
+{#
+ # Billing Form (Bootstrap 5 Override)
+ #
+ # Renders billing address fields within a Bootstrap card.
+ #
+ # Expected context:
+ # checkout - WC_Checkout object with:
+ # .get_checkout_fields('billing') - Array of billing field configs
+ #
+ # WooCommerce PHP equivalent: checkout/form-billing.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+
+
+
+
+ {{ do_action('woocommerce_before_checkout_billing_form', checkout) }}
+
+
+ {% if billing_fields is defined %}
+ {% for key, field in billing_fields %}
+ {{ woocommerce_form_field(key, field, checkout.get_value(key)) }}
+ {% endfor %}
+ {% endif %}
+
+
+ {{ do_action('woocommerce_after_checkout_billing_form', checkout) }}
+
+
+
+ {# Account creation fields (for guest checkout) #}
+ {% if checkout.is_registration_enabled() is defined and checkout.is_registration_enabled() and not is_user_logged_in() %}
+ {% if checkout.is_registration_required() is not defined or not checkout.is_registration_required() %}
+
+
+
+
+ {{ __('Create an account?') }}
+
+
+
+ {% endif %}
+
+ {{ do_action('woocommerce_before_checkout_registration_form', checkout) }}
+
+
+ {% if account_fields is defined %}
+ {% for key, field in account_fields %}
+ {{ woocommerce_form_field(key, field, checkout.get_value(key)) }}
+ {% endfor %}
+ {% endif %}
+
+
+ {{ do_action('woocommerce_after_checkout_registration_form', checkout) }}
+ {% endif %}
+
diff --git a/templates/checkout/form-checkout.html.twig b/templates/checkout/form-checkout.html.twig
new file mode 100644
index 0000000..51b83d9
--- /dev/null
+++ b/templates/checkout/form-checkout.html.twig
@@ -0,0 +1,52 @@
+{#
+ # Checkout Form (Bootstrap 5 Override)
+ #
+ # Main checkout page: 7+5 column layout (customer details + order review).
+ #
+ # Expected context:
+ # checkout - WC_Checkout object
+ #
+ # WooCommerce PHP equivalent: checkout/form-checkout.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+{{ do_action('woocommerce_before_checkout_form', checkout) }}
+
+
+
+{{ do_action('woocommerce_after_checkout_form', checkout) }}
diff --git a/templates/checkout/form-coupon.html.twig b/templates/checkout/form-coupon.html.twig
new file mode 100644
index 0000000..509e801
--- /dev/null
+++ b/templates/checkout/form-coupon.html.twig
@@ -0,0 +1,45 @@
+{#
+ # Checkout Coupon Form (Bootstrap 5 Override)
+ #
+ # Collapsible coupon code input on the checkout page.
+ #
+ # WooCommerce PHP equivalent: checkout/form-coupon.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+{% if wc_coupons_enabled() %}
+
+
+
+{% endif %}
diff --git a/templates/checkout/form-login.html.twig b/templates/checkout/form-login.html.twig
new file mode 100644
index 0000000..ba3f549
--- /dev/null
+++ b/templates/checkout/form-login.html.twig
@@ -0,0 +1,35 @@
+{#
+ # Checkout Login Form (Bootstrap 5 Override)
+ #
+ # Collapsible login prompt at the top of the checkout page.
+ #
+ # WooCommerce PHP equivalent: checkout/form-login.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+{% if is_user_logged_in() is defined and not is_user_logged_in() %}
+
+
+
+ {% include 'global/form-login.html.twig' with {
+ message: __('If you have shopped with us before, please enter your details below. If you are a new customer, please proceed to the Billing section.'),
+ redirect: wc_get_checkout_url(),
+ hidden: false
+ } %}
+
+{% endif %}
diff --git a/templates/checkout/form-shipping.html.twig b/templates/checkout/form-shipping.html.twig
new file mode 100644
index 0000000..3e30d19
--- /dev/null
+++ b/templates/checkout/form-shipping.html.twig
@@ -0,0 +1,69 @@
+{#
+ # Shipping Form (Bootstrap 5 Override)
+ #
+ # Renders shipping address fields with "ship to different address" toggle.
+ #
+ # Expected context:
+ # checkout - WC_Checkout object
+ # shipping_fields - Array of shipping field configs
+ # order_fields - Array of order note fields
+ #
+ # WooCommerce PHP equivalent: checkout/form-shipping.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+
+
+
+
+
+ {{ do_action('woocommerce_before_checkout_shipping_form', checkout) }}
+
+
+ {% if shipping_fields is defined %}
+ {% for key, field in shipping_fields %}
+ {{ woocommerce_form_field(key, field, checkout.get_value(key)) }}
+ {% endfor %}
+ {% endif %}
+
+
+ {{ do_action('woocommerce_after_checkout_shipping_form', checkout) }}
+
+
+
+
+{# Order notes #}
+
+ {{ do_action('woocommerce_before_order_notes', checkout) }}
+
+ {% if order_fields is defined and order_fields|length > 0 %}
+
+
+
+
+ {% for key, field in order_fields %}
+ {{ woocommerce_form_field(key, field, checkout.get_value(key)) }}
+ {% endfor %}
+
+
+
+ {% endif %}
+
+ {{ do_action('woocommerce_after_order_notes', checkout) }}
+
diff --git a/templates/checkout/order-received.html.twig b/templates/checkout/order-received.html.twig
new file mode 100644
index 0000000..af969ac
--- /dev/null
+++ b/templates/checkout/order-received.html.twig
@@ -0,0 +1,18 @@
+{#
+ # Order Received Message (Bootstrap 5 Override)
+ #
+ # Short confirmation text displayed on the thank-you page.
+ # HPOS compatible: no $post global, uses WC_Order methods only.
+ #
+ # Expected context:
+ # order - WC_Order object (optional)
+ #
+ # WooCommerce PHP equivalent: checkout/order-received.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+
+ {{ __('Thank you. Your order has been received.') }}
+
diff --git a/templates/checkout/payment-method.html.twig b/templates/checkout/payment-method.html.twig
new file mode 100644
index 0000000..9669e0a
--- /dev/null
+++ b/templates/checkout/payment-method.html.twig
@@ -0,0 +1,46 @@
+{#
+ # Single Payment Method (Bootstrap 5 Override)
+ #
+ # Renders a payment gateway as a list-group-item with radio and description.
+ #
+ # Expected context:
+ # gateway - WC_Payment_Gateway object with:
+ # .id - Gateway ID
+ # .get_title() - Gateway title
+ # .get_icon() - Gateway icon HTML
+ # .has_fields() - Whether gateway has inline fields
+ # .get_description() - Gateway description
+ # .chosen - Whether this is the selected gateway
+ # .payment_fields() - Renders inline payment fields
+ #
+ # WooCommerce PHP equivalent: checkout/payment-method.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+
+
+
+
+
+ {{ gateway.get_title()|esc_html }}
+ {{ gateway.get_icon()|raw }}
+
+
+
+ {% if gateway.has_fields() or gateway.get_description() %}
+
+ {% if gateway.get_description() %}
+
{{ gateway.get_description()|wp_kses_post }}
+ {% endif %}
+ {{ gateway.payment_fields() }}
+
+ {% endif %}
+
diff --git a/templates/checkout/payment.html.twig b/templates/checkout/payment.html.twig
new file mode 100644
index 0000000..360a012
--- /dev/null
+++ b/templates/checkout/payment.html.twig
@@ -0,0 +1,54 @@
+{#
+ # Payment Methods & Place Order (Bootstrap 5 Override)
+ #
+ # Renders payment gateway selection and the place order button.
+ #
+ # Expected context:
+ # available_gateways - Array of WC_Payment_Gateway objects
+ # order_button_text - Place order button label
+ #
+ # WooCommerce PHP equivalent: checkout/payment.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+
+ {{ do_action('woocommerce_review_order_before_payment') }}
+
+ {% if available_gateways is defined and available_gateways|length > 0 %}
+
+
+
+ {% for gateway_id, gateway in available_gateways %}
+ {% include 'checkout/payment-method.html.twig' with { gateway: gateway } %}
+ {% endfor %}
+
+
+ {% else %}
+
+ {{ __('Sorry, it seems that there are no available payment methods. Please contact us if you require assistance or wish to make alternate arrangements.') }}
+
+ {% endif %}
+
+
+ {{ do_action('woocommerce_review_order_before_submit') }}
+
+ {{ wp_nonce_field('woocommerce-process_checkout', 'woocommerce-process-checkout-nonce') }}
+
+
+ {{ order_button_text|default(__('Place order')) }}
+
+
+ {{ do_action('woocommerce_review_order_after_submit') }}
+
+
+ {{ do_action('woocommerce_review_order_after_payment') }}
+
diff --git a/templates/checkout/review-order.html.twig b/templates/checkout/review-order.html.twig
new file mode 100644
index 0000000..bdacebf
--- /dev/null
+++ b/templates/checkout/review-order.html.twig
@@ -0,0 +1,91 @@
+{#
+ # Order Review Table (Bootstrap 5 Override)
+ #
+ # Renders the order summary table during checkout.
+ #
+ # Expected context:
+ # cart_items - Array of cart items for review
+ # cart_subtotal - Subtotal HTML
+ # cart_total - Total HTML
+ # coupons - Applied coupons
+ # fees - Fees
+ #
+ # WooCommerce PHP equivalent: checkout/review-order.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+
+
+
+
+
+ {{ __('Product') }}
+ {{ __('Subtotal') }}
+
+
+
+ {{ do_action('woocommerce_review_order_before_cart_contents') }}
+
+ {% if cart_items is defined %}
+ {% for item in cart_items %}
+
+
+ {{ item.product_name|esc_html }}
+ × {{ item.quantity }}
+ {{ item.item_data_html|default('')|raw }}
+
+
+ {{ item.subtotal|raw }}
+
+
+ {% endfor %}
+ {% endif %}
+
+ {{ do_action('woocommerce_review_order_after_cart_contents') }}
+
+
+
+ {{ __('Subtotal') }}
+ {{ cart_subtotal|raw }}
+
+
+ {% if coupons is defined %}
+ {% for coupon in coupons %}
+
+ {{ __('Coupon:') }} {{ coupon.code|esc_html }}
+ {{ coupon.discount_html|raw }}
+
+ {% endfor %}
+ {% endif %}
+
+ {{ do_action('woocommerce_review_order_before_shipping') }}
+
+ {% if wc_shipping_enabled() is defined and wc_shipping_enabled() %}
+ {{ do_action('woocommerce_review_order_shipping') }}
+ {% endif %}
+
+ {{ do_action('woocommerce_review_order_after_shipping') }}
+
+ {% if fees is defined %}
+ {% for fee in fees %}
+
+ {{ fee.name|esc_html }}
+ {{ fee.total_html|raw }}
+
+ {% endfor %}
+ {% endif %}
+
+ {{ do_action('woocommerce_review_order_before_order_total') }}
+
+
+ {{ __('Total') }}
+ {{ cart_total|raw }}
+
+
+ {{ do_action('woocommerce_review_order_after_order_total') }}
+
+
+
+
diff --git a/templates/checkout/terms.html.twig b/templates/checkout/terms.html.twig
new file mode 100644
index 0000000..7a31300
--- /dev/null
+++ b/templates/checkout/terms.html.twig
@@ -0,0 +1,32 @@
+{#
+ # Terms & Conditions Checkbox (Bootstrap 5 Override)
+ #
+ # WooCommerce PHP equivalent: checkout/terms.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+{{ do_action('woocommerce_checkout_before_terms_and_conditions') }}
+
+{% if wc_terms_and_conditions_checkbox_enabled() is defined and wc_terms_and_conditions_checkbox_enabled() %}
+
+ {{ do_action('woocommerce_checkout_terms_and_conditions') }}
+
+
+
+
+ {{ wc_terms_and_conditions_checkbox_text()|raw }}
+
+
+
+
+{% endif %}
+
+{{ do_action('woocommerce_checkout_after_terms_and_conditions') }}
diff --git a/templates/checkout/thankyou.html.twig b/templates/checkout/thankyou.html.twig
new file mode 100644
index 0000000..9a92175
--- /dev/null
+++ b/templates/checkout/thankyou.html.twig
@@ -0,0 +1,75 @@
+{#
+ # Thank You / Order Confirmation (Bootstrap 5 Override)
+ #
+ # HPOS compatible: uses WC_Order object methods only, no $post global.
+ #
+ # Expected context:
+ # order - WC_Order object (or null on failure)
+ #
+ # WooCommerce PHP equivalent: checkout/thankyou.php
+ #
+ # @package WcBootstrap
+ # @since 0.1.0
+ #}
+
+{{ do_action('woocommerce_before_thankyou') }}
+
+{% if order is defined and order %}
+ {% if order.has_status('failed') %}
+
+
+ {{ __('Unfortunately your order cannot be processed as the originating bank/merchant has declined your transaction. Please attempt your purchase again.') }}
+
+
+
+
+ {{ __('Pay') }}
+
+
+ {% else %}
+
+
+ {% include 'checkout/order-received.html.twig' with { order: order } %}
+
+
+
+
+
+
+ {{ __('Order number:') }}
+ {{ order.get_order_number() }}
+
+
+ {{ __('Date:') }}
+ {{ order.get_date_created().date_i18n(wc_date_format()) }}
+
+ {% if order.get_billing_email() %}
+
+ {{ __('Email:') }}
+ {{ order.get_billing_email()|esc_html }}
+
+ {% endif %}
+
+ {{ __('Total:') }}
+ {{ order.get_formatted_order_total()|raw }}
+
+ {% if order.get_payment_method_title() %}
+
+ {{ __('Payment method:') }}
+ {{ order.get_payment_method_title()|esc_html }}
+
+ {% endif %}
+
+
+ {% endif %}
+
+ {{ do_action('woocommerce_thankyou_' ~ order.get_payment_method(), order.get_id()) }}
+ {{ do_action('woocommerce_thankyou', order.get_id()) }}
+{% else %}
+
+
+ {% include 'checkout/order-received.html.twig' %}
+
+{% endif %}