:root {
    --primary: #ff6b35;
    --primary-dark: #e0551f;
    --bg: #f7f7fb;
    --card: #ffffff;
    --text: #1f2430;
    --muted: #7a7f8c;
    --border: #e7e7ee;
    --radius: 14px;
    /* Dark navy accent used for price tags and the bottom bar's CTA button -
       mirrors the reference design's "Төлөх" pill, distinct from --primary
       (which stays the brand/active-category color, closer to the reference's
       amber active-category tile). */
    --navy: #1f3244;
}

* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    /* The page now scrolls normally (unlike the old fixed-height/internal-
       scroll app shell) so the category grid below can use native
       `position: sticky` relative to the real viewport - sticky only works
       relative to the nearest scrolling ancestor, and that has to be the
       document itself for it to dock to the very top of the screen. */
    overscroll-behavior-y: contain;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
    background: var(--bg);
    color: var(--text);
}

#app {
    min-height: 100vh;
    min-height: 100dvh; /* modern mobile browsers: account for URL bar */
}

/* ---- Header: circular logo + restaurant name/table, matching the
   reference design's "logo + name + branch" header row. ---- */
.restaurant-header {
    display: flex;
    align-items: center;
    gap: 12px;
    background: var(--card);
    padding: 16px;
    border-bottom: 1px solid var(--border);
}

.restaurant-logo {
    width: 56px;
    height: 56px;
    flex: 0 0 auto;
    border-radius: 50%;
    overflow: hidden;
    background: var(--primary);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    font-weight: 800;
}

.restaurant-logo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.restaurant-header-text {
    flex: 1;
    min-width: 0;
}

.restaurant-header-text h1 {
    margin: 0;
    font-size: 19px;
    font-weight: 800;
    color: var(--text);
    line-height: 1.25;
}

.restaurant-subtitle {
    margin-top: 2px;
    font-size: 14px;
    color: var(--muted);
}

.icon-btn-outline {
    border: 1px solid var(--border);
    background: #fff;
    border-radius: 50%;
    width: 34px;
    height: 34px;
    font-size: 16px;
    cursor: pointer;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* ---- Category selector: a grid of icon tiles (not a horizontal pill
   scroller) matching the reference design, sticking to the top of the
   viewport once the header scrolls past it. `.category-sentinel` is a
   zero-height marker menu.js watches with an IntersectionObserver to know
   the exact moment the grid becomes stuck, so it can add `.is-stuck` for
   the condensed styling below - sticky positioning alone doesn't shrink
   anything, so that toggle has to come from JS. ---- */
.category-sentinel {
    height: 0;
}

.category-grid {
    position: sticky;
    top: 0;
    z-index: 15; /* above menu content, below drawers (21) / modal (31) / toast (50) */
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
    background: var(--card);
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
}

.category-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    /*justify-content: center;*/
    gap: 6px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 16px;
    padding: 14px 4px;
    min-height: 76px;
    cursor: pointer;
    text-align: center;
    font-family: inherit;
    transition: background .15s ease, border-color .15s ease, padding .18s ease, min-height .18s ease;
}

.category-tile-icon {
    font-size: 24px;
    line-height: 1;
    transition: font-size .18s ease;
}

.category-tile-img {
    width: 28px;
    height: 28px;
    object-fit: cover;
    border-radius: 8px;
    transition: width .18s ease, height .18s ease;
}

