/*
 * components/home-v2.css
 *
 * What:  Full landing-page redesign to match the supplied EatNDeal
 *        mockup, top to bottom:
 *          • home shell  — left filter sidebar + right content column
 *          • hero        — headline + deliver-to + feature pills +
 *                          food collage + order-tracking card
 *          • cuisine rail— circular tiles with "N+ places" labels
 *          • resto rail  — restaurant cards (badge / heart / rating /
 *                          delivery / price / add button)
 *          • offers rail — 3 gradient promo banners
 *          • popular     — 4 dark "Explore" cuisine cards
 *          • features    — Fast Delivery / Live Tracking / Safe
 *                          Payments / Best Offers strip
 *          • app cta     — phone mockup + store badges + checklist
 * Why:   The user asked for an exact rebuild of the mockup. Dynamic
 *        sections (cuisines, restaurants) bind to live api data; the
 *        rest is static markup until the matching endpoints land.
 * Used:  Loaded by views/_layout.ejs. Markup lives in
 *        views/site/index.ejs + the home partials.
 *
 * Responsive: desktop ≥ 1024 px shows the sidebar; below that the
 *        sidebar collapses (mobile uses the bottom-sheet) and every
 *        rail/grid reflows to a single column or horizontal scroller.
 */

/* ── Delivery / Pickup segmented toggle ───────────────────────────── *
 * Two radios + labels rendered as a pill switch. The real radios are
 * visually hidden; the label that follows a :checked radio paints
 * brand-red. Keyboard accessible (focus ring on the active label). */
.mode-toggle {
    display: inline-flex;
    background: var(--color-bg-alt);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    padding: 3px;
    flex: 0 0 auto;
}
.mode-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.mode-toggle label {
    padding: 0.4rem 1rem;
    border-radius: var(--radius-pill);
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--color-text-muted);
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
    user-select: none;
}
.mode-toggle input:checked + label {
    background: var(--color-primary);
    color: #fff;
    box-shadow: var(--shadow-1);
}
.mode-toggle input:focus-visible + label { outline: 2px solid var(--color-primary); outline-offset: 2px; }
@media (max-width: 767px) {
    /* Mobile: KEEP the Delivery/Pickup toggle visible in the top
     * header (per user), just more compact so it fits next to the
     * location + cart. */
    .mode-toggle { padding: 2px; }
    .mode-toggle label { padding: 0.3rem 0.6rem; font-size: 0.75rem; }
}

/* ── Header quick-links (Rewards / Orders / Cart) ─────────────────── */
.header-quick { display: flex; align-items: center; gap: var(--space-4); }
.header-quick__item {
    display: inline-flex; flex-direction: column; align-items: center; gap: 2px;
    color: var(--color-text); font-size: 0.7rem; font-weight: 600;
    position: relative;
}
.header-quick__item:hover { color: var(--color-primary); }
.header-quick__badge {
    position: absolute; top: -6px; right: 4px;
    min-width: 16px; height: 16px; padding: 0 4px;
    background: var(--color-primary); color: #fff;
    border-radius: 8px; font-size: 0.65rem; font-weight: 700;
    display: grid; place-items: center;
    transition: transform 200ms ease, background 200ms ease;
}
/* Pulse + brief shadow when an item is added — `is-bumping` toggled by
   /js/ui/cart.js after each successful add-to-cart. */
.header-quick__badge.is-bumping {
    animation: cart-badge-bump 600ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes cart-badge-bump {
    0%   { transform: scale(1);    box-shadow: 0 0 0 0   rgba(229, 37, 42, 0.55); }
    30%  { transform: scale(1.4);  box-shadow: 0 0 0 8px rgba(229, 37, 42, 0);    }
    60%  { transform: scale(0.92); }
    100% { transform: scale(1);    box-shadow: 0 0 0 0   rgba(229, 37, 42, 0);    }
}
.site-header__ordernow { white-space: nowrap; }
/* Mobile: keep ONLY the Cart icon from the quick cluster in the top
 * header (Rewards / Orders move to the drawer + bottom-nav). Order
 * Now + Sign in are hidden (drawer carries auth). The cart label is
 * dropped so it's a compact icon. */
@media (max-width: 767px) {
    .site-header__ordernow, .site-header__signin { display: none; }
    /* Mobile: NOTHING from the quick cluster in the top header — the bottom-nav
       Cart tab carries the cart (with its count badge) now, per the user. This
       drops the duplicate cart icon from the header. */
    .header-quick { display: none; }
}

/* ── Shell: sidebar + content ─────────────────────────────────────── *
 * Full-bleed: the content uses the whole viewport width (minus side
 * padding) so the right side never shows empty space — matching the
 * Uber-Eats-style edge-to-edge feed the user asked for. No centered
 * max-width cap. minmax(0,1fr) on the content track lets its inner
 * horizontal sliders scroll instead of forcing the grid wider. */
.home-shell {
    width: 100%;
    padding: var(--space-3) var(--space-6) var(--space-10);
}
@media (min-width: 1024px) {
    .home-shell {
        display: grid;
        grid-template-columns: 280px minmax(0, 1fr);
        gap: var(--space-6);
        align-items: start;
    }
}
/* Flex column + gap (not margin) so the FIRST VISIBLE child never
 * carries dead top space — when the filters pill is display:none
 * (sidebar expanded) it's removed from the flex flow entirely, so
 * the hero sits flush at the top with no gap. */
.home-shell__content {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-8);
}

/* Compact "Filters" control that reopens the sidebar — hidden by
 * default, shown only when the sidebar is collapsed. Rendered as a
 * small STICKY circular icon at the top-left so it stays reachable
 * on scroll WITHOUT taking a full content row (keeps the top space
 * tight). The negative margin pulls the hero up to cancel most of
 * the flex gap. */
.filters-show {
    display: none;
    align-self: flex-start;
    align-items: center; gap: var(--space-2);
    background: #fff; border: 1px solid var(--color-border);
    border-radius: var(--radius-pill); padding: 0.45rem 0.9rem;
    /* Black when no filter is applied; goes red via .has-filters, which
     * filter-sheet.js toggles from the URL's applied-filter count. */
    font-weight: 700; font-size: 0.85rem; color: var(--color-text);
    cursor: pointer;
}
.filters-show.has-filters { color: var(--color-primary); }
.filters-show:hover { border-color: var(--color-primary); background: var(--color-bg-alt); }
/* Applied-filter count badge — small red pill pinned to the tile's
 * top-right corner. Filled/toggled by filter-sheet.js from the URL
 * params; [hidden] wins over the grid display so it truly disappears
 * when nothing is applied. Anchored on the button itself. */
