:root {
    --brand: #6f4518;
    --brand-dark: #4a2e0f;
    --cream: #fbf3e7;
    --text: #2c2016;

    /* Mobile app-shell palette (header, bottom nav, floating actions, quick-add
       accents). Kept separate from --brand/--brand-dark above, which stay wired
       to the admin-configurable primary/secondary color override in app.blade.php
       — these four are fixed design constants for the new mobile shell chrome. */
    --color-primary-dark: #3D0C0C;
    --color-primary-darker: #2A0808;
    --color-accent-gold: #F5B826;
    --color-whatsapp: #25D366;
    --page-bg: #FAFAFA;
}

body {
    font-family: 'Poppins', sans-serif;
    color: var(--text);
    background: #fff;
}

/* Bootstrap 4's .container tops out at max-width:1140px from the xl breakpoint
   (1200px) upward — it has no larger tier (unlike Bootstrap 5's xxl), so on
   wide desktop screens (1440px, 1920px+) every section using .container sits
   in a fixed 1140px column with large empty margins. This file loads after
   Bootstrap's own CSS (see app.blade.php), so overriding the same selector
   here wins the cascade on source order alone, no !important needed, and it
   applies site-wide since every template already uses plain .container.
   Breakpoints below 1200px are untouched, so mobile/tablet are unaffected. */
@media (min-width: 1200px) {
    .container {
        max-width: 1320px;
    }
}
@media (min-width: 1600px) {
    .container {
        max-width: 1600px;
    }
}

/* Product grid: 5-per-row on desktop (>=lg, matching the breakpoint the
   header/category-sidebar desktop layout already switches on). Bootstrap 4's
   12-column grid has no native 1/5 utility, so this is a custom column class
   applied alongside the existing col-6/col-md-3 classes in each grid template
   — below lg it's inert (those Bootstrap classes still control 2-up mobile /
   4-up tablet), it only takes over at >=992px. Card padding/type shrink
   slightly in the same breakpoint so the narrower 5-up card doesn't feel
   cramped. */
@media (min-width: 992px) {
    .col-lg-5th {
        flex: 0 0 20%;
        max-width: 20%;
    }
    .product-card .product-body,
    .product-card-body {
        padding: 0.85rem;
    }
    .product-card .product-body h6,
    .product-card-body h6 {
        font-size: 0.92rem;
    }
    .product-card .price {
        font-size: 0.95rem;
    }
    .product-card .price-old {
        font-size: 0.8rem;
    }
}

a {
    color: var(--brand);
}
a:hover {
    color: var(--brand-dark);
    text-decoration: none;
}

.btn-brand {
    background: var(--brand);
    color: #fff;
    border-radius: 30px;
    padding: 0.5rem 1.5rem;
    font-weight: 500;
}
.btn-brand:hover {
    background: var(--brand-dark);
    color: #fff;
}

.site-header {
    background: #fff;
    box-shadow: 0 2px 10px rgba(0,0,0,0.06);
    position: sticky;
    top: 0;
    z-index: 100;
}
.navbar-brand {
    display: flex;
    align-items: center;
    font-weight: 700;
    color: var(--brand-dark);
}
.navbar-brand img {
    height: 40px;
    width: 40px;
    object-fit: cover;
    border-radius: 50%;
    margin-right: 0.5rem;
}
.nav-link {
    font-weight: 500;
    color: var(--text) !important;
}

/* Topbar (>=lg only, desktop-header is d-none d-lg-block): phone left, currency
   + language right. Two flex children with justify-content:space-between, same
   as the rows below — the browser mirrors their order under [dir="rtl"] on its
   own, so no manual override is needed to get phone-right/currency-left in Arabic. */
.header-row-topbar {
    background: var(--cream);
    border-bottom: 1px solid #eee2d3;
    font-size: 0.8rem;
}
.header-row-topbar .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    min-height: 36px;
}
.topbar-phone {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--brand-dark);
    font-weight: 600;
    white-space: nowrap;
}
.topbar-phone:hover {
    color: var(--brand);
    text-decoration: none;
}
.topbar-phone svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}
.topbar-right {
    display: flex;
    align-items: center;
    gap: 1.25rem;
}
.topbar-currency {
    color: var(--text);
    font-weight: 600;
    opacity: 0.7;
    letter-spacing: 0.02em;
}
.header-row-topbar .header-lang-switch .dropdown-toggle {
    color: var(--brand-dark);
    opacity: 1;
}
.header-row-topbar .header-lang-switch .dropdown-toggle:hover {
    color: var(--brand);
}

/* Desktop header (>=lg): two-row layout. Row 1 (logo/search/account icons) and
   row 2 (nav links bar) use flexbox with `gap` for internal spacing — gap is not
   a physical left/right property, so unlike margin/padding utilities it needs no
   [dir="rtl"] override: the browser reverses flex item order under RTL on its
   own and gap just fills whichever space that reversal leaves. Only genuinely
   physical positioning (absolute-positioned badge/button, asymmetric input
   padding) gets explicit RTL overrides below. */
.header-row-top {
    background: #fff;
    padding: 1rem 0;
}
.header-row-top .container {
    display: flex;
    align-items: center;
    gap: 2rem;
}
.header-search-form {
    position: relative;
    flex: 1 1 auto;
    max-width: 640px;
    margin: 0 auto;
}
.header-search-form .form-control {
    width: 100%;
    border-radius: 30px;
    padding: 0.65rem 3.25rem 0.65rem 1.25rem;
    border: 1px solid #eee2d3;
    background: var(--cream);
}
.header-search-form .form-control:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 0.2rem rgba(111, 69, 24, 0.15);
}
.header-search-btn {
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: var(--brand);
    color: #fff;
}
.header-search-btn:hover {
    background: var(--brand-dark);
}
.header-search-btn svg {
    width: 16px;
    height: 16px;
}
.header-icons {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    flex-shrink: 0;
}
.header-icon-link {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--text);
    font-weight: 500;
    white-space: nowrap;
}
.header-icon-link:hover {
    color: var(--brand);
    text-decoration: none;
}
.header-icon-link svg {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
}
.header-icon-link.dropdown-toggle::after {
    margin-left: 0.3rem;
    vertical-align: 0.1em;
}
.header-cart-badge {
    position: absolute;
    top: -8px;
    right: -10px;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--brand);
    color: #fff;
    font-size: 0.65rem;
    font-weight: 600;
    line-height: 1;
}

.header-row-bottom {
    background: var(--brand);
}
.header-row-bottom .container {
    display: flex;
    align-items: center;
    gap: 2rem;
    min-height: 64px;
}
/* Taller/bolder than .header-nav-links a on purpose — it's the visual anchor for
   the category sidebar sitting directly below it on the homepage (same .container
   left edge, so the two align), and the row above was heightened to fit it. */
.header-categories-btn {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: #fff;
    font-weight: 700;
    font-size: 1.1rem;
    white-space: nowrap;
    flex-shrink: 0;
}
.header-categories-btn:hover {
    color: #fff;
    opacity: 0.9;
    text-decoration: none;
}
.header-categories-btn svg {
    width: 24px;
    height: 24px;
    flex-shrink: 0;
}
.header-nav-links {
    display: flex;
    align-items: center;
    gap: 1.75rem;
    list-style: none;
    margin: 0;
    padding: 0;
}
.header-nav-links a {
    color: #fff;
    opacity: 0.85;
    font-weight: 500;
}
.header-nav-links a:hover {
    opacity: 1;
    color: #fff;
    text-decoration: none;
}
.header-lang-switch .dropdown-toggle {
    color: #fff;
    font-weight: 600;
    opacity: 0.9;
}
.header-lang-switch .dropdown-toggle:hover {
    opacity: 1;
    text-decoration: none;
}

.hero {
    background: linear-gradient(135deg, var(--brand) 0%, var(--brand-dark) 100%);
    color: #fff;
    padding: 5rem 0;
}
.hero h1 {
    font-weight: 700;
    font-size: 2.5rem;
}
.hero .btn-light {
    border-radius: 30px;
    font-weight: 600;
    padding: 0.6rem 2rem;
}

.section-title {
    font-weight: 700;
    color: var(--brand-dark);
    margin-bottom: 1.5rem;
}
.section-title-icon {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Mobile-only horizontal scroll for the existing product grids (Featured/Popular/
   Set Menu/Latest): reuses the exact same .row/.col-6/.col-md-3/.col-lg-5th markup
   already on every one of these sections (and on menu/category/search/wishlist,
   which do NOT get this class and so keep their plain wrapping grid) — this is a
   pure CSS override of that same markup for the carousel look, not a duplicated
   mobile-only block, so desktop (untouched, this only applies below 992px) renders
   from identical DOM either way. Higher specificity (.product-carousel-row > .col-6)
   beats Bootstrap's own .col-6/.col-md-3 rules regardless of stylesheet order. */
@media (max-width: 991.98px) {
    .product-carousel-row {
        flex-wrap: nowrap;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        padding-bottom: 4px;
    }
    .product-carousel-row::-webkit-scrollbar {
        display: none;
    }
    .product-carousel-row > .col-6 {
        flex: 0 0 46%;
        max-width: 46%;
        scroll-snap-align: start;
    }
}

.category-pill {
    display: block;
    text-align: center;
    padding: 1rem 0.5rem;
    border-radius: 12px;
    background: var(--cream);
    color: var(--text);
    transition: transform .15s ease;
}
.category-pill:hover {
    transform: translateY(-3px);
    color: var(--brand-dark);
}
.category-pill img {
    width: 56px;
    height: 56px;
    object-fit: cover;
    border-radius: 50%;
    margin-bottom: 0.5rem;
}

.product-card {
    display: block;
    border: 1px solid #eee2d3;
    border-radius: 14px;
    overflow: hidden;
    height: 100%;
    transition: box-shadow .15s ease;
    background: #fff;
    color: var(--text);
}
.product-card:hover {
    box-shadow: 0 8px 24px rgba(111,69,24,0.15);
}
/* .product-card-media wraps the image link plus the heart/add buttons that float
   over it — position:relative anchors those two absolutely-positioned buttons to
   the image itself rather than the whole card, which matters once the add button
   is pulled halfway below the image's own bottom edge (see .product-card-add). */
.product-card-media {
    position: relative;
}
.product-card-media-link {
    display: block;
}
.product-card .product-img {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    object-position: center;
}
.product-card-body,
.product-card .product-body {
    display: block;
    padding: 1rem;
    color: var(--text);
}
.product-card-body:hover {
    color: var(--text);
    text-decoration: none;
}
.product-card .price {
    font-weight: 700;
    color: var(--brand);
}
.product-card .price-old {
    text-decoration: line-through;
    color: #aaa;
    font-size: 0.85rem;
    margin-right: 0.35rem;
}

/* Wishlist heart (mobile-only, see .d-lg-none on the element itself — desktop's
   product grid stays exactly as it was before this redesign, per instructions not
   to touch it). Top-left over the image in LTR, top-right in RTL: an absolute,
   physical position, so — like the header search button/cart badge above — it
   needs an explicit [dir="rtl"] override rather than relying on flex reversal. */
.product-card-heart {
    position: absolute;
    top: 10px;
    left: 10px;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.85);
    color: var(--color-primary-dark);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
    z-index: 2;
}
.product-card-heart:hover {
    color: var(--color-primary-dark);
    text-decoration: none;
}
.product-card-heart svg {
    width: 16px;
    height: 16px;
}
.product-card-heart.active {
    color: #e0245e;
}
[dir="rtl"] .product-card-heart {
    left: auto;
    right: 10px;
}

/* Quick-add pill (mobile-only): centered at the bottom of the image, half over the
   image and half over the card body below it — the -18px offset (half the button's
   own ~36px height) is what produces that straddle. */
