/* The POS grid — the till face of the PRODUCTS tab.
 *
 * Everything is scoped under .pos. It sits inside six different dashboards,
 * each with its own page styles and its own opinions about buttons, so nothing
 * here may leak out and nothing out there may be relied on.
 *
 * The layout is one idea: the grid takes the room, the cart takes a column, and
 * on a phone the cart becomes a sheet that the running total calls up. Both
 * panes scroll inside themselves — the page behind must never scroll, or a rep
 * loses the total the moment they reach for the third item.
 */

.pos {
    --pos-line:  #e2e8f0;
    --pos-ink:   #0f172a;
    --pos-mute:  #64748b;
    --pos-brand: #7c3aed;
    --pos-good:  #16a34a;
    --pos-bg:    #ffffff;
    --pos-soft:  #f8fafc;

    display: grid;
    grid-template-columns: minmax(0, 1fr) 340px;
    gap: 14px;
    align-items: stretch;
    /* A starting height only — pos_grid.js measures where the panel actually
       begins and sets the real one, so the Send button always lands above the
       dashboard's floating nav rather than behind it. dvh so the iOS toolbar
       sliding away does not resize it under the rep's thumb mid-order. */
    height: min(72dvh, 760px);
    min-height: 380px;
    font-family: inherit;
    color: var(--pos-ink);
}

.pos *, .pos *::before, .pos *::after { box-sizing: border-box; }

/* ── the grid side ───────────────────────────────────────────────────────── */

.pos__main {
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    border: 1px solid var(--pos-line);
    border-radius: 16px;
    background: var(--pos-bg);
    overflow: hidden;
}

.pos__bar {
    flex: 0 0 auto;
    padding: 10px 12px 8px;
    border-bottom: 1px solid var(--pos-line);
    background: var(--pos-soft);
}

.pos__search {
    position: relative;
    display: block;
}

.pos__search .fas {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--pos-mute);
    font-size: 13px;
    pointer-events: none;
}

.pos__search input {
    width: 100%;
    height: 42px;
    padding: 0 12px 0 34px;
    /* 16px, so iOS does not zoom the page in when the rep taps it. */
    font-size: 16px;
    color: var(--pos-ink);
    border: 1px solid var(--pos-line);
    border-radius: 10px;
    background: #fff;
    outline: none;
    -webkit-appearance: none;
    appearance: none;
}

.pos__search input:focus {
    border-color: var(--pos-brand);
    box-shadow: 0 0 0 3px rgba(124, 58, 237, .12);
}

.pos__cats {
    display: flex;
    gap: 6px;
    margin-top: 8px;
    padding-bottom: 2px;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
.pos__cats::-webkit-scrollbar { display: none; }

.pos__cat {
    flex: 0 0 auto;
    padding: 7px 13px;
    font-size: 12.5px;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
    color: var(--pos-mute);
    background: #fff;
    border: 1px solid var(--pos-line);
    border-radius: 999px;
    cursor: pointer;
    transition: background .12s, color .12s, border-color .12s;
}

.pos__cat:hover { color: var(--pos-ink); }

.pos__cat.is-on {
    color: #fff;
    background: var(--pos-brand);
    border-color: var(--pos-brand);
}

/* The tab that holds the till stops reserving room for the floating bottom
   bar: the panel clears it itself, and allowing for it twice pushed the panel
   past the foot of the screen — which made the PAGE scroll behind the till and
   hid the search box under the header. pos_grid.js adds the class. */
.page.pos-host { padding-bottom: 0 !important; }

.pos__scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* NOT `contain`. This list is part of the page, not a sheet over it, and
       `contain` means a swipe that reaches the top of the list is SWALLOWED
       rather than passed on — so with a thumb anywhere on the tiles the page
       could not be moved at all, and the search box above stayed out of reach.
       The owner reported the tab as stuck and unresponsive. `auto` hands the
       gesture on at the ends, which is what every list outside a modal should
       do. A sheet over the page is different and keeps `contain` — see
       .pos__lines and .pos__askl. (2026-09-29.) */
    overscroll-behavior: auto;
    -webkit-overflow-scrolling: touch;
    padding: 4px 12px 14px;
}

.pos__group[hidden] { display: none; }