.filters-show { position: relative; }
.filters-show__badge {
    position: absolute; top: -6px; right: -6px;
    min-width: 18px; height: 18px; padding: 0 5px;
    border-radius: var(--radius-pill);
    background: var(--color-primary); color: #fff;
    font-size: 0.68rem; font-weight: 700; font-style: normal;
    display: grid; place-items: center;
}
.filters-show__badge[hidden] { display: none; }
@media (min-width: 1024px) {
    /* Collapsed tile — sit the badge over the icon disc's corner. */
    html.is-filters-collapsed .home-shell .filters-show__badge { top: -4px; right: 0; }
}
@media (min-width: 1024px) {
    /* The reopen icon floats ABSOLUTELY over the hero's top-left
     * corner (next to the FAST DELIVERY badge) instead of taking its
     * own row — so collapsing the sidebar reclaims the top space.
     * Out of flow ⇒ the hero sits flush at the content top. */
    html.is-filters-collapsed .home-shell .home-shell__content { position: relative; }
    html.is-filters-collapsed .home-shell .filters-show {
        position: absolute;
        /* Match the cuisine rail's padding-top so the Filters disc and
         * the category discs sit on the same line (the rail pads its
         * top to give the hover-lift/ring room — see .cuisine-rail). */
        top: var(--space-2);
        left: var(--space-1);
        z-index: 30;
        flex-direction: column;              /* icon on top, label below */
        gap: var(--space-1);
        width: 72px; height: auto; padding: 0;
        border: 0; background: transparent; box-shadow: none;
        /* Black icon+label by default; red only when .has-filters says
         * filters are applied (same cue as the count badge). */
        color: var(--color-text);
        margin: 0;
    }
    html.is-filters-collapsed .home-shell .filters-show.has-filters { color: var(--color-primary); }
    /* The SVG becomes the disc (matches the cuisine tiles) and the "Filters"
       caption sits beneath it — same shape/label rhythm as Pizza / Sushi. */
    html.is-filters-collapsed .home-shell .filters-show svg {
        width: 68px; height: 68px; padding: 22px;
        box-sizing: border-box;
        background: var(--color-bg-alt);
        border-radius: var(--radius-md);
        transition: transform 120ms ease, box-shadow 120ms ease;
    }
    html.is-filters-collapsed .home-shell .filters-show:hover { background: transparent; }
    html.is-filters-collapsed .home-shell .filters-show:hover svg {
        transform: translateY(-3px); box-shadow: var(--shadow-2);
    }
    /* Show the label (was hidden in the old icon-only pill). */
    html.is-filters-collapsed .home-shell .filters-show span {
        display: block; font-weight: 700; font-size: 0.82rem;
    }
    /* The floating Filters icon sits over the top-left of the content.
     * Shift the whole cuisine slider (its scroll viewport + arrows) to
     * the right of the icon with a MARGIN — not padding. With padding the
     * scroller's left edge stays under the icon, so items slide beneath
     * it as you scroll (the first category gets clipped behind the icon).
     * A margin moves the viewport's left edge past the icon, so overflow
     * clips there and categories always start cleanly after the icon. */
    html.is-filters-collapsed .home-shell .rail-wrap { margin-left: 84px; }

    /* PICKUP PAGE — the content does NOT start with the cuisine rail here: the
     * "Pickup nearby" heading comes first, so the tile (pinned to top:0 of the
     * content) landed ON TOP of the heading and covered it.
     *
     * Push the tile down past the heading so it lines up with the cuisine tiles
     * beside it, exactly as it does on home. Keyed off a modifier class the
     * pickup view sets (home-shell--pickup) rather than :has() — the button is
     * a PRECEDING sibling of .pickup, so no sibling combinator can reach it,
     * and :has() isn't safe to rely on here. */
    /* Derived from the pickup list's actual stack above the rail discs:
     * list padding-top (space-5) + the "Pickup nearby" title line
     * (1.6rem × body line-height 1.5) + head margin-bottom (space-4)
     * + the rail's own padding-top (space-2) ≈ 82px. Keeps the Filters
     * disc level with the category discs instead of a hand-tuned px. */
    html.is-filters-collapsed .home-shell--pickup .filters-show {
        top: calc(var(--space-5) + (1.6rem * 1.5) + var(--space-4) + var(--space-2));
        /* Line the tile up with the list's left padding (space-6) so it
         * shares the "Pickup nearby" title's left edge. */
        left: var(--space-6);
    }
    /* The rail lives inside .pickup__list on this page, so it needs the same
     * clear-the-icon margin the home rail gets above. */
    html.is-filters-collapsed .home-shell--pickup .rail-wrap { margin-left: 84px; }
}

/* Sidebar hide button (chevron in the .fsb header). */
.fsb__hide {
    flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%;
    border: 0; background: var(--color-bg-alt); color: var(--color-text);
    display: grid; place-items: center; cursor: pointer; margin-left: var(--space-1);
}
.fsb__hide:hover { background: rgba(0,0,0,0.08); color: var(--color-primary); }

/* Collapsed state — sidebar hidden, content fills the row, the
 * compact Filters pill appears. Toggled by /js/pages/home.js adding
 * .is-filters-collapsed on .home-shell. */
@media (min-width: 1024px) {
    html.is-filters-collapsed .home-shell { grid-template-columns: 1fr; }
    html.is-filters-collapsed .home-shell .fsb { display: none; }
    html.is-filters-collapsed .home-shell .filters-show { display: inline-flex; }
}
/* On mobile the sidebar is already hidden (bottom sheet is used), so
 * never show the reopen pill there. */
/* Mobile: the reopen pill is hidden (the search-row Filters button
 * opens the overlay), but the .fsb__hide close X MUST stay visible —
 * it's the only way to close the full-screen filter overlay. */
@media (max-width: 1023px) { .filters-show { display: none; } }

/* Section heading row shared by every content rail. */
.hv2-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-4);
    gap: var(--space-3);
}
.hv2-head__title { font-size: 1.4rem; font-weight: 800; color: var(--color-text); display: inline-flex; align-items: center; gap: 8px; margin: 0; }
.hv2-head__title-icon { flex: 0 0 auto; color: var(--color-primary); }
/* When a "My Favourites" rail sits above the main grid, give the next
   section a little breathing room so the two titles don't crowd. */
[data-home-feed] section + section { margin-top: var(--space-5); }
.hv2-head__link  { color: var(--color-primary); font-weight: 600; font-size: 0.9rem; white-space: nowrap; }
.hv2-head__link:hover { text-decoration: underline; }

/* Curated home-feed rows (partials/home-row.ejs): the optional subtitle under
   a collection title, and the star on the paid "Featured" row. */
.home-row__sub { font-size: 0.85rem; color: var(--color-text-muted); font-weight: 500; margin-left: 2px; }
.home-row__star { color: var(--color-primary); }
.home-row--featured .hv2-head__title { color: var(--color-primary); }

/* home-rail — a SINGLE horizontal-scrolling carousel (Uber-Eats shelf). Unlike
   .resto-rail (a wrapping grid), this stays ONE line and slides sideways when
   there are many cards — same on desktop AND mobile (never a second row). */