.product-card-add {
    position: absolute;
    left: 50%;
    bottom: -18px;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.3rem 0.3rem 0.3rem 0.75rem;
    border: none;
    border-radius: 999px;
    background: #fff;
    color: var(--color-primary-dark);
    font-weight: 700;
    font-size: 0.78rem;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
    z-index: 2;
    white-space: nowrap;
}
[dir="rtl"] .product-card-add {
    padding: 0.3rem 0.75rem 0.3rem 0.3rem;
}
.product-card-add-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--color-primary-dark);
    color: #fff;
    font-size: 1rem;
    line-height: 1;
}

/* ==========================================================================
   "All Categories" full product list (Design Requirement 2, item 2).
   ========================================================================== */
.all-products-toolbar-icons {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    background: #f2efe9;
    border-radius: 999px;
    padding: 0.25rem;
}
.all-products-icon-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--text);
    opacity: 0.65;
}
.all-products-icon-btn svg {
    width: 16px;
    height: 16px;
}
.all-products-icon-btn.active,
.all-products-icon-btn:hover {
    opacity: 1;
    color: var(--color-primary-dark);
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}

.all-products-list {
    display: flex;
    flex-direction: column;
}
.all-products-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}
.all-products-grid-item {
    flex: 0 0 calc(50% - 0.5rem);
    max-width: calc(50% - 0.5rem);
}
@media (min-width: 768px) {
    .all-products-grid-item {
        flex-basis: calc(25% - 0.75rem);
        max-width: calc(25% - 0.75rem);
    }
}
.all-products-empty {
    padding: 2rem 0;
    text-align: center;
    color: var(--text);
    opacity: 0.6;
}
.all-products-loading {
    padding: 1rem 0;
    text-align: center;
    color: var(--text);
    opacity: 0.6;
    font-size: 0.85rem;
}
.all-products-sentinel {
    height: 1px;
}

/* Product row (list mode): image [image, text] DOM order reverses under RTL
   natively (see the partial's own comment) — only the physically-positioned add
   button below needs an explicit [dir="rtl"] flip. This is the single shared list
   item component reused on the home page's All Categories section, category pages,
   the menu page, and search results (see web/partials/product-list-item.blade.php)
   — restyle here once, every listing page picks it up. */
.product-list-item {
    position: relative;
    display: flex;
    /* stretch (not flex-end) so .product-list-item-body fills the same height as
       the image — title then starts right at the top of that box (near the
       image's own top edge) instead of the whole text block sitting bottom-
       aligned/low in the row, while .product-list-item-price's margin-top:auto
       still pushes the price down to the bottom of that box, keeping it (and the
       Add button anchored to the same offset) exactly where the previous fix
       placed them. */
    align-items: stretch;
    gap: 0.9rem;
    padding: 0.85rem 0;
    border-bottom: 1px solid #eee2d3;
}
.product-list-item:last-child {
    border-bottom: none;
}
.product-list-item-img {
    align-self: center;
    flex-shrink: 0;
    display: block;
    width: 140px;
    height: 140px;
    border-radius: 16px;
    overflow: hidden;
}
.product-list-item-img img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.product-list-item-body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    /* Nudges the title down from the very top of this stretched (see
       .product-list-item's align-items:stretch) column toward the image's
       vertical middle, without touching .product-list-item-price's own
       margin-top:auto below — that still soaks up whatever space is left and
       keeps the price/Add button pinned to the bottom, same as before. */
    padding-top: 2rem;
    color: var(--text);
}
.product-list-item-body:hover {
    color: var(--text);
    text-decoration: none;
}
.product-list-item-body h6 {
    color: #1a1a1a;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.product-list-item-desc {
    margin: 0.1rem 0 1rem;
    color: #8b8b8b;
    font-size: 0.82rem;
    line-height: 1.35;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.product-list-item-price {
    margin-top: auto;
}
.product-list-item-price .price {
    font-weight: 700;
    color: var(--color-primary-dark);
}
/* Shares the price's own line instead of floating as its own row: .product-list-
   item now bottom-aligns its flex children (see align-items:flex-end above, with
   .product-list-item-img re-centered via align-self so only the text column/price
   is what actually bottom-aligns) — that makes the price line's bottom edge land
   at a fixed, predictable offset (this row's own bottom padding) regardless of
   whether the description is present, so anchoring this button to that same
   "bottom" offset reliably keeps the two level with each other. Price itself
   renders at the near-image edge of the text column (default text-align start),
   so this sits at the row's outer/far edge — the opposite end of the same line —
   and stays within the row's own bounds instead of straddling past them. */
.product-list-item-add {
    position: absolute;
    right: 0;
    bottom: 0.85rem;
    display: flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.3rem 0.3rem 0.3rem 0.75rem;
    border: none;
    border-radius: 999px;
    background: #fff;
    color: var(--color-primary-dark);
    font-weight: 700;
    font-size: 0.78rem;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
    white-space: nowrap;
    z-index: 2;
}
[dir="rtl"] .product-list-item-add {
    right: auto;
    left: 0;
    padding: 0.3rem 0.75rem 0.3rem 0.3rem;
}

/* ==========================================================================
   Quick-add bottom sheet + toast (mobile only; on desktop this modal is never
   triggered since the buttons that open it are all d-lg-none, but the CSS is
   scoped by breakpoint anyway rather than relying on that).
   ========================================================================== */
@media (max-width: 991.98px) {
    .mobile-bottom-sheet .modal-dialog {
        margin: 0;
        display: flex;
        align-items: flex-end;
        min-height: 100%;
        max-width: 100%;
    }
    .mobile-bottom-sheet .modal-content {
        width: 100%;
        border-radius: 24px 24px 0 0;
        border: none;
        max-height: 85vh;
    }
    .mobile-bottom-sheet .modal-body {
        overflow-y: auto;
        padding: 1.25rem 1.5rem 1.5rem;
    }
}
.mobile-bottom-sheet .modal-header {
    padding: 1.25rem 1.5rem 0.75rem;
    border-bottom: none;
    align-items: center;
}
.mobile-bottom-sheet .modal-title {
    font-weight: 700;
    color: var(--color-primary-dark);
}
.mobile-bottom-sheet .close {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    margin: 0;
    padding: 0;
    border-radius: 50%;
    background: #f2ede5;
    color: var(--text);
    opacity: 1;
    font-weight: 400;
    line-height: 1;
    transition: background-color 0.15s ease;
}
.mobile-bottom-sheet .close:hover {
    background: #e6ddd0;
    color: var(--text);
    opacity: 1;
}

.quick-add-form-head {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    margin-bottom: 1.25rem;
}
.quick-add-form-head img {
    width: 68px;
    height: 68px;
    border-radius: 16px;
    object-fit: cover;
    flex-shrink: 0;
}
.quick-add-form-head h6 {
    margin: 0;
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--text);
}

.cart-toast {
    position: fixed;
    left: 50%;
    bottom: calc(var(--mobile-bottom-nav-height, 0px) + 20px);
    transform: translate(-50%, 12px);
    display: flex;
    align-items: center;
    gap: 0.75rem;
    background: var(--color-primary-dark);
    color: #fff;
    padding: 0.6rem 1.1rem;
    border-radius: 999px;
    font-size: 0.85rem;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease, transform 0.2s ease;
    z-index: 1100;
    max-width: 88vw;
    text-align: center;
}
.cart-toast.show {
    opacity: 1;
    transform: translate(-50%, 0);
    /* showUndoToast() sets pointer-events back on via this same class so the
       Undo button is actually clickable while visible; plain showToast() calls
       never add a button, so this has nothing to affect there. */
    pointer-events: auto;
}
.cart-toast-undo {
    flex-shrink: 0;
    background: none;
    border: none;
    padding: 0;
    color: var(--color-accent-gold);
    font-weight: 700;
    font-size: 0.85rem;
    text-decoration: underline;
}
@media (min-width: 992px) {
    .cart-toast {
        bottom: 20px;
    }
}

/* ==========================================================================
   Fly-to-cart animation (mobile-shell.js's flyToCart/bounce helpers). The
   clone's own left/top/width/height are set inline per-flight (real, live
   coordinates from getBoundingClientRect()) — only its static look and the two
   landing pulses live here. transform/opacity only, so this stays compositor-
   only (no layout thrash) throughout the flight.
   ========================================================================== */
.fly-to-cart-clone {
    position: fixed;
    margin: 0;
    border-radius: 50%;
    object-fit: cover;
    pointer-events: none;
    z-index: 2000;
    will-change: transform, opacity;
}

@keyframes cartIconBounce {
    0% { transform: scale(1) rotate(0deg); }
    35% { transform: scale(1.3) rotate(-6deg); }
    65% { transform: scale(0.9) rotate(4deg); }
    100% { transform: scale(1) rotate(0deg); }
}
.cart-icon-bounce {
    animation: cartIconBounce 0.4s ease-out;
}

@keyframes cartBadgePop {
    0% { transform: scale(1); }
    40% { transform: scale(1.5); }
    70% { transform: scale(0.85); }
    100% { transform: scale(1); }
}
.cart-badge-pop {
    animation: cartBadgePop 0.4s ease-out;
}

.banner-slide img {
    width: 100%;
    border-radius: 14px;
}
.banner-slide.h-100 img {
    height: 100%;
    object-fit: cover;
}

/* Desktop homepage sidebar (category list next to the banner). Spacing between
   a row's own children uses `gap`, not margin — like the header icons, that
   means no [dir="rtl"] override is needed for it: flex row children reverse
   order under RTL natively, and gap just fills whatever space that leaves.
   Only true physical properties (the sublist's asymmetric indent) get a
   manual RTL rule, in the RTL section below. */
.category-sidebar {
    height: 100%;
    display: flex;
    flex-direction: column;
    background: var(--cream);
    border-radius: 14px;
    padding: 0.5rem 0;
}
.category-sidebar-empty {
    padding: 1rem 1.25rem;
    color: var(--text);
    opacity: 0.6;
    font-size: 0.9rem;
}
.category-sidebar-item {
    border-bottom: 1px solid rgba(111, 69, 24, 0.1);
}
.category-sidebar-item:last-child {
    border-bottom: none;
}
.category-sidebar-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding-right: 0.5rem;
}
.category-sidebar-link {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.65rem 0.75rem;
    color: var(--text);
    font-weight: 500;
    min-width: 0;
}
.category-sidebar-link:hover {
    color: var(--brand);
    text-decoration: none;
}
.category-sidebar-link img {
    width: 32px;
    height: 32px;
    object-fit: cover;
    border-radius: 50%;
    flex-shrink: 0;
}
.category-sidebar-link span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.category-sidebar-toggle {
    flex-shrink: 0;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--text);
    opacity: 0.55;
}
.category-sidebar-toggle:hover {
    opacity: 1;
    color: var(--brand);
    background: rgba(111, 69, 24, 0.08);
}
.category-sidebar-toggle svg {
    width: 16px;
    height: 16px;
    transition: transform 0.15s ease;
}
.category-sidebar-toggle[aria-expanded="true"] svg {
    transform: rotate(180deg);
}
.category-sidebar-sublist {
    display: flex;
    flex-direction: column;
    padding: 0 0.75rem 0.5rem 3.25rem;
}
.category-sidebar-sublink {
    padding: 0.35rem 0;
    color: var(--text);
    opacity: 0.75;
    font-size: 0.9rem;
}
.category-sidebar-sublink:hover {
    opacity: 1;
    color: var(--brand);
    text-decoration: none;
}

.hero-sidebar {
    border-radius: 14px;
    padding: 3rem 2rem;
}

.site-footer {
    background: var(--brand-dark);
    color: #f1e6d6;
    padding: 3rem 0 1rem;
    margin-top: 3rem;
}
.site-footer h5 {
    color: #fff;
    font-weight: 600;
}
.site-footer a {
    color: #e6d6bd;
}
.site-footer a:hover {
    color: #fff;
}
.footer-bottom {
    border-top: 1px solid rgba(255,255,255,0.15);
    margin-top: 1.5rem;
    padding-top: 1rem;
    font-size: 0.85rem;
    text-align: center;
}