.category-tile-label {
    font-size: 11.5px;
    font-weight: 700;
    color: var(--text);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.category-tile.active {
    background: var(--primary);
    border-color: var(--primary);
}

.category-tile.active .category-tile-label {
    color: #fff;
}

/* Condensed strip once the grid has stuck to the top of the viewport -
   see the IntersectionObserver in menu.js that toggles this class. */
.category-grid.is-stuck {
    padding: 8px 12px;
    box-shadow: 0 4px 16px rgba(20, 22, 30, .10);
}

.category-grid.is-stuck .category-tile {
    padding: 6px 4px;
    min-height: 0;
    border-radius: 12px;
    gap: 3px;
}

.category-grid.is-stuck .category-tile-icon {
    font-size: 15px;
}

.category-grid.is-stuck .category-tile-img {
    width: 18px;
    height: 18px;
    border-radius: 5px;
}

.category-grid.is-stuck .category-tile-label {
    font-size: 10px;
    -webkit-line-clamp: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Persistent order-status banner, floating just above the bottom cart bar
   (#cartBar): shows the current order's status directly on the main screen
   at all times, so the customer doesn't have to open the cart drawer (or
   catch the small confirmation popup before it auto-closes) just to check
   whether their food is coming. Tappable as a shortcut into the cart
   drawer for more detail, but the status itself is readable without
   tapping anything. Its `bottom` offset is computed in JS
   (positionActiveOrderBanner()) from the live position of #cartBar, so it
   always sits directly above that bar no matter the bar's own height or
   the device's safe-area inset - `top` is deliberately left unset here. */
.active-order-banner {
    position: fixed;
    left: 12px;
    right: 12px;
    max-width: 420px;
    margin: 0 auto;
    z-index: 15; /* above the menu content, below drawers (21) / modal (31) / toast (50) */
    background: var(--card);
    border-radius: var(--radius);
    border-left: 4px solid var(--primary);
    box-shadow: 0 10px 28px rgba(20, 22, 30, .16);
    padding: 12px 14px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    font-size: 14px;
    color: var(--text);
    cursor: pointer;
    opacity: 0;
    transform: translateY(14px);
    transition: opacity .25s ease, transform .25s ease;
}

/* Same [hidden] cascade rule this project has needed for every other custom
   overlay (.drawer, .confirm-overlay): an unconditional `display: flex` in
   author CSS beats the browser's built-in `[hidden] { display: none }` rule
   regardless of specificity, so without this the (invisible, opacity:0)
   banner would keep sitting fixed over the page and swallowing clicks. */
.active-order-banner[hidden] {
    display: none;
}

.active-order-banner.banner-in {
    opacity: 1;
    transform: translateY(0);
}

.active-order-banner-text strong {
    color: inherit;
}

.active-order-banner.status-served {
    border-left-color: #1a9c56;
}

.active-order-banner.status-served .active-order-banner-text strong {
    color: #1a9c56;
}

.active-order-banner.status-cancelled {
    border-left-color: #c0392b;
}

.active-order-banner.status-cancelled .active-order-banner-text strong {
    color: #c0392b;
}

.active-order-banner-arrow {
    font-size: 18px;
    line-height: 1;
    opacity: .4;
    flex: 0 0 auto;
}

.menu-list {
    padding: 14px 16px calc(150px + env(safe-area-inset-bottom));
}

.category-section-title {
    font-size: 16px;
    font-weight: 800;
    margin: 20px 0 10px;
}

.category-section:first-child .category-section-title {
    margin-top: 2px;
}

.loading, .empty {
    text-align: center;
    color: var(--muted);
    padding: 40px 0;
}

/* ---- Menu item tiles: a 2-column grid of image-first cards (price badge
   top-right, name overlaid on the image) matching the reference design,
   instead of the old horizontal list row. Tapping anywhere on the tile
   adds one to the cart; once it's in the cart, a dark overlay with
   −/qty/+ controls appears on top of the image (see .item-tile-overlay
   and menu.js's click handling). ---- */
.item-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.item-tile {
    position: relative;
    border-radius: 16px;
    overflow: hidden;
    background: #eef0f5;
    aspect-ratio: 1 / 1.05;
    cursor: pointer;
    box-shadow: 0 2px 10px rgba(20, 22, 30, .07);
}

.item-tile-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.item-tile-placeholder {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 34px;
    background: #eef0f5;
}

.item-tile-price {
    position: absolute;
    top: 8px;
    right: 8px;
    background: rgba(255, 255, 255, .95);
    color: var(--navy);
    font-weight: 800;
    font-size: 14px;
    padding: 4px 9px;
    border-radius: 10px;
    line-height: 1.3;
}

.item-tile-spicy {
    position: absolute;
    top: 8px;
    left: 8px;
    background: rgba(255, 255, 255, .95);
    border-radius: 10px;
    padding: 3px 7px;
    font-size: 13px;
    line-height: 1.3;
}

.item-tile-bottom {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 24px 10px 10px;
    background: linear-gradient(to top, rgba(15, 17, 23, .78), rgba(15, 17, 23, 0));
}

.item-tile-sub {
    color: rgba(255, 255, 255, .82);
    font-size: 11px;
    margin-bottom: 2px;
}

.item-tile-name {
    color: #fff;
    font-size: 13px;
    font-weight: 700;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* In-cart overlay: hidden (opacity 0, not interactive) until .item-tile
   gets the .in-cart class in menu.js's renderItemCard(). Matches the
   reference design's frosted horizontal band across the middle of the
   image (NOT the whole tile) - the price badge up top and the dish name
   at the bottom stay fully visible/legible while an item is in the cart. */
.item-tile-overlay {
    position: absolute;
    left: 0;
    right: 0;
    top: 36%;
    bottom: 34%;
    background: rgba(35, 38, 44, .5);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 24px;
    opacity: 0;
    pointer-events: none;
    transition: opacity .15s ease;
}

.item-tile.in-cart .item-tile-overlay {
    opacity: 1;
    pointer-events: auto;
}

.item-tile-qty-btn {
    width: 34px;
    height: 34px;
    border: none;
    background: none;
    color: #fff;
    font-size: 24px;
    font-weight: 800;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.item-tile-qty-num {
    color: #fff;
    font-size: 19px;
    font-weight: 800;
    min-width: 18px;
    text-align: center;
}

/* ---- Bottom cart summary bar (replaces the old round FAB): a thumbnail
   strip for whatever's in the cart, a running total, and a "Захиалах"
   button - tapping anywhere on the bar opens the full cart drawer (order
   type, notes, and the real submit button all still live there
   unchanged). Once the cart is empty but an order is already in flight,
   it collapses to a single "Миний захиалга" row instead (see
   #viewOrderBtn / renderCart() in menu.js). ---- */
.cart-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 12;
    background: var(--card);
    border-top: 1px solid var(--border);
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -6px 24px rgba(20, 22, 30, .10);
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    cursor: pointer;
}

.cart-bar[hidden] {
    display: none;
}

.cart-bar-items {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    padding-bottom: 10px;
    margin-bottom: 10px;
    border-bottom: 1px solid var(--border);
}

.cart-bar-items[hidden] {
    display: none;
}

/* Each cart-bar item is a scaled-down version of the main .item-tile card
   (image fills the tile, name overlaid at the bottom on a gradient) rather
   than a small thumbnail-plus-caption - matching the reference design's
   horizontally-scrolling row of mini item cards once several dishes are in
   the cart. */
.cart-bar-item {
    position: relative;
    flex: 0 0 auto;
    width: 108px;
    height: 108px;
    border-radius: 14px;
    overflow: hidden;
    background: #eef0f5;
}

.cart-bar-item-thumb {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.cart-bar-item-thumb-placeholder {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    background: #eef0f5;
}

.cart-bar-item-qty {
    position: absolute;
    top: 6px;
    left: 6px;
    background: var(--primary);
    color: #fff;
    font-size: 12px;
    font-weight: 800;
    min-width: 20px;
    height: 20px;
    border-radius: 7px;
    padding: 0 5px;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1;
}

.cart-bar-item-remove {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .95);
    color: var(--text);
    border: none;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1;
}

.cart-bar-item-bottom {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 16px 6px 6px;
    background: linear-gradient(to top, rgba(15, 17, 23, .8), rgba(15, 17, 23, 0));
}

.cart-bar-item-name {
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    line-height: 1.2;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.cart-bar-footer[hidden] {
    display: none;
}

.cart-bar-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.cart-bar-total {
    display: flex;
    flex-direction: column;
}

.cart-bar-total-label {
    font-size: 12px;
    color: var(--muted);
}

.cart-bar-total strong {
    font-size: 19px;
}

.cart-bar-cta {
    background: var(--navy);
    color: #fff;
    border: none;
    border-radius: 30px;
    padding: 13px 22px;
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
}

.cart-bar-view-order {
    width: 100%;
    border: none;
    background: var(--primary);
    color: #fff;
    padding: 13px;
    border-radius: 30px;
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
}

.cart-bar-view-order[hidden] {
    display: none;
}

.overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .4);
    z-index: 20;
}

.drawer {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 21;
    background: var(--card);
    border-radius: 18px 18px 0 0;
    max-height: 82vh;
    max-height: 82dvh;
    display: flex;
    flex-direction: column;
    padding: 16px calc(16px + env(safe-area-inset-right)) calc(16px + env(safe-area-inset-bottom)) calc(16px + env(safe-area-inset-left));
}

/* IMPORTANT: `.drawer` sets `display: flex` unconditionally, which (being a normal
   author-stylesheet rule) beats the browser's built-in `[hidden] { display: none }`
   user-agent rule regardless of the plain `.drawer` selector's specificity. Without
   this override, setting the `hidden` attribute on #cartDrawer/#myOrdersDrawer has
   NO visual effect and the drawer never actually closes. `.drawer[hidden]` is more
   specific than `.drawer` alone, so it correctly wins and hides the element. */
.drawer[hidden] {
    display: none;
}

.drawer-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
}

.icon-btn {
    border: none;
    background: none;
    font-size: 20px;
    cursor: pointer;
}

.cart-items {
    overflow-y: auto;
    flex: 1;
}

/* Order-confirmation item row: ✕ remove + thumbnail + name + qty×price,
   matching the reference design's cart-review list. */
.cart-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
}