.home-rail {
    display: flex; flex-wrap: nowrap; gap: var(--space-4);
    margin: 0; padding: 0; list-style: none;
    overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    /* No visible scrollbar — navigation is via the arrows (desktop) / swipe
       (mobile). Scroll still works; the bar is just hidden. */
    scrollbar-width: none; -ms-overflow-style: none;
}
.home-rail::-webkit-scrollbar { display: none; height: 0; width: 0; }
.home-rail > li { flex: 0 0 auto; width: 250px; max-width: 82%; scroll-snap-align: start; }
@media (max-width: 767px) {
    /* Card peeks the next one so it's clearly swipeable. */
    .home-rail > li { width: 76%; }
}

/* Featured-PRODUCT cards (partials/home-product-row.ejs) — smaller than the
   restaurant cards; tap opens the product modal. */
.home-rail--product > li { width: 168px; max-width: 60%; }
@media (max-width: 767px) { .home-rail--product > li { width: 44%; } }
.hp-card {
    display: flex; flex-direction: column; width: 100%; text-align: left;
    background: #fff; border: 1px solid var(--color-border-soft); border-radius: var(--radius-lg);
    overflow: hidden; cursor: pointer; padding: 0; font: inherit; color: inherit;
    transition: box-shadow .15s ease, transform .15s ease;
}
.hp-card:hover { box-shadow: 0 6px 18px rgba(15, 23, 42, .1); transform: translateY(-2px); }
.hp-card__media { position: relative; width: 100%; aspect-ratio: 1 / 1; background: var(--color-bg-alt, #f1f5f9); display: flex; align-items: center; justify-content: center; }
.hp-card__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
/* No-image placeholder — gray image icon; base layer beneath the photo. */
.hp-card__ph { position: absolute; inset: 0; background: #f3f4f6 url('/img/no-image.svg') center / 36% no-repeat; }
.hp-card__veg { position: absolute; top: 6px; left: 6px; width: 12px; height: 12px; border: 2px solid #15803d; border-radius: 3px; background: #fff; }
.hp-card__veg::after { content: ''; position: absolute; top: 2px; left: 2px; width: 4px; height: 4px; border-radius: 50%; background: #15803d; }
/* Non-veg variant — red border + red dot (same box, flipped colour). */
.hp-card__veg--nonveg { border-color: #dc2626; }
.hp-card__veg--nonveg::after { background: #dc2626; }
.hp-card__body { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px 10px; }
/* Offer badges on a home-rail product card (BOGO + product cashback), same
   look as the restaurant menu — wrap so two badges never overflow the card. */
/* Offer chips overlay the bottom-left of the image so the body stays a fixed height. */
.hp-card__offers { position: absolute; left: 6px; bottom: 6px; right: 6px; z-index: 2; display: flex; flex-direction: column; align-items: flex-start; gap: 3px; }
.hp-card__offer { display: inline-block; max-width: 100%; padding: 2px 7px; border-radius: 6px; font-size: 0.64rem; font-weight: 800; line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; box-shadow: 0 1px 3px rgba(0,0,0,.18); }
.hp-card__offer--bogo { background: #fef3c7; color: #92400e; }
.hp-card__offer--cashback { background: #dcfce7; color: #166534; }
.hp-card__name { font-size: 0.85rem; font-weight: 600; color: var(--color-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hp-card__price { font-size: 0.85rem; font-weight: 700; color: var(--color-primary); }

/* Small round arrow nav buttons (top-right of rails). Decorative on
 * touch; functional scroll nudge on desktop via home.js (optional). */
.hv2-nav { display: inline-flex; gap: var(--space-2); }
.hv2-nav__btn {
    width: 34px; height: 34px; border-radius: 50%;
    border: 1px solid var(--color-border);
    background: #fff; color: var(--color-text);
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer;
}
.hv2-nav__btn:hover { background: var(--color-bg-alt); border-color: var(--color-primary); color: var(--color-primary); }

/* ── Hero ─────────────────────────────────────────────────────────── */
.hero-v2 {
    position: relative;
    background: linear-gradient(120deg, #FFF1EC 0%, #FFE6DE 100%);
    border-radius: 24px;
    padding: var(--space-8);
    overflow: hidden;
    display: grid;
    grid-template-columns: 1.1fr 0.9fr;
    gap: var(--space-6);
    align-items: center;
}
.hero-v2__badge {
    display: inline-flex; align-items: center; gap: 6px;
    background: #E8F8EE; color: #15893f;
    font-weight: 700; font-size: 0.78rem;
    padding: 0.3rem 0.7rem; border-radius: var(--radius-pill);
    margin-bottom: var(--space-4);
}
.hero-v2__title { font-size: 2.6rem; line-height: 1.08; font-weight: 800; letter-spacing: -0.02em; }
.hero-v2__title em { color: var(--color-primary); font-style: normal; }
.hero-v2__subtitle { margin-top: var(--space-3); color: var(--color-text-muted); font-size: 1.05rem; max-width: 30ch; }

.hero-v2__actions { display: flex; gap: var(--space-3); margin-top: var(--space-5); flex-wrap: wrap; }
.hero-v2__deliver {
    display: flex; align-items: center; gap: var(--space-2);
    background: #fff; border: 1px solid var(--color-border);
    border-radius: var(--radius-md); padding: 0.7rem 0.9rem;
    min-width: 240px; cursor: pointer; text-align: left;
}
.hero-v2__deliver-label { font-size: 0.7rem; color: var(--color-text-soft); display: block; }
.hero-v2__deliver-value { font-size: 0.95rem; font-weight: 600; color: var(--color-text); display: block; }
.hero-v2__locate {
    display: inline-flex; align-items: center; gap: 6px;
    background: var(--color-primary); color: #fff;
    padding: 0.7rem 1.3rem; border-radius: var(--radius-md);
    font-weight: 700; border: 0; cursor: pointer;
}
.hero-v2__locate:hover { background: var(--color-primary-dark); }

.hero-v2__usps { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-top: var(--space-5); }
.hero-v2__usp { display: inline-flex; align-items: center; gap: 6px; font-size: 0.82rem; color: var(--color-text-muted); }
.hero-v2__usp svg { color: var(--color-primary); flex: 0 0 auto; }

/* Hero art — food collage built from tinted discs (placeholder for
 * real photography). Each disc carries an emoji so the hero isn't
 * empty before any photo asset lands. */
.hero-v2__art { position: relative; min-height: 280px; }
.hero-v2__disc {
    position: absolute; border-radius: 50%;
    display: grid; place-items: center;
    box-shadow: var(--shadow-2);
    font-size: 2.6rem;
}
.hero-v2__disc--a { width: 180px; height: 180px; background: #2b2b2b; top: 0;   right: 60px; font-size: 4rem; }
.hero-v2__disc--b { width: 120px; height: 120px; background: #f6c945; bottom: 30px; right: 10px; }
.hero-v2__disc--c { width: 140px; height: 140px; background: #e6502e; bottom: 0;  right: 140px; }
.hero-v2__disc--d { width: 70px;  height: 70px;  background: #d83a52; top: 30px;  right: 0; font-size: 1.8rem; }
.hero-v2__pin {
    position: absolute; top: 20px; right: 40px;
    width: 34px; height: 34px; color: var(--color-primary);
}
.hero-v2__track {
    position: absolute; bottom: -6px; left: 0;
    background: #fff; border-radius: var(--radius-md);
    box-shadow: var(--shadow-2); padding: 0.6rem 0.9rem;
    display: flex; align-items: center; gap: var(--space-2);
    font-size: 0.8rem;
}
.hero-v2__track-dot { width: 26px; height: 26px; border-radius: 50%; background: var(--color-primary); display: grid; place-items: center; color: #fff; }
.hero-v2__track-title { font-weight: 700; }
.hero-v2__track-sub { color: var(--color-text-soft); }
.hero-v2__track-link { color: var(--color-primary); font-weight: 600; }

/* ── Rail wrapper + header prev/next arrows (Uber-Eats style) ──────────
   Arrows live in the section heading (.hv2-head__nav) so they show on EVERY
   desktop width (never clipped by the card rail) — disabled at the ends. */
.rail-wrap { position: relative; }
.hv2-head__actions { display: inline-flex; align-items: center; gap: 14px; flex: 0 0 auto; }
.hv2-head__nav { display: inline-flex; gap: 8px; flex: 0 0 auto; }
.rail-arrow {
    width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto;
    background: #fff; border: 1px solid var(--color-border); color: var(--color-text);
    display: grid; place-items: center; cursor: pointer;
    transition: color .15s, border-color .15s, opacity .15s;
}
.rail-arrow:hover:not(:disabled) { color: var(--color-primary); border-color: var(--color-primary); }
.rail-arrow:disabled { opacity: .38; cursor: default; }
.rail-arrow[hidden] { display: none; }   /* honour the attr over display:grid */
/* Floating variant — cuisine rail arrows sit OVER the rail edges (they are
   direct children of .rail-wrap; header arrows live in .hv2-head__nav). */
.rail-wrap > .rail-arrow { position: absolute; top: 50%; transform: translateY(-50%); z-index: 3; box-shadow: var(--shadow-2); }
.rail-wrap > .rail-arrow.rail-arrow--prev { left: -6px; }
.rail-wrap > .rail-arrow.rail-arrow--next { right: -6px; }
@media (max-width: 767px) { .hv2-head__nav, .rail-wrap > .rail-arrow { display: none; } }   /* touch-scroll on mobile */

/* ── Cuisine rail ─────────────────────────────────────────────────── */
.cuisine-rail {
    display: flex; gap: var(--space-3);
    overflow-x: auto; scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
    /* Top/bottom padding gives the active pill's ring (and the hover
       lift) room to breathe — overflow-x:auto clips the Y axis too.
       The first pill's LEFT ring is handled by a small padding-left on
       the first item below. */
    padding-top: var(--space-2); padding-bottom: var(--space-2); margin: 0; list-style: none;
    scroll-behavior: smooth;
}
.cuisine-rail::-webkit-scrollbar { display: none; }
.cuisine-rail__item { flex: 0 0 auto; width: 72px; scroll-snap-align: start; text-align: center; }
/* First pill: tiny left padding so its active ring isn't clipped by the
   rail's overflow / tucked under the collapsed Filters icon. */
.cuisine-rail__item:first-child { padding-left: 3px !important; }
.cuisine-rail__disc {
    width: 68px; height: 68px; border-radius: var(--radius-md);
    background: var(--color-bg-alt);
    display: grid; place-items: center; overflow: hidden;
    position: relative; font-size: 1.85rem;
    transition: transform 120ms ease, box-shadow 120ms ease;
}
.cuisine-rail__item:hover .cuisine-rail__disc { transform: translateY(-3px); box-shadow: var(--shadow-2); }
.cuisine-rail__disc img { width: 100%; height: 100%; object-fit: cover; }
.cuisine-rail__name { display: block; font-weight: 700; margin-top: var(--space-1); font-size: 0.82rem; }
.cuisine-rail__count { display: block; font-size: 0.78rem; color: var(--color-text-soft); }

/* Active pill — the cuisine the feed is currently filtered to. Ring
   round the disc + brand-colour label so the user can see WHICH
   category is driving the restaurant list below (home.js adds the
   .is-active-filter class from the ?cuisine= URL). */
.cuisine-rail__item.is-active-filter .cuisine-rail__disc {
    box-shadow: 0 0 0 2px var(--color-primary);
}
.cuisine-rail__item.is-active-filter .cuisine-rail__name { color: var(--color-primary); }

/* Delivery line on restaurant cards — muted for closed / no-delivery. */
.resto-card__delivery--muted { color: var(--color-text-soft); }

/* Note shown when a picked cuisine had no restaurants → fallback feed. */
.feed-note { background: var(--color-primary-soft); color: var(--color-text); border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); margin: 0 0 var(--space-4); font-weight: 600; }

/* ── Feed loading state ───────────────────────────────────────────── */
/* Shown ONLY over the restaurant feed while an in-place cuisine filter
   fetches. The rail + filters above are untouched (no flicker), but the
   user still gets a clear "loading" cue right where the cards will
   appear: the current list dims and a spinner spins over it. */
[data-home-feed] { position: relative; }
[data-home-feed].is-loading { min-height: 180px; }
[data-home-feed].is-loading > * { opacity: 0.35; pointer-events: none; }
[data-home-feed].is-loading::after {
    content: ""; position: absolute; left: 50%; top: 60px;
    width: 36px; height: 36px; margin-left: -18px;
    border: 3px solid var(--color-border-soft);
    border-top-color: var(--color-primary);
    border-radius: 50%;
    animation: feed-spin 0.7s linear infinite;
}
@keyframes feed-spin { to { transform: rotate(360deg); } }

/* ── Restaurant rail ──────────────────────────────────────────────── */
.resto-rail {
    display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4);
    margin: 0; padding: 0; list-style: none;
}
/* The full "all restaurants" grid (view=restaurants) — fluid auto-fill instead
 * of the fixed 4-col, so it fills the width at any viewport (collapses to a
 * single column on a phone since 220px min only fits once). Replaces the old
 * inline style="display:grid;..." on that <ul> (CSP #9). Double-class so it
 * wins over the responsive .resto-rail overrides in the media queries below. */
.resto-rail.resto-rail--grid {
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}
.resto-card {
    position: relative; background: #fff;
    border: 1px solid var(--color-border-soft);
    border-radius: var(--radius-lg); overflow: hidden;
    display: flex; flex-direction: column;
    transition: transform 120ms ease, box-shadow 120ms ease;
}
.resto-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-2); }
.resto-card__media {
    position: relative; aspect-ratio: 16 / 11;
    background: linear-gradient(135deg, rgba(255,255,255,0.35), transparent 60%), var(--color-bg-alt);
    display: grid; place-items: center; font-size: 3.2rem;
}
.resto-card__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.resto-card__badge {
    position: absolute; top: 10px; left: 10px; z-index: 2;
    padding: 0.25rem 0.6rem; border-radius: var(--radius-sm);
    font-size: 0.72rem; font-weight: 700; color: #fff;
    background: var(--color-success);
}
.resto-card__badge--trending { background: var(--color-primary); }
.resto-card__badge--popular  { background: #f59e0b; }
.resto-card__badge--new      { background: #15893f; }
.resto-card__badge--offer    { background: var(--color-success); display: inline-flex; align-items: center; gap: 5px; }
/* Count chip — shown only when a restaurant has more than one offer. */
.resto-card__badge-count { background: rgba(255, 255, 255, 0.28); border-radius: 999px; padding: 0 6px; font-size: 0.68rem; font-weight: 800; line-height: 1.5; }
/* Heart icon (signed-in only). Filled when active. Pinned to the
   media area; sits above the offer badge layer (z-index:3 vs 2). */
.resto-card__fav {
    position: absolute; top: 8px; right: 8px; z-index: 3;
    width: 32px; height: 32px; border-radius: 50%;
    background: rgba(255,255,255,0.92); border: 0; cursor: pointer;
    display: grid; place-items: center; color: var(--color-text-soft);
    box-shadow: 0 1px 4px rgba(0,0,0,0.18);
    padding: 0; line-height: 0;
    transition: transform 120ms ease, color 120ms ease, background 120ms ease;
}
.resto-card__fav svg { width: 17px; height: 17px; }
.resto-card__fav:hover { color: var(--color-primary); transform: scale(1.06); }
.resto-card__fav.is-active { color: var(--color-primary); background: #fff; }
.resto-card__fav.is-active svg { fill: currentColor; stroke: currentColor; }
.resto-card__fav:disabled { opacity: 0.6; cursor: progress; }
/* Tiny pop animation on toggle. */
.resto-card__fav.is-pulsing { animation: fav-pulse 360ms ease; }
@keyframes fav-pulse {
    0%   { transform: scale(1); }
    35%  { transform: scale(1.25); }
    65%  { transform: scale(0.92); }
    100% { transform: scale(1); }
}
.resto-card__body { padding: var(--space-3); display: flex; flex-direction: column; gap: 4px; }
.resto-card__name { font-weight: 700; font-size: 1rem; display: flex; align-items: center; gap: 4px; }
.resto-card__verified { color: #2563eb; flex: 0 0 auto; }
.resto-card__cuisines {
    font-size: 0.82rem; color: var(--color-text-muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0;
}
.resto-card__meta { display: flex; align-items: center; gap: var(--space-2); font-size: 0.82rem; color: var(--color-text-muted); }
.resto-card__rating {
    display: inline-flex; align-items: center; gap: 3px;
    background: #15893f; color: #fff; font-weight: 700;
    padding: 0.05rem 0.4rem; border-radius: var(--radius-sm); font-size: 0.78rem;
}
.resto-card__time, .resto-card__dist { display: inline-flex; align-items: center; gap: 3px; }
.resto-card__dist svg { color: var(--color-primary); }
.resto-card__delivery { color: var(--color-success); font-size: 0.8rem; font-weight: 600; }
/* Closed badge — RED (defined after the base so it wins the cascade). */
.resto-card__delivery--closed { color: #dc2626; }
.resto-card__foot { display: flex; align-items: center; justify-content: space-between; margin-top: 2px; }
.resto-card__price { font-size: 0.82rem; color: var(--color-text-muted); }
.resto-card__add {
    width: 30px; height: 30px; border-radius: 50%;
    border: 1px solid var(--color-primary); background: #fff;
    color: var(--color-primary); font-size: 1.2rem; line-height: 1;
    cursor: pointer; display: grid; place-items: center;
}
.resto-card__add:hover { background: var(--color-primary); color: #fff; }

/* ── Offers rail ──────────────────────────────────────────────────── */
.offers-rail { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }
.offer-banner {
    position: relative; border-radius: var(--radius-lg);
    padding: var(--space-5); min-height: 150px; color: #fff;
    display: flex; flex-direction: column; justify-content: center;
    overflow: hidden;
}
.offer-banner--red    { background: linear-gradient(135deg, #e5252a, #b3161b); }
.offer-banner--orange { background: linear-gradient(135deg, #f9a825, #f57f17); }
.offer-banner--purple { background: linear-gradient(135deg, #7e3ff2, #5b2bc4); }
.offer-banner__title { font-size: 1.5rem; font-weight: 800; line-height: 1.1; }
.offer-banner__sub   { font-size: 0.9rem; opacity: 0.95; margin-top: 4px; }
.offer-banner__cta   { margin-top: var(--space-3); font-weight: 700; font-size: 0.85rem; display: inline-flex; align-items: center; gap: 4px; }
.offer-banner__code  { display: inline-block; margin-top: var(--space-3); background: rgba(255,255,255,0.22); border: 1px dashed rgba(255,255,255,0.65); border-radius: var(--radius-sm); padding: 0.15rem 0.5rem; font-weight: 700; letter-spacing: 0.04em; font-size: 0.8rem; }

/* Real store-offer banners (anchors). Titles come from merchant copy and
   can be long, so clamp them to 2 lines at a calmer size. */
.offer-banner--real { text-decoration: none; cursor: pointer; }
.offer-banner--real .offer-banner__title { font-size: 1.15rem; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.offer-banner--real .offer-banner__sub { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.offer-banner__from { margin-top: auto; padding-top: var(--space-2); font-size: 0.78rem; font-weight: 700; opacity: 0.9; }
.offer-banner--real .offer-banner__cta { margin-top: var(--space-2); }

/* ── Popular cuisines (dark cards) ───────────────────────────────── */
.popcuisine-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4); }
.popcuisine-card {
    position: relative; border-radius: var(--radius-lg); overflow: hidden;
    background: #1d1d1d; color: #fff; min-height: 96px;
    display: flex; align-items: center; justify-content: space-between;
    padding: var(--space-4); gap: var(--space-2);
}
.popcuisine-card__copy { z-index: 1; }
.popcuisine-card__name { font-weight: 800; font-size: 1.15rem; }
.popcuisine-card__explore { color: var(--color-primary); font-weight: 700; font-size: 0.82rem; display: inline-flex; align-items: center; gap: 4px; margin-top: 4px; }
.popcuisine-card__art { width: 84px; height: 84px; border-radius: var(--radius-md); background: var(--color-bg-alt); display: grid; place-items: center; font-size: 2.4rem; flex: 0 0 auto; overflow: hidden; }
.popcuisine-card__art img { width: 100%; height: 100%; object-fit: cover; }

/* ── Feature strip ────────────────────────────────────────────────── */
.feature-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4); }
.feature-item {
    border-radius: var(--radius-lg); padding: var(--space-4);
    display: flex; align-items: center; gap: var(--space-3);
}
.feature-item--a { background: #FFF1EC; }
.feature-item--b { background: #ECFBF1; }
.feature-item--c { background: #F1EEFF; }
.feature-item--d { background: #FFF8E8; }
.feature-item__icon { width: 44px; height: 44px; border-radius: 50%; background: #fff; display: grid; place-items: center; flex: 0 0 auto; font-size: 1.4rem; }
.feature-item__title { font-weight: 700; font-size: 0.95rem; }
.feature-item__sub   { font-size: 0.8rem; color: var(--color-text-muted); }

/* ── Top line: welcome strip (LEFT) + "get the app" card (RIGHT) on ONE row,
   under the category rail. Mobile: block stack — only the welcome strip shows
   (the app card is desktop-only; you're already on a phone). ── */
.home-topline { display: block; }
.app-mini { display: none; }
/* Mobile web browser — show the get-the-app card too (it is server-side
   omitted inside our WebView wrapper, so this only ever hits real browsers).
   Stacked full-width card under the welcome strip; same look as desktop. */
@media (max-width: 767px) {
    .app-mini {
        position: relative; display: flex; align-items: center; gap: 14px;
        width: 100%; margin: var(--space-4) 0 0; padding: 14px 16px; border-radius: 16px;
        background: var(--color-bg); border: 1px solid var(--color-border); box-shadow: var(--shadow-1);
    }
    .app-mini__radio { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
    .app-mini__qr { position: relative; flex: 0 0 auto; width: 84px; height: 84px; border-radius: 10px; background: #fff; border: 1px solid var(--color-border); padding: 5px; overflow: hidden; }
    .app-mini__img { position: absolute; inset: 5px; width: calc(100% - 10px); height: calc(100% - 10px); object-fit: contain; display: none; }
    #app-ios:checked ~ .app-mini__qr .app-mini__img--ios         { display: block; }
    #app-android:checked ~ .app-mini__qr .app-mini__img--android { display: block; }
    .app-mini__body { min-width: 0; }
    .app-mini__title { margin: 8px 0 0; font-weight: 800; font-size: 0.95rem; color: var(--color-text); }
    .app-mini__sub { margin: 2px 0 0; font-size: 0.8rem; color: var(--color-text-muted); }
    .app-mini__actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
    .app-mini__tabs { display: flex; gap: 8px; }
    .app-mini__tab { display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 12px; border-radius: 999px; border: 1px solid var(--color-border); background: var(--color-bg-alt, #f7f8fa); color: var(--color-text); font-weight: 700; font-size: 0.8rem; cursor: pointer; user-select: none; }
    .app-mini__tab-ic { width: 15px; height: 15px; flex: 0 0 auto; }
    #app-ios:checked ~ .app-mini__body .app-mini__tab[for="app-ios"],
    #app-android:checked ~ .app-mini__body .app-mini__tab[for="app-android"] { background: #111; color: #fff; border-color: #111; }
}
@media (min-width: 768px) {
    /* Pull the promo zone (welcome strip + offer carousel) tighter to the
     * category rail — the shell's flex gap (space-8) PLUS the strips' own
     * vertical margins left too much air. The strips carry no margin of their
     * own inside the topline; a negative margin-top trims the flex gap so the
     * category → welcome → offer spacing reads tight, not loose. */
    .home-topline { display: flex; align-items: center; gap: var(--space-4); margin-top: calc(-1 * var(--space-4)); }
    .home-topline .welcome-strip { flex: 1 1 auto; min-width: 0; margin: 0; }
    .home-topline .app-mini { flex: 0 0 auto; margin: 0 0 0 auto; }
    /* Solo row (welcome banner switched off): the card is the only thing on
     * the line, so let it fill the width and gain a bit of height instead of
     * leaving a wide gap where the strip used to be. */
    .home-topline--solo .app-mini { flex: 1 1 auto; width: 100%; max-width: none; padding: 20px 24px; }
    .offer-banner-row { margin-top: calc(-1 * var(--space-4)); }
    .app-mini {
        position: relative; display: flex; align-items: center; gap: 16px; max-width: 100%;
        padding: 14px 18px; border-radius: 16px;
        background: var(--color-bg); border: 1px solid var(--color-border); box-shadow: var(--shadow-1);
    }
    .app-mini__radio { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
    /* QR area — both platform QRs stacked; only the selected tab's shows. */
    .app-mini__qr { position: relative; flex: 0 0 auto; width: 96px; height: 96px; border-radius: 10px; background: #fff; border: 1px solid var(--color-border); padding: 5px; overflow: hidden; }
    .app-mini__img { position: absolute; inset: 5px; width: calc(100% - 10px); height: calc(100% - 10px); object-fit: contain; display: none; }
    #app-ios:checked ~ .app-mini__qr .app-mini__img--ios         { display: block; }
    #app-android:checked ~ .app-mini__qr .app-mini__img--android { display: block; }
    .app-mini__body { min-width: 0; }
    .app-mini__title { margin: 10px 0 0; font-weight: 800; font-size: 0.98rem; color: var(--color-text); }
    .app-mini__sub { margin: 2px 0 0; font-size: 0.82rem; color: var(--color-text-muted); }
    /* Action row — platform tabs + the "Rate us" link, side by side at the TOP
     * of the body. Wraps so a narrow card drops "Rate us" to its own line
     * instead of squeezing the tabs. */
    .app-mini__actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
    /* "Rate us" — a LINK to the reviews page, not a platform tab. Same pill
     * geometry as the tabs so the row reads as one control group, but outlined
     * in the brand colour so it never looks like a third platform to pick
     * (the tabs go solid black when selected; this one never does). */
    .app-mini__rate { display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--color-primary); background: transparent; color: var(--color-primary); font-weight: 700; font-size: 0.82rem; text-decoration: none; white-space: nowrap; }
    .app-mini__rate:hover { background: var(--color-primary); color: #fff; }
    .app-mini__rate-ic { width: 15px; height: 15px; flex: 0 0 auto; }
    /* iOS / Android tabs — sit at the TOP of the body (the platform picker). */
    .app-mini__tabs { display: flex; gap: 8px; }
    .app-mini__tab { display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--color-border); background: var(--color-bg-alt, #f7f8fa); color: var(--color-text); font-weight: 700; font-size: 0.82rem; cursor: pointer; user-select: none; }
    .app-mini__tab:hover { border-color: var(--color-primary); }
    .app-mini__tab-ic { width: 15px; height: 15px; flex: 0 0 auto; }
    #app-ios:checked ~ .app-mini__body .app-mini__tab[for="app-ios"],
    #app-android:checked ~ .app-mini__body .app-mini__tab[for="app-android"] { background: #111; color: #fff; border-color: #111; }
}

/* ── App CTA (legacy — no longer rendered; the .app-mini card replaced it) ── */
.appcta {
    background: linear-gradient(120deg, #FFF1EC 0%, #FFE6DE 100%);
    border-radius: 24px; padding: var(--space-8);
    display: grid; grid-template-columns: 1fr auto 1fr; gap: var(--space-6);
    align-items: center;
}
.appcta__title { font-size: 2rem; font-weight: 800; line-height: 1.1; }
.appcta__sub { color: var(--color-text-muted); margin-top: var(--space-2); }
.appcta__badges { display: flex; gap: var(--space-3); margin-top: var(--space-4); align-items: center; flex-wrap: wrap; }
.appcta__badge { height: 44px; border-radius: 8px; background: #111; color: #fff; display: inline-flex; align-items: center; gap: 8px; padding: 0 14px; font-weight: 600; font-size: 0.85rem; }
.appcta__qr { width: 76px; height: 76px; border-radius: 8px; background: #fff; display: grid; place-items: center; border: 1px solid var(--color-border); padding: 5px; cursor: pointer; overflow: hidden; }
.appcta__qr-code { width: 100%; height: 100%; display: block; object-fit: contain; }
.appcta__phone { width: 200px; height: 360px; border-radius: 28px; background: #111; border: 6px solid #111; box-shadow: var(--shadow-2); overflow: hidden; justify-self: center; display: grid; place-items: center; color: #fff; font-size: 2.4rem; }
.appcta__checks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }
.appcta__check { display: flex; align-items: center; gap: var(--space-2); font-weight: 600; }
.appcta__check svg { color: #15893f; flex: 0 0 auto; }

/* ── Responsive ───────────────────────────────────────────────────── */
@media (max-width: 1023px) {
    .resto-rail      { grid-template-columns: repeat(2, 1fr); }
    .offers-rail     { grid-template-columns: 1fr; }
    .popcuisine-grid { grid-template-columns: repeat(2, 1fr); }
    .feature-strip   { grid-template-columns: repeat(2, 1fr); }
    .appcta          { grid-template-columns: 1fr; text-align: center; }
    .appcta__phone   { display: none; }
}
@media (max-width: 767px) {
    .home-shell { padding: var(--space-2) var(--space-3) var(--space-10); }
    .home-shell__content { gap: var(--space-6); }

    /* Hero banner hidden on mobile per the user — the feed starts
     * straight at the cuisine grid. Location is still settable from
     * the header chip + the mobile search row. */
    .hero-v2 { display: none; }

    .hv2-head__title { font-size: 1.15rem; }

    /* Cuisines — single horizontal scrolling row, STICKY just below
     * the (also sticky) search bar so both stay pinned to the top
     * while the feed scrolls underneath. Full-bleed white strip.
     *
     * Scoped with :not(.home-rail-wrap) so ONLY the cuisine rail is sticky
     * + full-bleed. The feed shelves (favourites / order-again / product
     * rows) reuse `.rail-wrap home-rail-wrap`; without this guard they all
     * became sticky at the same top offset with edge-bleed + a stray white
     * strip. They stay position:relative (the base .rail-wrap rule). */
    .rail-wrap:not(.home-rail-wrap) {
        position: sticky;
        top: 56px;                              /* below the sticky mobile search row */
        z-index: 40;
        background: #fff;
        margin: 0 calc(-1 * var(--space-3));    /* extend to the viewport edges */
        padding: var(--space-2) var(--space-3);
        border-bottom: 1px solid var(--color-border-soft);
    }
    .cuisine-rail {
        display: flex; gap: var(--space-3);
        overflow-x: auto; -webkit-overflow-scrolling: touch;
        scrollbar-width: none; scroll-snap-type: x proximity;
    }
    .cuisine-rail::-webkit-scrollbar { display: none; }
    .cuisine-rail__item { flex: 0 0 auto; width: 60px; scroll-snap-align: start; }
    .cuisine-rail__disc { width: 58px; height: 58px; border-radius: 14px; font-size: 1.55rem; }
    .cuisine-rail__name { font-size: 0.68rem; margin-top: var(--space-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .rail-arrow { display: none; }

    /* Restaurant rail — single column on mobile: one full-width card
     * per row, stacked vertically (NOT a side swipe). Same vertical-
     * feed UX as the dish grid — the user wants one restaurant per
     * screen-width row that the feed scrolls through, and paginates
     * via the IntersectionObserver as you reach the bottom. */
    .resto-rail {
        display: grid; grid-template-columns: 1fr; gap: var(--space-4);
        overflow: visible;
    }
    .resto-rail > li { width: auto; max-width: none; }

    /* Offers — horizontal swipe. */
    .offers-rail {
        display: flex; overflow-x: auto; scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch; scrollbar-width: none; gap: var(--space-3);
    }
    .offers-rail::-webkit-scrollbar { display: none; }
    .offers-rail > * { flex: 0 0 80%; max-width: 320px; scroll-snap-align: start; }

    /* Popular cuisines + features — 2-up grids. */
    .popcuisine-grid { grid-template-columns: 1fr 1fr; }
    .feature-strip   { grid-template-columns: 1fr 1fr; }
    .feature-item    { flex-direction: column; align-items: flex-start; gap: var(--space-2); }

    /* App CTA — stack, hide the phone mock. */
    .appcta { grid-template-columns: 1fr; text-align: left; padding: var(--space-5); }
    .appcta__phone { display: none; }
    .appcta__title { font-size: 1.5rem; }
}

/* Scan-to-download QR popup (foodpanda-style) — opens from the QR badge. */
body.appqr-open { overflow: hidden; }
.appqr { position: fixed; inset: 0; z-index: 1300; display: flex; align-items: center; justify-content: center; padding: 20px; }
.appqr[hidden] { display: none; }
.appqr__backdrop { position: absolute; inset: 0; background: rgba(15, 23, 42, .55); }
.appqr__panel { position: relative; width: 320px; max-width: 92vw; background: #1f1f1f; color: #fff; border-radius: 22px; padding: 26px 24px 22px; text-align: center; box-shadow: 0 24px 60px rgba(0, 0, 0, .4); }
.appqr__x { position: absolute; top: 12px; right: 12px; width: 30px; height: 30px; border: none; border-radius: 50%; background: rgba(255, 255, 255, .14); color: #fff; cursor: pointer; font-size: .9rem; }
.appqr__code { width: 200px; height: 200px; margin: 4px auto 18px; background: #fff; border-radius: 16px; padding: 12px; }
.appqr__code img { width: 100%; height: 100%; display: block; }
.appqr__title { margin: 0 0 16px; font-size: 1.15rem; font-weight: 800; line-height: 1.3; }
.appqr__stores { display: flex; gap: 10px; justify-content: center; }
.appqr__store { height: 42px; border-radius: 9px; background: #000; border: 1px solid rgba(255, 255, 255, .18); color: #fff; display: inline-flex; align-items: center; gap: 6px; padding: 0 14px; font-weight: 600; font-size: .82rem; }
@media (max-width: 560px) { .appqr__code { width: 170px; height: 170px; } }

/* Browse mode (Collections & offers filter) — back-to-home bar above the set. */
.browse-back { display: inline-flex; align-items: center; gap: 6px; color: var(--color-primary); font-weight: 700; text-decoration: none; margin-bottom: var(--space-3); }
.browse-back:hover { text-decoration: underline; }

/* ── Welcome strip (super-admin configured) — under the category rail ──
   Text mode = friendly gradient card (icon + title + subtitle + soft glow);
   image mode = full-width banner. */
.welcome-strip { margin: var(--space-4) 0 var(--space-5); border-radius: 20px; overflow: hidden; }
.welcome-strip--text { box-shadow: 0 10px 30px rgba(229, 37, 42, .18); }
.welcome-strip__link { display: block; color: inherit; text-decoration: none; }

/* Text mode — gradient card. Flex on whichever element wraps the content
   (the section, or the link when a click-through is set). */
.welcome-strip--text { position: relative; background: linear-gradient(120deg, var(--color-primary) 0%, #ff5f83 100%); color: #fff; padding: 24px 28px; }
.welcome-strip--text,
.welcome-strip--text .welcome-strip__link { display: flex; align-items: center; gap: 18px; }
/* Soft decorative glow on the trailing edge. */
.welcome-strip--text::after { content: ''; position: absolute; right: -50px; top: 50%; transform: translateY(-50%); width: 210px; height: 210px; border-radius: 50%; background: rgba(255, 255, 255, .12); pointer-events: none; }
/* Leading icon badge. */
.welcome-strip__ic { flex: 0 0 auto; width: 54px; height: 54px; border-radius: 50%; background: rgba(255, 255, 255, .22); display: grid; place-items: center; font-size: 1.7rem; }
.welcome-strip__body { position: relative; z-index: 1; min-width: 0; }
.welcome-strip--text .welcome-strip__title { margin: 0; font-size: 1.5rem; font-weight: 800; line-height: 1.2; }
.welcome-strip--text .welcome-strip__sub { margin: 5px 0 0; font-size: 1rem; opacity: .95; }

/* Image mode — a FIXED short banner the SAME height as the text banner. ANY
   uploaded image auto-fits the box (object-fit: cover crops overflow), so a big
   upload never overflows or breaks the layout — it just resizes into the box. */
.welcome-strip--image { height: 120px; background: none; }
.welcome-strip--image .welcome-strip__link { display: block; width: 100%; height: 100%; }
.welcome-strip__img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Mobile — matches the home's own 767px breakpoint so the banner switches to
   the compact card exactly when the rest of the home goes mobile (PWA feel). */
@media (max-width: 767px) {
    .welcome-strip { margin: var(--space-3) 0 var(--space-4); border-radius: 16px; }
    .welcome-strip--text { padding: 16px 18px; }
    .welcome-strip--text,
    .welcome-strip--text .welcome-strip__link { gap: 13px; }
    .welcome-strip__ic { width: 44px; height: 44px; font-size: 1.4rem; }
    .welcome-strip--text .welcome-strip__title { font-size: 1.2rem; }
    .welcome-strip--text .welcome-strip__sub { font-size: 0.88rem; }
    .welcome-strip--text::after { width: 150px; height: 150px; right: -45px; }
    /* Match the text banner's compact height on mobile. */
    .welcome-strip--image { height: 100px; }
}
/* Very small phones — keep the title on a comfortable size, tighten the icon. */
@media (max-width: 420px) {
    .welcome-strip--text { padding: 15px 16px; }
    .welcome-strip__ic { width: 40px; height: 40px; font-size: 1.25rem; }
    .welcome-strip--text .welcome-strip__title { font-size: 1.1rem; }
    .welcome-strip--text .welcome-strip__sub { font-size: 0.85rem; }
}

/* ============================================================
   /app download landing — the fallback page shown by
   AppController.appRedirect on desktop, an unknown device, or
   while the store URLs are still empty. Works on every device
   (unlike .app-mini, which is a desktop-only home widget).
   ============================================================ */
.app-page { display: grid; place-items: center; padding: var(--space-8, 40px) var(--space-4, 16px); }
.app-page__card {
    width: 100%; max-width: 640px; text-align: center;
    background: var(--color-bg); border: 1px solid var(--color-border);
    border-radius: 20px; box-shadow: var(--shadow-1); padding: var(--space-6, 28px);
}
.app-page__title { margin: 0; font-size: 1.6rem; font-weight: 800; }
.app-page__sub   { margin: 8px 0 var(--space-5, 22px); color: var(--color-text-muted); }
.app-page__grid  { display: flex; gap: var(--space-5, 22px); justify-content: center; flex-wrap: wrap; }
.app-page__col   { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.app-page__plat  { display: inline-flex; align-items: center; gap: 7px; font-weight: 800; }
.app-page__qr    { width: 160px; height: 160px; background: #fff; border: 1px solid var(--color-border); border-radius: 12px; padding: 8px; }
.app-page__qr img { width: 100%; height: 100%; display: block; object-fit: contain; }
.app-page__store {
    display: inline-flex; align-items: center; min-height: 44px; padding: 0 20px;
    border-radius: 8px; background: #111; color: #fff; font-weight: 700; text-decoration: none;
}
.app-page__store:hover { background: #000; }
.app-page__soon  { margin: var(--space-5, 22px) 0 0; color: var(--color-text-muted); font-size: 0.9rem; }
.app-page__home  { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 12px; margin-top: var(--space-4, 16px); color: var(--color-primary); font-weight: 700; text-decoration: none; }
@media (max-width: 560px) {
    .app-page__qr { width: 140px; height: 140px; }
    .app-page__title { font-size: 1.35rem; }
}

/* ── Mobile touch-target polish (PWA audit C2) ────────────────────────
 * These two base rules live in THIS file, so their 44px mobile overrides
 * must also live here (home-v2.css loads after filter-sidebar.css, so an
 * override placed there would lose the cascade). Enlarge the hit area to
 * 44px without changing the glyph size. */
@media (max-width: 767px) {
    .resto-card__fav { width: 44px; height: 44px; }   /* was 32px */
    .fsb__hide       { width: 44px; height: 44px; }   /* was 30px */
}