.auth-card {
    max-width: 440px;
    margin: 3rem auto;
    padding: 2rem;
    border: 1px solid #eee2d3;
    border-radius: 14px;
}
.auth-card h2 {
    color: var(--brand-dark);
    font-weight: 700;
    margin-bottom: 1.5rem;
}
.auth-divider {
    display: flex;
    align-items: center;
    text-align: center;
    color: #999;
    font-size: 0.85rem;
    margin: 1.25rem 0;
}
.auth-divider::before,
.auth-divider::after {
    content: "";
    flex: 1;
    border-bottom: 1px solid #eee2d3;
}
.auth-divider:not(:empty)::before {
    margin-right: 0.75rem;
}
.auth-divider:not(:empty)::after {
    margin-left: 0.75rem;
}
.btn-google {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    border: 1px solid #dadce0;
    background: #fff;
    color: #3c4043;
    font-weight: 500;
}
.btn-google:hover {
    background: #f8f8f8;
    color: #3c4043;
}

[dir="rtl"] .navbar-brand img {
    margin-right: 0;
    margin-left: 0.5rem;
}
[dir="rtl"] .price-old {
    margin-right: 0;
    margin-left: 0.35rem;
}

/* Desktop header row 1/2: these four rules are the only genuinely physical
   (non-flex, non-gap) positioning in the new header, so they're the only part
   that needs a manual flip — the search button sits absolute-positioned inside
   its input (not reordered by flex), the input's own icon-clearance padding is
   asymmetric, and the cart badge is absolute-positioned off the icon's corner. */
[dir="rtl"] .header-search-form .form-control {
    padding: 0.65rem 1.25rem 0.65rem 3.25rem;
}
[dir="rtl"] .header-search-btn {
    right: auto;
    left: 6px;
}
[dir="rtl"] .header-cart-badge {
    right: auto;
    left: -10px;
}
[dir="rtl"] .whatsapp-float-btn {
    right: auto;
    left: 20px;
}
/* Category sidebar sublist: indented under the parent icon+label above it.
   That indent is a physical left-padding (3.25rem to clear the 32px icon plus
   its gap), so it needs flipping to the opposite side under RTL — same
   reasoning as the other physical-position rules in this section. The row's
   own icon/label/toggle spacing uses `gap` (see .category-sidebar-row in the
   main stylesheet section), which needs no override since flex row children
   already reverse natively under RTL. */
[dir="rtl"] .category-sidebar-sublist {
    padding: 0 3.25rem 0.5rem 0.75rem;
}
[dir="rtl"] .category-sidebar-row {
    padding-right: 0;
    padding-left: 0.5rem;
}

/* ==========================================================================
   RTL overrides
   Bootstrap 4's spacing/text/float utilities (.ml-*, .mr-*, .pl-*, .pr-*,
   .text-left, .text-right) are physical properties, not logical ones, so
   they do not auto-flip under dir="rtl" the way Bootstrap 5's .ms-*/.me-*
   do. Each rule below targets exactly the utility classes actually used in
   this site's views (grep-audited), flipped to the opposite side. Bootstrap
   marks its own spacing/text utilities `!important`, so these must match
   that to win the cascade.
   ========================================================================== */

[dir="rtl"] .ml-auto {
    margin-left: 0 !important;
    margin-right: auto !important;
}
[dir="rtl"] .ml-2 {
    margin-left: 0 !important;
    margin-right: 0.5rem !important;
}
[dir="rtl"] .ml-lg-2 {
    margin-left: 0 !important;
    margin-right: 0.5rem !important;
}
[dir="rtl"] .mr-2 {
    margin-right: 0 !important;
    margin-left: 0.5rem !important;
}
[dir="rtl"] .pl-3 {
    padding-left: 0 !important;
    padding-right: 1rem !important;
}
[dir="rtl"] .text-right {
    text-align: left !important;
}

/* Dropdown menus (language switcher, account menu): anchor to the opposite
   edge so they open toward the reading direction instead of off the side
   the navbar items just moved to. */
[dir="rtl"] .dropdown-menu-right {
    right: auto !important;
    left: 0 !important;
}

/* Breadcrumb: .breadcrumb is a flex container, so under dir="rtl" the browser
   already reverses the visual order of .breadcrumb-item children natively —
   the DOM order (Home, Menu, current page) already matches the desired RTL
   reading order (Home should read first = rightmost), so item order is left
   untouched here on purpose. What Bootstrap does NOT flip automatically is
   the "/" separator's own physical CSS: padding-left on each item after the
   first, and — importantly — `float: left` on the "/" ::before pseudo-element
   itself. That float keeps the "/" glued to the item's physical left edge
   regardless of dir, which is what actually produced the garbled look
   ("MenuHome" jammed together) rather than any item being out of order. */
[dir="rtl"] .breadcrumb-item + .breadcrumb-item {
    padding-left: 0;
    padding-right: 0.5rem;
}
[dir="rtl"] .breadcrumb-item + .breadcrumb-item::before {
    float: right;
    padding-right: 0;
    padding-left: 0.5rem;
}

/* Radio/checkbox inputs: Bootstrap positions .form-check-input with a
   negative left margin pulled into the left padding reserved by
   .form-check — both physical, so under RTL the input renders on the
   opposite side from its label instead of immediately before it. */
[dir="rtl"] .form-check {
    padding-left: 0;
    padding-right: 1.25rem;
}
[dir="rtl"] .form-check-input {
    margin-left: 0;
    margin-right: -1.25rem;
}

/* Product hero row (image + name/price/description/variations): .row is a
   flex container, so under dir="rtl" the browser already reverses which
   physical side each DOM child lands on. That's correct and desired for
   e.g. the breadcrumb above, where DOM order already matches RTL reading
   order. It is NOT what's wanted here: the image is DOM-first (so LTR gets
   image-left/content-right, which is right for LTR), but that same DOM
   order means native RTL reversal puts content on the left and the image
   on the right — pushing the primary text away from where an RTL reader's
   eye lands first. row-reverse undoes exactly that one reversal, restoring
   image-left/content-right under RTL too (mirroring the LTR case instead
   of inheriting the generic flex behavior), without duplicating markup. */
[dir="rtl"] .product-hero-row {
    flex-direction: row-reverse;
}

/* Sequential image+text rows (cart line item thumbnail, category header
   icon): these use an inline margin-right to space the image from the text
   that follows it. Native flex reversal under RTL correctly moves the image
   to the row's start (right) side — that part needs no fix, same reasoning
   as the breadcrumb above — but the inline margin-right stays physically on
   the right regardless of dir, so it ends up pushing space away from the
   text instead of toward it. Inline styles need !important to override. */
[dir="rtl"] .img-margin-end {
    margin-right: 0 !important;
    margin-left: 1rem !important;
}

/* Global text alignment: Bootstrap's Reboot sets `body { text-align: left }`
   explicitly (a physical value, not the logical `start`), and text-align is
   an inherited property — so every heading, paragraph, and label on the
   site inherits a hardcoded left-alignment regardless of dir, unless it has
   its own more specific override. This is the single point of truth for
   the site's default text alignment; fixing it here (rather than patching
   individual elements) cascades correctly to product titles/descriptions,
   variation labels, form labels, etc. site-wide. Elements with their own
   explicit text-align (e.g. .category-pill, .footer-bottom, .text-right)
   are unaffected, since an explicit rule always wins over an inherited one. */
[dir="rtl"] body {
    text-align: right;
}
/* Product description box: no RTL override needed here — [dir="rtl"] body's
   text-align:right above already cascades to this <p>, and the box itself
   (background/border-radius/shadow/padding) is direction-agnostic. */
.product-description-box {
    background: #FAF7F4;
    border-radius: 14px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
    padding: 14px;
}
[dir="rtl"] .auth-divider:not(:empty)::before {
    margin-right: 0;
    margin-left: 0.75rem;
}
[dir="rtl"] .auth-divider:not(:empty)::after {
    margin-left: 0;
    margin-right: 0.75rem;
}

/* Google Maps location picker (address forms / checkout). The search input and
   the locate button are each reparented independently into the map's own control
   tray by map-picker.js (top corner and bottom corner respectively) — including
   which side they sit on under RTL — so only their own appearance needs styling
   here; positioning itself is left to Maps' native control layout, same as its
   own built-in controls, rather than CSS absolute positioning. */
.map-picker-canvas {
    height: 280px;
    width: 100%;
}
.map-picker-search {
    width: 260px;
    max-width: calc(100vw - 40px);
    margin: 10px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
}
.map-picker-locate {
    width: 40px;
    height: 40px;
    margin: 10px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    color: #555;
    border: none;
    border-radius: 50%;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    cursor: pointer;
}
.map-picker-locate:hover {
    background: #f5f5f5;
    color: var(--brand);
}
.map-picker-locate:disabled {
    opacity: 0.6;
    cursor: wait;
}
.map-picker-locate-status:empty {
    display: none;
}

/* Floating WhatsApp button (all public pages, via web.layouts.app). Fixed to
   the viewport rather than any scrolling container, so it only needs to clear
   the sticky header's z-index:100 (see .site-header above) to stay on top. */
.whatsapp-float-btn {
    position: fixed;
    right: 20px;
    bottom: 20px;
    width: 56px;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #25D366;
    border-radius: 50%;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
    z-index: 1000;
    transition: transform 0.15s ease;
}
.whatsapp-float-btn:hover {
    transform: scale(1.06);
}

/* ==========================================================================
   Mobile app-shell (<lg): header, bottom nav, floating actions.
   Desktop (.desktop-header, >=lg) is untouched by anything below — every
   selector here targets classes only rendered inside the d-lg-none markup.
   Stacking order per spec: banner/cards (auto) < add buttons (2) <
   whatsapp (1000) < home (1001) < bottom nav (1002) < sticky .site-header (100,
   already defined above — the mobile shell header lives inside it and does not
   need its own z-index).
   ========================================================================== */

:root {
    --mobile-bottom-nav-height: 60px;
}

.mobile-shell-header {
    position: relative;
    background: linear-gradient(180deg, var(--color-primary-dark) 0%, var(--color-primary-darker) 100%);
    padding: 0.85rem 0 2rem;
    color: #fff;
}
/* Non-home pages only render the hamburger/bell/avatar row (see app.blade.php) —
   the extra 2rem bottom padding above exists to make room for the greeting/
   location/search/wave block that's hidden here, so it's trimmed back down to
   match the top padding instead of leaving a tall empty gap under the icons. */
.mobile-shell-header-compact {
    padding-bottom: 0.85rem;
}
.mobile-shell-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}
.mobile-shell-greeting {
    display: flex;
    flex-direction: column;
    min-width: 0;
    font-size: 0.95rem;
}
.mobile-shell-greeting-hi {
    color: rgba(255, 255, 255, 0.75);
}
.mobile-shell-greeting-name {
    font-weight: 700;
    font-size: 1.05rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.mobile-shell-icons {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    flex-shrink: 0;
}
.mobile-shell-menu-btn,
.mobile-shell-icon-btn {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    flex-shrink: 0;
}
.mobile-shell-menu-btn svg,
.mobile-shell-icon-btn svg {
    width: 19px;
    height: 19px;
}
.mobile-shell-icon-btn:hover {
    color: #fff;
    text-decoration: none;
}
.mobile-shell-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    overflow: hidden;
    flex-shrink: 0;
    border: 2px solid rgba(255, 255, 255, 0.35);
}
.mobile-shell-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.mobile-shell-avatar svg {
    width: 20px;
    height: 20px;
}