.cart-item-remove {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border: none;
    background: none;
    color: var(--text);
    font-size: 16px;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.cart-item-thumb {
    flex: 0 0 auto;
    width: 52px;
    height: 52px;
    border-radius: 10px;
    object-fit: cover;
    background: #eef0f5;
}

.cart-item-thumb-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
}

.cart-item-name {
    flex: 1;
    min-width: 0;
    font-weight: 700;
    font-size: 15px;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cart-item-price-col {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 2px;
}

.cart-item-qtyprice {
    font-size: 15px;
    font-weight: 700;
    white-space: nowrap;
}

.cart-item-qty {
    color: var(--primary-dark);
}

.cart-item-x {
    color: var(--muted);
    margin: 0 3px;
    font-weight: 600;
}

.cart-item-price {
    color: var(--navy);
}

/* "Авч явах" сонгосон үед, тухайн хоол needs_packaging бол нэмэлт мөр -
   захиалгын дүнд яагаад нэмэлт мөнгө орсныг харуулна. */
.cart-item-packaging-fee {
    font-size: 12px;
    font-weight: 700;
    color: var(--primary-dark);
    white-space: nowrap;
}

.my-order-card {
    padding: 12px 0;
    border-bottom: 1px solid var(--border);
}

.my-order-head {
    display: flex;
    justify-content: space-between;
    font-weight: 700;
    margin-bottom: 4px;
}

.my-order-status {
    font-size: 13px;
    font-weight: 600;
    color: var(--primary-dark);
}

.my-order-items {
    font-size: 13px;
    color: var(--muted);
    margin: 4px 0;
}

.my-order-type {
    font-size: 12px;
    color: var(--muted);
    margin-bottom: 2px;
}

.my-order-total {
    font-weight: 700;
    font-size: 14px;
}

.my-order-time {
    font-size: 12px;
    color: var(--muted);
}

/* Status colors: served orders turn green everywhere a status is shown; a
   cancelled order is shown in red so it's clearly distinguishable too. */
.status-text.status-served,
.my-order-status.status-served,
.active-order-status.status-served {
    color: #1a9c56;
}

.status-text.status-cancelled,
.my-order-status.status-cancelled,
.active-order-status.status-cancelled {
    color: #c0392b;
}

/* "Active order" status card shown inside the cart drawer ("Таны захиалга"),
   so the customer can see their current order's status without needing to
   reopen the small confirmation popup. */
.active-order-box {
    background: #fff7f2;
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 10px 12px;
    margin-bottom: 12px;
    font-size: 13px;
}

.active-order-title {
    font-weight: 700;
    margin-bottom: 2px;
}

.active-order-status {
    font-weight: 600;
    color: var(--primary-dark);
    font-size: 14px;
}

.active-order-type {
    font-size: 12px;
    color: var(--muted);
    margin-top: 2px;
}

/* "Энд идэх" / "Авч явах" segmented toggle shown in the cart drawer before
   placing an order - a simple 2-button full-width, equally-split pattern,
   since (unlike categories) exactly one of the two is always the answer. */
.order-type-select {
    display: flex;
    gap: 8px;
    margin-top: 10px;
}

.order-type-btn {
    flex: 1;
    border: 1px solid var(--border);
    background: #fff;
    padding: 10px 8px;
    border-radius: 10px;
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
    cursor: pointer;
}

.order-type-btn.active {
    background: var(--primary);
    border-color: var(--primary);
    color: #fff;
}

/* Захиалга баталгаажсны дараа (confirmed/preparing/ready) төрлийг түгжинэ -
   сонгогдсон товч өнгөө хадгална, гэхдээ дарж болохгүй гэдгийг тод харуулах
   үүднээс бүдэгрүүлж, курсорыг "not-allowed" болгосон. */
.order-type-btn.locked {
    cursor: not-allowed;
    opacity: 0.65;
}

.order-type-btn.locked.active {
    background: var(--muted);
    border-color: var(--muted);
}

.order-type-lock-note {
    font-size: 12px;
    color: var(--muted);
    margin-top: 6px;
}

#orderNote {
    width: 100%;
    margin-top: 10px;
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 10px;
    font-family: inherit;
    resize: none;
    height: 50px;
}