.pos__grouph {
    position: sticky;
    top: 0;
    /* 1, not 2: the dashboard's sidebar is z-index 2, and a sticky heading at
       the same level painted over its links whenever the menu was open. It
       only has to sit above the tiles, which carry no z-index at all. */
    z-index: 1;
    margin: 0;
    padding: 10px 2px 7px;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--pos-mute);
    background: linear-gradient(var(--pos-bg) 76%, rgba(255, 255, 255, 0));
}

.pos__items {
    display: grid;
    /* auto-fill, so the same rule gives three columns on a phone and eleven on
       a counter screen without a breakpoint for each. 96px rather than 112:
       a till is judged by how much of the menu is in front of you, and the
       tiles were bigger than they needed to be to stay readable. */
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 6px;
}

/* ── one tile ────────────────────────────────────────────────────────────── */

.pos__item {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 5px;
    text-align: left;
    color: inherit;
    background: #fff;
    border: 1px solid var(--pos-line);
    border-radius: 12px;
    cursor: pointer;
    /* No tap highlight and no double-tap zoom: this is a button that will be
       hit twice in a second, on purpose. */
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    user-select: none;
    transition: border-color .12s, box-shadow .12s, transform .06s;
}

.pos__item[hidden] { display: none; }

.pos__item:hover  { border-color: #cbd5e1; }
.pos__item:active { transform: scale(.97); }

.pos__item:focus-visible {
    outline: none;
    border-color: var(--pos-brand);
    box-shadow: 0 0 0 3px rgba(124, 58, 237, .18);
}

.pos__item.is-on {
    border-color: var(--pos-brand);
    background: #faf5ff;
}

.pos__shot {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    border-radius: 8px;
    overflow: hidden;
    background: var(--pos-soft);
}

.pos__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.pos__badge {
    position: absolute;
    top: 4px;
    right: 4px;
    min-width: 19px;
    height: 19px;
    padding: 0 4px;
    display: none;
    align-items: center;
    justify-content: center;
    font-size: 11.5px;
    font-weight: 800;
    line-height: 1;
    color: #fff;
    background: var(--pos-brand);
    border-radius: 999px;
    box-shadow: 0 1px 4px rgba(15, 23, 42, .3);
}

.pos__item.is-on .pos__badge { display: flex; }

.pos__name {
    font-size: 11px;
    font-weight: 600;
    line-height: 1.22;
    /* Two lines then an ellipsis: a ragged grid is slower to scan than a
       truncated name is to recognise. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.pos__meta {
    display: flex;
    /* When the price and the stock pill do not fit side by side on a narrow
       tile, the pill drops under the price — the price is never cut to "…". */
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 2px 4px;
    margin-top: auto;
}

.pos__price {
    font-size: 11.5px;
    font-weight: 800;
    color: var(--pos-good);
    white-space: nowrap;
}

.pos__left { display: none; }   /* replaced by the stock dot below */
/* How many are left: a coloured pill beside the price, in the old "N left" slot. Green while there are
   plenty, amber at or under the reorder level, red at none. */
.pos__stock {
    position: static;
    flex: 0 0 auto;
    margin-left: auto;
    /* About half what it was. It is a count, not a control: nobody taps it,
       and at the old size it read as the loudest thing on a tile whose job is
       to show the product. */
    min-width: 13px;
    height: 13px;
    padding: 0 3px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 8px;
    font-weight: 800;
    line-height: 1;
    color: #fff;
    border-radius: 999px;
    box-shadow: 0 1px 4px rgba(15, 23, 42, .28);
    pointer-events: none;
}
.pos__stock--ok  { background: #16a34a; }
.pos__stock--low { background: #f59e0b; color: #1f2937; }
.pos__stock--out { background: #dc2626; }
/* a variant's own picture beside its name in the chooser */
.pos__fimg {
    flex: 0 0 44px;
    width: 44px;
    height: 44px;
    border-radius: 9px;
    object-fit: cover;
    background: var(--pos-soft);
}
.pos__fimg--none { display: inline-block; }
/* the typed quantity on a line */
.pos__qin {
    width: 46px;
    height: 28px;
    padding: 0 4px;
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    background: #fff;
    -moz-appearance: textfield;
}
.pos__qin::-webkit-outer-spin-button, .pos__qin::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pos__qin:focus { outline: none; border-color: var(--pos-brand); box-shadow: 0 0 0 3px rgba(67, 0, 120, .12); }

/* The two answers a tap can give. */
@keyframes posHit { 0% { transform: scale(1); } 45% { transform: scale(.93); } 100% { transform: scale(1); } }
@keyframes posMax { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }

.pos__item.is-hit { animation: posHit .3s ease; }
.pos__item.is-max { animation: posMax .3s ease; border-color: #f87171; }

.pos__none {
    padding: 34px 12px;
    text-align: center;
    font-size: 13px;
    color: var(--pos-mute);
}

/* ── the cart side ───────────────────────────────────────────────────────── */

.pos__cart {
    display: flex;
    flex-direction: column;
    min-height: 0;
    border: 1px solid var(--pos-line);
    border-radius: 16px;
    background: var(--pos-bg);
    overflow: hidden;
}

.pos__carth {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 11px 13px;
    border-bottom: 1px solid var(--pos-line);
    background: var(--pos-soft);
}

.pos__carth-t {
    font-size: 12px;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--pos-mute);
}

.pos__restart {
    padding: 6px 11px;
    font-size: 11.5px;
    font-weight: 700;
    color: #b91c1c;
    background: #fef2f2;
    border: 1px solid #fecaca;
    border-radius: 8px;
    cursor: pointer;
}
.pos__restart:hover { background: #fee2e2; }

.pos__who {
    flex: 0 0 auto;
    display: block;
    padding: 10px 13px 0;
}

.pos__who > span {
    display: block;
    margin-bottom: 5px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--pos-mute);
}

.pos__who input {
    width: 100%;
    height: 40px;
    padding: 0 11px;
    font-size: 16px;          /* again: no iOS zoom */
    font-weight: 600;
    color: var(--pos-ink);
    border: 1px solid var(--pos-line);
    border-radius: 10px;
    background: #fff;
    outline: none;
    -webkit-appearance: none;
    appearance: none;
}

.pos__who input:focus {
    border-color: var(--pos-brand);
    box-shadow: 0 0 0 3px rgba(124, 58, 237, .12);
}

.pos__who input.is-bad {
    border-color: #ef4444;
    box-shadow: 0 0 0 3px rgba(239, 68, 68, .15);
}

.pos__lines {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding: 10px 13px;
}

.pos__empty {
    margin: 26px 0;
    text-align: center;
    font-size: 12.5px;
    color: var(--pos-mute);
}

.pos__line {
    padding: 9px 0;
    border-bottom: 1px dashed var(--pos-line);
    /* The thumbnail sits beside the two text rows rather than above them, so
       the line keeps the height it always had. */
    display: flex;
    align-items: flex-start;
    gap: 8px;
}
.pos__line:last-child { border-bottom: 0; }

/* The body takes the rest of the row. min-width:0 is what lets a long dish
   name wrap instead of pushing the price off the edge. */
.pos__lbody { flex: 1 1 auto; min-width: 0; }

/* Deliberately small, and capped twice: a fixed box so it never reflows the
   list, and max-height so it can never be taller than the name-and-price block
   it sits beside even if that block shrinks. */
.pos__lthumb {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    max-height: 32px;
    border-radius: 7px;
    object-fit: cover;
    background: var(--pos-line);
    margin-top: 1px;
}

.pos__ltop {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
}

.pos__lname {
    font-size: 12.5px;
    font-weight: 700;
    line-height: 1.3;
    min-width: 0;
    overflow-wrap: anywhere;
}

.pos__lsum {
    font-size: 12.5px;
    font-weight: 800;
    color: var(--pos-good);
    white-space: nowrap;
}

.pos__lbot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-top: 6px;
}

.pos__lunit {
    font-size: 11px;
    color: var(--pos-mute);
}

.pos__step {
    display: inline-flex;
    align-items: center;
    gap: 2px;
}

.pos__step button {
    width: 27px;
    height: 27px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 700;
    line-height: 1;
    color: var(--pos-ink);
    background: var(--pos-soft);
    border: 1px solid var(--pos-line);
    border-radius: 7px;
    cursor: pointer;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}
.pos__step button:hover { background: #eef2f7; }

.pos__step .pos__drop {
    margin-left: 4px;
    color: #b91c1c;
    background: #fef2f2;
    border-color: #fecaca;
}

.pos__q {
    min-width: 26px;
    text-align: center;
    font-size: 13px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}

.pos__foot {
    flex: 0 0 auto;
    padding: 11px 13px;
    padding-bottom: max(11px, env(safe-area-inset-bottom));
    border-top: 1px solid var(--pos-line);
    background: var(--pos-soft);
}

.pos__total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
}

.pos__total > span {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--pos-mute);
}

.pos__total > b {
    font-size: 21px;
    font-weight: 800;
    color: var(--pos-ink);
    font-variant-numeric: tabular-nums;
}

.pos__count {
    margin-top: 2px;
    font-size: 11.5px;
    color: var(--pos-mute);
}

.pos__send {
    width: 100%;
    height: 46px;
    margin-top: 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    font-size: 14.5px;
    font-weight: 800;
    color: #fff;
    background: var(--pos-brand);
    border: 0;
    border-radius: 11px;
    cursor: pointer;
    touch-action: manipulation;
    transition: background .12s, opacity .12s;
}

.pos__send:hover:not(:disabled) { background: #6d28d9; }

.pos__send:disabled {
    background: #cbd5e1;
    cursor: not-allowed;
}

/* ── the phone sheet ─────────────────────────────────────────────────────── */

.pos__peek { display: none; }

@media (max-width: 900px) {
    .pos {
        grid-template-columns: minmax(0, 1fr);
    }

    /* The cart stops being a column and becomes a sheet, called up by the
       running total. On a phone the grid needs the whole width; a 340px
       sidebar would leave two cramped columns of tiles. */
    .pos__cart {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1080;        /* above the dashboard's own bottom bar */
        max-height: 82dvh;
        border-radius: 18px 18px 0 0;
        border-bottom: 0;
        box-shadow: 0 -10px 34px rgba(15, 23, 42, .22);
        transform: translateY(101%);
        transition: transform .22s ease;
        visibility: hidden;
    }

    .pos.cart-open .pos__cart {
        transform: translateY(0);
        visibility: visible;
    }

    /* The dim covers the dashboard's bottom bar too (z-index 1000): a
       navigation button floating over an open cart is a mis-tap waiting to
       happen. */
    .pos.cart-open::before {
        content: '';
        position: fixed;
        inset: 0;
        z-index: 1079;
        background: rgba(15, 23, 42, .42);
    }

    /* While the cart is open the running total behind it is noise. */
    .pos.cart-open .pos__peek { display: none; }

    .pos__peek {
        position: fixed;
        left: 12px;
        right: 12px;
        /* Clear of the dashboard's own bottom bar: that is fixed at bottom:20px
           and 68px tall, so anything under 88px would be sitting on the rep's
           navigation. */
        bottom: calc(96px + env(safe-area-inset-bottom));
        z-index: 1070;
        display: flex;
        align-items: center;
        gap: 10px;
        height: 52px;
        padding: 0 15px;
        font-size: 14px;
        font-weight: 800;
        color: #fff;
        background: var(--pos-brand);
        border: 0;
        border-radius: 13px;
        box-shadow: 0 6px 22px rgba(124, 58, 237, .4);
        cursor: pointer;
        touch-action: manipulation;
    }

    .pos__peek[hidden] { display: none; }

    .pos__peek-n {
        min-width: 25px;
        height: 25px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-size: 12.5px;
        background: rgba(255, 255, 255, .25);
        border-radius: 999px;
    }

    .pos__peek-t { margin-left: auto; font-variant-numeric: tabular-nums; }

    /* 76px gives FOUR across the 324px a phone actually leaves for the grid
       (390 viewport, less the page's own padding and the scroll gutter). The
       tile still comes out ~78px wide — well above the 44px a thumb needs —
       and a waiter sees half again as much of the menu without scrolling. */
    .pos__items { grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); }
    .pos__name  { font-size: 10px; line-height: 1.2; }
    .pos__item  { padding: 4px; gap: 3px; }
    .pos__price { font-size: 10.5px; }
    /* Halved here too, or the phone size — which is where every rep
       actually works — keeps the old pill and the change is invisible. */
    .pos__stock { min-width: 12px; height: 12px; font-size: 7.5px; padding: 0 3px; }
    .pos__left  { font-size: 8.5px; }
}

/* Below this a fourth column would leave under 70px per tile, which is where
   a two-line dish name starts breaking badly. Three, and keep them legible. */
@media (max-width: 340px) {
    .pos__items { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* A rep who prefers the keyboard, and anyone who has asked for less movement. */
@media (prefers-reduced-motion: reduce) {
    .pos *, .pos *::before, .pos *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
    }
}

/* ── the flip control ────────────────────────────────────────────────────── */

.posflip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px;
    background: #f1f5f9;
    border: 1px solid #e2e8f0;
    border-radius: 999px;
}

.posflip button {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    font-size: 12.5px;
    font-weight: 700;
    line-height: 1;
    color: #64748b;
    background: transparent;
    border: 0;
    border-radius: 999px;
    cursor: pointer;
    touch-action: manipulation;
    transition: background .14s, color .14s, box-shadow .14s;
}

.posflip button.is-on {
    color: #0f172a;
    background: #fff;
    box-shadow: 0 1px 3px rgba(15, 23, 42, .14);
}

@media (max-width: 420px) {
    .posflip button span { display: none; }
    .posflip button { padding: 8px 13px; }
}

/* ── which one? ──────────────────────────────────────────────────────────────
 *
 * A dish sold in several forms is one tile; this is the tap's answer. It stays
 * open while it is being used, because a table that wants two mediums and a
 * large should be three taps in one place.
 */

.pos__forms {
    position: absolute;
    left: 4px;
    bottom: 4px;
    padding: 2px 6px;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: .02em;
    color: #fff;
    background: rgba(15, 23, 42, .72);
    border-radius: 999px;
    pointer-events: none;
}

.pos__ask {
    position: fixed;
    inset: 0;
    z-index: 1120;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: rgba(15, 23, 42, .48);
}

.pos__ask[hidden] { display: none; }

.pos__askbox {
    width: min(420px, 100%);
    max-height: min(78dvh, 620px);
    display: flex;
    flex-direction: column;
    background: var(--pos-bg, #fff);
    border-radius: 16px;
    box-shadow: 0 18px 50px rgba(15, 23, 42, .34);
    overflow: hidden;
}

.pos__askh {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 13px 15px;
    font-size: 14.5px;
    font-weight: 800;
    color: #0f172a;
    border-bottom: 1px solid #e2e8f0;
    background: #f8fafc;
}

.pos__askx {
    width: 30px;
    height: 30px;
    flex: 0 0 auto;
    font-size: 19px;
    line-height: 1;
    color: #64748b;
    background: transparent;
    border: 0;
    border-radius: 8px;
    cursor: pointer;
}
.pos__askx:hover { background: #e2e8f0; color: #0f172a; }

.pos__askl {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.pos__form {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    /* 52px: a thumb, not a cursor. */
    min-height: 52px;
    padding: 10px 13px;
    text-align: left;
    color: #0f172a;
    background: #fff;
    border: 1px solid #e2e8f0;
    border-radius: 11px;
    cursor: pointer;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    transition: border-color .12s, background .12s, transform .06s;
}

.pos__form:hover  { border-color: #cbd5e1; }
.pos__form:active { transform: scale(.985); }

.pos__form.is-on {
    border-color: var(--pos-brand, #7c3aed);
    background: #faf5ff;
}

.pos__form[data-full] {
    opacity: .55;
    cursor: not-allowed;
}

.pos__fname {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 13.5px;
    font-weight: 700;
    overflow-wrap: anywhere;
}

.pos__fprice {
    flex: 0 0 auto;
    font-size: 13px;
    font-weight: 800;
    color: var(--pos-good, #16a34a);
    white-space: nowrap;
}

.pos__fq {
    flex: 0 0 auto;
    min-width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 12.5px;
    font-weight: 800;
    color: #fff;
    background: var(--pos-brand, #7c3aed);
    border-radius: 999px;
}
.pos__fq:empty { background: transparent; }

.pos__form.is-hit { animation: posHit .3s ease; }

.pos__askdone {
    flex: 0 0 auto;
    margin: 0;
    height: 46px;
    font-size: 14.5px;
    font-weight: 800;
    color: #fff;
    background: var(--pos-brand, #7c3aed);
    border: 0;
    border-radius: 0;
    cursor: pointer;
    touch-action: manipulation;
}
.pos__askdone:hover { background: #6d28d9; }

@media (max-width: 900px) {
    /* ── centred on a phone too, 2026-09-22 ──────────────────────────────
     *
     * It used to come up from the bottom "where the thumb already is". That
     * put it exactly where every floating control also lives — the Preview
     * bar, the cart button — and the owner's screenshot shows the bar sitting
     * on the second of two options with the first one half covered.
     *
     * Owner: "the variants options should be styled to be like a beautiful
     * dynamic popup modal centralized on the screen and it should be
     * responsive not to ever conflict with the preview or cart button."
     *
     * Centred, with a margin on every side, so nothing anchored to an edge can
     * ever reach it. The list inside scrolls; the box never grows past the
     * screen. */
    .pos__ask { align-items: center; padding: 14px; }
    .pos__askbox {
        width: min(460px, calc(100vw - 28px));
        max-height: min(78dvh, 620px);
        border-radius: 18px;
    }
    .pos__askdone { padding-bottom: 0; height: auto; min-height: 48px; }
}

/* ── the cart's label ────────────────────────────────────────────────────────
 *
 * Two parts that read as one field: who and when, which nobody may change
 * because it is what every list, receipt and day-close groups the cart by, and
 * the number or name, which they may.
 */
.pos__label {
    display: flex;
    align-items: stretch;
    border: 1px solid var(--pos-line);
    border-radius: 10px;
    overflow: hidden;
    background: #fff;
}

.pos__label:focus-within {
    border-color: var(--pos-brand);
    box-shadow: 0 0 0 3px rgba(124, 58, 237, .12);
}

.pos__labelfix {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    padding: 0 10px;
    font-size: 13px;
    font-weight: 700;
    white-space: nowrap;
    color: var(--pos-mute);
    background: var(--pos-soft);
    border-right: 1px solid var(--pos-line);
    user-select: none;
}

.pos__labelval {
    flex: 1 1 auto;
    min-width: 0;
    height: 40px;
    padding: 0 11px;
    font-size: 16px;          /* 16px, or iOS zooms the page when it is tapped */
    font-weight: 700;
    color: var(--pos-ink);
    border: 0;
    background: transparent;
    outline: none;
    -webkit-appearance: none;
    appearance: none;
}

.pos__labelval.is-bad {
    background: #fef2f2;
    box-shadow: inset 0 0 0 2px #ef4444;
}

/* On a narrow phone the prefix is the longer half; let it shrink before the
   number does, and never let the pair force the sheet sideways. */
@media (max-width: 380px) {
    .pos__labelfix {
        font-size: 12px;
        padding: 0 8px;
        overflow: hidden;
        text-overflow: ellipsis;
        display: block;
        line-height: 40px;
        max-width: 58%;
    }
}

/* ── Details, at the foot of every tile ──────────────────────────────────────
 *
 * Tapping a tile ADDS the product to the order, which left a rep no way simply
 * to look at one — no pictures, no brand, no description. This opens the same
 * product card the shop's own grid opens, and it is why the tile became a div
 * with role=button: a button cannot contain a button. */
.pos__detail {
    display: block;
    width: 100%;
    margin-top: 5px;
    padding: 3px 0;
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    background: #f8fafc;
    color: #475569;
    font: inherit;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .2px;
    line-height: 1;
    cursor: pointer;
    /* The house floor is for the things a finger aims at; this is a secondary
       control inside one that is already tappable, so it stays compact.
    
       `min-height: 0` alone was not enough and the button still came out 40px
       tall: style.css sets `min-height: var(--ui-tap)` through a selector
       carrying a dozen :not() clauses, and each one counts, so no reasonable
       selector here outranks it. The house's own way out of that rule is to be
       named in the list, which .pos__detail now is — the same exemption the
       quantity steppers and the small × buttons already use. */
    min-height: 0;
    height: 22px;
}
.pos__detail:hover  { background: #eef2ff; border-color: #c7d2fe; color: #4338ca; }
.pos__detail:active { transform: scale(.97); }

/* ── sold out ─────────────────────────────────────────────────────────────
   Listed like everything else, never added (owner, 2026-09-15). Five taps on
   one tell the store it is needed — see soldOutTap() in pos_grid.js. */
.pos__item.is-out { cursor: not-allowed; background: #fbfbfc; }
.pos__item.is-out .pos__img { filter: grayscale(.8); opacity: .7; }
.pos__item.is-out .pos__name { color: #64748b; }
.pos__item.is-out .pos__price { color: #94a3b8; }
.pos__out {
    position: absolute;
    left: 6px;
    right: 6px;
    bottom: 6px;
    padding: 3px 0;
    text-align: center;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: #fff;
    background: rgba(220, 38, 38, .88);
    border-radius: 6px;
    pointer-events: none;
}
.pos__form.is-out { opacity: .62; cursor: not-allowed; background: #f8fafc; }
.pos__form.is-out .pos__fq { width: auto; min-width: 0; padding: 0 2px; background: transparent; color: #dc2626; font-size: 10px; font-weight: 800;
    text-transform: uppercase; letter-spacing: .05em; white-space: nowrap; }
@media (max-width: 480px) {
    .pos__out { left: 4px; right: 4px; bottom: 4px; font-size: 8.5px; padding: 2px 0; }
}


/* ─── the variant chooser, 2026-09-22 ────────────────────────────────────────
 *
 * Owner: "Selecting products with variants is not well styled and organized as
 * the preview button seats ontop the variant options hence some variant options
 * are covered… should be styled to be like a beautiful dynamic popup modal
 * centralized on the screen and it should be responsive not to ever conflict
 * with the preview or cart button."
 *
 * The box was already centred; what put the Preview bar over it was a plain
 * z-index race — the bar sits at 1500 on the shop and the chooser at 1200. It
 * is raised above everything it can meet, AND the bar is hidden outright while
 * a choice is being made: two rules, because a z-index alone is a race the next
 * floating control can re-enter.
 *
 * A row is no longer one line. It is a picture, a name, and a right-hand column
 * holding the price with its own quantity field beneath — which is why the row
 * is a <div role="button"> now and not a <button>: an <input> inside a <button>
 * is invalid markup that swallows its own taps.
 */
.pos__ask { z-index: 2400; }
.pos__askbox {
    width: min(460px, calc(100vw - 28px));
    max-height: min(84dvh, 680px);
    animation: posAskIn .18s cubic-bezier(.2, .9, .3, 1);
}
@keyframes posAskIn {
    from { opacity: 0; transform: translateY(10px) scale(.97); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .pos__askbox { animation: none; }
}

/* Nothing floats over an open chooser. */
.pos.ask-open .pos__peek,
.pos.ask-open .pos__cart { display: none !important; }

/* ── a row ─────────────────────────────────────────────────────────────── */
.pos__form {
    align-items: stretch;
    gap: 11px;
    padding: 10px 12px;
}
.pos__fmain {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 3px;
}
.pos__fon {
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .02em;
    color: var(--pos-brand, #7c3aed);
}
.pos__fside {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: center;
    gap: 6px;
}

/* ── the quantity field beneath the price ──────────────────────────────── */
.pos__fqty {
    display: inline-flex;
    align-items: stretch;
    border: 1px solid #dbe3ee;
    border-radius: 9px;
    overflow: hidden;
    background: #fff;
}
.pos__fqbtn {
    width: 30px;
    min-height: 30px;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 15px;
    font-weight: 800;
    line-height: 1;
    color: #334155;
    background: #f1f5f9;
    border: 0;
    cursor: pointer;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}
.pos__fqbtn:hover  { background: #e2e8f0; }
.pos__fqbtn:active { background: #cbd5e1; }
.pos__fqin {
    width: 42px;
    flex: 0 0 auto;
    text-align: center;
    font: inherit;
    font-size: 13px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: #0f172a;
    background: #fff;
    border: 0;
    border-left: 1px solid #eef2f7;
    border-right: 1px solid #eef2f7;
    /* The spinners are a mis-tap on a phone and a second control nobody needs
       beside the two buttons that already do the job. */
    -moz-appearance: textfield;
    appearance: textfield;
}
.pos__fqin::-webkit-outer-spin-button,
.pos__fqin::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pos__fqin:focus {
    outline: 2px solid var(--pos-brand, #7c3aed);
    outline-offset: -2px;
}

.pos__form[data-full] .pos__fqty { display: none; }

/* ── narrow phones: the row stacks rather than squeezing the name ──────── */
@media (max-width: 400px) {
    .pos__askbox { width: calc(100vw - 20px); }
    .pos__fimg   { width: 40px; height: 40px; }
    .pos__fname  { font-size: 12.5px; }
    .pos__fqin   { width: 38px; }
    .pos__fqbtn  { width: 28px; }
}
/* Very short screens — a landscape phone — keep the list scrollable rather
   than letting the box run off the top and bottom. */
@media (max-height: 480px) {
    .pos__askbox { max-height: calc(100dvh - 24px); }
}

/* The dismiss, not the commit: a choice adds itself now. */
.pos__askdone--quiet {
    background: #eef2f7;
    color: #334155;
    font-weight: 800;
}
.pos__askdone--quiet:hover { background: #e2e8f0; }