.mobile-shell-location {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.85rem;
    color: rgba(255, 255, 255, 0.85);
    font-size: 0.85rem;
}
.mobile-shell-location:hover {
    color: #fff;
    text-decoration: none;
}
.mobile-shell-location svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}
.mobile-shell-location span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mobile-shell-search {
    margin-top: 0.85rem;
}
/* The icon used to be absolutely positioned over the input, which relied on
   the pill's border-radius math lining up with the icon's own inset — any
   mismatch let the dark header background show through the pill's curved
   corner behind the icon, making it read as sitting outside the white box.
   A flex row keeps the icon a normal layout sibling inside the same white
   pill, so it is structurally impossible for it to render outside the box. */
.mobile-shell-search-box {
    display: flex;
    align-items: center;
    border-radius: 999px;
    background: #fff;
    padding-left: 1.1rem;
}
.mobile-shell-search-box:focus-within {
    box-shadow: 0 0 0 0.2rem rgba(245, 184, 38, 0.35);
}
.mobile-shell-search-box input {
    flex: 1 1 auto;
    min-width: 0;
    width: 100%;
    border: none;
    background: transparent;
    padding: 0.7rem 0.5rem 0.7rem 0;
    color: var(--text);
    font-size: 0.9rem;
}
.mobile-shell-search-box input:focus {
    outline: none;
}
.mobile-shell-search-box button {
    flex-shrink: 0;
    width: 34px;
    height: 34px;
    margin: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: var(--color-primary-dark);
    color: #fff;
}
.mobile-shell-search-box button svg {
    width: 15px;
    height: 15px;
}
[dir="rtl"] .mobile-shell-search-box {
    padding-left: 0;
    padding-right: 1.1rem;
}
[dir="rtl"] .mobile-shell-search-box input {
    padding: 0.7rem 0 0.7rem 0.5rem;
}

/* ==========================================================================
   Product list header (mobile-only): filter/search bar shared by category,
   menu, and search pages (not the home page, which keeps its own header from
   the earlier redesign). See web/partials/product-list-header.blade.php.
   ========================================================================== */
.product-list-header {
    background: var(--color-primary-dark);
    padding: 0.85rem 0;
}
.product-list-header-row {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0;
}
.product-list-filter-btn {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
}
.product-list-filter-btn svg {
    width: 19px;
    height: 19px;
}
/* Same flex-row construction as .mobile-shell-search-box (see above) — the icon
   is a normal layout child of the white pill, not absolutely positioned over it,
   so it cannot repeat the "icon renders outside the box" bug. */
.product-list-search-box {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    border-radius: 999px;
    background: #fff;
    padding-left: 1.1rem;
}
.product-list-search-box input {
    flex: 1 1 auto;
    min-width: 0;
    border: none;
    background: transparent;
    padding: 0.6rem 0.4rem 0.6rem 0;
    color: var(--text);
    font-size: 0.85rem;
}
.product-list-search-box input:focus {
    outline: none;
}
.product-list-search-icon {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    margin-right: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-primary-dark);
    opacity: 0.55;
}
.product-list-search-icon svg {
    width: 15px;
    height: 15px;
}
[dir="rtl"] .product-list-search-box {
    padding-left: 0;
    padding-right: 1.1rem;
}
[dir="rtl"] .product-list-search-box input {
    padding: 0.6rem 0 0.6rem 0.4rem;
}
[dir="rtl"] .product-list-search-icon {
    margin-right: 0;
    margin-left: 6px;
}
/* Solid dark maroon per spec, same as the header behind it — a subtle light
   border (same technique as .mobile-shell-avatar above) is what actually makes
   its circular boundary read against an identical-color background, without
   changing the requested fill color itself. */
.product-list-search-submit {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-radius: 50%;
    background: var(--color-primary-dark);
    color: #fff;
}
.product-list-search-submit svg {
    width: 17px;
    height: 17px;
}
[dir="rtl"] .product-list-search-submit svg {
    transform: scaleX(-1);
}

.product-list-filter-group + .product-list-filter-group {
    margin-top: 1.25rem;
}
.product-list-filter-label {
    font-weight: 600;
    font-size: 0.85rem;
    margin-bottom: 0.5rem;
    color: var(--text);
}
.product-list-filter-options {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}
.product-list-filter-option {
    padding: 0.4rem 1rem;
    border-radius: 999px;
    background: var(--cream);
    color: var(--text);
    font-size: 0.85rem;
    font-weight: 500;
}
.product-list-filter-option:hover {
    text-decoration: none;
    color: var(--text);
}
.product-list-filter-option.active {
    background: var(--color-primary-dark);
    color: #fff;
}

/* Floating category pill: see product-list-category-pill.blade.php's own comment
   for why justify-content:flex-end alone (no [dir="rtl"] override) is enough here. */
.product-list-category-pill-wrap {
    display: flex;
    justify-content: flex-end;
    padding-top: 0;
}
.product-list-category-pill {
    position: relative;
    margin-top: -20px;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: 0.35rem;
    max-width: 60%;
    padding: 0.5rem 1.1rem;
    border: none;
    border-radius: 999px;
    background: var(--color-primary-dark);
    color: #fff;
    font-weight: 600;
    font-size: 0.85rem;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.18);
}
.product-list-category-pill span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.product-list-category-pill svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}
.product-list-category-options {
    display: flex;
    flex-direction: column;
}
.product-list-category-option {
    padding: 0.75rem 0.25rem;
    color: var(--text);
    font-weight: 500;
    border-bottom: 1px solid #eee2d3;
}
.product-list-category-option:last-child {
    border-bottom: none;
}
.product-list-category-option:hover {
    text-decoration: none;
    color: var(--text);
}
.product-list-category-option.active {
    color: var(--color-primary-dark);
    font-weight: 700;
}

.mobile-shell-wave {
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    width: 100%;
    height: 20px;
    display: block;
}

.mobile-shell-drawer {
    padding: 1rem 0 1.25rem;
}
.mobile-shell-drawer-links {
    list-style: none;
    margin: 0 0 1rem;
    padding: 0;
}
.mobile-shell-drawer-links li + li {
    border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.mobile-shell-drawer-links a {
    display: block;
    padding: 0.65rem 0.1rem;
    color: #fff;
    font-weight: 500;
}
.mobile-shell-drawer-links a:hover {
    color: var(--color-accent-gold);
    text-decoration: none;
}
.mobile-shell-drawer-langs {
    display: flex;
    gap: 0.6rem;
    margin-bottom: 1rem;
}
.mobile-shell-drawer-langs a {
    padding: 0.3rem 0.9rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    font-weight: 600;
    font-size: 0.8rem;
}
.mobile-shell-drawer-langs a.active {
    background: var(--color-accent-gold);
    color: var(--color-primary-dark);
}
.mobile-shell-drawer-auth {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
.mobile-shell-drawer-auth .btn-outline-secondary {
    color: #fff;
    border-color: rgba(255, 255, 255, 0.4);
}
.mobile-shell-drawer-auth .btn-outline-secondary:hover {
    color: var(--color-primary-dark);
    background: #fff;
}

/* Reserve room at the bottom of every mobile page for the fixed bottom nav, plus
   enough extra to clear the full raised height of the floating Home button (see
   .mobile-home-float-btn below) so it never overlaps the last row of product
   cards/carousels regardless of scroll position, plus a small buffer. */
@media (max-width: 991.98px) {
    .mobile-shell-main {
        padding-bottom: calc(var(--mobile-bottom-nav-height) + 35px);
    }
}

.mobile-bottom-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: var(--mobile-bottom-nav-height);
    background: var(--color-primary-dark);
    /* Flat/straight top edge on purpose — no border-radius here. A rounded
       corner treatment didn't scale consistently across different mobile
       viewport widths (looked fine on some, distorted/misaligned on others),
       so this bar is now a plain full-width rectangle. The circular notch
       right below (for the floating Home button) is a separate, local cutout
       and is unaffected by this — it still gives the button its own embedded
       look even though the bar's outer edge is now straight. */
    display: flex;
    align-items: center;
    justify-content: space-around;
    box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.18);
    z-index: 1002;
    /* Carves a circular notch out of the bar's top-center edge so the floating
       Home button (raised above, centered) reads as embedded into its own
       cutout rather than just stacked on top of a flat bar. The page background
       never actually shows through here — the padding-bottom reserve above keeps
       scrolled content well clear of this region at any scroll position. */
    -webkit-mask-image: radial-gradient(circle 30px at 50% 0px, transparent 99%, #000 100%);
    mask-image: radial-gradient(circle 30px at 50% 0px, transparent 99%, #000 100%);
}
.mobile-bottom-nav-item {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    color: rgba(255, 255, 255, 0.65);
}
.mobile-bottom-nav-item:hover,
.mobile-bottom-nav-item.active {
    color: #fff;
}
.mobile-bottom-nav-item svg {
    width: 23px;
    height: 23px;
}
.mobile-bottom-nav-badge {
    position: absolute;
    top: 2px;
    right: 6px;
    min-width: 16px;
    height: 16px;
    padding: 0 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--color-accent-gold);
    color: var(--color-primary-dark);
    font-size: 0.6rem;
    font-weight: 700;
    line-height: 1;
}
[dir="rtl"] .mobile-bottom-nav-badge {
    right: auto;
    left: 6px;
}

/* Home float button: centered in the bottom nav's notch cutout above, vertically
   centered on the nav's own top edge (bottom offset = nav height - half the
   button's own height) so it sits half in/half out of the carved gap instead of
   just floating on top of it. Always horizontally centered (not a directional
   element, so no RTL override needed). */
.mobile-home-float-btn {
    position: fixed;
    left: 50%;
    bottom: calc(var(--mobile-bottom-nav-height) - 25px);
    transform: translateX(-50%);
    width: 50px;
    height: 50px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-primary-dark);
    border: 3px solid #fff;
    border-radius: 50%;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
    z-index: 1001;
}
.mobile-home-float-btn:hover {
    background: var(--color-primary-darker);
}

/* Press flash: instant feedback on touchstart/mousedown (see mobile-shell.js),
   before the real page navigation even starts. Keeps the button's own
   translateX(-50%) centering baked into every keyframe step — an animation's
   transform value fully replaces the static one for its duration, so dropping
   it here would make the button jump off-center mid-flash. */
@keyframes homeBtnPress {
    /* Every step keeps the button's own drop-shadow (0 4px 12px ...) as the first
       box-shadow layer and adds a second layer that expands and fades outward —
       a visible white halo on top of the press-and-release scale bounce. */
    0%   { transform: translateX(-50%) scale(1);    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25), 0 0 0 0 rgba(255, 255, 255, 0.65); }
    35%  { transform: translateX(-50%) scale(0.85); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25), 0 0 0 6px rgba(255, 255, 255, 0.45); }
    65%  { transform: translateX(-50%) scale(1.05); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25), 0 0 0 12px rgba(255, 255, 255, 0.15); }
    100% { transform: translateX(-50%) scale(1);    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25), 0 0 0 16px rgba(255, 255, 255, 0); }
}
.mobile-home-float-btn.is-pressed {
    animation: homeBtnPress 0.3s ease-out;
}

/* Loading ring: shown from click until the real page navigation actually
   unloads this one (see mobile-shell.js) — a plain CSS spinner (one colored
   border side, rotating) laid over a slightly-larger invisible ring so it reads
   clearly around the button's own edge without resizing it. */
.mobile-home-float-btn::after {
    content: '';
    position: absolute;
    top: -6px;
    left: -6px;
    right: -6px;
    bottom: -6px;
    border-radius: 50%;
    border: 3px solid transparent;
    border-top-color: #fff;
    opacity: 0;
    pointer-events: none;
}
.mobile-home-float-btn.is-loading::after {
    opacity: 1;
    animation: homeBtnRingSpin 0.7s linear infinite;
}
@keyframes homeBtnRingSpin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

/* Bottom nav icons: same instant press-flash pattern as the Home button above
   (consistency for every other full-page-reload nav link), just without the
   translateX centering offset or loading ring the Home button also has. */
@keyframes navItemPress {
    0% { transform: scale(1); }
    40% { transform: scale(0.85); }
    100% { transform: scale(1); }
}
.mobile-bottom-nav-item.is-pressed {
    animation: navItemPress 0.25s ease;
}