/* Only shown while "Авч явах" is selected (toggled via [hidden] in JS - no
   competing `display` rule here, so the plain [hidden] { display: none }
   user-agent rule applies without needing the [hidden] override this
   project has needed elsewhere for .drawer/.confirm-overlay/.active-order-banner). */
.packaging-note-wrap {
    margin-top: 10px;
}

#packagingNote {
    width: 100%;
    border: 1px solid var(--primary);
    border-radius: 10px;
    padding: 10px;
    font-family: inherit;
    resize: none;
    height: 50px;
    background: #fff7f2;
}

.drawer-footer {
    padding-top: 10px;
}

.cart-total-row {
    font-size: 15px;
    margin-bottom: 10px;
}

.btn-primary {
    width: 100%;
    background: var(--primary);
    color: #fff;
    border: none;
    padding: 14px;
    border-radius: 12px;
    font-size: 16px;
    font-weight: 700;
    cursor: pointer;
}

.btn-primary:disabled {
    background: #c9ccd4;
    color: #fff;
    cursor: not-allowed;
    box-shadow: none;
}

.btn-secondary {
    width: 100%;
    background: #fff;
    color: var(--text);
    border: 1px solid var(--border);
    padding: 12px;
    border-radius: 12px;
    font-size: 15px;
    cursor: pointer;
    margin-top: 14px;
}

.modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: var(--card);
    border-radius: var(--radius);
    padding: 24px;
    z-index: 31;
    width: 88%;
    max-width: 360px;
    text-align: center;
}

.status-text {
    font-size: 16px;
    font-weight: 600;
    color: var(--primary-dark);
}

.order-type-line {
    font-size: 13px;
    color: var(--muted);
    margin: -6px 0 10px;
}

.spinner {
    width: 32px;
    height: 32px;
    margin: 14px auto;
    border: 3px solid var(--border);
    border-top-color: var(--primary);
    border-radius: 50%;
    animation: spin 0.9s linear infinite;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

/* ---- Toast notifications (replaces native alert()) ---- */
.toast-container {
    position: fixed;
    top: max(16px, env(safe-area-inset-top));
    left: 16px;
    right: 16px;
    z-index: 50;
    display: flex;
    flex-direction: column;
    gap: 10px;
    align-items: center;
}

.toast {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    background: var(--card);
    border-radius: 10px;
    padding: 12px 12px 12px 14px;
    box-shadow: 0 10px 30px rgba(20, 22, 30, .18);
    border-left: 4px solid var(--muted);
    font-size: 14px;
    line-height: 1.4;
    width: 100%;
    max-width: 380px;
    opacity: 0;
    transform: translateY(-12px);
    transition: opacity .2s ease, transform .2s ease;
}

.toast-in {
    opacity: 1;
    transform: translateY(0);
}

.toast-out {
    opacity: 0;
    transform: translateY(-12px);
}

.toast-success {
    border-left-color: #1a9c56;
}

.toast-error {
    border-left-color: #c0392b;
}

.toast-info {
    border-left-color: var(--primary);
}

.toast-icon {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: 700;
    color: #fff;
    margin-top: 1px;
}

.toast-success .toast-icon {
    background: #1a9c56;
}

.toast-error .toast-icon {
    background: #c0392b;
}

.toast-info .toast-icon {
    background: var(--primary);
}

.toast-message {
    flex: 1;
    word-break: break-word;
    color: var(--text);
}

.toast-close {
    flex: 0 0 auto;
    border: none;
    background: none;
    cursor: pointer;
    color: var(--muted);
    font-size: 12px;
    padding: 2px;
    line-height: 1;
}

.toast-close:hover {
    color: var(--text);
}

/* ---- Camera QR-scan fallback screen (menu.php with no ?t= token) ---- */
.scan-app {
    min-height: 100vh;
    min-height: 100dvh;
    background: var(--navy);
    color: #fff;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: max(28px, env(safe-area-inset-top)) 20px 32px;
    box-sizing: border-box;
    text-align: center;
}

.scan-header h1 {
    font-size: 20px;
    line-height: 1.4;
    margin: 0 0 8px;
    font-weight: 700;
}

.scan-subtitle {
    margin: 0 0 24px;
    font-size: 14px;
    color: rgba(255, 255, 255, .72);
}

.scan-stage {
    position: relative;
    width: 100%;
    max-width: 340px;
    aspect-ratio: 1 / 1;
    border-radius: 20px;
    background: rgba(255, 255, 255, .06);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

.scan-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity .25s ease;
}

.scan-video.active {
    opacity: 1;
}

.scan-placeholder {
    font-size: 64px;
    opacity: .5;
}

.scan-frame {
    position: absolute;
    inset: 14%;
    pointer-events: none;
}

.scan-frame-corner {
    position: absolute;
    width: 34px;
    height: 34px;
    border: 4px solid #ffc72c;
}

.scan-frame-corner-tl {
    top: 0;
    left: 0;
    border-right: none;
    border-bottom: none;
    border-radius: 10px 0 0 0;
}

.scan-frame-corner-tr {
    top: 0;
    right: 0;
    border-left: none;
    border-bottom: none;
    border-radius: 0 10px 0 0;
}

.scan-frame-corner-bl {
    bottom: 0;
    left: 0;
    border-right: none;
    border-top: none;
    border-radius: 0 0 0 10px;
}

.scan-frame-corner-br {
    bottom: 0;
    right: 0;
    border-left: none;
    border-top: none;
    border-radius: 0 0 10px 0;
}

.scan-message {
    margin: 20px 0 0;
    min-height: 20px;
    font-size: 14px;
    color: rgba(255, 255, 255, .85);
}

.scan-message-error {
    color: #ff9b8a;
}

.scan-actions {
    margin-top: 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 100%;
    max-width: 300px;
}

.scan-main[hidden] {
    display: none;
}

.scan-main {
    display: contents;
}

/* Full-screen error state (permission denied / no camera / unsupported
   browser) - replaces scanMain entirely, on a light background per the
   reference app's "QR уншигч эхлүүлэхэд алдаа гарлаа" error screen. */
.scan-error-view[hidden] {
    display: none;
}

.scan-error-view {
    position: fixed;
    inset: 0;
    z-index: 10;
    background: #fff;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 28px;
    padding: 24px;
    text-align: center;
}

.scan-error-title {
    margin: 0;
    max-width: 300px;
    font-size: 21px;
    font-weight: 800;
    line-height: 1.4;
    color: var(--navy);
}

.scan-error-retry {
    border: none;
    cursor: pointer;
    background: var(--primary);
    color: #fff;
    font-size: 16px;
    font-weight: 700;
    padding: 16px 44px;
    border-radius: 30px;
    box-shadow: 0 8px 20px rgba(255, 107, 53, .35);
}