/* WhatsApp float button: on mobile it must clear the fixed bottom nav (unlike the
   desktop-only rule above, which just anchors it to the viewport corner) and per
   spec always sits on the physical left edge of the screen — unlike the cart badge/
   search icon elsewhere in this file, this one position is NOT mirrored under RTL. */
@media (max-width: 991.98px) {
    .whatsapp-float-btn {
        left: 16px;
        right: auto;
        bottom: calc(var(--mobile-bottom-nav-height) + 14px);
        z-index: 1000;
    }
    [dir="rtl"] .whatsapp-float-btn {
        left: 16px;
        right: auto;
    }
}

/* ==========================================================================
   Horizontal scroll-snap carousels (mobile home page): banner, categories,
   and (further below) product rails all share this one pattern instead of a
   JS carousel library — a plain flex row with scroll-snap-type covers the
   "swiper, snap-scroll, no visible scrollbar" requirement with no dependency.
   flex row children already reverse under dir="rtl" natively (same convention
   as elsewhere in this file), so swiping/scroll direction and item order both
   mirror correctly with no extra rule needed here.
   ========================================================================== */
.hscroll {
    display: flex;
    gap: 0.85rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
}
.hscroll::-webkit-scrollbar {
    display: none;
}
.hscroll-item {
    scroll-snap-align: start;
    flex: 0 0 auto;
    min-width: 0;
}

.section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 0.9rem;
}
.section-head-link {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--color-primary-dark);
}
.section-head-link:hover {
    color: var(--brand);
    text-decoration: none;
}

.banner-hscroll-item {
    width: 88%;
    max-width: 420px;
}
.banner-hscroll-item img {
    width: 100%;
    height: 150px;
    object-fit: cover;
    border-radius: 20px;
    display: block;
}

.category-circle-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    width: 72px;
    text-align: center;
    color: var(--text);
}
.category-circle-item:hover {
    color: var(--color-primary-dark);
    text-decoration: none;
}
.category-circle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: var(--cream);
    overflow: hidden;
    flex-shrink: 0;
}
.category-circle img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.category-circle-name {
    font-size: 0.75rem;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

.highlight-banner-hscroll-item {
    width: 88%;
    max-width: 420px;
    display: block;
    border-radius: 20px;
    overflow: hidden;
}
.highlight-banner-hscroll-item img {
    width: 100%;
    max-width: 100%;
    height: auto;
    border-radius: 20px;
    display: block;
}

.highlight-banner-single {
    display: block;
    width: 100%;
    border-radius: 20px;
    overflow: hidden;
}
.highlight-banner-single img {
    width: 100%;
    max-width: 100%;
    height: auto;
    border-radius: 20px;
    display: block;
}

.product-item-note-group {
    position: relative;
    margin-bottom: 1.25rem;
}
.product-item-note-label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 700;
}
.product-item-note-label-icon {
    flex-shrink: 0;
    color: var(--color-primary-dark);
}
.product-item-note-input {
    resize: none;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.product-item-note-counter {
    margin-top: 0.25rem;
    font-size: 0.75rem;
    text-align: end;
}

/* ==========================================================================
   Quick-add sheet: variation/add-on option rows (product-options-fields.blade.
   php). Each row is a <label> wrapping its own (visually restyled, still fully
   native/functional) radio or checkbox input, so clicking anywhere on the row
   toggles it — no JS beyond mobile-shell.js's existing live-total listener.
   ========================================================================== */
.option-group {
    margin-bottom: 1.25rem;
}
.option-group-label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 0.5rem;
}
.option-group-label-icon {
    flex-shrink: 0;
    color: var(--color-primary-dark);
}
.option-list {
    display: flex;
    flex-direction: column;
}
.option-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 13px 10px;
    margin: 0;
    border-bottom: 1px solid #f0e9de;
    border-radius: 10px;
    cursor: pointer;
    transition: background-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
}
.option-list .option-row:last-child {
    border-bottom: none;
}
.option-row:active {
    transform: scale(0.98);
}
/* Selected-row highlight: a light maroon wash plus a thin maroon ring, layered
   on top of (not instead of) the plain bottom-border list so the current pick
   still reads clearly even where :has() isn't supported — the row just falls
   back to the bare list look, still fully usable. */
.option-row:has(.option-row-input:checked) {
    background: rgba(61, 12, 12, 0.06);
    box-shadow: inset 0 0 0 1px rgba(61, 12, 12, 0.35);
}

.option-row-input {
    appearance: none;
    -webkit-appearance: none;
    width: 20px;
    height: 20px;
    margin: 0;
    flex-shrink: 0;
    border: 2px solid #d9cfc0;
    border-radius: 50%;
    position: relative;
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}
.option-row-input[type="checkbox"] {
    border-radius: 6px;
}
.option-row-input:checked {
    border-color: var(--color-primary-dark);
}
.option-row-input[type="checkbox"]:checked {
    background: var(--color-primary-dark);
}
.option-row-input[type="radio"]:checked::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--color-primary-dark);
    transform: translate(-50%, -50%) scale(1);
    animation: optionRowDotIn 0.16s ease;
}
.option-row-input[type="checkbox"]:checked::after {
    content: '';
    position: absolute;
    top: 44%;
    left: 50%;
    width: 5px;
    height: 9px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: translate(-50%, -55%) rotate(45deg);
    animation: optionRowCheckIn 0.16s ease;
}
@keyframes optionRowDotIn {
    from { transform: translate(-50%, -50%) scale(0.3); opacity: 0; }
    to   { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}
@keyframes optionRowCheckIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.option-row-body {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.option-row-name {
    font-size: 0.92rem;
    color: var(--text);
}
.option-row-price {
    flex-shrink: 0;
    font-size: 0.8rem;
    font-weight: 600;
    color: #999;
}

/* ==========================================================================
   Quick-add sheet: quantity stepper + Add to Cart submit button.
   ========================================================================== */
.qty-stepper {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 4px;
    background: #f5efe6;
    border-radius: 999px;
}
.qty-stepper-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: none;
    border-radius: 50%;
    background: var(--color-primary-dark);
    color: #fff;
    flex-shrink: 0;
    transition: transform 0.1s ease, background-color 0.15s ease;
}
.qty-stepper-btn:hover {
    background: var(--color-primary-darker);
}
.qty-stepper-btn:active {
    transform: scale(0.9);
}
.qty-stepper-btn:disabled {
    background: #cabfb0;
    color: #fff;
    opacity: 0.6;
    cursor: not-allowed;
}
.qty-stepper-btn:disabled:active {
    transform: none;
}
/* Smart minus/remove (cart page only, via data-remove-url — see
   mobile-shell.js's updateStepperState()): swaps the "−" icon for a trash
   icon once quantity is at its floor, signalling the button's role changed
   from "decrease" to "remove this line" before the shopper taps it. The
   button itself stays enabled/maroon here (unlike the plain-disabled minus
   used on the quick-add sheet/product page), just a soft red tint so it
   reads as a different, deliberate action. */
.qty-stepper-icon-trash {
    display: none;
}
.qty-stepper-btn-minus.is-remove {
    background: #8a3b3b;
}
.qty-stepper-btn-minus.is-remove:hover {
    background: #6b2c2c;
}
.qty-stepper-btn-minus.is-remove .qty-stepper-icon-minus {
    display: none;
}
.qty-stepper-btn-minus.is-remove .qty-stepper-icon-trash {
    display: block;
}
.qty-stepper-input {
    width: 32px;
    border: none;
    background: transparent;
    text-align: center;
    font-weight: 700;
    font-size: 0.95rem;
    color: var(--text);
    -moz-appearance: textfield;
}
.qty-stepper-input::-webkit-outer-spin-button,
.qty-stepper-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.btn-cart-submit {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    width: 100%;
    height: 50px;
    border: none;
    border-radius: 999px;
    background: var(--color-primary-dark);
    color: #fff;
    font-weight: 700;
    font-size: 0.95rem;
    margin-top: 0.5rem;
    text-decoration: none;
    transition: transform 0.1s ease, background-color 0.15s ease;
}
/* Reused as a plain <a> (checkout/browse-menu links) as well as <button
   type="submit"> — text-decoration/color need repeating in :hover since
   Bootstrap's own a:hover would otherwise win on specificity+source order. */
.btn-cart-submit:hover {
    background: var(--color-primary-darker);
    color: #fff;
    text-decoration: none;
}
.btn-cart-submit:active {
    transform: scale(0.98);
}
.btn-cart-submit-total::before {
    content: '\2014';
    margin-inline-end: 0.5rem;
    opacity: 0.75;
}
.btn-cart-submit-total:empty::before {
    content: '';
    margin: 0;
}

/* ==========================================================================
   Cart page (web/cart/index.blade.php): item cards, order summary card, empty
   state. Each item card's box/layout (border, shadow, radius, flex, colors)
   is inline in the Blade template on purpose — not here — so it can't be
   affected by cascade/specificity/caching anywhere in this file. class=
   "cart-item-card" is kept on that element only as a JS hook (mobile-shell.js
   ::closest('.cart-item-card') + the .is-removing toggle below), not for any
   visual rule.
   ========================================================================== */
/* Optimistic "removing" state while the Undo toast is up — see
   removeCartLineWithUndo() in mobile-shell.js. Nothing has actually been sent
   to the server yet at this point, so this is purely visual. Deliberately the
   ONLY rule targeting .cart-item-card in this stylesheet. */
.cart-item-card.is-removing {
    opacity: 0.35;
    pointer-events: none;
}

.cart-summary-card {
    background: var(--cream);
    border-radius: 16px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
    padding: 1.25rem;
    margin-top: 0.5rem;
}
.cart-summary-title {
    font-weight: 700;
    color: var(--text);
    font-size: 1.05rem;
    margin-bottom: 1rem;
}
.cart-summary-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    font-size: 0.9rem;
    color: var(--text);
    margin-bottom: 0.6rem;
}
.cart-summary-divider {
    border-top: 1px solid rgba(61, 12, 12, 0.12);
    margin: 0.85rem 0;
}
.cart-summary-row-total {
    font-size: 1.1rem;
    font-weight: 700;
    margin-bottom: 1rem;
}
.cart-summary-row-total span:last-child {
    color: var(--color-primary-dark);
}
.cart-summary-help {
    font-size: 0.78rem;
    color: #999;
    margin-bottom: 1rem;
}

.cart-empty-state {
    text-align: center;
    padding: 3.5rem 1rem;
}
.cart-empty-state svg {
    color: var(--color-primary-dark);
    opacity: 0.45;
    margin-bottom: 1rem;
}
.cart-empty-state-text {
    color: #999;
    font-size: 0.95rem;
    margin-bottom: 1.25rem;
}
.cart-empty-state-btn {
    max-width: 260px;
    margin: 0 auto;
}

/* ==========================================================================
   Checkout page: Delivery Type picker (web/checkout/index.blade.php) — a
   centered modal, not a bottom sheet. .modal-dialog-centered is Bootstrap 4's
   own vertical-centering utility (no custom top/left/transform positioning
   needed for that part); everything below is just the rounded-all-corners
   look, explicit width, fade+scale entrance, and the two option cards.
   ========================================================================== */
.order-type-trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 0.5rem 0.75rem;
    border: 1px solid #ced4da;
    border-radius: 6px;
    background: #fff;
    color: var(--text);
    font-size: 0.95rem;
}
.order-type-trigger:focus {
    outline: none;
    border-color: var(--color-primary-dark);
    box-shadow: 0 0 0 3px rgba(61, 12, 12, 0.12);
}
.order-type-modal .modal-dialog {
    width: 90%;
    max-width: 380px;
    margin: 1.75rem auto;
    /* Fade + scale-up (95% -> 100%) instead of Bootstrap's default fade +
       slide-down-from-top — same .show toggle Bootstrap's own JS already
       applies to the .modal element, just a different transform here. */
    transition: transform 0.2s ease-out, opacity 0.2s ease-out;
    transform: scale(0.95);
    opacity: 0;
}
.order-type-modal.show .modal-dialog {
    transform: scale(1);
    opacity: 1;
}
.order-type-modal .modal-content {
    border-radius: 16px;
    border: none;
    overflow: hidden;
}
.order-type-modal .modal-title {
    font-weight: 700;
    color: var(--color-primary-dark);
}
.order-type-options {
    display: flex;
    gap: 0.85rem;
}
.order-type-card {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    padding: 1.25rem 1rem;
    border: 2px solid #f0e9de;
    border-radius: 14px;
    background: #fff;
    color: var(--text);
    transition: border-color 0.15s ease, background-color 0.15s ease, transform 0.1s ease;
}
.order-type-card-icon {
    width: 88px;
    height: 88px;
    object-fit: contain;
    flex-shrink: 0;
}
.order-type-card span {
    font-weight: 600;
    font-size: 0.9rem;
}
.order-type-card.active {
    border-color: var(--color-primary-dark);
    background: rgba(61, 12, 12, 0.06);
}
.order-type-card:active {
    transform: scale(0.98);
}

/* ==========================================================================
   Checkout page (web/checkout/index.blade.php) — mobile only, per request.
   .checkout-card's un-media-queried rule below is the exact desktop parity
   baseline (matches the plain "border rounded p-3 mb-3" it replaced,
   byte-for-byte look), so desktop is unaffected; every premium-look override
   lives inside @media (max-width: 991.98px), same scoping convention as the
   rest of this redesign (.mobile-bottom-sheet, .product-carousel-row, etc.).
   Card-title icons carry d-lg-none in the markup itself for the same reason.
   ========================================================================== */
.checkout-card {
    border: 1px solid #dee2e6;
    border-radius: 0.25rem;
    padding: 1rem;
    margin-bottom: 1rem;
    background: #fff;
}
.checkout-card-title {
    margin: 0 0 1rem;
}

/* The Delivery Details collapse toggle is mobile-only chrome (see the d-lg-none/
   d-none d-lg-flex split in checkout/index.blade.php) — on desktop the section
   must always render expanded regardless of the Bootstrap collapse plugin's
   aria-expanded/.show state, since only the mobile <button> ever toggles it. */
@media (min-width: 992px) {
    .checkout-collapsible-body {
        display: block !important;
        height: auto !important;
    }
}

@media (max-width: 991.98px) {
    .checkout-card {
        border: none;
        border-radius: 16px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
        padding: 16px;
        margin-bottom: 14px;
    }
    .checkout-card-title {
        display: flex;
        align-items: center;
        gap: 0.4rem;
        font-weight: 700;
        font-size: 1rem;
        color: var(--text);
    }
    .checkout-card-title-icon {
        flex-shrink: 0;
        color: var(--color-primary-dark);
        width: 18px;
        height: 18px;
        object-fit: contain;
    }
    .checkout-collapsible-toggle {
        width: 100%;
        justify-content: space-between;
        border: none;
        background: none;
        padding: 0;
        text-align: start;
    }
    .checkout-collapsible-toggle-label {
        display: flex;
        align-items: center;
        gap: 0.4rem;
    }
    .checkout-collapsible-toggle:focus {
        outline: none;
    }
    .checkout-collapsible-optional {
        font-weight: 400;
        font-size: 0.8rem;
        color: #999;
    }
    .checkout-collapsible-chevron {
        flex-shrink: 0;
        color: var(--text);
        opacity: 0.55;
        transition: transform 0.2s ease;
    }
    .checkout-collapsible-toggle[aria-expanded="true"] .checkout-collapsible-chevron {
        transform: rotate(180deg);
    }
    .checkout-field-label {
        display: block;
        font-weight: 600;
        font-size: 0.85rem;
        color: var(--text);
        margin-bottom: 0.35rem;
    }

    /* Custom select: appearance:none + a maroon chevron drawn as a background
       image (no extra DOM element needed) — background-position is a physical
       property, so it needs the [dir="rtl"] flip below, same convention as
       .img-margin-end elsewhere in this file. */
    .checkout-select {
        appearance: none;
        -webkit-appearance: none;
        border: 1px solid #e6dcd0;
        border-radius: 12px;
        padding: 0.6rem 2.25rem 0.6rem 0.85rem;
        background-color: #fff;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%233D0C0C' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: right 0.85rem center;
        background-size: 14px;
        font-size: 0.9rem;
    }
    [dir="rtl"] .checkout-select {
        padding: 0.6rem 0.85rem 0.6rem 2.25rem;
        background-position: left 0.85rem center;
    }
    .checkout-select:focus {
        outline: none;
        border-color: var(--color-primary-dark);
        box-shadow: 0 0 0 3px rgba(61, 12, 12, 0.12);
    }

    .checkout-input {
        border: 1px solid #e6dcd0;
        border-radius: 12px;
        padding: 0.6rem 0.85rem;
        font-size: 0.9rem;
    }
    .checkout-input:focus {
        outline: none;
        border-color: var(--color-primary-dark);
        box-shadow: 0 0 0 3px rgba(61, 12, 12, 0.12);
    }
    .checkout-textarea {
        resize: none;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
    }

    .checkout-coupon-row {
        display: flex;
        gap: 0.5rem;
    }
    .checkout-coupon-row .checkout-input {
        flex: 1;
        min-width: 0;
    }
    .checkout-coupon-apply {
        flex-shrink: 0;
        border: none;
        border-radius: 999px;
        padding: 0.6rem 1.25rem;
        background: var(--color-primary-dark);
        color: #fff;
        font-weight: 600;
        font-size: 0.85rem;
        transition: background-color 0.15s ease, transform 0.1s ease;
    }
    .checkout-coupon-apply:hover {
        background: var(--color-primary-darker);
        color: #fff;
    }
    .checkout-coupon-apply:active {
        transform: scale(0.97);
    }

    .checkout-map-wrap {
        margin: 1rem 0;
        padding: 12px;
        background: #FAF7F4;
        border-radius: 14px;
    }

    /* Custom checkbox: same visual language as .option-row-input's checkbox
       variant (product options sheet), kept as its own class rather than
       reused directly so this stays strictly mobile-scoped instead of
       leaking into the (already-unscoped) shared component. */
    .checkout-checkbox-label {
        display: flex;
        align-items: center;
        gap: 0.6rem;
        cursor: pointer;
    }
    .checkout-checkbox {
        appearance: none;
        -webkit-appearance: none;
        width: 20px;
        height: 20px;
        margin: 0;
        flex-shrink: 0;
        border: 2px solid #d9cfc0;
        border-radius: 6px;
        position: relative;
        cursor: pointer;
        transition: border-color 0.15s ease, background-color 0.15s ease;
    }
    .checkout-checkbox:checked {
        background: var(--color-primary-dark);
        border-color: var(--color-primary-dark);
    }
    .checkout-checkbox:checked::after {
        content: '';
        position: absolute;
        top: 44%;
        left: 50%;
        width: 5px;
        height: 9px;
        border: solid #fff;
        border-width: 0 2px 2px 0;
        transform: translate(-50%, -55%) rotate(45deg);
    }

    /* Payment method rows: same selectable-row pattern as .option-row (product
       options sheet) — a maroon-ringed circle that fills with a dot when
       checked, plus a light maroon wash + inset ring on the selected row. */
    .checkout-option-list {
        display: flex;
        flex-direction: column;
    }
    .checkout-option-row {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        padding: 13px 10px;
        border-bottom: 1px solid #f0e9de;
        border-radius: 10px;
        cursor: pointer;
        transition: background-color 0.15s ease, box-shadow 0.15s ease;
    }
    .checkout-option-list .checkout-option-row:last-child {
        border-bottom: none;
    }
    .checkout-option-row:has(.checkout-option-row-input:checked) {
        background: rgba(61, 12, 12, 0.06);
        box-shadow: inset 0 0 0 1px rgba(61, 12, 12, 0.35);
    }
    .checkout-option-row-input {
        appearance: none;
        -webkit-appearance: none;
        width: 20px;
        height: 20px;
        margin: 0;
        flex-shrink: 0;
        border: 2px solid #d9cfc0;
        border-radius: 50%;
        position: relative;
        cursor: pointer;
        transition: border-color 0.15s ease;
    }
    .checkout-option-row-input:checked {
        border-color: var(--color-primary-dark);
    }
    .checkout-option-row-input:checked::after {
        content: '';
        position: absolute;
        top: 50%;
        left: 50%;
        width: 10px;
        height: 10px;
        border-radius: 50%;
        background: var(--color-primary-dark);
        transform: translate(-50%, -50%);
    }
    .checkout-option-row-icon {
        width: 30px;
        height: 30px;
        object-fit: contain;
        flex-shrink: 0;
    }
    .checkout-option-row span {
        font-size: 0.92rem;
        color: var(--text);
    }

    /* Order Summary — same cream-wash card treatment as the cart page's
       summary card, kept as its own mobile-scoped class rather than reusing
       .cart-summary-card directly (that class has no viewport gating, so
       reusing it here would style checkout's desktop summary too). */
    .checkout-summary-card {
        background: var(--cream);
        border-radius: 16px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
        padding: 16px;
        margin-bottom: 14px;
    }
    .checkout-summary-title {
        font-weight: 700;
        color: var(--text);
        font-size: 1.05rem;
        margin-bottom: 1rem;
    }
    .checkout-summary-row {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.5rem;
        font-size: 0.9rem;
        color: var(--text);
        margin-bottom: 0.6rem;
    }
    .checkout-summary-divider {
        border-top: 1px solid rgba(61, 12, 12, 0.12);
        margin: 0.85rem 0;
    }
    .checkout-summary-row-total {
        font-size: 1.1rem;
        font-weight: 700;
        margin-bottom: 1rem;
    }
    .checkout-summary-row-total span:last-child {
        color: var(--color-primary-dark);
    }

    .checkout-place-order-btn {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        height: 50px;
        border: none;
        border-radius: 999px;
        background: var(--color-primary-dark);
        color: #fff;
        font-weight: 700;
        font-size: 0.95rem;
        transition: background-color 0.15s ease, transform 0.1s ease;
    }
    .checkout-place-order-btn:hover {
        background: var(--color-primary-darker);
        color: #fff;
    }
    .checkout-place-order-btn:active {
        transform: scale(0.98);
    }
}

/* ==========================================================================
   Delivery Area picker (#areaModal, web/partials/area-modal.blade.php) —
   same mobile-bottom-sheet shell as #quickAddModal/#orderTypeModal, applied
   at every viewport (not mobile-only), same precedent as .order-type-*
   above: there's no reason to keep a worse native <select> on desktop when
   this works fine there too.
   ========================================================================== */
.area-search-input {
    width: 100%;
    border: 1px solid #e6dcd0;
    border-radius: 12px;
    padding: 0.6rem 0.85rem;
    font-size: 0.9rem;
    margin-bottom: 0.85rem;
}
.area-search-input:focus {
    outline: none;
    border-color: var(--color-primary-dark);
    box-shadow: 0 0 0 3px rgba(61, 12, 12, 0.12);
}
.area-option-list {
    display: flex;
    flex-direction: column;
    max-height: 60vh;
    overflow-y: auto;
}
.area-option-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    text-align: start;
    padding: 13px 10px;
    border: none;
    border-bottom: 1px solid #f0e9de;
    border-radius: 10px;
    background: none;
    transition: background-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
}
.area-option-list .area-option-row:last-child {
    border-bottom: none;
}
.area-option-row.active {
    background: rgba(61, 12, 12, 0.06);
    box-shadow: inset 0 0 0 1px rgba(61, 12, 12, 0.35);
}
.area-option-row:active {
    transform: scale(0.98);
}
.area-option-radio {
    display: block;
    width: 20px;
    height: 20px;
    border: 2px solid #d9cfc0;
    border-radius: 50%;
    position: relative;
    flex-shrink: 0;
    transition: border-color 0.15s ease;
}
.area-option-row.active .area-option-radio {
    border-color: var(--color-primary-dark);
}
.area-option-row.active .area-option-radio::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--color-primary-dark);
    transform: translate(-50%, -50%);
}
.area-option-name {
    flex: 1;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--text);
}
.area-option-fee {
    flex-shrink: 0;
    font-size: 0.82rem;
    font-weight: 500;
    color: #999;
}

/* ==========================================================================
   My Account pages (web/account/*.blade.php + web/orders/index.blade.php) —
   mobile only, same convention as the Checkout section above: every rule
   outside the media query below matches the plain Bootstrap look it replaced
   (list-group, "border rounded p-3", table) so desktop is pixel-identical to
   before; the premium dark-maroon/gold card treatment only applies under
   max-width:991.98px. Form inputs/selects/checkboxes/pill-buttons reuse the
   existing .checkout-input/.checkout-select/.checkout-checkbox*/
   .checkout-place-order-btn/.checkout-coupon-* classes above rather than
   duplicating them.
   ========================================================================== */
.account-avatar-wrap {
    position: relative;
    display: inline-block;
}
.account-avatar {
    width: 96px;
    height: 96px;
    object-fit: cover;
    border-radius: 50%;
}
.account-avatar-edit-btn {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: var(--color-primary-dark);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid #fff;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
    cursor: pointer;
    margin: 0;
    transition: background-color 0.15s ease;
}
.account-avatar-edit-btn:hover {
    background: var(--color-primary-darker);
}
.account-avatar-edit-btn svg {
    width: 15px;
    height: 15px;
}
[dir="rtl"] .account-avatar-edit-btn {
    right: auto;
    left: 0;
}

.account-stat-card {
    border: 1px solid #dee2e6;
    border-radius: 0.25rem;
    padding: 1rem;
    text-align: center;
}
.account-address-card,
.account-order-item {
    border: 1px solid #dee2e6;
    border-radius: 0.25rem;
    padding: 1rem;
    margin-bottom: 1rem;
}
.account-order-item {
    display: flex;
    align-items: center;
    color: inherit;
}
.account-order-item:hover {
    color: inherit;
    text-decoration: none;
}
.account-order-item:active {
    transform: scale(0.98);
}

/* Order thumbnail (first item's product image) + "+N" overflow badge for
   multi-item orders — same rounded-image sizing language as .cart-item-card's
   product thumbnail on the cart page, shrunk down for a list row. */
.account-order-thumb-wrap {
    position: relative;
    flex-shrink: 0;
    margin-inline-end: 12px;
}
.account-order-thumb {
    display: block;
    width: 56px;
    height: 56px;
    border-radius: 12px;
    object-fit: cover;
    background: #F5EDE5;
}
.account-order-thumb-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: 12px;
    background: #F5EDE5;
    color: var(--color-primary-dark);
    opacity: 0.5;
}
.account-order-thumb-placeholder svg {
    width: 24px;
    height: 24px;
}
.account-order-thumb-count {
    position: absolute;
    bottom: -6px;
    right: -6px;
    min-width: 20px;
    height: 20px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--color-primary-dark);
    color: #fff;
    font-size: 0.65rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid #fff;
}
[dir="rtl"] .account-order-thumb-count {
    right: auto;
    left: -6px;
}

/* Order status badge — color-coded by status bucket (see order_status values
   in config/constant.php: pending / confirmed·processing·cooking·done·
   out_for_delivery ("ongoing") / delivered·completed ("success") /
   canceled·failed·returned ("canceled")). Global, not mobile-gated — the
   color coding is a data-accuracy fix that should read the same everywhere,
   not a mobile-only layout change. */
.order-status-badge {
    display: inline-block;
    padding: 0.25rem 0.75rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    white-space: nowrap;
}
.order-status-badge--pending {
    background: #E3E7EE;
    color: #4A5568;
}
.order-status-badge--ongoing {
    background: #FBE8C2;
    color: #8A5A12;
}
.order-status-badge--success {
    background: #D7F0DD;
    color: #1E7A3D;
}
.order-status-badge--canceled {
    background: #F5D5D5;
    color: #8B2E2E;
}

/* Left accent bar on each order card, same color family as the status badge
   above it, for faster scanning down the list. border-inline-start (not
   border-left) so it stays on the correct visual side under RTL automatically. */
.account-order-item--pending {
    border-inline-start: 4px solid #8996AC;
}
.account-order-item--ongoing {
    border-inline-start: 4px solid var(--color-accent-gold);
}
.account-order-item--success {
    border-inline-start: 4px solid #2E9D53;
}
.account-order-item--canceled {
    border-inline-start: 4px solid #B23A3A;
}

/* Filter pills (All / Ongoing / History) — global, same maroon-active /
   light-inactive language as .checkout-option-row and .area-option-row. */
.order-filter-tabs {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.order-filter-pill {
    display: inline-block;
    padding: 0.4rem 1rem;
    border-radius: 999px;
    border: 1px solid #e6dcd0;
    background: #fff;
    color: var(--text);
    font-size: 0.85rem;
    font-weight: 600;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.order-filter-pill:hover {
    color: var(--text);
    text-decoration: none;
    border-color: var(--color-primary-dark);
}
.order-filter-pill.active {
    background: var(--color-primary-dark);
    border-color: var(--color-primary-dark);
    color: #fff;
}
.order-filter-pill.active:hover {
    color: #fff;
}

/* Wallet transaction list (web/account/wallet.blade.php) — one card per
   transaction, same white/rounded-16/soft-shadow language as
   .account-order-item, with a credit/debit icon badge + single color-coded,
   signed amount instead of the old 4-column Date/Type/Credit/Debit table.
   Global, not mobile-gated, same precedent as .order-status-badge above. */
.wallet-tx-card {
    display: flex;
    align-items: center;
    gap: 12px;
    background: #fff;
    border: 1px solid #F0E0D5;
    border-radius: 16px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
    padding: 14px;
    margin-bottom: 12px;
}
.wallet-tx-icon {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
}
.wallet-tx-icon svg {
    width: 18px;
    height: 18px;
}
.wallet-tx-icon--credit {
    background: #2E9D53;
}
.wallet-tx-icon--debit {
    background: #B23A3A;
}
.wallet-tx-body {
    flex: 1;
    min-width: 0;
}
.wallet-tx-type {
    font-weight: 700;
    color: var(--text);
    font-size: 0.92rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.wallet-tx-date {
    font-size: 0.78rem;
    color: #999;
    margin-top: 2px;
}
.wallet-tx-amount {
    flex-shrink: 0;
    font-weight: 700;
    font-size: 0.95rem;
    white-space: nowrap;
}
.wallet-tx-amount--credit {
    color: #1E7A3D;
}
.wallet-tx-amount--debit {
    color: #8B2E2E;
}

.account-balance-card {
    border: 1px solid #dee2e6;
    border-radius: 0.25rem;
    padding: 1rem;
    margin-bottom: 1.5rem;
    text-align: center;
}

@media (max-width: 991.98px) {
    /* Tab nav — vertical list kept as-is structurally, restyled as a rounded,
       shadowed card with a maroon active row instead of Bootstrap's default
       blue .list-group-item.active. */
    .account-nav {
        border: none;
        border-radius: 16px;
        overflow: hidden;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
    }
    .account-nav-item {
        display: flex;
        align-items: center;
        gap: 0.65rem;
        border: none;
        border-bottom: 1px solid #f0e9de;
        border-radius: 0;
        padding: 13px 14px;
        background: #fff;
        color: var(--text);
        font-weight: 600;
        font-size: 0.92rem;
    }
    .account-nav-item:last-child {
        border-bottom: none;
    }
    .account-nav-item:hover {
        color: var(--text);
        text-decoration: none;
        background: #FAF7F4;
    }
    .account-nav-item-icon {
        flex-shrink: 0;
        width: 18px;
        height: 18px;
        object-fit: contain;
        color: var(--color-primary-dark);
        opacity: 0.7;
    }
    .account-nav-item.active {
        background: var(--color-primary-dark);
        color: #fff;
        font-weight: 700;
    }
    .account-nav-item.active:hover {
        color: #fff;
        background: var(--color-primary-dark);
    }
    .account-nav-item.active .account-nav-item-icon {
        color: #fff;
        opacity: 1;
    }
    .account-nav-item.active img.account-nav-item-icon {
        filter: brightness(0) invert(1);
    }

    .account-section-title {
        font-weight: 700;
        font-size: 1.1rem;
        color: var(--text);
    }

    /* Profile avatar: soft shadow ring + camera icon-button overlapping the
       bottom-right corner, replacing the plain bordered "Change Photo" box. */
    .account-avatar {
        border: 3px solid #fff;
        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15), 0 0 0 3px rgba(61, 12, 12, 0.12);
    }

    .account-stat-card {
        background: #fff;
        border: 1px solid #F0E0D5;
        border-radius: 16px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
        padding: 16px;
    }
    .account-stat-card .h4 {
        color: var(--color-primary-dark);
    }

    /* Address list items + Order history rows: same white/cream card, rounded-16,
       soft-shadow language as .cart-item-card (cart page) and .checkout-card. */
    .account-address-card {
        background: #fff;
        border: 1px solid #F0E0D5;
        border-radius: 16px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
        padding: 14px;
        margin-bottom: 14px;
    }
    .account-order-item {
        display: flex;
        align-items: center;
        background: #fff;
        border: 1px solid #F0E0D5;
        border-radius: 16px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
        padding: 14px;
        margin-bottom: 12px;
    }

    /* Wallet balance / Loyalty points balance: cream-wash highlight card, same
       treatment as .cart-summary-card / .checkout-summary-card. */
    .account-balance-card {
        background: var(--cream);
        border: none;
        border-radius: 16px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
        padding: 20px;
        margin-bottom: 1.25rem;
    }
    .account-balance-label {
        font-size: 0.85rem;
        color: #8a7768;
        margin-bottom: 0.35rem;
    }
    .account-balance-value {
        font-size: 1.7rem;
        font-weight: 700;
        color: var(--color-primary-dark);
    }

    /* Wallet / Loyalty transaction tables -> stacked cards. Each <tr> becomes
       a card row; each <td> keeps its data-label as a leading mini-caption via
       ::before, same "responsive table" technique, none used elsewhere in this
       file yet since every other list in this redesign is a div-based card. */
    .account-table-wrap {
        background: #fff;
        border-radius: 16px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
        padding: 4px 14px;
        margin-bottom: 1rem;
    }
    .account-table thead {
        display: none;
    }
    .account-table,
    .account-table tbody,
    .account-table tr,
    .account-table td {
        display: block;
        width: 100%;
    }
    .account-table tr {
        padding: 12px 0;
        border-bottom: 1px solid #f0e9de;
    }
    .account-table tr:last-child {
        border-bottom: none;
    }
    .account-table td {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 3px 0;
        border: none;
        font-size: 0.88rem;
        text-align: start;
    }
    .account-table td::before {
        content: attr(data-label);
        font-weight: 600;
        color: #999;
        font-size: 0.78rem;
        margin-inline-end: 0.75rem;
    }
}

/* ==========================================================================
   AI chat widget (floating launcher + panel), all public pages via
   web.layouts.app, only when LicenseFeatures::enabled('ai_chat'). Uses
   --brand/--brand-dark (the admin-configurable primary/secondary color that
   every other branded button/header on the site already reads) rather than
   the fixed mobile app-shell palette above — this widget isn't part of that
   shell, it's a separate site-wide feature that should follow each tenant's
   actual brand color.
   Position: same physical corner as the WhatsApp float button above it
   (stacked with a gap), and — like WhatsApp on mobile and the Home button —
   deliberately NOT mirrored under dir="rtl". Every other floating action
   button in this file already treats screen corner as a fixed physical
   position rather than a logical/directional one; this one relies on the
   OpenAI reply text itself being written right-to-left, not on the widget's
   own chrome flipping sides.
   Stacking: launcher (1010) sits above the app-shell's own floating elements
   (WhatsApp 1000 < Home 1001 < bottom nav 1002); the open panel (1030) sits
   above all of them plus the sticky header (100).
   ========================================================================== */
.chat-widget-launcher {
    position: fixed;
    right: 20px;
    bottom: 92px; /* WhatsApp's own 20px + its 56px height + a 16px gap */
    width: 56px;
    height: 56px;
    border: none;
    border-radius: 50%;
    background: var(--brand);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.28);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1010;
    cursor: pointer;
    transition: transform 0.15s ease, background 0.15s ease;
}
.chat-widget-launcher:hover {
    background: var(--brand-dark);
    transform: scale(1.06);
}
.chat-widget-launcher-icon-close {
    display: none;
}
.chat-widget-launcher.is-open .chat-widget-launcher-icon-chat {
    display: none;
}
.chat-widget-launcher.is-open .chat-widget-launcher-icon-close {
    display: block;
}
/* WhatsApp (Route::is('web.home') + its own admin toggle) and the chat
   widget (feature:ai_chat) are independently, separately controlled — see
   web.layouts.app — so .whatsapp-float-btn is genuinely absent from the DOM
   on any page/config where it's off, not just visually hidden. The 92px
   offset above assumes it IS present and stacks directly on top of it;
   this :has() rule drops the launcher straight down to WhatsApp's own
   corner spot instead whenever that assumption doesn't hold, so there's
   never a dead gap where WhatsApp would have been. */
body:not(:has(.whatsapp-float-btn)) .chat-widget-launcher {
    bottom: 20px;
}
@media (max-width: 991.98px) {
    .chat-widget-launcher {
        left: 16px;
        right: auto;
        bottom: calc(var(--mobile-bottom-nav-height) + 14px + 56px + 12px);
    }
    body:not(:has(.whatsapp-float-btn)) .chat-widget-launcher {
        bottom: calc(var(--mobile-bottom-nav-height) + 14px);
    }
}

.chat-widget-panel {
    position: fixed;
    right: 20px;
    bottom: 158px;
    width: 370px;
    max-width: calc(100vw - 40px);
    height: 560px;
    max-height: calc(100vh - 180px);
    background: #fff;
    border-radius: 16px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.22);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    z-index: 1030;
    opacity: 0;
    transform: translateY(16px) scale(0.98);
    pointer-events: none;
    transition: opacity 0.18s ease, transform 0.18s ease;
}
.chat-widget-panel.is-open {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
}
@media (max-width: 991.98px) {
    .chat-widget-panel {
        left: 12px;
        right: 12px;
        bottom: calc(var(--mobile-bottom-nav-height) + 14px);
        width: auto;
        max-width: none;
        /* --chat-widget-vvh is kept in sync with window.visualViewport.height
           by chat-widget.js (falls back to 100vh before that JS runs, or if
           the browser has no VisualViewport API) — using it here instead of
           a bare 100vh already helps with iOS Safari's collapsing address
           bar, on top of the dedicated keyboard-open state below. */
        height: calc(var(--chat-widget-vvh, 100vh) - var(--mobile-bottom-nav-height) - 90px);
        max-height: none;
    }

    /* Keyboard-open state (see chat-widget.js's VisualViewport 'resize'
       listener — toggled once the visible viewport has shrunk by more than
       ~120px, the on-screen-keyboard heuristic). The panel switches from
       "anchored above the bottom nav" to a full-bleed takeover pinned to
       the TOP of the real visible area: the bottom nav is under the
       keyboard anyway at that point, so there's nothing to leave room for.
       Because the panel is a flex column (header/typing/input all
       flex-shrink:0, .chat-widget-messages is the only flex:1 1 auto,
       overflow-y:auto child), simply sizing the container to the real
       visible height is enough — the input row naturally ends up pinned
       exactly above the keyboard and the message list is what
       grows/shrinks, with zero extra positioning math needed. */
    .chat-widget-panel.keyboard-open {
        left: 0;
        right: 0;
        top: 0;
        bottom: auto;
        height: var(--chat-widget-vvh, 100vh);
        max-height: none;
        border-radius: 0;
        /* iOS Safari quirk: a `position: fixed` element can visibly drift
           away from the actually-visible area's top edge while the keyboard
           is open, because the page itself shifts under it. chat-widget.js
           keeps --chat-widget-vv-offset-top equal to
           window.visualViewport.offsetTop to correct for that — 0px and a
           no-op everywhere else. This rule (declared after the base
           .is-open rule below, so it wins the cascade once both classes are
           present) intentionally does NOT reference .is-open's own
           translateY/scale open-animation transform: by the time
           keyboard-open can ever be true, the panel is already open and
           settled, so there's nothing to preserve from that transform.  */
        transform: translateY(var(--chat-widget-vv-offset-top, 0px));
    }
    /* Minimal header while the keyboard eats most of the screen — the
       online-status line is the first thing to go, per the requirement
       that the header can collapse to maximize usable space. */
    .chat-widget-panel.keyboard-open .chat-widget-header {
        padding: 8px 16px;
    }
    .chat-widget-panel.keyboard-open .chat-widget-header-status {
        display: none;
    }
}

.chat-widget-header {
    background: var(--brand);
    color: #fff;
    padding: 14px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-shrink: 0;
}
.chat-widget-header-info {
    display: flex;
    flex-direction: column;
}
.chat-widget-header-name {
    font-weight: 700;
    font-size: 0.95rem;
}
.chat-widget-header-status {
    font-size: 0.72rem;
    opacity: 0.85;
    display: flex;
    align-items: center;
    gap: 5px;
}
.chat-widget-status-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #3ddc71;
    display: inline-block;
}
.chat-widget-header-actions {
    display: flex;
    align-items: center;
    gap: 4px;
}
.chat-widget-clear {
    background: transparent;
    border: none;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0.85;
    cursor: pointer;
}
.chat-widget-clear:hover {
    opacity: 1;
    background: rgba(255, 255, 255, 0.14);
}
.chat-widget-close {
    background: transparent;
    border: none;
    color: #fff;
    font-size: 1.5rem;
    line-height: 1;
    opacity: 0.85;
    cursor: pointer;
}
.chat-widget-close:hover {
    opacity: 1;
}

/* Inline "are you sure?" bar for the clear action — never a browser
   confirm() dialog (disruptive, unstyleable). Slides in between the header
   and the message thread; the messages area's own flex-grow means it just
   shrinks to make room rather than anything overlapping. */
.chat-widget-clear-confirm {
    background: #fdecea;
    border-bottom: 1px solid #f7cfc9;
    padding: 9px 14px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-shrink: 0;
    flex-wrap: wrap;
}
.chat-widget-clear-confirm-text {
    font-size: 0.78rem;
    color: #a02622;
    flex: 1 1 auto;
    min-width: 140px;
}
.chat-widget-clear-confirm-actions {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
}
.chat-widget-clear-confirm-cancel,
.chat-widget-clear-confirm-danger {
    border: none;
    border-radius: 8px;
    padding: 5px 11px;
    font-size: 0.76rem;
    font-weight: 600;
    cursor: pointer;
}
.chat-widget-clear-confirm-cancel {
    background: #fff;
    color: var(--text);
    border: 1px solid #e5dbca;
}
.chat-widget-clear-confirm-cancel:hover {
    background: #f5f0e6;
}
.chat-widget-clear-confirm-danger {
    background: #c0392b;
    color: #fff;
}
.chat-widget-clear-confirm-danger:hover {
    background: #a02622;
}

.chat-widget-messages {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    background: var(--page-bg);
}

.chat-widget-msg {
    display: flex;
}
.chat-widget-msg-user {
    justify-content: flex-end;
}
.chat-widget-msg-assistant {
    justify-content: flex-start;
}
.chat-widget-bubble {
    max-width: 82%;
    padding: 9px 13px;
    border-radius: 14px;
    font-size: 0.86rem;
    line-height: 1.45;
    white-space: pre-wrap;
    word-break: break-word;
}
.chat-widget-msg-user .chat-widget-bubble {
    background: var(--brand);
    color: #fff;
    border-bottom-right-radius: 4px;
}
.chat-widget-msg-assistant .chat-widget-bubble {
    background: #fff;
    color: var(--text);
    border: 1px solid #eee1d1;
    border-bottom-left-radius: 4px;
}
.chat-widget-bubble-error {
    background: #fdecea !important;
    color: #a02622 !important;
    border-color: #f7cfc9 !important;
}

.chat-widget-login-hint {
    margin-top: 6px;
    font-size: 0.82rem;
}
.chat-widget-login-hint a {
    color: var(--brand);
    font-weight: 600;
    text-decoration: underline;
}

/* Suggested product cards inline in the thread — deliberately their own
   smaller markup rather than @include-ing partials/product-card.blade.php:
   these arrive as JSON from the chat API and are rendered client-side by
   chat-widget.js, so there's no server-side $product model to feed that
   partial. Same visual language (rounded card, price styling) and —
   critically — the exact same data-quick-add/data-product-id/data-has-options
   attributes as product-card.blade.php's own Add button, so the site's
   existing global click handlers in mobile-shell.js (bottom-sheet variation
   picker, direct add, fly-to-cart, cart badge/toast) work on these cards with
   zero additional JS of their own. */
.chat-widget-suggested-items {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-width: 88%;
}
.chat-widget-product-card {
    display: flex;
    align-items: center;
    gap: 10px;
    background: #fff;
    border: 1px solid #eee1d1;
    border-radius: 12px;
    padding: 8px;
}
.chat-widget-product-card-img {
    width: 52px;
    height: 52px;
    border-radius: 8px;
    object-fit: cover;
    flex-shrink: 0;
    background: #f3ede3;
}
.chat-widget-product-card-body {
    flex: 1 1 auto;
    min-width: 0;
}
.chat-widget-product-card-name {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.chat-widget-product-card-price-old {
    font-size: 0.72rem;
    color: #aaa;
    text-decoration: line-through;
    margin-inline-end: 4px;
    font-weight: 400;
}
.chat-widget-product-card-price {
    font-size: 0.8rem;
    color: var(--brand-dark);
    font-weight: 700;
}
.chat-widget-product-card-add {
    flex-shrink: 0;
    border: none;
    border-radius: 8px;
    background: var(--brand);
    color: #fff;
    font-size: 0.72rem;
    font-weight: 600;
    padding: 7px 11px;
    cursor: pointer;
}
.chat-widget-product-card-add:hover {
    background: var(--brand-dark);
}

.chat-widget-typing {
    padding: 0 14px 8px;
    display: flex;
    gap: 4px;
    flex-shrink: 0;
}
.chat-widget-typing span {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #bbb;
    animation: chatWidgetTypingBounce 1.2s infinite ease-in-out;
}
.chat-widget-typing span:nth-child(2) { animation-delay: 0.15s; }
.chat-widget-typing span:nth-child(3) { animation-delay: 0.3s; }
@keyframes chatWidgetTypingBounce {
    0%, 60%, 100% { transform: translateY(0); opacity: 0.5; }
    30% { transform: translateY(-4px); opacity: 1; }
}

.chat-widget-input-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px;
    border-top: 1px solid #eee1d1;
    flex-shrink: 0;
    background: #fff;
}
.chat-widget-input {
    flex: 1 1 auto;
    border: 1px solid #e5dbca;
    border-radius: 20px;
    padding: 9px 15px;
    font-size: 0.86rem;
    outline: none;
}
.chat-widget-input:focus {
    border-color: var(--brand);
}
.chat-widget-send {
    flex-shrink: 0;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    border: none;
    background: var(--brand);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}
.chat-widget-send:hover {
    background: var(--brand-dark);
}
.chat-widget-send:disabled {
    opacity: 0.5;
    cursor: default;
}
