@import '_content/Blazor.Interactive.FreeCalendar/Blazor.Interactive.FreeCalendar.efkoh1n9rq.bundle.scp.css';
@import '_content/Blazor.Interactive.FreePanel/Blazor.Interactive.FreePanel.63e5cnk9vm.bundle.scp.css';
@import '_content/Blazor.Interactive.FreeTable.Panel/Blazor.Interactive.FreeTable.Panel.kqipw4zy6o.bundle.scp.css';
@import '_content/Blazor.Interactive.FreeTable/Blazor.Interactive.FreeTable.dnazt5nael.bundle.scp.css';
@import '_content/YTF.POS.Shared.UI/YTF.POS.Shared.UI.gjsyu7vb1d.bundle.scp.css';

/* /Components/Kanban/KanbanCard.razor.rz.scp.css */
/* One card on the kitchen board, wherever it is drawn: in a column of the board, or as the sample
   on the recipe designer. Moved here from the board page with the markup, so the sample is styled
   by the same rules as the real thing - a copy of them would be a preview of something else the
   first time either was touched.

   What the card takes from AROUND it is custom properties, which inherit through the component
   boundary: --kb-card-max from the board's columns, --kb-dept from the card's own station. Both
   have a fallback, so a card drawn anywhere else still looks like a card. The classes the board's
   scripts add - warn, critical, folded, over, done - land on elements this component rendered,
   so the rules for them are here too. */

/* The comfort ceiling. Applied to the card and not to the track, so a column that is not an exact
   multiple of a card still fills edge to edge instead of leaving a track-sized hole. */
.kb-card[b-3qv9288lmc] { max-width: var(--kb-card-max, 31rem); }

/* ---- card ---- */

/* The transition lives HERE, on the card itself, not on the leaving modifier. A rule that both
   turns a transition on and changes the property it animates is asking the browser to do two
   things in one style recalculation, and it is the sort of thing that works until it doesn't.
   The card can always animate; the modifier only says where to. */
.kb-card[b-3qv9288lmc] {
    background: #fff;
    border: 1px solid var(--pos-gray-200);
    border-left: 4px solid var(--kb-dept, var(--pos-gray-300));
    border-radius: .35rem;
    padding: .6rem .7rem;
    display: flex;
    flex-direction: column;
    gap: .45rem;
    transition: opacity .3s ease, transform .3s ease;
    animation: kb-arrive-b-3qv9288lmc .28s ease-out;
}

/* Arriving. A card is a new DOM element only when it genuinely moved - the keys hold the rest
   still through every reload - so this plays exactly when new work lands in a column and never
   on the constant re-renders behind it. On a screen nobody is touching, that movement is the
   only thing that says "look, this changed". */
@keyframes kb-arrive-b-3qv9288lmc {
    from { opacity: 0; transform: translateY(-.35rem); }
    to { opacity: 1; transform: none; }
}

/* One row: everything identifying the bill on the left, the clock pinned right. */
.kb-card-head[b-3qv9288lmc] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
}

/* The identifying half. It WRAPS - a long table name plus a combined-bill label will not always
   fit a narrow column, and when it does not the chips drop under the heading, which is where they
   used to live anyway. Baselines are shared so the small type sits on the heading's line rather
   than floating in the middle of it. */
.kb-card-what[b-3qv9288lmc] {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .1rem .4rem;
    font-size: .78rem;
    color: var(--pos-gray-500);
}

/* Never shrinks and never wraps. It is the number the whole board is being read for, and a clock
   that reflowed to "25:00:" as a card got busy would be worse than no clock. */
.kb-elapsed[b-3qv9288lmc] {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--pos-gray-600);
    line-height: 1;
    white-space: nowrap;
}

.kb-label[b-3qv9288lmc] {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--pos-gray-600);
}

/* ---- lines ---- */

.kb-lines[b-3qv9288lmc] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .2rem;
}

/* The <li> carries the STATE and holds the row's two halves side by side: the label, which is the
   hit area for the tick, and the send-back button, which must sit OUTSIDE that label or pressing
   it would tick the row as well. */
.kb-line[b-3qv9288lmc] {
    display: flex;
    align-items: flex-start;
    gap: .3rem;
    font-size: .95rem;
    line-height: 1.3;
}

.kb-line-hit[b-3qv9288lmc] {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: flex-start;
    gap: .4rem;
    margin: 0;
}

/* On the columns that tick, the whole row is the target. A cook with a wet hand or a runner with
   a tray in one arm aims at the item they can read, not at the box beside it. Only these columns
   pay for the extra height: Ordering and Received are read rather than tapped, and this padding
   on all 26 rows of a big bill would make a card nobody can see the end of. */
.kb-line--tap .kb-line-hit[b-3qv9288lmc] {
    cursor: pointer;
    user-select: none;
    padding: .25rem .3rem;
    margin: 0 -.3rem;
    border-radius: .3rem;
}

.kb-line--tap .kb-line-hit:hover[b-3qv9288lmc] { background: var(--pos-gray-100); }
.kb-line--tap .kb-line-hit:active[b-3qv9288lmc] { background: var(--pos-gray-200); }

/* focus-within, because the thing that takes focus is the input inside the label. */
.kb-line--tap .kb-line-hit:focus-within[b-3qv9288lmc] { outline: 2px solid var(--pos-teal); outline-offset: -1px; }

/* At a station, a cooked item is dealt with: struck through and faded back. */
.kb-line--done .kb-name[b-3qv9288lmc] { color: var(--pos-gray-400); text-decoration: line-through; }

/* At the pass the reading inverts. A cooked item is the one to PICK UP, so it stays plain and
   full strength; the items still in the pan are the ones that recede. Never struck through
   here - that would say "handled" about the drinks somebody still has to carry. */
.kb-line--ready .kb-name[b-3qv9288lmc] { color: var(--pos-gray-900); font-weight: 600; }
.kb-line--ready .kb-qty[b-3qv9288lmc] { color: var(--pos-teal); }

.kb-line--pending[b-3qv9288lmc] { opacity: .45; }
.kb-line--pending .kb-qty[b-3qv9288lmc] { color: var(--pos-gray-500); }

/* PART of the line is made, at a station that makes them one at a time: it sits with what is still
   cooking but is not faded with it, because some of it is ready to carry. */
.kb-line--part .kb-name[b-3qv9288lmc] { color: var(--pos-gray-900); font-weight: 600; }

/* "1 of 3 ready". Filled teal, the pass's own "this can go" colour - never gold, which is the remake,
   and never red, which is late. Filled so it cannot be read as more of the dish's name, which the
   shop types in two languages already, and kept whole so it never breaks across a line. */
.kb-part[b-3qv9288lmc] {
    display: inline-block;
    margin: .1rem 0 0 .35rem;
    padding: 0 .35rem;
    border-radius: .2rem;
    background: var(--pos-teal);
    color: #fff;
    font-size: .78rem;
    font-weight: 700;
    line-height: 1.35;
    white-space: nowrap;
    vertical-align: .05em;
}

.kb-qty[b-3qv9288lmc] {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    color: var(--pos-teal);
    min-width: 1.1rem;
}

.kb-name[b-3qv9288lmc] {
    flex: 1 1 auto;
    min-width: 0;
    color: var(--pos-gray-900);
    overflow-wrap: anywhere;
}

/* The dish, for a kitchen that does not all read the same language. Big enough to tell two
   stuffed items apart across a bench, small enough that a twelve-line ticket still fits on the
   card - the photo is a confirmation of the name beside it, not a replacement for it.

   The box is drawn whether or not there is a picture in it, so the names stay in one column;
   empty, it is a faint outline that reads as "no photo" rather than as a broken image. */
.kb-thumb[b-3qv9288lmc] {
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: .25rem;
    background: var(--pos-gray-100);
    box-shadow: inset 0 0 0 1px var(--pos-gray-200);
    overflow: hidden;
}

.kb-thumb img[b-3qv9288lmc] {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.kb-mods[b-3qv9288lmc],
.kb-set[b-3qv9288lmc],
.kb-note[b-3qv9288lmc] {
    display: block;
    font-size: .78rem;
    line-height: 1.25;
}

.kb-mods[b-3qv9288lmc] { color: var(--pos-gray-500); }
/* Which set a piece belongs to: teal, so it reads as a heading over the line rather than as one
   more modifier, and the pass can match it to the set's own card at a glance. */
.kb-set[b-3qv9288lmc] { color: var(--pos-teal); font-weight: 600; }
.kb-note[b-3qv9288lmc] { color: var(--pos-gold-dark); font-weight: 600; }

/* A remake. Filled gold rather than gold text, because it has to beat the note directly above it
   in the same colour - a note changes what the cook does, this changes whether they cook it at
   all. Not red: red is the critical state, and one red ticket among forty must go on meaning
   "this is late" and nothing else. */
.kb-remake[b-3qv9288lmc] {
    display: block;
    margin-top: .1rem;
    font-size: .78rem;
    line-height: 1.25;
}

.kb-remake-tag[b-3qv9288lmc] {
    display: inline-block;
    padding: 0 .3rem;
    border-radius: .2rem;
    background: var(--pos-gold);
    color: var(--pos-gray-900);
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
}

/* The chosen problem: the half a cook acts on, so it keeps the weight. */
.kb-remake-why[b-3qv9288lmc] {
    margin-left: .3rem;
    color: var(--pos-gold-dark);
    font-weight: 600;
}

/* The note beside it: detail, so it recedes rather than competing with the reason. */
.kb-remake-note[b-3qv9288lmc] {
    margin-left: .3rem;
    color: var(--pos-gray-600);
}

/* A line the till took off the bill after the ticket was printed: the name struck through and
   the whole row faded, with a REMOVED badge and the reason under it, so the card still matches
   the slip in the cook's hand without asking anything of them. Gray, deliberately: gold is a
   remake and red is late, and this is neither. Never a tap target, so none of the --tap hover. */
.kb-line--void[b-3qv9288lmc] {
    opacity: .6;
}

.kb-void-name[b-3qv9288lmc] {
    text-decoration: line-through;
    color: var(--pos-gray-500);
}

.kb-void[b-3qv9288lmc] {
    display: block;
    margin-top: .1rem;
    font-size: .78rem;
    line-height: 1.25;
}

.kb-void-tag[b-3qv9288lmc] {
    display: inline-block;
    padding: 0 .3rem;
    border-radius: .2rem;
    background: var(--pos-gray-700);
    color: #fff;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
}

.kb-void-why[b-3qv9288lmc] {
    margin-left: .3rem;
    color: var(--pos-gray-600);
}

/* The way back to the kitchen. Held at the far end of the row, as far from the tick as the row
   allows, because the two must never be confused: one says the customer has it, the other says
   they refused it. */
.kb-return[b-3qv9288lmc] {
    flex: 0 0 auto;
    border: 1px solid var(--pos-gray-300);
    border-radius: .3rem;
    background: #fff;
    padding: .15rem .4rem;
    line-height: 1.2;
    color: var(--pos-gray-500);
    cursor: pointer;
}

.kb-return:hover[b-3qv9288lmc] {
    border-color: var(--pos-gold-dark);
    color: var(--pos-gold-dark);
}

.kb-return:focus-visible[b-3qv9288lmc] { outline: 2px solid var(--pos-teal); outline-offset: 2px; }

/* The print button: the send-back button's shape, in teal rather than gold, because printing is
   ordinary work and a return is an event. Marked (filled) only where it is the next thing to do -
   a Manual station's drink whose stickers have not been printed. */
.kb-print[b-3qv9288lmc] {
    flex: 0 0 auto;
    border: 1px solid var(--pos-gray-300);
    border-radius: .3rem;
    background: #fff;
    padding: .15rem .4rem;
    line-height: 1.2;
    color: var(--pos-gray-500);
    cursor: pointer;
}

.kb-print:hover:not(:disabled)[b-3qv9288lmc] {
    border-color: var(--pos-teal);
    color: var(--pos-teal);
}

.kb-print--due[b-3qv9288lmc] {
    border-color: var(--pos-teal);
    background: var(--pos-teal);
    color: #fff;
}

.kb-print--due:hover:not(:disabled)[b-3qv9288lmc] { color: #fff; }
.kb-print:disabled[b-3qv9288lmc] { opacity: .5; cursor: default; }
.kb-print:focus-visible[b-3qv9288lmc] { outline: 2px solid var(--pos-teal); outline-offset: 2px; }

/* A real checkbox, drawn rather than left to the browser so it matches the board at three metres.
   The tick is a data URI for the same reason every other icon in the app is drawn: a control's
   own artwork must not wait on a font from a CDN. */
.kb-check[b-3qv9288lmc] {
    appearance: none;
    -webkit-appearance: none;
    flex: 0 0 auto;
    width: 1.15rem;
    height: 1.15rem;
    margin: .05rem 0 0;
    border: 2px solid var(--pos-gray-400);
    border-radius: .25rem;
    background: #fff;
    cursor: pointer;
}

.kb-check:checked[b-3qv9288lmc] {
    border-color: var(--pos-teal);
    background: var(--pos-teal) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='white'%3E%3Cpath d='M13.5 3.5 6 11 2.5 7.5 1 9l5 5 9-9z'/%3E%3C/svg%3E") center / .8rem no-repeat;
}

/* The row already draws the focus ring, so the box does not draw a second one inside it. */
.kb-check:focus-visible[b-3qv9288lmc] { outline: none; }

/* The station an item goes to, on the columns that have no station heading above the card. It sits
   straight after the item's name and wraps with it, so a long name pushes it down rather than
   stretching the line. */
.kb-station[b-3qv9288lmc] {
    display: inline-block;
    font-size: .7rem;
    font-weight: 600;
    color: var(--pos-gray-600);
    border-left: 3px solid var(--kb-dept, var(--pos-gray-400));
    padding-left: .3rem;
    margin-left: .3rem;
    vertical-align: baseline;
}

/* With an icon the mark is one character, so the stripe would be as tall as the glyph and read as
   a divider rather than as a station. The colour goes on the GLYPH instead - which is also the
   only way the mark stays legible at the size a single icon has to be. */
.kb-station--icon[b-3qv9288lmc] {
    border-left: 0;
    padding-left: 0;
    color: var(--kb-dept, var(--pos-gray-500));
}

.kb-station--icon[b-3qv9288lmc]  .svg-icon {
    font-size: .95rem;
    line-height: 1;
}

/* On a heading there is room for both, and the heading is where the icon is learnt. It is reached
   with ::deep because the glyph is SvgIcon's markup and so never carries this stylesheet's scope
   attribute - the same reason NavMenu reaches its own icons that way. */
.kb-take-name[b-3qv9288lmc]  .kb-head-icon {
    margin-right: .25rem;
    font-size: .95rem;
}

/* ---- batches (Served) ---- */

/* Solid once every item in the batch is cooked, so a whole round reads as takeable at a glance. */
/* ---- the Served card's body ----
   Three things a runner distinguishes: what to carry now, what is coming, what is done. */

.kb-served[b-3qv9288lmc] {
    display: flex;
    flex-direction: column;
    gap: .45rem;
}

.kb-served-none[b-3qv9288lmc] {
    margin: 0;
    font-size: .85rem;
    color: var(--pos-gray-500);
}

/* A station's round: heading carries the name once and the tick-all, lines sit under it. */
.kb-take[b-3qv9288lmc] {
    border-left: 3px solid var(--kb-dept, var(--pos-gray-400));
    padding-left: .45rem;
    display: flex;
    flex-direction: column;
    gap: .15rem;
}

.kb-take-head[b-3qv9288lmc] {
    display: flex;
    align-items: center;
    gap: .35rem;
    width: 100%;
    border: 0;
    background: none;
    padding: .15rem 0;
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--pos-gray-700);
    cursor: pointer;
    text-align: left;
}

.kb-take-head:hover[b-3qv9288lmc] { color: var(--pos-teal); }
.kb-take-head:hover .kb-check[b-3qv9288lmc] { border-color: var(--pos-teal); }
.kb-take-head:focus-visible[b-3qv9288lmc] { outline: 2px solid var(--pos-teal); outline-offset: 2px; border-radius: .2rem; }

.kb-take-name[b-3qv9288lmc] { min-width: 0; overflow-wrap: anywhere; }

.kb-take-count[b-3qv9288lmc] {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    color: var(--pos-teal);
}

/* Context, not work: quieter heading, and only a few lines unless opened. */
.kb-quiet[b-3qv9288lmc] {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    padding-top: .3rem;
    border-top: 1px dashed var(--pos-gray-200);
}

.kb-quiet-head[b-3qv9288lmc] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--pos-gray-500);
}

.kb-quiet-count[b-3qv9288lmc] { font-variant-numeric: tabular-nums; }

/* Opens the still-cooking half. Looks like the control it is, rather than a label. */
.kb-more[b-3qv9288lmc] {
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
    color: var(--pos-gray-500);
    text-decoration: underline dotted;
    text-underline-offset: .2em;
    cursor: pointer;
}

.kb-more:hover[b-3qv9288lmc] { color: var(--pos-gray-700); }
.kb-more:focus-visible[b-3qv9288lmc] { outline: 2px solid var(--pos-teal); outline-offset: 2px; border-radius: .2rem; }

/* ---- the elapsed-time bar ----
   Three segments against the board's one target, so bars are comparable down a column. The
   segments get progressively heavier so the eye reads left-to-right as "waiting, then working".
   The target tick is where the bar is meant to end. */

.kb-bar[b-3qv9288lmc] { display: flex; flex-direction: column; gap: .15rem; }

.kb-track[b-3qv9288lmc] {
    position: relative;
    display: flex;
    height: .4rem;
    background: var(--pos-gray-100);
    border-radius: .2rem;
    overflow: hidden;
}

/* flex: 0 0 auto, NOT the default. A flex child shrinks to fit, so once the segments add up to
   more than the track every one of them is squeezed and each then shows a share it does not
   have. They must keep the width they were given and let the track clip the excess: the bar
   then fills left to right in real time and simply runs out, which is what "past target" looks
   like. The gold ring and the total say by how much. */
.kb-seg[b-3qv9288lmc] {
    flex: 0 0 auto;
    height: 100%;
    width: 0;
    transition: width .5s linear;
}

.kb-seg--order[b-3qv9288lmc] { background: var(--pos-gray-300); }
.kb-seg--queue[b-3qv9288lmc] { background: var(--pos-gray-500); }
.kb-seg--cook[b-3qv9288lmc] { background: var(--pos-teal); }

.kb-target[b-3qv9288lmc] {
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--pos-gray-400);
    opacity: .55;
}

/* Past the target, and the segments are capped at the track so they cannot say it themselves:
   a bar sixteen minutes over and one two hours over are both simply full. So the overflow is
   drawn ON the track (a gold ring, which no segment can cover) and on the total, which is the
   only number that still moves once the bar has filled. Recolouring a segment would not do -
   the one that overran is often the one with no width at all. */
.kb-bar--over .kb-track[b-3qv9288lmc] {
    box-shadow: inset 0 0 0 1.5px var(--pos-gold-dark);
    background: var(--pos-gold-light);
}

.kb-bar--over .kb-target[b-3qv9288lmc] { background: var(--pos-gold-dark); opacity: 1; }

.kb-bar--over .kb-total[b-3qv9288lmc] {
    color: var(--pos-gold-dark);
    font-weight: 700;
}

/* Frozen: every item is cooked, so the bar stops. Past here the clock would be measuring a
   customer eating, and a bar that kept growing would push every leisurely table into the
   overflow colour that means "late" everywhere else on this board. */
.kb-bar--done .kb-seg[b-3qv9288lmc] { transition: none; }

.kb-bar-foot[b-3qv9288lmc] {
    display: flex;
    justify-content: space-between;
    gap: .5rem;
    font-size: .7rem;
    color: var(--pos-gray-500);
}

.kb-stage-name[b-3qv9288lmc] { text-transform: uppercase; letter-spacing: .05em; }
.kb-total[b-3qv9288lmc] { font-variant-numeric: tabular-nums; }

/* ---- actions ---- */

.kb-actions[b-3qv9288lmc] { display: flex; gap: .4rem; }

.kb-action[b-3qv9288lmc] {
    flex: 1 1 auto;
    font-weight: 600;
    padding: .45rem .5rem;
}

.kb-action-back[b-3qv9288lmc] { flex: 0 0 auto; padding: .45rem .7rem; }

/* ---- held for a later send (the later board) ---- */

/* The time it goes, where a kitchen card has its age: the one number the card is read for. */
.kb-goes[b-3qv9288lmc] { color: var(--pos-teal-dark); }

.kb-left[b-3qv9288lmc] {
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--pos-gray-600);
}

/* A round for a bill already being served, not an order of its own: dashed, and named. */
.kb-card--round[b-3qv9288lmc] {
    border-style: dashed;
    border-left-style: dashed;
}

.kb-round-hint[b-3qv9288lmc] {
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    font-weight: 600;
    color: var(--pos-teal-dark);
}

/* Within a quarter of an hour of going: the kitchen may want to start on it. Gold, as warn is. */
.kb-card--soon[b-3qv9288lmc] {
    border-color: var(--pos-gold);
    box-shadow: inset 0 0 0 1px var(--pos-gold);
}

.kb-card--soon .kb-left[b-3qv9288lmc] { color: var(--pos-gold-dark); }

/* ---- states ----
   Gold for warn, red for critical, and nothing else on the page competes for either. */

.kb-card--warn[b-3qv9288lmc] {
    border-color: var(--pos-gold);
    box-shadow: inset 0 0 0 1px var(--pos-gold);
}

.kb-card--warn .kb-elapsed[b-3qv9288lmc] { color: var(--pos-gold-dark); }

.kb-card--critical[b-3qv9288lmc] {
    border-color: var(--pos-red);
    box-shadow: inset 0 0 0 2px var(--pos-red);
}

.kb-card--critical .kb-elapsed[b-3qv9288lmc] { color: var(--pos-red); }

/* Leaving: the card is on its way to another column. Rendered the moment the tap lands, while the
   write is still in flight, so a cook sees the card go rather than blink out of existence when the
   reload replaces the board.

   It fades to a quarter rather than to nothing, on purpose. The animation runs alongside the
   write, and on a bad connection that write can take seconds - a card faded to zero would then be
   a piece of work that had simply disappeared off the board while the kitchen waited. A quarter
   still reads as "going", and still reads as THERE. */
.kb-card--leaving[b-3qv9288lmc] {
    opacity: .25;
    transform: scale(.96);
    pointer-events: none;
}

/* Folded: still on the board, no longer taking the eye. Quieter, and without the elapsed bar -
   a bar is for judging something that is still being waited on.

   The DIRECT-CHILD selector matters. A Served card keeps its body when it folds, and that body's
   groups have kb-lines lists of their own, nested inside .kb-take and .kb-quiet. An unscoped
   .kb-card--folded .kb-lines reached those too and emptied the card down to its headings - which
   threw away the "all of To take, at least three of the rest" rule that decides how much of a bill
   a runner can see. Folding is the WHOLE card going quiet; how much of a section shows is the
   section's own business, and the two must not fight. */
.kb-card--folded[b-3qv9288lmc] { opacity: .62; }

.kb-card--folded > .kb-lines[b-3qv9288lmc],
.kb-card--folded .kb-bar[b-3qv9288lmc] { font-size: .9rem; }
.kb-card--folded .kb-elapsed[b-3qv9288lmc] { font-size: .9rem; }

@media (prefers-reduced-motion: reduce) {
    .kb-seg[b-3qv9288lmc],
    .kb-card[b-3qv9288lmc] { transition: none; }

    .kb-card[b-3qv9288lmc] { animation: none; }
}
/* /Components/Kanban/KanbanColumnView.razor.rz.scp.css */
/* One column of the board (KanbanColumnView). The row of columns around it, the splitter and the
   custom properties every column reads - the card widths, the column floor - are the page's. */

/* height: 100% of the splitter's pane, which is stretched to the row's height and so is a
   definite height for this to fill. The Down flow depends on it: its CSS columns need a height to
   fill before they start the next one. */
.kb-col[b-x0mhuz7s1w] {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    min-width: 0;
    background: var(--pos-gray-50);
}

/* CENTRED, not baseline: the heading shares this row with buttons now, and a 2rem target hung off
   a text baseline sits low and drags the row's height around with it. */
.kb-col-head[b-x0mhuz7s1w] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .35rem .75rem;
    background: #fff;
    border-bottom: 1px solid var(--pos-gray-200);
    flex: 0 0 auto;
}

.kb-col-head h2[b-x0mhuz7s1w] {
    margin: 0;
    font-size: .95rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--pos-gray-700);
}

/* The three things a person standing at the board changes: how the bills are laid out, whether
   dish photos show, and which end new work arrives at. Quiet until they are wanted - this is a
   screen read from three metres, and a row of lit controls in every column heading would compete
   with the food - but a real target under a finger, because a mis-tap here changes the shop's
   board for everybody. A lit one says the setting is on, or that the column is in its second
   state; the tooltip says which way the tap goes. */
.kb-col-tools[b-x0mhuz7s1w] {
    display: flex;
    align-items: center;
    gap: .1rem;
    margin-left: auto;
}

.kb-tool[b-x0mhuz7s1w] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2rem;
    min-height: 2rem;
    padding: 0 .25rem;
    border: 0;
    border-radius: .3rem;
    background: none;
    color: var(--pos-gray-400);
    cursor: pointer;
}

.kb-tool:hover[b-x0mhuz7s1w] { background: var(--pos-gray-100); color: var(--pos-gray-700); }
.kb-tool:focus-visible[b-x0mhuz7s1w] { outline: 2px solid var(--pos-teal); outline-offset: -2px; }

.kb-tool--on[b-x0mhuz7s1w] { color: var(--pos-teal); }
.kb-tool--on:hover[b-x0mhuz7s1w] { color: var(--pos-teal-dark); }

.kb-tool[b-x0mhuz7s1w]  .svg-icon { font-size: 1.05rem; }

.kb-count[b-x0mhuz7s1w] {
    font-variant-numeric: tabular-nums;
    font-size: .85rem;
    font-weight: 600;
    color: var(--pos-gray-500);
    background: var(--pos-gray-100);
    border-radius: 1rem;
    padding: .05rem .5rem;
}

.kb-col-body[b-x0mhuz7s1w] {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: .6rem;
    display: flex;
    flex-direction: column;
    gap: .6rem;
}

/* The way to start an order from the kitchen screen. Dashed and teal so it reads as an action
   rather than as a card with nothing on it - a solid tile at the head of a column of solid tiles
   would be taken for a ticket. It never shrinks: this is the one thing on the column that is
   always there, and a busy Ordering column must not squeeze it away. */
.kb-new-order[b-x0mhuz7s1w] {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .1rem;
    width: 100%;
    padding: .8rem .7rem;
    border: 2px dashed var(--pos-teal);
    border-radius: .35rem;
    background: #fff;
    color: var(--pos-teal-dark);
    cursor: pointer;
}

.kb-new-order:hover[b-x0mhuz7s1w] { background: var(--pos-teal-light); }
.kb-new-order:focus-visible[b-x0mhuz7s1w] { outline: 2px solid var(--pos-teal); outline-offset: 2px; }

.kb-new-order[b-x0mhuz7s1w]  .svg-icon { font-size: 1.35rem; line-height: 1; }
.kb-new-order-name[b-x0mhuz7s1w] { font-weight: 700; font-size: 1rem; }
.kb-new-order-hint[b-x0mhuz7s1w] { font-size: .75rem; color: var(--pos-gray-500); }

.kb-col-empty[b-x0mhuz7s1w] {
    margin: .5rem 0 0;
    font-size: .85rem;
    color: var(--pos-gray-400);
    text-align: center;
}

/* ---- one section per bill ---- */

/* A column is a list of bills, and BillLayout says which way that list runs. Rows: one row per
   bill, its cards flowing left to right, and the column scrolls down through the bills. Columns:
   one column per bill, its cards stacked downward, and the column scrolls sideways through them.

   Both are the same markup. Only this box and the cards box inside it change direction, which is
   what lets a column switch mode without rebuilding a single card. */
.kb-bills[b-x0mhuz7s1w] {
    display: flex;
    flex-direction: column;
    gap: .75rem;
}

.kb-bill[b-x0mhuz7s1w] {
    display: flex;
    flex-direction: column;
    gap: .4rem;
    min-width: 0;
}

/* The table's name, said once for every card under it. Teal rather than a station's colour: this
   is a bill, and the station colours belong to the cards. It wraps, because a long table name
   plus a Grab reference will not always fit a narrow column. */
.kb-bill-head[b-x0mhuz7s1w] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .1rem .4rem;
    font-size: .78rem;
    color: var(--pos-gray-500);
    padding-left: .5rem;
    border-left: 3px solid var(--pos-teal);
}

/* The cards themselves, flowing across the column rather than down it. auto-fill takes whatever
   width the splitters give this column and fits as many cards as will go - so a narrow column
   holds one and a column dragged wide holds three or four, with no second setting to keep in step
   with the first.

   align-content: start keeps a short column's cards at the top instead of spreading them down the
   height, and align-items: start lets each card be its own height rather than every card in a row
   stretching to the tallest - a one-item ticket beside a twelve-item one should not be twelve
   items tall. */
.kb-bill-cards[b-x0mhuz7s1w] {
    display: grid;
    /* min(..., 100%): in a column narrower than one comfortable card the single track is the
       column's width, and the card fills it, rather than a 19rem track overflowing the column. */
    grid-template-columns: repeat(auto-fill, minmax(min(var(--kb-card-min, 19rem), 100%), 1fr));
    align-content: start;
    align-items: start;
    gap: .6rem;
}

/* COLUMNS MODE: one column per bill, side by side, each filled top to bottom. The panel scrolls
   sideways through the bills and no longer scrolls down at all - each bill scrolls its OWN cards,
   so a table with six rounds cannot stretch the panel or push its neighbours off the bottom.

   Every lane is between one readable card and one comfortable one, so the twentieth bill of a busy
   night is still legible with the rest off to the right. */
.kb-col-body--columns[b-x0mhuz7s1w] {
    overflow-y: hidden;
}

/* A lane is one comfortable card wide and no wider. It was minmax(--kb-card-min, 1fr), which on a
   panel holding two bills gave each of them half a wall screen to sit in - and a ticket drawn that
   wide reads as a banner, which is the very thing --kb-card-max exists to stop. Capped, the lanes
   pack to the left and the room that is left over sits at the END of the panel, where it says
   plainly that there is no more work, rather than inside every lane. */
.kb-col-body--columns .kb-bills[b-x0mhuz7s1w] {
    flex: 1 1 0;
    min-height: 0;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(var(--kb-card-min, 19rem), var(--kb-card-max, 31rem));
    overflow-x: auto;
}

.kb-col-body--columns .kb-bill[b-x0mhuz7s1w] {
    min-height: 0;
}

/* STRETCH, and it has to be said here. The box is a grid everywhere else, where align-items: start
   keeps a one-item ticket from growing to the height of the twelve-item one beside it - but this
   rule turns the box into a COLUMN flex container, and in one of those align-items is the
   HORIZONTAL axis. The inherited "start" then meant every card shrank to the width of its own
   longest line and sat in the left of its lane with a gap beside it. */
.kb-col-body--columns .kb-bill-cards[b-x0mhuz7s1w] {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* In a lane of its own a card takes the lane's width, and the lane is already capped at the
   comfort ceiling, so the card's own copy of it would only round the two apart. ::deep, because
   the card is KanbanCard's markup and never carries this component's scope. */
.kb-col-body--columns[b-x0mhuz7s1w]  .kb-card {
    max-width: none;
}

/* The cards themselves are KanbanCard, with their own stylesheet beside them. What is left
   here is the board around them: the columns, the bills and their headings, and the strip of
   finished tickets at the foot of Preparing. */

.kb-heading[b-x0mhuz7s1w] {
    font-size: 1.02rem;
    font-weight: 700;
    color: var(--pos-gray-900);
    line-height: 1.2;
}

/* The bill's number, in its heading. The card head draws its round the same way, from its own
   copy of this rule. */
.kb-label[b-x0mhuz7s1w] {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--pos-gray-600);
}

/* The delivery app's number. Teal like the till's copy of it, so the same fact reads the same way
   on both screens, and tabular so a column of them lines up. */
.kb-ref[b-x0mhuz7s1w] {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--pos-teal-dark);
    white-space: nowrap;
}

.kb-paid[b-x0mhuz7s1w] {
    font-weight: 600;
    color: var(--pos-teal);
    background: var(--pos-teal-light);
    border-radius: .2rem;
    padding: 0 .35rem;
}

/* ---- the way back from a mis-tap ----
   Folded to a line each and parked at the foot of Preparing: present enough to be found in a
   hurry, quiet enough not to compete with the food still to cook. */

.kb-done-strip[b-x0mhuz7s1w] {
    margin-top: .4rem;
    padding-top: .5rem;
    border-top: 1px dashed var(--pos-gray-300);
    display: flex;
    flex-direction: column;
    gap: .3rem;
}

.kb-done-head[b-x0mhuz7s1w] {
    margin: 0;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--pos-gray-500);
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .1rem .4rem;
}

/* Says what the strip is for, because a heading at the foot of a column otherwise reads as the
   next stage rather than as an undo bin. */
.kb-done-hint[b-x0mhuz7s1w] {
    font-size: .68rem;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--pos-gray-400);
}

.kb-done[b-x0mhuz7s1w] {
    display: flex;
    align-items: center;
    gap: .5rem;
    background: var(--pos-gray-100);
    border: 1px solid var(--pos-gray-200);
    border-radius: .3rem;
    padding: .35rem .5rem;
}

/* Both set by the clock in the browser once the undo window has run out. */
.kb-done--expired[b-x0mhuz7s1w] { display: none; }
.kb-done-strip--empty[b-x0mhuz7s1w] { display: none; }

.kb-done-body[b-x0mhuz7s1w] {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .2rem;
}

.kb-done-what[b-x0mhuz7s1w] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .1rem .4rem;
    font-size: .8rem;
}

/* The undo window draining away. Runs right-to-left, opposite to the elapsed bars on the cards
   above, because this one is a chance running out rather than time piling up. */
.kb-done-timer[b-x0mhuz7s1w] {
    height: .2rem;
    background: var(--pos-gray-200);
    border-radius: .1rem;
    overflow: hidden;
}

.kb-done-timer-fill[b-x0mhuz7s1w] {
    height: 100%;
    width: 100%;
    background: var(--pos-gray-400);
    transition: width 1s linear;
}

/* Last fifth: the undo is about to go. */
.kb-done-timer--last .kb-done-timer-fill[b-x0mhuz7s1w] { background: var(--pos-gold); }

@media (prefers-reduced-motion: reduce) {
    .kb-done-timer-fill[b-x0mhuz7s1w] { transition: none; }
}

.kb-done-where[b-x0mhuz7s1w] { font-weight: 700; color: var(--pos-gray-700); }
.kb-done-label[b-x0mhuz7s1w] { font-variant-numeric: tabular-nums; color: var(--pos-gray-500); }
.kb-done-items[b-x0mhuz7s1w] { color: var(--pos-gray-500); }
/* /Components/Kitchen/RecipeNote.razor.rz.scp.css */
/* The kitchen note. Drawn QUIETER than the modifiers above it on a card and LOUDER than nothing,
   which is the whole trick: the modifiers are what the customer asked for and this is how to make
   it, so a cook reads down to it rather than past it. */
.recipe-note[b-6ctopm77cr] {
    margin-top: .15rem;
    font-size: .82em;
    line-height: 1.35;
    color: var(--pos-gray-700);
}

/* A line of the note. It wraps INSIDE itself and never runs into the next one: the shop's line
   breaks are the steps, and two steps sharing a row would read as one. */
.recipe-line[b-6ctopm77cr] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 .25rem;
}

/* A blank line is a gap somebody put there on purpose - between the ingredients and the method,
   usually - so it holds its height instead of collapsing to nothing. */
.recipe-line--blank[b-6ctopm77cr] { height: .5em; }

/* A bullet point. The dot hangs in a column of its own, so a point that runs onto a second line
   lines up under its words and the dots stay in a straight line down the note. */
.recipe-bullet[b-6ctopm77cr] {
    display: flex;
    align-items: baseline;
    gap: .35rem;
}

.recipe-bullet > .recipe-line[b-6ctopm77cr] {
    flex: 1 1 auto;
    min-width: 0;
}

.recipe-dot[b-6ctopm77cr] {
    flex: 0 0 auto;
    color: var(--pos-teal);
    font-weight: 700;
}

/* A table: an amount per ingredient, most of the time. As wide as its contents and no wider, with
   light rules - it sits in a ticket already drawn with a border of its own, and heavy lines inside
   a card would read as a second card. The figures are tabular so a column of amounts lines up. */
.recipe-table[b-6ctopm77cr] {
    margin: .2rem 0;
    max-width: 100%;
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;
}

.recipe-table th[b-6ctopm77cr],
.recipe-table td[b-6ctopm77cr] {
    padding: .05rem .45rem;
    border: 1px solid var(--pos-gray-300);
    vertical-align: middle;
    overflow-wrap: anywhere;
}

.recipe-table th[b-6ctopm77cr] {
    background: var(--pos-gray-100);
    color: var(--pos-gray-800);
    font-weight: 700;
    text-align: start;
}

.recipe-table .recipe-align-center[b-6ctopm77cr] { text-align: center; }
.recipe-table .recipe-align-end[b-6ctopm77cr] { text-align: end; }

/* A snippet's mark, with its label when the token asked for one. One box, so a mark never sits at
   the end of a line with its label on the next - which reads as two things. Inline-flex, so it
   sits in a table cell's text as well as in a line's row. */
.recipe-mark[b-6ctopm77cr] {
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    white-space: nowrap;
    vertical-align: middle;
}

/* ::deep, because the glyph is SvgIcon's own markup and never carries this component's scope. It
   reaches an emoji and a drawn path alike - both carry .svg-icon, and both size off font-size. */
.recipe-mark[b-6ctopm77cr]  .svg-icon { font-size: 1.25em; }

/* What the shop wrapped in ** - the line that wants attention. Teal rather than heavier black:
   on a card that is already dense, weight alone is not seen and the accent is. */
.recipe-bold[b-6ctopm77cr] {
    font-weight: 700;
    color: var(--pos-teal-dark);
}

.recipe-italic[b-6ctopm77cr] { font-style: italic; }

/* Struck through, and quieter with it: a crossed-out ingredient is one the cook must NOT reach
   for, and it should not compete with the ones they must. */
.recipe-strike[b-6ctopm77cr] {
    text-decoration: line-through;
    color: var(--pos-gray-500);
}
/* /Components/Layout/DisplayLayout.razor.rz.scp.css */
/* Locked to the viewport like the app shell, but with nothing around it. A customer screen has no
   scrollbar and no chrome: whatever the page cannot fit is the page's problem to solve.

   BLACK AT REST, and the page paints its own white over it when there is something to show. A
   screen sitting white and empty on a counter all day reads as a page that failed to load; black
   reads as a screen with nothing on it, which is the truth. Pure black rather than the theme's
   darkest gray, because the only thing being asked of it is to look switched off. */
.display-shell[b-v1nn8hn6h1] {
    position: fixed;
    inset: 0;
    overflow: hidden;
    background: #000;
    color: var(--pos-gray-500);
    display: flex;
    flex-direction: column;
}
/* /Components/Layout/MainLayout.razor.rz.scp.css */
.page[b-aiwuwpauik] {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100vh; /* <-- Add this */
    overflow: hidden; /* <-- Add this to stop page-level scrolling */
}

/* The page/main wrappers above are locked to the viewport (the designer canvas wants
   a fixed-viewport shell), which means the ARTICLE is the app's one and only scroll
   container. Without this rule any page taller than the viewport is silently CLIPPED
   — no scrollbar, no wheel scrolling (first noticed on /admin/analytics, the tallest
   page). min-height: 0 lets the flex child shrink to the viewport instead of growing
   to its content height. Pages that fit (e.g. the designer) show no scrollbar and are
   unaffected. */
article.content[b-aiwuwpauik] {
    overflow-y: auto;
    min-height: 0;
}

/* AT EVERY WIDTH, and that is the whole point of this rule. app.css makes .content a flex
   container and names no direction, so an article left to that alone is a flex ROW - and a page
   inside one is a row flex ITEM with min-width: auto, which cannot shrink below its own
   min-content width. The POS screen's dock came out 742px wide inside a 440px phone, clipped at
   the right edge with the Order panel pushed off it, because this rule used to sit INSIDE the
   641px query below and a narrow screen never got it. Nothing wants a row here: every page in the
   app is a column that fills the article and scrolls inside itself.

   The padding comes out of the query with it. Every page draws its own, so the px-4 on the
   article was 48px of a phone's width spent on nothing. */
article[b-aiwuwpauik] {
    padding: 0 !important;
    flex-grow: 1;
    display: flex;
    flex-direction: column;
}

main[b-aiwuwpauik] {
    flex: 1;
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow: hidden;
    background-color: var(--pos-gray-50);
}

.sidebar[b-aiwuwpauik] {
    background-color: var(--pos-gray-800);
    background-image: none;
    border-right: 1px solid var(--pos-gray-700);
}

@media (min-width: 641px) {
    .page[b-aiwuwpauik] {
        flex-direction: row;
    }

    /* Wide enough for the longest label ("Order Categories", indented under its group) and no
       wider; the screen the shift is spent on gets the rest. The transition is on the width
       alone, and overflow is hidden so nothing scrolls sideways while it runs. Icons-only is
       :root.nav-icons, set by js/navShell.js before the first paint (auto under 1200px, or the
       operator's own choice). An EXPANDED sidebar is 220px in the flow at every width - it used
       to lie over the page under 1200px, which only worked while a tap on a link closed it again;
       see js/navShell.js.

       REM, and not the 220px it reads as: the labels inside it are rem, so a device that has
       turned its display size up (js/displayScale.js) needs the column to come up with them or
       the longest label is simply clipped. 13.75rem IS 220px at the normal size, so nothing
       moves until somebody asks it to. The 1200px query that decides icons-only stays in px on
       purpose - it is about how much screen there is, which the display size does not change. */
    .sidebar[b-aiwuwpauik] {
        width: 13.75rem;
        height: 100vh;
        position: sticky;
        top: 0;
        flex-shrink: 0;
        overflow-x: hidden;
        transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    }

    :root.nav-icons .sidebar[b-aiwuwpauik] {
        width: 4rem;
    }
}
/* /Components/Layout/NavMenu.razor.rz.scp.css */
/* The sidebar's chrome. Sizes are deliberately tight: a POS sidebar is read once a shift and
   then only glanced at, so every rem spent on air here is a rem taken from the screen the shift
   is actually spent on. The row is min-height rather than height, so a pair that stacks grows
   the row instead of overflowing it. */

.top-row[b-hwsgpih3wu] {
    min-height: 3.5rem;
    background-color: var(--pos-gray-900); /* Darker than the sidebar for contrast */
    display: flex;
    align-items: center;
    border-bottom: 1px solid var(--pos-gray-700);
}

.navbar-brand[b-hwsgpih3wu] {
    font-size: 1.15rem;
    font-weight: 600;
    letter-spacing: 0.5px;
    color: var(--pos-gold); /* The brand mark is the sidebar's one gold element. */
    text-align: center;
}

.nav-item[b-hwsgpih3wu] {
    font-size: 0.95rem;
    padding: 0 0.5rem 0.125rem;
}

    /* Direct children only: a group's pages sit in a wrapper of their own, and its first and
       last item must not pick up the air meant for the top and bottom of the whole nav. */
    .nav > .nav-item:first-of-type[b-hwsgpih3wu] {
        padding-top: 0.5rem;
    }

    .nav > .nav-item:last-of-type[b-hwsgpih3wu] {
        padding-bottom: 0.75rem;
    }

    /* One pill for a link, a group heading and the sign-out button alike. ::deep because the
       <a> is NavLink's markup and never carries this component's scope attribute. The glyph and
       the label are spaced by the gap, so neither needs a margin of its own. */
    .nav-item[b-hwsgpih3wu]  .nav-link {
        color: var(--pos-gray-300);
        background: none;
        border: none;
        border-radius: 0.375rem;
        margin: 0;
        width: 100%;
        min-height: 2.5rem;
        padding: 0.3rem 0.6rem;
        display: flex;
        align-items: center;
        gap: 0.6rem;
        line-height: 1.15;
        transition: background-color 0.15s ease, color 0.15s ease;
    }

        .nav-item[b-hwsgpih3wu]  .nav-link:hover {
            background-color: var(--pos-gray-700);
            color: #ffffff;
        }

    .nav-item[b-hwsgpih3wu]  a.active {
        background-color: var(--pos-teal);
        color: #ffffff;
        box-shadow: 0 2px 4px rgba(var(--pos-teal-rgb), 0.3);
    }

/* Every sidebar glyph is an inline <SvgIcon> from the SvgIcons registry, drawn in a 1.25rem box
   that fills with currentColor - which is why the icon goes white on hover and on the active
   teal row along with its label. It must not shrink when a label is long. */
.nav-item[b-hwsgpih3wu]  .nav-glyph {
    flex: 0 0 auto;
}

/* A group heading (Shop, Menu, Hardware) is the same pill as a link, plus a chevron on the right
   that turns when the group is open. The glyph is FreeIcon's built-in chevron-down; only the
   turning is ours. */
.nav-item[b-hwsgpih3wu]  .nav-group-chevron {
    flex: 0 0 auto;
    opacity: 0.7;
    transition: transform 0.2s ease;
}

.nav-group-toggle.open[b-hwsgpih3wu]  .nav-group-chevron {
    transform: rotate(180deg);
}

/* Pages of an open group sit one step in, under the heading, a little smaller and a little
   shorter: a tree reads by its indent, and the indent only has to be seen, not walked. */
.nav-sub-item[b-hwsgpih3wu] {
    padding-bottom: 0;
}

    .nav-sub-item[b-hwsgpih3wu]  .nav-link {
        padding-left: 1.7rem;
        min-height: 2.25rem;
        font-size: 0.9rem;
    }

/* A closed group's pages. Hidden by class rather than left out of the markup, so the icon-only
   sidebar below can show them anyway. */
.nav-group-pages.closed[b-hwsgpih3wu] {
    display: none;
}

/* The icon-only sidebar. js/navShell.js puts .nav-icons on <html> - before the first paint,
   from the stored choice or the viewport - and everything it changes is here, inside the
   wide-screen query, because below 641px the nav is a drawer and icons-only has no meaning. The
   brand, every label and the group headings are hidden rather than not rendered, a group's
   pages show as plain icons whether it is open or not, and the glyph sits centred in its pill.
   The scope attribute lands on this component's own element in each selector, so :root may
   lead it. */
@media (min-width: 641px) {
    :root.nav-icons .top-row[b-hwsgpih3wu] {
        justify-content: center;
        padding-left: 0;
        padding-right: 0;
    }

    :root.nav-icons .navbar-brand[b-hwsgpih3wu],
    :root.nav-icons .nav-group-item[b-hwsgpih3wu],
    :root.nav-icons .nav-lang[b-hwsgpih3wu],
    :root.nav-icons .nav-item[b-hwsgpih3wu]  .nav-operator-switch,
    :root.nav-icons .nav-scale-now[b-hwsgpih3wu],
    :root.nav-icons .nav-item[b-hwsgpih3wu]  .nav-label {
        display: none;
    }

    /* Collapsed to 64px there is no room for a glyph, two buttons and a figure. The FIGURE goes
       and the two buttons stay, because what somebody opens this for is to change the size, not
       to read what it is - and the screen in front of them says that better than "115%" does.
       The glyph goes with it: it only names the row, and the two magnifiers say the same thing. */
    :root.nav-icons .nav-scale[b-hwsgpih3wu]  .nav-glyph {
        display: none;
    }

    :root.nav-icons .nav-scale[b-hwsgpih3wu] {
        justify-content: center;
        padding-left: 0;
        padding-right: 0;
    }

    /* The rail is 4rem and every other row gives 0.5rem of it back on each side. This one cannot
       afford to: two 1.75rem buttons and their gap is 3.65rem, which fits 4rem and does not fit
       3rem. It is the only row whose content has a width it must have rather than a width it
       would like. */
    :root.nav-icons .nav-scale-item[b-hwsgpih3wu] {
        padding-left: 0;
        padding-right: 0;
    }

    :root.nav-icons .nav-group-pages.closed[b-hwsgpih3wu] {
        display: block;
    }

    :root.nav-icons .nav-item[b-hwsgpih3wu]  .nav-link {
        justify-content: center;
        padding-left: 0;
        padding-right: 0;
        min-height: 2.5rem;
        position: relative;
    }

    /* Icon-only: there is no label for the badge to sit at the end of, so it rides the glyph's
       top corner. The count still shows rather than a bare dot - "how many" is the whole of what
       this badge says, and a collapsed sidebar is not a reason to stop saying it. */
    :root.nav-icons .nav-item[b-hwsgpih3wu]  .nav-badge {
        position: absolute;
        top: 0.15rem;
        right: 0.55rem;
        margin-left: 0;
        min-width: 1.05rem;
        padding: 0 0.2rem;
        font-size: 0.62rem;
        line-height: 1.05rem;
        border-radius: 0.55rem;
    }
}

/* The sign-out item POSTs a form, so it's a <button> rather than an <a>. Strip the user-agent
   button chrome so it renders pixel-identical to the anchor nav-links above. */
.nav-item form[b-hwsgpih3wu] {
    margin: 0;
}

.nav-item button.nav-link[b-hwsgpih3wu] {
    font: inherit;
    text-align: left;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
}

/* The label beside a nav glyph. A flex row of its own rather than a block, so a stacked pair
   is centred against the glyph by its ink and not by a line-height strut. */
.nav-item[b-hwsgpih3wu]  .nav-label {
    display: flex;
    align-items: center;
    line-height: 1.15;
    min-width: 0;
}

/* The operator at this till: their name over their role, in the shape of a pair, and a small
   swap glyph at the end saying the row is how the till is handed over. */
.nav-item .nav-operator-label[b-hwsgpih3wu] {
    flex-direction: column;
    align-items: flex-start;
}

.nav-operator-role[b-hwsgpih3wu] {
    font-size: .78em;
    opacity: .6;
}

.nav-item[b-hwsgpih3wu]  .nav-operator-switch {
    flex: 0 0 auto;
    opacity: .6;
}

/* The count of prints still waiting, and the sidebar's only badge. GOLD, because the theme keeps
   gold for the one thing that has to be seen, and because nothing else in the nav is coloured at
   all - a shop that is keeping up has a sidebar with no decoration on it.

   ::deep like .nav-label beside it: the span sits inside NavLink's own <a>, which this
   stylesheet's scope attribute does not reach.

   The margin-left pushes it to the far end of the pill. On a group heading the chevron carries
   ms-auto as well, so the two settle as [label ......... badge][chevron] and neither needs to know
   about the other. */
.nav-item[b-hwsgpih3wu]  .nav-badge {
    flex: 0 0 auto;
    margin-left: auto;
    min-width: 1.35rem;
    padding: 0 0.35rem;
    border-radius: 0.7rem;
    background-color: var(--pos-gold);
    color: #241a02;
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 1.35rem;
    text-align: center;
    /* Ink on gold, never the row's own colour: the active row is white-on-teal and the badge
       would otherwise disappear into it on the one row most likely to be active. */
}

/* A count of something gone wrong - a printer not answering - is red, as the theme keeps red. */
.nav-item[b-hwsgpih3wu]  .nav-badge.nav-badge-alert {
    background-color: var(--pos-red);
    color: #fff;
}

/* The language switch's own label. It names the two languages, so it is not a <T> and does not
   use the pair CSS - but it deliberately looks like one, because that is what makes a button
   showing "English 中文" read as a switch between them. */
.nav-lang[b-hwsgpih3wu] {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    line-height: 1.15;
}

.nav-lang-2[b-hwsgpih3wu] {
    font-size: .78em;
    opacity: .6;
}

/* THE DISPLAY-SIZE STEPPER. Laid out like a nav pill - a glyph, then what the row is about - so
   the sidebar still reads as one column of glyphs, but NOT given the .nav-link class: the two
   steps inside it are the buttons and the row itself is not pressable, so it must not light up
   under the pointer promising that it is. */
.nav-scale[b-hwsgpih3wu] {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    min-height: 2.5rem;
    padding: 0.3rem 0.6rem;
    color: var(--pos-gray-300);
    line-height: 1.15;
}

.nav-scale-steps[b-hwsgpih3wu] {
    display: inline-flex;
    align-items: center;
    gap: .15rem;
    min-width: 0;
}

.nav-scale-btn[b-hwsgpih3wu] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* A REM of the scale it is setting, so turning the size up makes the button that turns it
       up bigger too - which is the point. 1.75rem is also what lets the pair survive the
       collapsed rail: two of them plus the gap is 3.65rem inside 4rem, at every step of the
       ladder, because the rail is a rem as well. */
    min-width: 1.75rem;
    min-height: 1.75rem;
    padding: 0;
    font-size: .85rem;
    color: inherit;
    background: none;
    border: 1px solid var(--pos-gray-700);
    border-radius: .3rem;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
}

.nav-scale-btn:hover[b-hwsgpih3wu] {
    background-color: var(--pos-gray-700);
    color: #fff;
}

/* THE FIGURE IS DRAWN BY THE STYLESHEET, out of the custom property js/displayScale.js writes
   onto <html> before the first paint - custom properties inherit, so it arrives here on its own.
   That way the ladder can be any length and this stays one rule and one element. Rendered from
   the circuit it would say 100% until the circuit had connected and read localStorage, then
   jump. */
.nav-scale-now[b-hwsgpih3wu] {
    min-width: 2.8rem;
    font-size: .8rem;
    font-variant-numeric: tabular-nums;
    text-align: center;
    opacity: .75;
}

.nav-scale-now[b-hwsgpih3wu]::after {
    content: var(--ytf-scale-label, "100%");
}

/* The end of the ladder. Greyed and unpressable from CSS rather than a disabled attribute, for
   the same reason the figure is: the circuit does not know which step this device is on, and a
   button that looked live until it connected would be a button that stopped working. Two
   selectors whatever the ladder is, because the script says WHICH END rather than which step. */
:root[data-scale-at="min"] .nav-scale-btn[data-scale-down][b-hwsgpih3wu],
:root[data-scale-at="max"] .nav-scale-btn[data-scale-up][b-hwsgpih3wu] {
    opacity: .3;
    pointer-events: none;
}

/* Two toggles share the top row and only one is ever shown. On a wide screen the hamburger
   collapses the sidebar to its icons; on a narrow one the sidebar IS the top bar, there is
   nothing to collapse, and the same glyph opens the menu as a drawer instead. The drawer's state
   is a checkbox the <label> drives, so it needs no circuit round trip and works before Blazor
   has connected; the checkbox itself is never seen. */
.navbar-toggler[b-hwsgpih3wu] {
    position: absolute;
    width: 0;
    height: 0;
    opacity: 0;
    pointer-events: none;
}

.mobile-toggle[b-hwsgpih3wu] {
    display: none;
    color: #fff;
    cursor: pointer;
    margin: 0;
    line-height: 1;
}

.nav-scrollable[b-hwsgpih3wu] {
    display: none;
}

@media (max-width: 640.98px) {
    .desktop-toggle[b-hwsgpih3wu] {
        display: none;
    }

    .mobile-toggle[b-hwsgpih3wu] {
        display: inline-flex;
    }

    /* The drawer: over the page rather than pushing it down, because the page is locked to the
       viewport and a twenty-row nav above it would leave nothing to see. A tap that navigates
       closes it - the nav's onclick unticks this checkbox - and a tap on a group heading, the
       language switch or the size stepper leaves it open. NavMenu.razor has why that is read off
       the click's target rather than stopped on the way up. */
    .navbar-toggler:checked ~ .nav-scrollable[b-hwsgpih3wu] {
        display: block;
        position: fixed;
        top: calc(3.5rem + 1px);
        left: 0;
        right: 0;
        bottom: 0;
        overflow-y: auto;
        background-color: var(--pos-gray-800);
        z-index: 1030;
    }
}

@media (min-width: 641px) {
    .nav-scrollable[b-hwsgpih3wu] {
        /* Never collapse the sidebar for wide screens */
        display: block;
        /* The top row is 3.5rem plus its 1px border. */
        height: calc(100vh - 3.5rem - 1px);
        overflow-y: auto;
        scrollbar-width: none;
        -ms-overflow-style: none;
    }

        .nav-scrollable[b-hwsgpih3wu]::-webkit-scrollbar {
            display: none;
        }
}
/* /Components/Layout/ScreenGuard.razor.rz.scp.css */
.screen-refused[b-inzxzmp1up] {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: .5rem;
    max-width: 32rem;
    margin: 12vh auto 0;
    padding: 0 1rem;
}

    .screen-refused[b-inzxzmp1up]  .screen-refused-glyph {
        font-size: 2.5rem;
        color: var(--pos-gray-400);
        margin-bottom: .5rem;
    }
/* /Components/Menu/AvailabilityDialog.razor.rz.scp.css */
/* The sheet's own controls. Everything here is sized for a thumb: this is opened mid-service, on
   a tablet, by somebody who has just come back from the kitchen. */

.stock-state[b-9ryu5ogb7l] {
    font-size: 1.15rem;
    font-weight: 600;
    padding: .75rem 1rem;
    border-radius: .5rem;
    background: var(--pos-gray-100);
    color: var(--pos-gray-700);
    margin-bottom: 1rem;
}

.stock-state.is-off[b-9ryu5ogb7l] {
    background: var(--pos-red-light);
    color: var(--pos-red-dark);
}

/* Hidden rides BESIDE the stock line rather than replacing it: a row can be both, and the sheet
   owns both switches, so neither fact may push the other off the screen. */
.stock-state-hidden[b-9ryu5ogb7l] {
    margin-left: .5rem;
    padding: .1rem .45rem;
    border-radius: .35rem;
    background: var(--pos-gray-200);
    color: var(--pos-gray-700);
    font-size: .85rem;
    white-space: nowrap;
}

.stock-state-hidden[b-9ryu5ogb7l]  .svg-icon {
    margin-right: .2rem;
}

/* A note is prose, so it keeps a reading measure rather than running the width of the sheet. */
.stock-note[b-9ryu5ogb7l] {
    max-width: 46rem;
    margin: 1rem 0 0;
    color: var(--pos-gray-600);
    font-size: .9rem;
}

.stock-note[b-9ryu5ogb7l]  .svg-icon {
    margin-right: .25rem;
}

.stock-choice-heading[b-9ryu5ogb7l] {
    margin: 1.25rem 0 .5rem;
    font-weight: 600;
    color: var(--pos-gray-700);
}

.stock-choices[b-9ryu5ogb7l] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: .75rem;
}

/* One choice. Tall enough to hit without looking, and its own note under the label so the length
   is legible without opening anything. */
.stock-choice[b-9ryu5ogb7l] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .15rem;
    width: 100%;
    min-height: 4.5rem;
    padding: .6rem .75rem;
    border: 2px solid var(--pos-gray-300);
    border-radius: .5rem;
    background: #fff;
    color: var(--pos-gray-800);
    text-align: center;
}

.stock-choice:hover:not(:disabled)[b-9ryu5ogb7l] {
    border-color: var(--pos-red);
    color: var(--pos-red-dark);
}

.stock-choice:active:not(:disabled)[b-9ryu5ogb7l] {
    background: var(--pos-red-light);
}

.stock-choice:disabled[b-9ryu5ogb7l] {
    opacity: .55;
}

/* Putting something back is the opposite move and gets the opposite colour, full width above the
   four that take it off. */
.stock-choice-back[b-9ryu5ogb7l] {
    border-color: var(--pos-teal);
    color: var(--pos-teal-dark);
    margin-bottom: .5rem;
}

.stock-choice-back:hover:not(:disabled)[b-9ryu5ogb7l] {
    border-color: var(--pos-teal-dark);
    color: var(--pos-teal-dark);
    background: var(--pos-teal-light);
}

.stock-choice-back:active:not(:disabled)[b-9ryu5ogb7l] {
    background: var(--pos-teal-light);
}

/* Stopping a count sits under the row that sets one, and needs the same air the headings get, or
   it reads as part of that row. */
.stock-count-stop[b-9ryu5ogb7l] {
    margin-top: 1rem;
}

.stock-choice-label[b-9ryu5ogb7l] {
    font-size: 1.05rem;
    font-weight: 600;
}

.stock-choice-note[b-9ryu5ogb7l] {
    font-size: .8rem;
    color: var(--pos-gray-600);
    line-height: 1.2;
}

/* ---- The sell-down countdown ---- */

/* What is running, stated before anything can be changed - the same habit as the state line at the
   top of the sheet: the row is NAMED, and its state is READ, before a tap writes anything. */
.stock-count-state[b-9ryu5ogb7l] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .25rem .75rem;
    padding: .6rem .85rem;
    border-radius: .5rem;
    background: var(--pos-gold-light);
    color: var(--pos-gray-800);
    margin-bottom: .75rem;
}

.stock-count-figure[b-9ryu5ogb7l] {
    font-size: 1.1rem;
    font-weight: 600;
}

.stock-count-window[b-9ryu5ogb7l] {
    font-size: .85rem;
    color: var(--pos-gray-600);
}

.stock-count-label[b-9ryu5ogb7l] {
    display: block;
    margin-bottom: .35rem;
    font-size: .9rem;
    color: var(--pos-gray-600);
}

/* Quantity, period, go. It WRAPS rather than shrinking: on a narrow tablet a number box squeezed
   down to three characters beside a full-width select is how a 10 gets typed as a 1. */
.stock-count-row[b-9ryu5ogb7l] {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

/* The number is the decision on this row, so it is the one sized for a thumb and for reading
   across a kitchen. The period beside it is a secondary control on purpose: it has a sensible
   default, and giving it the same weight as the four buttons above would make the sheet look
   like it was asking the same question twice.

   Minus, number, plus as ONE segmented control: they share a border and read as a single thing
   rather than three, which is what stops the row looking like four separate decisions. */
.stock-count-stepper[b-9ryu5ogb7l] {
    display: flex;
    align-items: stretch;
    flex: 0 0 auto;
}

/* As wide as they are tall, which is the size a thumb actually needs. Three rem is the same
   height as the box and the select beside them, so the row sits on one line. */
.stock-count-step[b-9ryu5ogb7l] {
    width: 3rem;
    min-height: 3rem;
    padding: 0;
    border: 2px solid var(--pos-gray-300);
    background: #fff;
    color: var(--pos-gray-800);
    font-size: 1.4rem;
    font-weight: 600;
    line-height: 1;
}

.stock-count-step:first-child[b-9ryu5ogb7l] {
    border-radius: .5rem 0 0 .5rem;
}

.stock-count-step:last-child[b-9ryu5ogb7l] {
    border-radius: 0 .5rem .5rem 0;
}

.stock-count-step:hover:not(:disabled)[b-9ryu5ogb7l] {
    border-color: var(--pos-teal);
    color: var(--pos-teal-dark);
}

.stock-count-step:active:not(:disabled)[b-9ryu5ogb7l] {
    background: var(--pos-teal-light);
}

.stock-count-step:disabled[b-9ryu5ogb7l] {
    opacity: .45;
}

.stock-count-qty[b-9ryu5ogb7l] {
    flex: 0 0 4.5rem;
    width: 4.5rem;
    height: 3rem;
    border-radius: 0;
    border-left-width: 0;
    border-right-width: 0;
    font-size: 1.25rem;
    font-weight: 600;
    text-align: center;
}

/* The browser's own spinners go: two four-pixel arrows stacked in the corner of the field are
   exactly the control the buttons either side replace, and leaving both would offer the same
   thing twice at two very different sizes. */
.stock-count-qty[b-9ryu5ogb7l] {
    appearance: textfield;
    -moz-appearance: textfield;
}

.stock-count-qty[b-9ryu5ogb7l]::-webkit-outer-spin-button,
.stock-count-qty[b-9ryu5ogb7l]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.stock-count-period[b-9ryu5ogb7l] {
    flex: 1 1 9rem;
    height: 3rem;
}

.stock-count-go[b-9ryu5ogb7l] {
    flex: 0 0 auto;
    min-height: 3rem;
    padding-inline: 1rem;
}

.stock-count-go[b-9ryu5ogb7l]  .svg-icon {
    margin-right: .35rem;
}
/* /Components/Menu/IngredientUsesEditor.razor.rz.scp.css */
.uses[b-ecywx8dtvv] {
    display: flex;
    flex-direction: column;
    gap: .4rem;
    margin-bottom: 1rem;
}

/* One ingredient: its name, then the parts with a stepper either side, then the remove button. */
.uses-row[b-ecywx8dtvv] {
    display: flex;
    align-items: center;
    gap: .6rem;
}

.uses-name[b-ecywx8dtvv] {
    flex: 1 1 auto;
    min-width: 0;
}

.uses-stepper[b-ecywx8dtvv] {
    display: flex;
    align-items: center;
    gap: .35rem;
}

/* Wide enough for "99 parts" in either language, so the buttons beside it never move. */
.uses-parts[b-ecywx8dtvv] {
    min-width: 5.5rem;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.uses-add[b-ecywx8dtvv] {
    max-width: 22rem;
}
/* /Components/Menu/ItemImageCropper.razor.rz.scp.css */
.cropper-stage[b-6cyzsk0hbv] {
    position: relative;
    width: 360px;
    height: 360px;
    margin: 0 auto;
    background: var(--pos-gray-100);
    border: 1px solid var(--pos-gray-300);
    border-radius: 4px;
    overflow: hidden;
}

.cropper-canvas[b-6cyzsk0hbv] {
    display: block;
    width: 360px;
    height: 360px;
    cursor: grab;
    touch-action: none;
}

    .cropper-canvas:active[b-6cyzsk0hbv] {
        cursor: grabbing;
    }

/* The drop target covers the stage until a picture is loaded. */
.cropper-drop[b-6cyzsk0hbv] {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    color: var(--pos-gray-600);
    border: 2px dashed var(--pos-gray-400);
    border-radius: 4px;
    background: var(--pos-gray-50);
}

    .cropper-drop.cropper-drop-hidden[b-6cyzsk0hbv] {
        display: none;
    }

    .cropper-drop.cropper-drop-over[b-6cyzsk0hbv] {
        border-color: var(--pos-teal);
        color: var(--pos-teal-dark);
        background: var(--pos-teal-light);
    }
/* /Components/Menu/MenuItemForm.razor.rz.scp.css */
/* The item's photo, square as it is shown as a tile on the order screen. */
.menu-photo[b-qndbu58qgu] {
    width: 140px;
    height: 140px;
    object-fit: cover;
    border-radius: 6px;
    background: var(--pos-gray-200);
    flex: 0 0 auto;
}

.menu-photo-empty[b-qndbu58qgu] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: var(--pos-gray-500);
    border: 1px dashed var(--pos-gray-400);
}
/* /Components/Menu/MenuTree.razor.rz.scp.css */
/* ---- Tree (sections and categories) ---- */

.menu-tree-section + .menu-tree-section[b-dlq2luby8e] {
    margin-top: 0.5rem;
}

.menu-tree-row[b-dlq2luby8e] {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    width: 100%;
    padding: 0.3rem 0.75rem;
    border: 0;
    background: none;
    text-align: left;
    color: var(--pos-gray-800);
    border-radius: 0;
}

    .menu-tree-row:hover[b-dlq2luby8e] {
        background: var(--pos-gray-100);
    }

    .menu-tree-row.active[b-dlq2luby8e] {
        background: var(--pos-teal-light);
        color: var(--pos-teal-dark);
    }

.menu-tree-section-row[b-dlq2luby8e] {
    font-weight: 600;
}

.menu-tree-category-row[b-dlq2luby8e] {
    padding-left: 2.1rem;
}

/* The grip sits in the indent the category row already has, laid over it rather than taking a
   column of its own: the tree pane is the narrowest of the three and the row's name wants the
   width. It is FAINT rather than hidden: a grip that only appears under the pointer is a gesture
   nobody finds, which is how this list came to have no easy way of being reordered. */
.menu-tree-cat[b-dlq2luby8e] {
    position: relative;
}

/* ::deep, because the grip is ReorderGrip's markup and never carries this component's scope. */
.menu-tree-cat[b-dlq2luby8e]  .menu-tree-grip {
    position: absolute;
    left: 0.6rem;
    top: 50%;
    transform: translateY(-50%);
    z-index: 1;
    cursor: grab;
    line-height: 1;
    color: var(--pos-gray-400);
    opacity: 0.4;
}

.menu-tree-cat:hover[b-dlq2luby8e]  .menu-tree-grip {
    opacity: 1;
}

/* The row the drop would land on. A RING rather than a line along one edge: dragging downwards
   leaves the row after its target and dragging upwards leaves it before, so an edge would be
   pointing the wrong way half the time. The ring also tells the drop target apart from the
   selected row, which is this same teal filled flat. */
.menu-tree-cat.drag-over .menu-tree-row[b-dlq2luby8e] {
    background: var(--pos-teal-light);
    box-shadow: inset 0 0 0 2px var(--pos-teal);
}

.menu-tree-add[b-dlq2luby8e] {
    padding-left: 2.1rem;
    color: var(--pos-gray-500);
    font-size: 0.85rem;
}

.menu-tree-row.active .count-pill[b-dlq2luby8e] {
    background: #fff;
}
/* /Components/Menu/StockBadge.razor.rz.scp.css */
/* Red, small, and the same on every screen that draws it. */
.stock-badge[b-5a2slh1tfc] {
    display: inline-block;
    padding: .1rem .4rem;
    border-radius: .3rem;
    background: var(--pos-red);
    color: #fff;
    font-size: .75rem;
    font-weight: 600;
    line-height: 1.15;
}

/* A countdown is a warning, not a refusal: gold, the theme's "look at this one thing" colour,
   against the red that means the till will not sell it. */
.stock-badge-left[b-5a2slh1tfc] {
    background: var(--pos-gold);
    color: #2b2b2b;
}
/* /Components/Menu/StockUsesList.razor.rz.scp.css */
/* What one row of the menu reaches: see StockUsesList.razor. Drawn on the out-of-stock sheet and
   in the Ingredients page's edit dialog, so it brings its own rules rather than borrowing either
   dialog's. */

.stock-uses[b-qxc2l9k4wd] {
    margin-top: 1rem;
}

.stock-uses-heading[b-qxc2l9k4wd] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    margin-bottom: .5rem;
    font-weight: 600;
    color: var(--pos-gray-700);
}

/* Said only while the list follows a number nobody has saved yet. Quiet and on the heading's
   own line, so it explains the list without competing with it. */
.stock-uses-preview[b-qxc2l9k4wd] {
    color: var(--pos-gray-600);
    font-size: .85rem;
    font-weight: 400;
}

.stock-uses-empty[b-qxc2l9k4wd] {
    color: var(--pos-gray-600);
    font-size: .9rem;
}

/* A short window onto the list, scrolled on its own, so a group asked by fifteen dishes does not
   stretch a dialog and push its other half a screen away. About four and a half rows: the half
   row cut off at the bottom is what says there is more. On a short screen it gives way to a third
   of the height, so what is below it stays in reach. The padding keeps a scrollbar off the
   right-hand tiles. */
.stock-uses-scroll[b-qxc2l9k4wd] {
    max-height: min(11.5rem, 33vh);
    overflow-y: auto;
    padding-right: .25rem;
}

/* Two columns where the sheet has room, one on a phone. */
.stock-uses-list[b-qxc2l9k4wd] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: .4rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.stock-use[b-qxc2l9k4wd] {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .4rem .65rem;
    border-radius: .4rem;
    background: var(--pos-gray-100);
    color: var(--pos-gray-800);
    font-size: .9rem;
    line-height: 1.25;
}

/* Off for a reason of its own: the badge says which, and the row steps back. */
.stock-use.is-off[b-qxc2l9k4wd] {
    background: var(--pos-red-light);
    color: var(--pos-gray-600);
}

/* One line, whatever the name: cut with an ellipsis rather than wrapped, so every row is one
   height and the box above shows the four and a half rows it was sized for. A flex item gives
   up its width only with min-width: 0, and an ellipsis needs a block box to cut. */
.stock-use-name[b-qxc2l9k4wd] {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The badge is StockBadge's markup, so this needs ::deep. Kept whole, like the kind below. */
.stock-use[b-qxc2l9k4wd]  .stock-badge {
    flex: 0 0 auto;
    white-space: nowrap;
}

/* What kind an add-on is, kept whole: it is the name that gives way. */
.stock-use-kind[b-qxc2l9k4wd] {
    flex: 0 0 auto;
    color: var(--pos-gray-600);
    font-size: .75rem;
    white-space: nowrap;
}

/* The figure the list is opened for, so it is the one that stands out on the row. */
.stock-use-parts[b-qxc2l9k4wd] {
    flex: 0 0 auto;
    font-weight: 600;
    color: var(--pos-teal-dark);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
/* /Components/Pages/AuditPage.razor.rz.scp.css */
/* A route the action never named, shown as it is: small, and allowed to wrap at its slashes. */
.audit-route[b-wdh8tdt940] {
    font-size: .85em;
    overflow-wrap: anywhere;
}

/* A column's old or new value can be a paragraph (a dish's description) or a long code. */
.audit-value[b-wdh8tdt940] {
    max-width: 22rem;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}

/* "One bill" with a way to open it and a way out of the filter, in one pill. */
.audit-chip[b-wdh8tdt940] {
    display: inline-flex;
    align-items: center;
    font-weight: normal;
    font-size: .9em;
}
/* /Components/Pages/CalendarPage.razor.rz.scp.css */
/* EACH KIND OF ENTRY HAS ITS COLOUR HERE, as theme variables, once for its items on the month, its
   swatch in the legend and its rows in the agenda. A new kind adds its block beside the closure's.

   A closure is the shop being OFF, which is what the theme's red is for - in its light shade, so a
   month of holidays reads as marked rather than as alarming. The month's items are MonthCalendar's
   own markup, so the rule reaches them through ::deep. */
.calendar-page[b-2sn4xpxlgz]  .mc-item.calendar-kind-closure,
.calendar-swatch.calendar-kind-closure[b-2sn4xpxlgz] {
    background: var(--pos-red-light);
    color: var(--pos-red-dark);
}

.calendar-row.calendar-kind-closure[b-2sn4xpxlgz] {
    border-left-color: var(--pos-red);
}

.calendar-row.calendar-kind-closure[b-2sn4xpxlgz]  .calendar-row-glyph {
    color: var(--pos-red);
}

/* Out of stock is the shop being off too, so it is red as well - OUTLINED, where a closure is
   filled, because a dish being off is a smaller thing than the shop being shut, and the two sit in
   the same cells. A ring rather than a border, so the chip is the same size as any other. */
.calendar-page[b-2sn4xpxlgz]  .mc-item.calendar-kind-stock,
.calendar-swatch.calendar-kind-stock[b-2sn4xpxlgz] {
    background: #fff;
    color: var(--pos-red-dark);
    box-shadow: inset 0 0 0 1px var(--pos-red-border);
}

.calendar-row.calendar-kind-stock[b-2sn4xpxlgz] {
    border-left-color: var(--pos-red-border);
}

.calendar-row.calendar-kind-stock[b-2sn4xpxlgz]  .calendar-row-glyph {
    color: var(--pos-red-dark);
}

/* ---- The legend under the month: one key per kind, and the shaded days ---- */
.calendar-legend[b-2sn4xpxlgz] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem .75rem;
    margin-top: .6rem;
    font-size: .875rem;
    color: var(--pos-gray-600);
}

/* A kind's key is its switch, drawn as plainly as a legend: no border until the pointer is on it,
   faded while its kind is hidden so it is plain what is off and where to tap to have it back. */
.calendar-key[b-2sn4xpxlgz] {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    min-height: 2.25rem;
    padding: .2rem .5rem;
    border: 1px solid transparent;
    border-radius: .375rem;
    background: transparent;
    color: inherit;
    font: inherit;
}

button.calendar-key:hover[b-2sn4xpxlgz] {
    border-color: var(--pos-gray-200);
}

.calendar-key.is-off[b-2sn4xpxlgz] {
    opacity: .4;
}

.calendar-swatch[b-2sn4xpxlgz] {
    flex: 0 0 auto;
    width: 1.5rem;
    height: .8rem;
    border-radius: .2rem;
}

/* The shaded day's own ground, as MonthCalendar draws it (app.css sets --fc-off). */
.calendar-swatch.is-off[b-2sn4xpxlgz] {
    background: var(--pos-gray-100);
    border: 1px solid var(--pos-gray-200);
}

/* ---- The agenda beside the month ---- */
.calendar-heading[b-2sn4xpxlgz] {
    margin: 0 0 .5rem;
    font-size: 1rem;
    font-weight: 600;
}

.calendar-heading:not(:first-child)[b-2sn4xpxlgz] {
    margin-top: 1.25rem;
}

.calendar-empty[b-2sn4xpxlgz] {
    font-size: .875rem;
}

.calendar-agenda[b-2sn4xpxlgz] {
    display: flex;
    flex-direction: column;
    gap: .35rem;
}

/* An entry in words, and its button: the whole row opens it. Its kind shows in the edge and the
   glyph, so a list of mixed kinds still reads at a glance. */
.calendar-row[b-2sn4xpxlgz] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .1rem;
    width: 100%;
    padding: .5rem .75rem;
    border: 1px solid var(--pos-gray-200);
    border-left: 3px solid var(--pos-teal);
    border-radius: .375rem;
    background: #fff;
    color: inherit;
    font: inherit;
    text-align: start;
}

.calendar-row:hover[b-2sn4xpxlgz] {
    background: var(--pos-gray-50);
}

.calendar-row-dates[b-2sn4xpxlgz] {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.calendar-row-count[b-2sn4xpxlgz] {
    font-weight: 400;
    font-size: .8rem;
    color: var(--pos-gray-500);
}

.calendar-row-title[b-2sn4xpxlgz] {
    font-size: .875rem;
    color: var(--pos-gray-700);
}

.calendar-span[b-2sn4xpxlgz] {
    margin-bottom: .5rem;
    font-weight: 600;
}

/* ---- The out-of-stock dialog: what was off, and when ---- */
.calendar-stock-list[b-2sn4xpxlgz] {
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.calendar-stock-row[b-2sn4xpxlgz] {
    padding: .5rem .75rem;
    border: 1px solid var(--pos-gray-200);
    border-left: 3px solid var(--pos-red-border);
    border-radius: .375rem;
}

.calendar-stock-name[b-2sn4xpxlgz] {
    font-weight: 600;
}

.calendar-stock-level[b-2sn4xpxlgz] {
    margin-left: .4rem;
    font-weight: 400;
    font-size: .8rem;
    color: var(--pos-gray-500);
}

.calendar-stock-when[b-2sn4xpxlgz] {
    font-size: .875rem;
    color: var(--pos-gray-700);
}
/* /Components/Pages/CustomerDisplayPage.razor.rz.scp.css */
/* Every size here is vmin with a clamp, because nothing knows how big this screen is: a customer
   display is one shape on one terminal and a tall strip on the next.

   The numbers are reckoned against the shop's own, MEASURED off it rather than guessed - 961 x 601
   CSS px, which is a 1280 x 800 panel at 213 dpi with the WebView scaling by 1.33, so 1vmin is
   about 6px there. This is a screen read across a counter, not a page at arm's length.

   WHITE AND TEAL. Gold was the accent while the page was near-black; on white it is teal, which is
   the brand's own colour and leaves gold for the one-thing-to-look-at it is reserved for. */

/* The two between them cover the shell, so painting both white is what wakes the screen up - no
   wrapper element, and nothing to keep in step with the markup. */
.display-top[b-b60ok684o3] {
    flex: 0 0 auto;
    background: #fff;
    color: var(--pos-gray-900);
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 2vmin;
    padding: 2.2vmin 3vmin;
    border-bottom: 1px solid var(--pos-gray-200);
}

.display-shop[b-b60ok684o3] {
    font-size: clamp(.9rem, 3.4vmin, 1.6rem);
    font-weight: 600;
    color: var(--pos-teal);
}

.display-heading[b-b60ok684o3] {
    font-size: clamp(.8rem, 3vmin, 1.4rem);
    color: var(--pos-gray-500);
}

/* What they are paying for on the left, what it comes to and how to pay it on the right. Both at
   once, because a customer asked for money wants to check the bill and then scan, and a screen
   showing one and then the other would have them asking for the first one back. */
.display-split[b-b60ok684o3] {
    flex: 1 1 auto;
    display: flex;
    min-height: 0;
    background: #fff;
    color: var(--pos-gray-900);
}

/* A portrait or squarish screen has no room for two columns, so they stack. */
@media (max-aspect-ratio: 1 / 1) {
    .display-split[b-b60ok684o3] {
        flex-direction: column;
    }

    .display-pay[b-b60ok684o3] {
        flex: 1 1 auto;
        border-left: none;
        border-top: 1px solid var(--pos-gray-200);
    }
}

.display-bill[b-b60ok684o3] {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
}

/* One number scales the whole bill: BillView and BillLine are in em below this. */
.display-lines[b-b60ok684o3] {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 1.6vmin 3vmin;
    --bill-size: clamp(.9rem, 3.2vmin, 1.5rem);
}

/* A strip below a growing child holds its own height, or it gives up and hides behind the scroll. */
.display-sum[b-b60ok684o3] {
    flex: 0 0 auto;
    padding: 1.6vmin 3vmin 2.2vmin;
    border-top: 1px solid var(--pos-gray-200);
    background: var(--pos-gray-50);
}

.display-total[b-b60ok684o3] {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 2vmin;
    font-size: clamp(1.4rem, 6vmin, 3.5rem);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--pos-teal);
}

.display-pay[b-b60ok684o3] {
    flex: 0 0 42%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1.4vmin;
    padding: 2.5vmin;
    min-width: 0;
    min-height: 0;
    border-left: 1px solid var(--pos-gray-200);
    background: var(--pos-gray-50);
    text-align: center;
}

.display-quiet[b-b60ok684o3] {
    font-size: clamp(.85rem, 3.2vmin, 1.6rem);
    color: var(--pos-gray-600);
}

.display-big[b-b60ok684o3] {
    font-size: clamp(2.5rem, 14vmin, 8rem);
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--pos-teal);
}

/* The picture is the errand on this half of the screen: a customer holding a phone over it wants it
   as big as the box allows, and square whatever shape the box is. It is the flex item that gives
   way, so a short screen shrinks the picture rather than pushing the amount off the top. White,
   with a hairline rather than a shadow - a phone camera reads a code off flat white best. */
.display-qr[b-b60ok684o3] {
    flex: 0 1 auto;
    min-height: 0;
    max-height: 50vmin;
    max-width: 100%;
    aspect-ratio: 1;
    object-fit: contain;
    background: #fff;
    border: 1px solid var(--pos-gray-200);
    border-radius: 1.2vmin;
    padding: 1.2vmin;
}

.display-account[b-b60ok684o3] {
    font-size: clamp(.95rem, 3.2vmin, 1.6rem);
}

.display-tender[b-b60ok684o3] {
    display: flex;
    flex-direction: column;
    gap: .6vmin;
    width: 100%;
    font-size: clamp(1rem, 3.8vmin, 1.9rem);
    color: var(--pos-gray-600);
    font-variant-numeric: tabular-nums;
}

.display-tender > div[b-b60ok684o3] {
    display: flex;
    justify-content: space-between;
    gap: 2vmin;
}

.display-tender-change[b-b60ok684o3] {
    color: var(--pos-teal);
    font-weight: 600;
}

.display-method[b-b60ok684o3] {
    font-size: clamp(.8rem, 2.6vmin, 1.2rem);
    color: var(--pos-gray-500);
}

/* Setup only: seen on a terminal nobody has signed in on yet, and never by a customer. It sits on
   the shell's black, because a terminal waiting for a cashier is not awake yet either. */
.display-unpaired[b-b60ok684o3] {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3vmin;
    padding: 6vmin;
    text-align: center;
    color: var(--pos-gray-500);
}

.display-unpaired p[b-b60ok684o3] {
    margin: 0;
    font-size: clamp(.9rem, 3.4vmin, 1.6rem);
}

.display-retry[b-b60ok684o3] {
    padding: 1.4vmin 4vmin;
    font-size: clamp(.85rem, 3vmin, 1.4rem);
    color: var(--pos-teal-light);
    background: transparent;
    border: 1px solid var(--pos-gray-700);
    border-radius: .6vmin;
}

/* THE ROTATION between customers: the shop's own posters and clips, stacked one on top of another
   with exactly one lit. Which one is displayReel.js's business - see there for why it is not the
   circuit's.

   It fills the shell rather than sitting in its flow, because the shell is a column built for a
   header above a split and this is neither: it is the whole panel. */
.display-reel[b-b60ok684o3] {
    position: absolute;
    inset: 0;
    overflow: hidden;
}

/* All of them are here all the time; opacity is the only thing that moves. A crossfade rather than
   a cut because the alternative on a screen a customer is idly watching is a flicker of black
   between every pair of slides, and because it costs nothing: both pictures are already decoded. */
.display-reel-slide[b-b60ok684o3] {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity .6s ease;
}

.display-reel-slide.is-showing[b-b60ok684o3] {
    opacity: 1;
}

/* CONTAIN, never cover. A poster cropped to fit is a poster with the offer cut off it, and the
   shop cannot see that from here - the screen it happens on is in the shop, facing away. What is
   left over is the shell's black, which is the same ground the reel would have shown anyway. */
.display-reel-slide img[b-b60ok684o3],
.display-reel-slide video[b-b60ok684o3] {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}
/* /Components/Pages/DepartmentsPage.razor.rz.scp.css */
/* The page, its body and its properties pane take app.css's split-panel rules (.split-page,
   .split-body, .split-props), shared by every split-panel page. */

/* One row of the station list. Its grip and its drop line are app.css's (.ft-grip,
   .ft-drop-target), shared by every reorderable list. */
.dept-row[b-1scjocl5j8] {
    cursor: pointer;
}

/* text-truncate inside a flex row needs a floor of zero to shrink to. */
.dept-text[b-1scjocl5j8] {
    min-width: 0;
}

/* The two marks a station carries onto the Kanban board: its icon and its colour. Both are
   picked from a fixed set rather than typed, so the shop cannot invent a colour that collides
   with the board's warn and critical states or an icon the renderer has no glyph for. */

.dept-icons[b-1scjocl5j8] {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
}

/* A tile big enough for a thumb, since the same dialog is used on a tablet. */
.dept-swatch[b-1scjocl5j8] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.6rem;
    height: 2.6rem;
    padding: 0;
    border: 1px solid var(--pos-gray-300);
    border-radius: .35rem;
    background: #fff;
    color: var(--pos-gray-700);
    cursor: pointer;
}

.dept-swatch:hover[b-1scjocl5j8] { border-color: var(--pos-teal); }

.dept-swatch:focus-visible[b-1scjocl5j8] { outline: 2px solid var(--pos-teal); outline-offset: 2px; }

/* Chosen. Teal ring plus a lift, because on a wall of tiles a border colour alone is easy to miss. */
.dept-swatch--on[b-1scjocl5j8] {
    border-color: var(--pos-teal);
    box-shadow: inset 0 0 0 2px var(--pos-teal);
    color: var(--pos-teal-dark);
}

.dept-swatch-fill[b-1scjocl5j8] {
    width: 1.5rem;
    height: 1.5rem;
    border-radius: .25rem;
}

/* The row's own copy of the mark, drawn the way the board draws it: the colour as a stripe, the
   icon inside it. Fixed width so the names still line up down the list when a station has no
   icon at all. */
.dept-mark[b-1scjocl5j8] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 1.6rem;
    /* Sits on the NAME's line rather than the top of the text block, which in a flex row aligned
       to start would leave it floating above a two-line row. */
    height: 1.5rem;
    /* The stripe is drawn ONLY when the shop chose a colour. Falling back to grey drew a bar on
       every station that had not chosen one - a vertical rule between the grip and the name that
       meant nothing, and read as a stray divider rather than as "no colour". The width is kept
       either way, so the names still line up down the list whether or not a station is marked. */
    border-left: 3px solid var(--dept, transparent);
    color: var(--dept, var(--pos-gray-500));
}

.dept-mark[b-1scjocl5j8]  .svg-icon { font-size: 1rem; line-height: 1; }

/* WHAT THIS STATION PRINTS, shown and not edited. The same list is one DepartmentPrints table
   read the other way round on Print settings, and offering it in two shapes on two screens is
   what had shops asking which of the two won - so this side states the answer and links there.
   Teal, the colour a lit chip has over there, so the two read as the same fact. */
.dept-prints[b-1scjocl5j8] {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    margin-bottom: .25rem;
    min-height: 1.6rem;
    align-items: center;
}

.dept-print[b-1scjocl5j8] {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    border-radius: 2rem;
    padding: .25rem .65rem;
    background: var(--pos-teal-light);
    color: var(--pos-teal-dark);
    font-size: .8125rem;
    font-weight: 600;
    line-height: 1.2;
}

.dept-print[b-1scjocl5j8]  .svg-icon {
    flex: 0 0 auto;
}

/* WHAT WILL NOT PRINT AS SET UP. Gold, the colour the theme keeps for the one thing that must be
   seen, and never red: nothing here is broken yet, and most of it is one setting away from right. */
.dept-warning[b-1scjocl5j8] {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
    margin-bottom: .4rem;
    padding: .5rem .75rem;
    border-radius: .375rem;
    background: var(--pos-gold-light);
    color: var(--pos-gray-900);
    font-size: .875rem;
}

.dept-warning[b-1scjocl5j8]  .svg-icon {
    flex: 0 0 auto;
    margin-top: .15rem;
    color: var(--pos-gold-dark);
}

.dept-row-warning[b-1scjocl5j8] { color: var(--pos-gold-dark); }
/* /Components/Pages/DisplaySlidesPage.razor.rz.scp.css */
/* The thumbnail is how a row is recognised, so it gets a fixed box and the picture is fitted INSIDE
   it rather than cropped to fill. A poster cropped to a letterbox thumbnail can lose the very thing
   the shop put on it. Sized for a list row: the pane beside it shows the slide at its width. */
.slide-thumb[b-ab2ls9q0f6] {
    position: relative;
    flex: 0 0 auto;
    width: 4.5rem;
    height: 2.6rem;
    border-radius: .25rem;
    overflow: hidden;
    background: var(--pos-gray-900);
}

.slide-thumb img[b-ab2ls9q0f6],
.slide-thumb video[b-ab2ls9q0f6] {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

/* Resting, not removed: dimmed, because a slide the shop has switched off is still a slide, and it
   still has to be recognisable enough to switch back on. */
.slide-thumb-off[b-ab2ls9q0f6] {
    opacity: .4;
}

/* Says "this one moves", on the one thumbnail that cannot show it. A video's poster frame is a
   still and reads as a picture; without this the two kinds are indistinguishable in the list. */
.slide-badge[b-ab2ls9q0f6] {
    position: absolute;
    right: .25rem;
    bottom: .25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 50%;
    background: rgb(0 0 0 / .55);
    color: #fff;
    font-size: .7rem;
    line-height: 1;
}

/* The upload's progress under the file box. A plain bar in the theme's teal rather than Bootstrap's
   .progress, whose bar colour is a literal blue that --bs-primary does not reach. The second leg -
   the server handing the file to the API - cannot be measured, so the full bar pulses instead. */
.upload-progress[b-ab2ls9q0f6] {
    margin-top: .5rem;
}

.upload-bar[b-ab2ls9q0f6] {
    height: .5rem;
    border-radius: 999px;
    background: var(--pos-gray-200);
    overflow: hidden;
}

.upload-bar-fill[b-ab2ls9q0f6] {
    height: 100%;
    background: var(--pos-teal);
    transition: width .2s linear;
}

.upload-bar-fill.storing[b-ab2ls9q0f6] {
    animation: upload-pulse-b-ab2ls9q0f6 1.2s ease-in-out infinite;
}

@keyframes upload-pulse-b-ab2ls9q0f6 {
    50% { opacity: .45; }
}

@media (prefers-reduced-motion: reduce) {
    .upload-bar-fill[b-ab2ls9q0f6] { transition: none; }
    .upload-bar-fill.storing[b-ab2ls9q0f6] { animation: none; }
}

/* The selected slide in the pane, at the pane's width and the screen's own shape, fitted inside
   rather than cropped, on the black the screen plays it on. */
.slide-preview[b-ab2ls9q0f6] {
    aspect-ratio: 16 / 10;
    max-height: 18rem;
    border-radius: .375rem;
    overflow: hidden;
    background: var(--pos-gray-900);
}

.slide-preview img[b-ab2ls9q0f6],
.slide-preview video[b-ab2ls9q0f6] {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}
/* /Components/Pages/GrabExportPage.razor.rz.scp.css */
/* Two steps down one page. A reading measure goes on the PROSE, never on the pane, so the notes
   are capped and the tables use the room. */

.grab-step[b-j68puyqddf] {
    margin-bottom: 2rem;
}

.grab-step-title[b-j68puyqddf] {
    padding-bottom: .4rem;
    border-bottom: 1px solid var(--pos-gray-200);
    margin-bottom: .75rem;
}

.grab-note[b-j68puyqddf] {
    max-width: 46rem;
    color: var(--bs-secondary-color);
    margin-bottom: .75rem;
}

.grab-pick[b-j68puyqddf] {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    align-items: start;
    margin-bottom: 1rem;
}

.grab-pick .form-control[b-j68puyqddf] {
    max-width: 26rem;
}

.grab-tally[b-j68puyqddf] {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    margin-bottom: .75rem;
}

.grab-ok[b-j68puyqddf] {
    color: var(--pos-teal);
}

/* Gold is the theme's "one thing to look at", so it is spent on the COUNT and the badge - the
   few characters somebody has to notice - and never on a paragraph. A whole block of gold prose
   is not an emphasis, it is a wall. */
.grab-warn[b-j68puyqddf] {
    color: var(--pos-gold-dark);
    font-weight: 500;
}

.grab-name[b-j68puyqddf] {
    font-weight: 500;
}

.grab-details[b-j68puyqddf] {
    max-width: 46rem;
    margin-bottom: 1rem;
}

.grab-details summary[b-j68puyqddf] {
    cursor: pointer;
}

.grab-list[b-j68puyqddf] {
    margin: .5rem 0 0;
    padding-left: 1.2rem;
    color: var(--bs-secondary-color);
}

.grab-list li[b-j68puyqddf] {
    margin-bottom: .25rem;
}

/* The line under the photo switch answers "what will that do", so it is quieter than a note
   and sits tight under the control it explains. */
.grab-hint[b-j68puyqddf] {
    margin-top: -.25rem;
    margin-bottom: .75rem;
    font-size: .9em;
}

/* The thing that can go irreversibly wrong. Gold marks it, but down the side: the words
   themselves stay ordinary text so they can actually be read. */
.grab-callout[b-j68puyqddf] {
    border-left: 3px solid var(--pos-gold);
    background: var(--pos-gold-light);
    padding: .6rem .75rem;
    border-radius: .25rem;
    color: var(--bs-body-color);
}

/* The two upload boxes the portal has, plus the one case that is neither. Cards rather than a
   dropdown: which one somebody wants depends on a sentence, and a <select> has nowhere to put it. */
.grab-modes[b-j68puyqddf] {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin-bottom: 1rem;
}

.grab-mode[b-j68puyqddf] {
    display: flex;
    gap: .5rem;
    align-items: start;
    flex: 1 1 16rem;
    max-width: 24rem;
    padding: .6rem .75rem;
    border: 1px solid var(--pos-gray-200);
    border-radius: .35rem;
    cursor: pointer;
}

.grab-mode-on[b-j68puyqddf] {
    border-color: var(--pos-teal);
    background: var(--pos-teal-light);
}

.grab-mode-body[b-j68puyqddf] {
    display: flex;
    flex-direction: column;
}

.grab-mode-name[b-j68puyqddf] {
    font-weight: 500;
}

.grab-mode-note[b-j68puyqddf] {
    font-size: .85em;
    color: var(--bs-secondary-color);
}

/* Confirming the upload. It sits under the download because that is the order the two happen in,
   and it is quieter than the download button: one is the thing you came for, the other is the
   bookkeeping that makes the next visit shorter. */
.grab-confirm[b-j68puyqddf] {
    margin-bottom: 1rem;
}
/* /Components/Pages/KanbanBoardsPage.razor.rz.scp.css */
/* The shop's own steps, in the right pane when Kitchen steps is picked. Set apart as a panel rather
   than dropped in as a row of checkboxes, because it is a different kind of setting from a board:
   these say what the SHOP does, a board says what one screen shows of it. */

.shop-steps[b-lm4yj8titj] {
    display: flex;
    flex-direction: column;
    gap: .75rem;
    margin-bottom: 1.25rem;
    padding: 1rem 1.25rem;
    background: #fff;
    border: 1px solid var(--pos-gray-200);
    border-radius: .5rem;
}

.shop-steps-head[b-lm4yj8titj] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
}

.shop-steps-row[b-lm4yj8titj] {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

/* One tile per step, wide enough to carry what the step IS - the names alone ("Received",
   "Preparing") do not tell a shop owner what they are switching off. */
.shop-step[b-lm4yj8titj] {
    flex: 1 1 12rem;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .1rem;
    padding: .6rem .75rem;
    border: 1px solid var(--pos-gray-300);
    border-radius: .4rem;
    background: var(--pos-gray-50);
    text-align: left;
    cursor: pointer;
}

.shop-step:hover[b-lm4yj8titj] { border-color: var(--pos-teal); }
.shop-step:focus-visible[b-lm4yj8titj] { outline: 2px solid var(--pos-teal); outline-offset: 2px; }
.shop-step:disabled[b-lm4yj8titj] { opacity: .6; cursor: default; }

/* On is the working state, so it takes the teal. Off is left plain rather than reddened: not
   working a step is a perfectly ordinary choice, not a warning. */
.shop-step--on[b-lm4yj8titj] {
    border-color: var(--pos-teal);
    background: #fff;
}

.shop-step-switch[b-lm4yj8titj] { font-size: 1.35rem; line-height: 1; color: var(--pos-gray-400); }
.shop-step--on .shop-step-switch[b-lm4yj8titj] { color: var(--pos-teal); }

.shop-step-name[b-lm4yj8titj] {
    font-weight: 600;
    color: var(--pos-gray-500);
}

.shop-step--on .shop-step-name[b-lm4yj8titj] { color: var(--pos-gray-900); }

.shop-step-what[b-lm4yj8titj] {
    font-size: .78rem;
    color: var(--pos-gray-500);
}
/* ---- what each STATION works ----
   One row per station, one tick per step, on the same template as its headings. A separate box per
   row rather than one grid of display: contents rows, because a row carries its own link back to
   following the shop.

   The name column takes what it needs and the tick columns are equal, so the ticks line up down
   the grid however long the station names run. It gives way at a width of its own: below 40rem the
   name goes onto its own line and the ticks sit under it, which is the most a phone can do with
   four columns. */
.station-steps[b-lm4yj8titj] {
    display: flex;
    flex-direction: column;
    gap: .4rem;
    padding-top: .75rem;
    border-top: 1px dashed var(--pos-gray-200);
}

.station-steps-head[b-lm4yj8titj] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .15rem .5rem;
}

.station-grid[b-lm4yj8titj] {
    display: flex;
    flex-direction: column;
}

.station-grid-row[b-lm4yj8titj] {
    display: grid;
    grid-template-columns: minmax(8rem, 18rem) repeat(3, minmax(4.5rem, 7rem)) auto;
    align-items: center;
    gap: .25rem .5rem;
    padding: .25rem .4rem;
    border-radius: .3rem;
}

.station-grid-row:hover[b-lm4yj8titj] { background: var(--pos-gray-50); }

.station-grid-head[b-lm4yj8titj] {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--pos-gray-500);
    text-align: center;
}

.station-grid-head:hover[b-lm4yj8titj] { background: none; }

.station-name[b-lm4yj8titj] {
    display: flex;
    align-items: center;
    gap: .35rem;
    min-width: 0;
    font-size: .9rem;
}

.station-glyph[b-lm4yj8titj] { line-height: 1; }

.station-cell[b-lm4yj8titj] { text-align: center; }

/* Bigger than Bootstrap's default box: this is a grid of them and a mis-tap sets the wrong
   station's step. */
.station-cell .form-check-input[b-lm4yj8titj] {
    width: 1.15rem;
    height: 1.15rem;
    margin: 0;
    cursor: pointer;
}

/* FOLLOWING THE SHOP rather than answering for itself. Drawn as the shop's answer - the board
   behaves that way, so showing an empty box would contradict the screen - but dashed and quiet,
   so a value set here is never mistaken for one that is only being borrowed. The same difference
   the board editor draws with .is-inherited. */
.station-cell .form-check-input.is-inherited[b-lm4yj8titj] {
    border-style: dashed;
    border-color: var(--pos-gray-400);
}

/* A borrowed tick is GRAY where a station's own is teal. The dashed edge alone said nothing once
   the box was filled - a checked box hides its own border - and these cells are read in columns of
   eight, where the only thing anybody is looking for is which of them differ. */
.station-cell .form-check-input.is-inherited:checked[b-lm4yj8titj] {
    background-color: var(--pos-gray-400);
    border-color: var(--pos-gray-400);
}

.station-follow[b-lm4yj8titj] { text-align: right; }

@media (max-width: 40rem) {
    .station-grid-row[b-lm4yj8titj] {
        grid-template-columns: repeat(3, 1fr);
        gap: .1rem .25rem;
    }

    .station-name[b-lm4yj8titj] { grid-column: 1 / -1; }
    .station-follow[b-lm4yj8titj] { grid-column: 1 / -1; text-align: left; }
    .station-grid-head > span:first-child[b-lm4yj8titj] { display: none; }
}

/* ---- The split panel ----
   The page takes app.css's split-panel rules (.split-page, .split-body, .split-props). The kitchen
   steps are the first entry of the left list rather than a section above the panel: up there they
   took half a laptop's screen and left the boards a strip to scroll in. */

/* The heading between the steps entry and the boards: the boards are a list of their own, dragged
   into order, and the steps are not one of them. */
.boards-head[b-lm4yj8titj] {
    padding: .9rem 1rem .35rem;
    border-top: 1px solid var(--pos-gray-200);
}

.steps-row[b-lm4yj8titj] {
    cursor: pointer;
}

/* One row of the board list. Its grip and its drop line are app.css's (.ft-grip,
   .ft-drop-target), shared by every reorderable list. */
.board-row[b-lm4yj8titj] {
    cursor: pointer;
}

/* text-truncate inside a flex row needs a floor of zero to shrink to. */
.board-text[b-lm4yj8titj] {
    min-width: 0;
}

/* A reading measure on the prose only, never on the pane: the stage blocks, pickers and number
   boxes want the room. */
.board-props p.form-text[b-lm4yj8titj],
.board-props .form-text[b-lm4yj8titj],
.board-props .alert[b-lm4yj8titj] {
    max-width: 46rem;
}

/* One block per stage: the tick turns the column on, and its settings appear underneath. A stage
   that is off shows nothing at all, so what is on screen is exactly what the board does. */

.stage-list[b-lm4yj8titj] {
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.stage[b-lm4yj8titj] {
    border: 1px solid var(--pos-gray-200);
    border-radius: .4rem;
    padding: .7rem .9rem;
    background: var(--pos-gray-50);
}

.stage--on[b-lm4yj8titj] {
    background: #fff;
    border-color: var(--pos-gray-300);
}

/* A step the shop does not work: its box is disabled and the row recedes. */
.stage--off > .stage-head[b-lm4yj8titj] {
    opacity: .6;
}

.stage-head[b-lm4yj8titj] {
    margin: 0;
}

.stage-body[b-lm4yj8titj] {
    margin-top: .8rem;
    padding-top: .8rem;
    border-top: 1px dashed var(--pos-gray-200);
    display: flex;
    flex-direction: column;
    gap: .9rem;
}

.stations-head[b-lm4yj8titj] {
    display: flex;
    align-items: baseline;
    margin-bottom: .3rem;
}

.station-picks[b-lm4yj8titj] {
    display: flex;
    flex-wrap: wrap;
    gap: .15rem 1rem;
}

/* The station's own colour, shown where it is picked so the board and this page agree. */
.station-dot[b-lm4yj8titj] {
    display: inline-block;
    width: .65rem;
    height: .65rem;
    border-radius: .15rem;
    margin-right: .3rem;
    vertical-align: baseline;
    border: 1px solid rgba(0, 0, 0, .15);
}

/* A choice this board is only BORROWING from the default board. It has to read as selected - the
   board is already drawn that way - but not as chosen, or nobody could tell a value that was set
   here from one following another board. A dashed edge is the whole difference, and it survives
   being looked at from across a desk. */
.is-inherited[b-lm4yj8titj] {
    border-style: dashed;
}
/* /Components/Pages/KanbanPage.razor.rz.scp.css */
/* The Kanban board. A wall screen read from two or three metres away, so type is large, the
   colour vocabulary is small, and nothing depends on hover.

   Colour discipline follows the shop theme: gray carries the structure, teal is the working
   state, and gold is spent ONLY on a card that has gone past its warn threshold. Critical is the
   one red on the page. A station's own colour is a stripe down the left edge of its card and
   never a fill, so it can never be mistaken for a state. */

/* FILLS THE ARTICLE, the way every full-height page in this app does (.pos-page is the other
   one): the shell already sizes the article, so the page only has to grow into it and keep its
   own scrolling inside.

   It was height: calc(100vh - 4.5rem), a guess at the chrome above it - and that chrome only
   exists BELOW 641px, where the sidebar becomes a top bar. On a wide screen there is nothing above
   the article, so the board came out 4.5rem short and left a strip of empty page under it. */
.kb-page[b-x5ryz5lbyb] {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    gap: 0;
}

/* ---- top bar ---- */

.kb-top[b-x5ryz5lbyb] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .5rem .75rem;
    border-bottom: 1px solid var(--pos-gray-200);
    flex: 0 0 auto;
}

.kb-board-name[b-x5ryz5lbyb] {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--pos-gray-800);
}

.kb-board-pick[b-x5ryz5lbyb] { width: auto; min-width: 12rem; }

.kb-empty-board[b-x5ryz5lbyb] {
    margin: 2rem auto;
    padding: 1.5rem 2rem;
    max-width: 30rem;
    text-align: center;
    color: var(--pos-gray-600);
    background: var(--pos-gray-50);
    border: 1px solid var(--pos-gray-200);
    border-radius: .5rem;
}

.kb-empty-links[b-x5ryz5lbyb] {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    justify-content: center;
}

/* ---- columns ---- */

/* The columns sit in a SplitContainer, and how wide each one is comes from where this device last
   dragged its splitters (see SplitFor). Nothing about a column's width is stored on the board.

   --kb-col-floor is the one width the board still insists on: below the floor times the number of
   columns (--kb-col-count comes from the markup), the whole row stops shrinking and the board
   scrolls sideways instead - awkward, but every ticket stays readable. Above it the splitters
   share out whatever the screen has. */
.kb-columns[b-x5ryz5lbyb] {
    --kb-col-count: 4;
    --kb-col-floor: 13rem;

    /* One card. The MIN decides how many fit across a wide column; the MAX is a comfort ceiling -
       a single card in a column dragged wide would otherwise stretch the whole way and read as a
       banner rather than as a ticket. In rem, so both scale with the root size on a wall screen
       set to larger text. */
    --kb-card-min: 19rem;
    --kb-card-max: 31rem;

    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    overflow-x: auto;
    overflow-y: hidden;
}

.kb-columns[b-x5ryz5lbyb]  .split-pane-container {
    min-width: calc(var(--kb-col-count) * var(--kb-col-floor));
}
/* /Components/Pages/LaterBoardPage.razor.rz.scp.css */
/* The later board. Read from across a kitchen like the board beside it, so it borrows that
   board's look - gray structure, teal for the bill - and spends gold only on a card that is about
   to go (kanbanClock.js marks it). */

.lb-page[b-i6i0xtx0n4] {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

.lb-top[b-i6i0xtx0n4] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .4rem .75rem;
    padding: .5rem .75rem;
    border-bottom: 1px solid var(--pos-gray-200);
    flex: 0 0 auto;
}

.lb-title[b-i6i0xtx0n4] {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--pos-gray-800);
    display: inline-flex;
    align-items: center;
    gap: .35rem;
}

.lb-about[b-i6i0xtx0n4] {
    font-size: .85rem;
    color: var(--pos-gray-500);
    max-width: 46rem;
}

.lb-empty[b-i6i0xtx0n4] {
    margin: 2rem auto;
    padding: 1.5rem 2rem;
    max-width: 30rem;
    text-align: center;
    color: var(--pos-gray-600);
    background: var(--pos-gray-50);
    border: 1px solid var(--pos-gray-200);
    border-radius: .5rem;
}

/* One column per hour, side by side, and the page scrolls sideways through the hours. A column
   is one comfortable card wide: a wall screen with two hours on it leaves the rest of its width
   empty, which says plainly that nothing else is coming. */
.lb-columns[b-i6i0xtx0n4] {
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(min(19rem, 100%), 26rem);
    overflow-x: auto;
    background: var(--pos-gray-50);
}

.lb-col[b-i6i0xtx0n4] {
    display: flex;
    flex-direction: column;
    min-height: 0;
    min-width: 0;
    border-right: 1px solid var(--pos-gray-200);
}

.lb-col-head[b-i6i0xtx0n4] {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .35rem .75rem;
    background: #fff;
    border-bottom: 1px solid var(--pos-gray-200);
    flex: 0 0 auto;
}

.lb-col-head h2[b-i6i0xtx0n4] {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--pos-gray-700);
}

.lb-col-body[b-i6i0xtx0n4] {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: .6rem;
    display: flex;
    flex-direction: column;
    gap: .8rem;
}

.lb-bill[b-i6i0xtx0n4] {
    display: flex;
    flex-direction: column;
    gap: .4rem;
    min-width: 0;
}

/* The bill, said once above its card, as the board does it. */
.lb-bill-head[b-i6i0xtx0n4] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .1rem .4rem;
    font-size: .78rem;
    color: var(--pos-gray-500);
    padding-left: .5rem;
    border-left: 3px solid var(--pos-teal);
}

.lb-heading[b-i6i0xtx0n4] {
    font-size: .95rem;
    font-weight: 700;
    color: var(--pos-gray-800);
}

.lb-number[b-i6i0xtx0n4] {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.lb-ref[b-i6i0xtx0n4] {
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    font-weight: 600;
    color: var(--pos-gray-700);
}

.lb-paid[b-i6i0xtx0n4] {
    font-weight: 700;
    color: var(--pos-teal-dark);
    text-transform: uppercase;
    letter-spacing: .04em;
}
/* /Components/Pages/MenuEditorPage.razor.rz.scp.css */
/* The page, its body and its properties pane take app.css's split-panel rules (.split-page,
   .split-body, .split-props), shared by every split-panel page. */

/* ---- Items ---- */

.menu-toolbar[b-pjzkh78c9w] {
    background: var(--pos-gray-50);
}

.menu-items tr[b-pjzkh78c9w] {
    cursor: pointer;
}

.menu-thumb[b-pjzkh78c9w] {
    width: 36px;
    height: 36px;
    object-fit: cover;
    border-radius: 4px;
    background: var(--pos-gray-200);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--pos-gray-500);
}

/* ---- Properties ---- */

.menu-props[b-pjzkh78c9w] {
    background: var(--pos-gray-50);
}

/* ---- Finding an item anywhere in the menu ---- */

/* The BAR spans the page; the box inside it does not. Left to grow it reached 1400px on a wide
   monitor, which reads as one enormous input rather than as a toolbar - and what goes in it is a
   word. It still shrinks when the row runs out of room. */
/* .search-box (app.css) draws the box and its magnifier; this is only how much of the row it takes. */
.menu-search[b-pjzkh78c9w] {
    flex: 0 1 22rem;
    min-width: 9rem;
}

/* Sized to its longest option rather than left to fill: a select that stretches reads as the
   main control on the row, and the search is. */
.menu-filter-dept[b-pjzkh78c9w] {
    flex: 0 0 auto;
    width: auto;
    max-width: 14rem;
}

/* /Components/Pages/MenuSchedulesPage.razor.rz.scp.css */
/* The page, its body and its properties pane take app.css's split-panel rules (.split-page,
   .split-body, .split-props), shared by every split-panel page. */
/* /Components/Pages/ModifierGroupsPage.razor.rz.scp.css */
/* The page, its body and its properties pane take app.css's split-panel rules (.split-page,
   .split-body, .split-props), shared by every split-panel page. */

/* One row of the group list. Its grip and its drop line are app.css's (.ft-grip,
   .ft-drop-target), shared by every reorderable list; the grip hides itself while a search is on. */
.group-row[b-ejk34jpvf0] {
    cursor: pointer;
}

/* text-truncate inside a flex row needs a floor of zero to shrink to. */
.group-text[b-ejk34jpvf0] {
    min-width: 0;
}

/* The dialog row keeps its gutters between columns but none against the modal edges: the
   columns naming a row's left and right edge, counted from the field list in the markup. */
[b-ejk34jpvf0] .modifier-dialog-fields > [class*="col-"]:nth-child(2),
[b-ejk34jpvf0] .modifier-dialog-fields > [class*="col-"]:nth-child(6),
[b-ejk34jpvf0] .modifier-dialog-fields > .col-12 {
    padding-left: 0;
}

[b-ejk34jpvf0] .modifier-dialog-fields > [class*="col-"]:nth-child(4),
[b-ejk34jpvf0] .modifier-dialog-fields > [class*="col-"]:nth-child(7),
[b-ejk34jpvf0] .modifier-dialog-fields > .col-12 {
    padding-right: 0;
}
/* /Components/Pages/ModifiersPage.razor.rz.scp.css */
/* The page, its body and its properties pane take app.css's split-panel rules (.split-page,
   .split-body, .split-props), shared by every split-panel page. */

/* One row of the catalogue. Its grip and its drop line are app.css's (.ft-grip,
   .ft-drop-target), shared by every reorderable list; the grip hides itself while a search is on. */
.def-row[b-rsmm6rgtud] {
    cursor: pointer;
}

/* text-truncate inside a flex row needs a floor of zero to shrink to. */
.min-w-0[b-rsmm6rgtud] {
    min-width: 0;
}

/* The second line of a row: price, how many groups offer it, how many disagree. Inherits on the
   selected row, where muted grey would be unreadable against teal. */
.def-sub[b-rsmm6rgtud] {
    color: var(--pos-gray-600);
}

.def-row.active .def-sub[b-rsmm6rgtud] {
    color: inherit;
    opacity: .85;
}
/* /Components/Pages/OrderCategoriesPage.razor.rz.scp.css */
/* The page, its body and its properties pane take app.css's split-panel rules (.split-page,
   .split-body, .split-props), shared by every split-panel page. */

/* One row of the type list. Its grip and its drop line are app.css's (.ft-grip,
   .ft-drop-target), shared by every reorderable list. */
.category-row[b-48j3hm11ay] {
    cursor: pointer;
}

/* text-truncate inside a flex row needs a floor of zero to shrink to. */
.category-text[b-48j3hm11ay] {
    min-width: 0;
}

/* The charge rows are inputs, so the table keeps them tight and drops the outer padding. */
.charges-table td[b-48j3hm11ay] {
    padding-left: 0.25rem;
    padding-right: 0.25rem;
}

.packaging-groups[b-48j3hm11ay] {
    padding-left: 1.5rem;
}
/* /Components/Pages/PaymentMethodsPage.razor.rz.scp.css */
/* The page, its body and its properties pane take app.css's split-panel rules (.split-page,
   .split-body, .split-props), shared by every split-panel page. */

/* One row of the method list. Its grip and its drop line are app.css's (.ft-grip,
   .ft-drop-target), shared by every reorderable list. */
.method-row[b-tkxrrpstuo] {
    cursor: pointer;
}

/* text-truncate inside a flex row needs a floor of zero to shrink to. */
.method-text[b-tkxrrpstuo] {
    min-width: 0;
}

/* What the rounding rule does to a few real bills, so the rule can be read without doing sums. */
.rounding-preview[b-tkxrrpstuo] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
}

.rounding-sample[b-tkxrrpstuo] {
    border: 1px solid var(--pos-gray-200);
    border-radius: .375rem;
    padding: .15rem .5rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.rounding-arrow[b-tkxrrpstuo] {
    color: var(--pos-gray-400);
    margin: 0 .15rem;
}

/* A square the QR sits inside whole: the picture is shown as uploaded, never cropped. Capped,
   because a QR only has to be big enough to check — it is scanned off the customer display. */
.qr-preview[b-tkxrrpstuo] {
    aspect-ratio: 1;
    max-width: 16rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--pos-gray-200);
    border-radius: .5rem;
    background: #fff;
    padding: .5rem;
}

.qr-preview img[b-tkxrrpstuo] {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.qr-empty[b-tkxrrpstuo] {
    color: var(--pos-gray-400);
    text-align: center;
}

.qr-empty[b-tkxrrpstuo]  .svg-icon {
    font-size: 2.5rem;
}
/* /Components/Pages/PrepLabelsPage.razor.rz.scp.css */
/* The line above the chips: what they are, and the switch that turns them into removals. */
.prep-chips-head[b-hhiq60sfpq] {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: 1rem 0 .4rem;
    color: var(--pos-gray-600);
    font-size: .9rem;
}

    .prep-chips-head .btn[b-hhiq60sfpq] {
        margin-left: auto;
    }

/* How long a food keeps, quieter than its name, inside the same chip. */
.prep-chip-days[b-hhiq60sfpq] {
    margin-left: .4rem;
    font-size: .8em;
    opacity: .75;
}

/* The two steppers side by side where there is room, one above the other where there is not. */
.prep-counts[b-hhiq60sfpq] {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem 3rem;
}
/* /Components/Pages/PrintersPage.razor.rz.scp.css */
/* The page, its body and its properties pane take app.css's split-panel rules (.split-page,
   .split-body, .split-props), shared by every split-panel page. */

/* A sticker printer's roll and alignment: a heading and a rule of their own, so the fields a kind
   brings with it read as belonging to that kind. Bootstrap sizes a legend like a heading; here it
   is a label for a group. */
.printer-section[b-hlpdywjq8g] {
    margin-top: 1rem;
    padding-top: .75rem;
    border-top: 1px solid var(--pos-gray-200);
}

.printer-section legend[b-hlpdywjq8g] {
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: .5rem;
}

/* How to line a printer up. A reading measure on the prose only, never on the fieldset, so the
   fields above keep the whole width. */
.printer-steps[b-hlpdywjq8g] {
    max-width: 46rem;
    margin: .75rem 0 0;
    padding-left: 1.2rem;
}

.printer-steps li + li[b-hlpdywjq8g] {
    margin-top: .25rem;
}
/* /Components/Pages/RecipesPage.razor.rz.scp.css */
/* The dock fills what the header leaves, and clips: a designer is a fixed frame with three
   scrolling panes in it, not a page that grows. */
.recipes-page[b-jy2m2a662c] {
    height: 100%;
    min-height: 0;
}

.recipes-dock[b-jy2m2a662c] {
    min-height: 0;
    overflow: hidden;
}

/* ---- Panel 1: the menu as a worklist --------------------------------------------------------
   The mark sits in the tile's top-left, where the "has options" glyph does not. ::deep, because
   the tile is MenuPicker's markup and never carries this page's scope. */
.recipes-dock[b-jy2m2a662c]  .rc-badge {
    position: absolute;
    top: .25rem;
    left: .25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.15rem;
    height: 1.15rem;
    border-radius: 50%;
    font-size: .7rem;
    line-height: 1;
}

/* Nothing decided draws NOTHING at all - an empty circle on two thirds of a menu would be forty
   marks saying the same thing, and the eye needs the two that do not. */
.recipes-dock[b-jy2m2a662c]  .rc-badge--undecided { display: none; }

.recipes-dock[b-jy2m2a662c]  .rc-badge--written {
    background: var(--pos-teal);
    color: #fff;
}

.recipes-dock[b-jy2m2a662c]  .rc-badge--empty {
    background: var(--pos-gray-200);
    color: var(--pos-gray-600);
}

/* ---- Panel 2: the entries --------------------------------------------------------------------
   The grip, then the dish over the way it was ordered. The grip and the line the dragged entry
   would land on are app.css's (.ft-grip, .ft-drop-target). */
.rc-entry[b-jy2m2a662c] {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
    padding: .4rem .75rem;
    font-size: .9rem;
    cursor: pointer;
}


/* text-truncate inside a flex row needs a floor of zero to shrink to. */
.rc-entry-text[b-jy2m2a662c] {
    flex: 1 1 auto;
    min-width: 0;
}

.rc-entry-dish[b-jy2m2a662c] {
    display: block;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-weight: 600;
}

.rc-entry-what[b-jy2m2a662c] {
    display: block;
    font-size: .82rem;
    opacity: .8;
}

/* Picked and nothing written. Quiet, because it is not wrong - most dishes need nothing. */
.rc-entry-none[b-jy2m2a662c] {
    flex: 0 0 auto;
    font-size: .78rem;
    font-style: italic;
    opacity: .7;
}

/* ---- Panel 3: the designer --------------------------------------------------------------------
   The preview is laid out as a stretch of a board column: the column's own gray behind one card,
   so the card's white and its station stripe read the way they do on the wall. */
.rc-preview[b-jy2m2a662c] {
    padding: .6rem .75rem;
    border: 1px solid var(--pos-gray-200);
    border-radius: .4rem;
    background: var(--pos-gray-50);
}

/* The cards as the board lays out a bill's: as many across as fit, each at least one readable
   card wide, and each its own height. The same rule as the board's .kb-bill-cards, because this is
   a stretch of the same column; the card keeps its own comfort ceiling. */
.rc-cards[b-jy2m2a662c] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(19rem, 100%), 1fr));
    align-items: start;
    gap: .6rem;
}

.rc-preview-label[b-jy2m2a662c] {
    margin-bottom: .25rem;
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--pos-gray-500);
}

/* ---- The note box ----------------------------------------------------------------------------
   A textarea beside the live preview above, which is the shape the slip designer uses. Monospace,
   because the tokens are easier to see against a fixed pitch and the line breaks ARE the steps. */
.rc-note[b-jy2m2a662c] {
    font-family: ui-monospace, SFMono-Regular, "Cascadia Mono", Menlo, Consolas, monospace;
    font-size: .85rem;
    line-height: 1.5;
    resize: vertical;
}

/* The writing tools above the snippets - bold, for now. */
.rc-tools[b-jy2m2a662c] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem;
    margin-top: .35rem;
}

.rc-tool[b-jy2m2a662c] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2rem;
    height: 2rem;
    padding: 0 .4rem;
    border: 1px solid var(--pos-gray-300);
    border-radius: .35rem;
    background: #fff;
    font-size: .9rem;
    line-height: 1;
    cursor: pointer;
}

.rc-tool:hover[b-jy2m2a662c] { border-color: var(--pos-teal); }

.rc-tool:disabled[b-jy2m2a662c] { opacity: .5; cursor: default; }

.rc-tool[b-jy2m2a662c]  .svg-icon { font-size: 1.2em; }

/* The snippets take no clicks while a save is on its way, the same as every button on the page -
   IconPicker has no disabled state of its own, and a second mark inserted into a note that is
   still being written back would be put onto the note from before it. */
.rc-snippets--busy[b-jy2m2a662c] {
    pointer-events: none;
    opacity: .6;
}
/* /Components/Pages/RolesPage.razor.rz.scp.css */
/* The page, its body and its properties pane take app.css's split-panel rules (.split-page,
   .split-body, .split-props), shared by every split-panel page. */

/* A reading measure on the prose and the name, never on the pane (see CLAUDE.md). */
.roles-name[b-luraiuwk6d],
.roles-note[b-luraiuwk6d] {
    max-width: 30rem;
}

.roles-group[b-luraiuwk6d] {
    margin-bottom: 1.25rem;
}

.roles-group-title[b-luraiuwk6d] {
    font-size: .8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--pos-gray-600);
    border-bottom: 1px solid var(--pos-gray-200);
    padding-bottom: .25rem;
    margin-bottom: .5rem;
}

/* A switch a finger can land on: the whole label toggles it, and the row is tall enough to hit. */
.roles-permission[b-luraiuwk6d] {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    min-height: 2.75rem;
    padding: .35rem 0 .35rem 2.75em;
    margin: 0;
}

    .roles-permission .form-check-input[b-luraiuwk6d] {
        margin-top: .2rem;
    }

    .roles-permission .form-check-label[b-luraiuwk6d] {
        display: flex;
        flex-direction: column;
        gap: .1rem;
        cursor: pointer;
        max-width: 46rem;
    }

.roles-permission-label[b-luraiuwk6d] {
    font-weight: 500;
}

.roles-permission-text[b-luraiuwk6d] {
    font-size: .85rem;
    color: var(--pos-gray-600);
}
/* /Components/Pages/SalesPage.razor.rz.scp.css */
/* The day's line above the table: the two numbers a cashier opens this page for. */
.sales-totals[b-rtyk69ae43] {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    padding: .5rem .75rem;
    margin-bottom: .75rem;
    border: 1px solid var(--pos-gray-300);
    border-radius: .375rem;
    background: var(--pos-gray-100);
}

.sales-total-bills[b-rtyk69ae43] {
    font-weight: 600;
    color: var(--pos-gray-700);
}

.sales-total-amount[b-rtyk69ae43] {
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--pos-teal);
}

.sales-total-refund[b-rtyk69ae43] {
    color: var(--bs-danger);
    font-size: .875rem;
}

/* The DAY's cash position, under the takings: the float, the cash taken, and what should therefore
   be in the drawer. Quieter than the line above it because that one is the day's business and this
   one is a reconciliation aid - it becomes the head of the cash-up screen when that lands. */
.sales-day[b-rtyk69ae43] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .5rem;
    padding: .4rem .75rem;
    margin-bottom: .75rem;
    border: 1px solid var(--pos-gray-200);
    border-radius: .375rem;
    font-size: .9rem;
}

.sales-day-label[b-rtyk69ae43] {
    font-weight: 600;
    color: var(--pos-gray-700);
    margin: 0;
}

/* Wide enough for a four-figure float and no wider; it sits in a row of text, not a form. */
.sales-day-input[b-rtyk69ae43] {
    width: 7rem;
    font-variant-numeric: tabular-nums;
}

.sales-day-sep[b-rtyk69ae43] {
    color: var(--pos-gray-400);
}

.sales-day-expected[b-rtyk69ae43] {
    font-variant-numeric: tabular-nums;
    color: var(--pos-teal);
}

/* Says when the drawer figure spans more than this day, because the count carries forward. Gold,
   not red: nothing is wrong, the number simply covers more ground than the row it sits in. */
.sales-day-carried[b-rtyk69ae43] {
    margin-left: auto;
    font-size: .8rem;
    color: var(--pos-gold-dark);
}

/* The delivery app's number under the table or customer. Teal and tabular like every other copy
   of it, so the number a rider reads out looks the same here as on the till and the board. */
.sales-ref[b-rtyk69ae43] {
    font-variant-numeric: tabular-nums;
    color: var(--pos-teal-dark);
    white-space: nowrap;
}

/* WHICH WAY THE ORDER CAME IN, under the place. A pill rather than a plain line like the
   reference above it, because this is a LABEL and not a value - there is nothing to read off it,
   only a mark to spot while scanning a day.

   Teal, the same family as the reference, because both answer "which channel was this". The two
   never appear together in practice: a delivery order is keyed at the till and a customer
   ordering from their own phone is never asked for a reference.

   The glyph needs ::deep - the <svg> is SvgIcon's markup and never carries this page's scope
   attribute - and it must not shrink when the pair wraps onto two lines inside the pill. It is
   also the one glyph in the app that has to be drawn BIGGER than the words beside it: a QR code
   is a grid of squares, and at the pill's own .78rem it came out a smudge nobody could name.
   Sizing works through font-size because an SvgIcon is 1em square.

   Which is what the VERTICAL padding is for. The glyph is then the tallest thing in the box, so
   with none the pill came out exactly as tall as the glyph and the squares touched both edges. */
.sales-channel[b-rtyk69ae43] {
    display: inline-flex;
    align-items: center;
    gap: .3em;
    max-width: 100%;
    padding: .15em .58em;
    border-radius: .75em;
    background-color: var(--pos-teal-light);
    color: var(--pos-teal-dark);
    font-size: .78rem;
    line-height: 1.35;
}

    .sales-channel[b-rtyk69ae43]  .svg-icon {
        flex: 0 0 auto;
        font-size: 1.25em;
    }

/* What a hand-applied discount or surcharge moved this bill by, under its total. Gold, which on
   every screen in this app means the one thing worth looking at - and on a page somebody reads to
   check a day, a bill priced by hand is exactly that. It sits on its own line so the column of
   totals still lines up on the decimal point. */
.sales-adjusted[b-rtyk69ae43] {
    display: block;
    font-size: .8em;
    font-weight: 500;
    color: var(--pos-gold-dark);
    font-variant-numeric: tabular-nums;
}
/* /Components/Pages/SalesReportPage.razor.rz.scp.css */
/* The report fills the layout's article (a flex column) and each TAB scrolls inside its own pane,
   never the page - the same shape the POS screen has, because it is the same dock. The page used to
   be a container-fluid p-4; that padding is now the head's and the panes' own. */
.report-page[b-dalh39udww] {
    flex: 1 1 auto;
    min-height: 0;
    padding: 1.5rem 1.5rem 0;
}

.report-head[b-dalh39udww] {
    flex: 0 0 auto;
}

/* The dock fills what is left, and is pulled back out to the page's own edges so the PANE can carry
   the same 1.5rem the head carries. The inset has to live on the pane rather than on the dock: put
   it on the dock and every card sits a rem further in than the title above it, which is the
   misalignment this cancels. dock.css sizes the host at 100% of this. */
.report-dock[b-dalh39udww] {
    min-height: 0;
    position: relative;
    margin: 0 -1.5rem;
}

/* A tab's content scrolls inside the panel, inset to line up with the head above it. The app's page
   grey rather than the dock's white, so the cards read as cards. */
.report-pane[b-dalh39udww] {
    height: 100%;
    overflow-y: auto;
    padding: 1.5rem;
    background: var(--pos-gray-50);
}

/* A tab's own PDF, at the far end of the tab strip's row (DockPanelDef.Actions). Slimmer than a
   small button usually is, so the strip keeps the height its tabs give it. */
.report-pdf[b-dalh39udww] {
    padding-top: .1rem;
    padding-bottom: .1rem;
}

/* The tabs' cards in COLUMNS that sit side by side only while each has room, and stack at full
   width otherwise. Each column's flex basis is the least it may have beside another, and the row
   wraps as soon as the bases do not fit.

   In REM, so everything that takes room counts: the screen's width, the nav's (open, a column of
   its own; collapsed, 4rem), and the device's display scale, which makes every rem bigger. The
   Bootstrap columns this replaces decided by the SCREEN's width alone, at 1200px: on a 1280px
   tablet with the nav open each half came to 484px, the web's header broke into four rows, and
   its legend into one entry per row. */
.report-columns[b-dalh39udww] {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    align-items: flex-start;
}

/* A half: two of them need 73.5rem side by side. */
.report-column[b-dalh39udww] {
    flex: 1 1 36rem;
    min-width: 0;
}

/* The wider and the narrower of an uneven pair - the Itemised tab's dishes and what sits beside
   them - which need 63.5rem between them and grow two to one. */
.report-column-major[b-dalh39udww] {
    flex: 2 1 40rem;
    min-width: 0;
}

.report-column-minor[b-dalh39udww] {
    flex: 1 1 22rem;
    min-width: 0;
}

/* The whole width, always: the traffic graph is read left to right through the day. */
.report-column-full[b-dalh39udww] {
    flex: 1 1 100%;
    min-width: 0;
}

/* The label-and-amount rows and the report tables are in app.css (.report-rows, .report-table),
   because the itemised report reads the same way. Each Overall card's own styles are beside it in
   Components/Sales/ReportCards. */
/* /Components/Pages/ScheduledJobsPage.razor.rz.scp.css */
/* The page, its body and its properties pane take app.css's split-panel rules (.split-page,
   .split-body, .split-props), shared by every split-panel page. */

/* A reading measure on the prose and the field, never on the pane (see CLAUDE.md). */
.job-prose[b-kesbtpm4v1],
.job-cron[b-kesbtpm4v1],
.job-words[b-kesbtpm4v1] {
    max-width: 46rem;
}

/* What the schedule means, in words: the screen's language first, the other quieter under it. */
.job-words-1[b-kesbtpm4v1] {
    font-weight: 500;
}

.job-words-2[b-kesbtpm4v1] {
    font-size: .85rem;
    color: var(--pos-gray-600);
}

.job-next li[b-kesbtpm4v1] {
    font-variant-numeric: tabular-nums;
}

/* A switch a finger can land on, as on the Roles screen. */
.job-switch[b-kesbtpm4v1] {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    min-height: 2.75rem;
    padding: .35rem 0 .35rem 2.75em;
    margin: 0;
}

    .job-switch .form-check-label[b-kesbtpm4v1] {
        display: flex;
        flex-direction: column;
        gap: .1rem;
        cursor: pointer;
        max-width: 46rem;
    }

.job-switch-text[b-kesbtpm4v1] {
    font-size: .85rem;
    color: var(--pos-gray-600);
}

.job-outcome-done[b-kesbtpm4v1] {
    color: var(--pos-teal);
}

.job-outcome-failed[b-kesbtpm4v1] {
    color: var(--pos-red);
}

/* The active row is white on teal: the glyph takes the row's own colour there. */
.list-group-item.active .job-outcome[b-kesbtpm4v1] {
    color: inherit;
}

.job-message[b-kesbtpm4v1] {
    overflow-wrap: anywhere;
}
/* /Components/Pages/ShopLayoutPage.razor.rz.scp.css */
/* The page, its body and its properties pane take app.css's split-panel rules (.split-page,
   .split-body, .split-props), shared by every split-panel page. */

.shop-layout-tabs .nav-link[b-ix1iqt1pss] {
    display: inline-flex;
    align-items: center;
}

.shop-layout-tabs .nav-link.active .count-pill[b-ix1iqt1pss] {
    background: var(--pos-teal-light);
    color: var(--pos-teal-dark);
}

.shop-layout-tab-add[b-ix1iqt1pss] {
    color: var(--pos-gray-500);
}

.shop-layout-toolbar[b-ix1iqt1pss] {
    background: var(--pos-gray-50);
}

.shop-layout-props[b-ix1iqt1pss] {
    background: var(--pos-gray-50);
}
/* /Components/Pages/ShopSettingsPage.razor.rz.scp.css */
/* ---- One type scale for the whole page ----

   Four sizes and nothing else: a section title, a section's one-line intro, a setting's label, and
   a setting's description. Everything smaller than a label - the description, the "Why" summary and
   what is inside it, the rounding samples - is the same size, so the page reads as two levels
   rather than six. Before this the page was built out of Bootstrap's h6, .form-text, .small and a
   bare <p>, which is four sizes chosen a field at a time.

   The second language sizes itself: T's .t-2 is .78em of whatever it sits in, so setting the size
   once on the label or the description sets both halves. */

/* The search box. Capped rather than full width: a box the width of a monitor looks like it wants
   a sentence, and what goes in it is a word. Same shape as the stock screen's search, because the
   two do the same job. */
/* .search-box (app.css) draws the box and its magnifier. */
.settings-search[b-i6m1lrgsmb] {
    max-width: 28rem;
    margin-bottom: 1rem;
}

/* The rail and the page side by side. min-height: 0 is what lets the two scroll instead of growing
   the shell, which is locked to the viewport. */
.settings-body[b-i6m1lrgsmb] {
    display: flex;
    gap: 1.5rem;
    min-height: 0;
}

/* A FIXED width, not a splitter. Every other split-panel page here is draggable because both sides
   hold content worth trading width over; this side holds four short phrases, so a drag could only
   make it worse, and the page wants the rest for its prose. */
.settings-rail[b-i6m1lrgsmb] {
    flex: 0 0 13.5rem;
    overflow-y: auto;
    border-right: 1px solid var(--pos-gray-200);
    padding-right: .5rem;
}

.settings-rail.is-empty[b-i6m1lrgsmb] {
    display: none;
}

.settings-rail-item[b-i6m1lrgsmb] {
    display: block;
    width: 100%;
    text-align: left;
    border: 0;
    background: transparent;
    border-radius: .375rem;
    padding: .45rem .6rem;
    font-size: .9375rem;
    color: var(--pos-gray-700);
    line-height: 1.25;
}

.settings-rail-item + .settings-rail-item[b-i6m1lrgsmb] {
    margin-top: .15rem;
}

.settings-rail-item:hover[b-i6m1lrgsmb] {
    background: var(--pos-gray-100);
}

/* The section under the reader's eye. The class is written by wwwroot/js/settingsNav.js, never by
   the circuit: it changes with the scroll, and a render per frame is what that module exists to
   avoid. A tint plus a bar - the bar is what carries at a glance down a column of four. */
.settings-rail-item.is-current[b-i6m1lrgsmb] {
    background: var(--pos-teal-light);
    color: var(--pos-teal-dark);
    font-weight: 600;
    box-shadow: inset .2rem 0 0 0 var(--pos-teal);
}

/* The page itself. */
.settings-scroll[b-i6m1lrgsmb] {
    flex: 1 1 auto;
    min-width: 0;
    overflow-y: auto;
    /* The .6rem each side is what the rows bleed into. A row is inset by that much and pulled back
       out by the same, so its search highlight is wider than its text; without the padding here the
       right-hand bleed is scrollable overflow, and a narrow screen gets a horizontal scrollbar
       under the entire page. Setting overflow-x: hidden would have hidden the symptom and any
       real overflow with it. The trailing space is deliberate: without it the last section can
       never be scrolled up to the reading line, so the rail would light the one above it and a tap
       on the last entry would appear to do nothing. */
    padding: 0 .6rem 35vh;
}

/* ---- A section ---- */

/* The section is CAPPED, and this is the one place on the page where capping a container is right.
   The rule elsewhere - a reading measure goes on the prose, never on the pane - exists because a
   capped pane leaves inputs stopping short of a wide screen. Here the cap is what makes the two
   columns a pair: uncapped, the text keeps its 46rem measure and the control column is flung to the
   far edge of a 2048px monitor with a foot of nothing between a description and the thing it
   describes. 46rem of prose plus the gap plus the control column is what the number is. */
.settings-section[b-i6m1lrgsmb] {
    max-width: 70rem;
}

/* A rule between sections rather than a card around each one. Cards would say these are four
   things of the same kind to choose between, which is what the page used to be. */
.settings-section + .settings-section[b-i6m1lrgsmb] {
    margin-top: 2rem;
    padding-top: 2rem;
    border-top: 1px solid var(--pos-gray-200);
}

/* Title left, the way out to a related page right, on one row. A cross-reference written as a
   sentence under the intro was two more lines for a link. */
.settings-section-head[b-i6m1lrgsmb] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.settings-section-title[b-i6m1lrgsmb] {
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--pos-gray-900);
    margin: 0;
}

.settings-section-link[b-i6m1lrgsmb] {
    font-size: .8125rem;
    text-decoration: none;
}

.settings-section-link:hover[b-i6m1lrgsmb] {
    text-decoration: underline;
}

.settings-section-intro[b-i6m1lrgsmb] {
    font-size: .875rem;
    color: var(--pos-gray-600);
    margin: .2rem 0 .5rem;
    max-width: 46rem;
}

/* ---- A setting ----

   Every rule about a setting reaches into child components through :where(.settings-scroll) ::deep,
   because a row's label, description and "?" are SettingText's markup, and the slip rows are
   SlipPrintMatrix's. Kept here rather than split between them, so the page's one type scale stays
   in one file. The :where adds nothing to a rule's specificity - the scope attribute moves from
   the element to the pane, one for one - so the cascade is exactly what it was. */

/* Label and description on the left, the control on the right. The control column is a fixed width
   so every control on the page lines up down one edge, which is most of what makes a settings page
   feel ordered; the text takes what is left, capped at a reading measure. */
:where(.settings-scroll)[b-i6m1lrgsmb]  .setting {
    display: flex;
    align-items: start;
    gap: 1.5rem;
    padding: .85rem .6rem;
    margin: 0 -.6rem;
    border-radius: .375rem;
}

:where(.settings-scroll)[b-i6m1lrgsmb]  .setting + .setting {
    border-top: 1px solid var(--pos-gray-100);
}

:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-text {
    flex: 1 1 auto;
    min-width: 0;
    max-width: 46rem;
    /* The hint card's containing block. Anchoring the card here rather than to the little box round
       the "?" is what keeps it inside the pane: it is then as wide as the description, wherever
       along the label the "?" happens to sit. */
    position: relative;
}

/* The label, and the "?" that has more to say about it. */
:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-head {
    display: flex;
    align-items: flex-start;
    gap: .3rem;
}

/* 22rem is the basis, not a floor: 0 0 22rem refused to give anything back, so between the
   stacking width and a wide screen the control ate the row and the description was left with a
   couple of centimetres. It shrinks now, and stops at a width a select is still usable at. */
.setting-control[b-i6m1lrgsmb] {
    flex: 0 1 22rem;
    min-width: 11rem;
    max-width: 100%;
}

/* A stored setting the page will not use as it stands, and the one tap that puts it right. */
.setting-warning[b-i6m1lrgsmb] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem .6rem;
    margin-top: .45rem;
    font-size: .85rem;
    color: var(--pos-red-dark);
}

/* The days of the month as a week-wide grid, the shape a month is read in, each a toggle a finger
   can hit. */
.month-days[b-i6m1lrgsmb] {
    display: grid;
    grid-template-columns: repeat(7, minmax(2.4rem, 1fr));
    gap: .3rem;
}

.month-days .btn[b-i6m1lrgsmb] {
    min-height: 2.4rem;
    padding: 0;
    font-variant-numeric: tabular-nums;
}

:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-label {
    display: block;
    font-size: .9375rem;
    font-weight: 500;
    color: var(--pos-gray-900);
    margin-bottom: .1rem;
}

:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-help {
    font-size: .8125rem;
    color: var(--pos-gray-600);
}

/* A setting the search matched. Gold, and gold only ever means "the one thing to look at" - it is
   on screen only while somebody is searching, and it is the answer they asked for. The bar is what
   carries when several rows match and the tint alone stops being a signal. */
:where(.settings-scroll)[b-i6m1lrgsmb]  .setting.is-match {
    background: var(--pos-gold-light);
    box-shadow: inset .2rem 0 0 0 var(--pos-gold);
}

:where(.settings-scroll)[b-i6m1lrgsmb]  .setting.is-match + .setting,
:where(.settings-scroll)[b-i6m1lrgsmb]  .setting + .setting.is-match {
    border-top-color: transparent;
}

/* The switch, sized up from Bootstrap's default so it reads as a control rather than a tick, and
   with the left padding of a .form-check it does not need without a label beside it. The input is
   InputCheckbox's markup, so the size and the margin only reach it through ::deep - written plain,
   the switch stayed Bootstrap's size and hung 40px left of the column, on a margin meant for the
   padding taken away here. */
:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-switch {
    padding-left: 0;
    min-height: 0;
}

:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-switch .form-check-input {
    width: 2.75rem;
    height: 1.5rem;
    margin: 0;
}

/* ---- The "?" hint ---- */

/* Deliberately NOT positioned: see .setting-text. */
:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-hint {
    display: inline-flex;
}

:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-hint-btn {
    border: 0;
    background: transparent;
    padding: 0;
    line-height: 1;
    font-size: .9rem;
    color: var(--pos-gray-400);
    cursor: help;
}

:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-hint-btn:hover,
:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-hint:focus-within .setting-hint-btn {
    color: var(--pos-teal);
}

/* Hover OR focus, so a tap on a tablet opens it and the keyboard reaches it. The 2px gap under the
   label is small enough that a pointer travelling from the "?" into the card never leaves both, so
   the card can be read without it closing under the mouse. */
:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-hint-card {
    position: absolute;
    left: 0;
    top: calc(100% + 2px);
    z-index: 5;
    width: min(30rem, 100%);
    padding: .65rem .8rem;
    background: #fff;
    border: 1px solid var(--pos-gray-200);
    border-left: 3px solid var(--pos-teal);
    border-radius: 0 .375rem .375rem 0;
    box-shadow: 0 .5rem 1.25rem rgba(32, 36, 40, .16);
    font-size: .8125rem;
    color: var(--pos-gray-700);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .1s ease;
}

:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-hint:hover .setting-hint-card,
:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-hint:focus-within .setting-hint-card {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

/* Above its row instead, for a row sitting too low on the screen to show the card below it. The
   class is put on by wwwroot/js/settingsNav.js in the moment between the pointer arriving and the
   card being painted - a fit is a question about position, which is the browser's to answer. */
:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-hint.is-above .setting-hint-card {
    top: auto;
    bottom: calc(100% + 2px);
}

:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-hint-title {
    font-weight: 600;
    color: var(--pos-gray-900);
    margin-bottom: .3rem;
}

:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-hint-card p {
    margin: 0;
}

:where(.settings-scroll)[b-i6m1lrgsmb]  .setting-hint-card p + p {
    margin-top: .5rem;
}

/* ---- The rounding samples ---- */

/* What the rule does to a few real bills, so it can be read without doing sums. Deliberately the
   same shape as the strip on PaymentMethodDetailPage - the two rules compose, so they must be read
   the same way - and repeated here because scoped CSS does not cross pages. */
.rounding-preview[b-i6m1lrgsmb] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    padding: .25rem 0 .5rem;
}

.rounding-sample[b-i6m1lrgsmb] {
    border: 1px solid var(--pos-gray-200);
    border-radius: .375rem;
    padding: .15rem .5rem;
    font-size: .8125rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.rounding-arrow[b-i6m1lrgsmb] {
    color: var(--pos-gray-400);
    margin: 0 .15rem;
}

.settings-empty[b-i6m1lrgsmb] {
    padding: 1rem 0;
    font-size: .875rem;
    color: var(--pos-gray-600);
}

/* ---- Narrow ---- */

/* Narrow enough that a 13.5rem column is a third of the screen: the rail lies down and becomes a
   strip of chips over the page, and a setting's control drops under its description. Still the
   same markup and the same is-current class - only the direction changes. */
/* ---- Narrow ---- */

/* TWO breakpoints, because the two things give way at different widths. A setting row wants roughly
   22rem of control plus a readable description beside it, and runs out long before the rail does -
   so the row stacks first and the rail keeps its column. Both are guesses at the PANE's width made
   from the viewport's, which is all a media query can see, and the sidebar's own collapse at 1200px
   moves the answer: below it the sidebar is 64px and the pane is suddenly far wider. 64rem is the
   width at which the pane is too narrow with the sidebar already collapsed. */
@media (max-width: 64rem) {
    :where(.settings-scroll)[b-i6m1lrgsmb]  .setting {
        flex-direction: column;
        gap: .5rem;
    }

    .setting-control[b-i6m1lrgsmb] {
        flex: 0 0 auto;
        width: 100%;
        max-width: 28rem;
    }
}

@media (max-width: 52rem) {
    .settings-body[b-i6m1lrgsmb] {
        flex-direction: column;
        gap: .75rem;
    }

    .settings-rail[b-i6m1lrgsmb] {
        flex: 0 0 auto;
        display: flex;
        gap: .4rem;
        overflow-x: auto;
        overflow-y: hidden;
        border-right: 0;
        border-bottom: 1px solid var(--pos-gray-200);
        padding: 0 0 .5rem 0;
    }

    .settings-rail-item[b-i6m1lrgsmb] {
        width: auto;
        white-space: nowrap;
        flex: 0 0 auto;
    }

    .settings-rail-item + .settings-rail-item[b-i6m1lrgsmb] {
        margin-top: 0;
    }

    .settings-rail-item.is-current[b-i6m1lrgsmb] {
        box-shadow: inset 0 -.2rem 0 0 var(--pos-teal);
    }
}
/* /Components/Pages/SlipTemplateEditorPage.razor.rz.scp.css */
/* The block tree. Indentation carries the nesting, so a repeat's contents read as inside it. */

.slip-blocks[b-mk1m17z3jf] {
    list-style: none;
    margin: 0;
    padding-left: 0;
}

.slip-blocks .slip-blocks[b-mk1m17z3jf] {
    padding-left: 1rem;
    border-left: 1px dashed var(--pos-gray-300);
    margin-left: .5rem;
}

.slip-block[b-mk1m17z3jf] {
    display: flex;
    align-items: baseline;
    gap: .4rem;
    padding: .2rem .4rem;
    border-radius: 3px;
    cursor: pointer;
    font-size: .85rem;
}

.slip-block:hover[b-mk1m17z3jf] {
    background: var(--pos-gray-100);
}

.slip-block.active[b-mk1m17z3jf] {
    background: var(--pos-teal);
    color: #fff;
}

.slip-block.active .slip-block-kind[b-mk1m17z3jf] {
    color: rgb(255 255 255 / 0.75);
}

.slip-block-kind[b-mk1m17z3jf] {
    flex: 0 0 auto;
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--pos-gray-600);
}

/* `pre` rather than `nowrap`: leading spaces are how a design indents, so the tree has to show
   them. HTML would otherwise collapse them and an indented block would look unindented. */
.slip-block-text[b-mk1m17z3jf] {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: pre;
    font-family: "Cascadia Mono", "Consolas", monospace;
}

.slip-block-tools[b-mk1m17z3jf] {
    flex: 0 0 auto;
    opacity: 0;
}

.slip-block:hover .slip-block-tools[b-mk1m17z3jf],
.slip-block.active .slip-block-tools[b-mk1m17z3jf] {
    opacity: 1;
}

.slip-block.active .slip-block-tools .btn-link[b-mk1m17z3jf] {
    color: #fff;
}

/* ---- Dragging a block to a new place ------------------------------------

   The grab cursor is the only thing that says a row can be dragged at all. There is no handle:
   the rows are one line tall, and a handle narrow enough to fit would be harder to hit than the
   arrows it was meant to improve on. */
.slip-block[b-mk1m17z3jf] {
    cursor: grab;
}

.slip-block.dragging[b-mk1m17z3jf] {
    cursor: grabbing;
    opacity: .4;
}

/* The landing place, marked as a line ON the row rather than a box around it - a box says "into
   this block", which is the one thing a drop cannot do here. Gold, which the theme keeps for the
   one thing that has to be found at a glance. Inset, so the row does not move as it is marked;
   anything that shifts the list under a dragging cursor makes the target hard to hold. */
.slip-block.drag-over[b-mk1m17z3jf] {
    box-shadow: inset 0 3px 0 0 var(--pos-gold);
}

/* The dock fills what the header leaves. min-height:0 because a flex child will not shrink below
   its content otherwise, and the dock sizes its panels from ITS height - without this the three
   panels grow to fit their contents and the page scrolls instead of the panels. position:relative
   because a floating card is placed against this box. */
.slip-dock[b-mk1m17z3jf] {
    min-height: 0;
    position: relative;
}
/* /Components/Pages/StockPage.razor.rz.scp.css */
/* Fills the layout's article, so the tiles scroll under a filter bar that stays put. */
.stock-page[b-7dv0t7alq0] {
    flex: 1 1 auto;
    min-height: 0;
}

/* The filter bar. A flex row that wraps, so on a tablet the search takes a line of its own and
   the pills drop under it, rather than everything shrinking until nothing can be tapped. */
.stock-filters[b-7dv0t7alq0] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .75rem;
    margin-bottom: 1rem;
    /* It never gives up its own height to the tiles below - the trap the Kanban bar's segments
       and the menu picker's category strip both fell into. */
    flex: 0 0 auto;
}

/* .search-box (app.css) draws the box and its magnifier; this one is bigger, for a finger. */
.stock-search[b-7dv0t7alq0] {
    flex: 1 1 18rem;
    min-width: 14rem;
}

.stock-search input[b-7dv0t7alq0] {
    min-height: 3rem;
    font-size: 1.05rem;
}

.stock-pills[b-7dv0t7alq0] {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

/* A filter is a finger target, not a link. */
.stock-pill[b-7dv0t7alq0] {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    min-height: 3rem;
    padding: .35rem .9rem;
    border: 2px solid var(--pos-gray-300);
    border-radius: 2rem;
    background: #fff;
    color: var(--pos-gray-700);
    font-weight: 600;
}

.stock-pill:hover:not(:disabled)[b-7dv0t7alq0] {
    border-color: var(--pos-teal);
}

.stock-pill.is-on[b-7dv0t7alq0] {
    background: var(--pos-teal);
    border-color: var(--pos-teal);
    color: #fff;
}

.stock-pill:disabled[b-7dv0t7alq0] {
    opacity: .5;
}

.stock-pill-count[b-7dv0t7alq0] {
    padding: 0 .4rem;
    border-radius: 1rem;
    background: var(--pos-gray-100);
    color: var(--pos-gray-700);
    font-size: .85rem;
    font-weight: 700;
}

.stock-pill.is-on .stock-pill-count[b-7dv0t7alq0] {
    background: rgba(255, 255, 255, .25);
    color: #fff;
}

/* What is off is the one thing on this page somebody may be looking for from across the room. */
.stock-pill-off.is-on[b-7dv0t7alq0] {
    background: var(--pos-red);
    border-color: var(--pos-red);
}

.stock-pill-off:not(.is-on):not(:disabled)[b-7dv0t7alq0] {
    border-color: var(--pos-red-border);
    color: var(--pos-red-dark);
}

.stock-body[b-7dv0t7alq0] {
    min-height: 0;
    overflow-y: auto;
}

/* Sticky, because a long list of dishes scrolls past its own heading and the three sections
   otherwise run into one another. */
.stock-heading[b-7dv0t7alq0] {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: 0 0 .6rem;
    padding: .5rem 0;
    background: #fff;
    color: var(--pos-gray-700);
}

.stock-heading + .stock-grid[b-7dv0t7alq0] {
    margin-bottom: 1.5rem;
}

.stock-heading-count[b-7dv0t7alq0] {
    padding: 0 .5rem;
    border-radius: 1rem;
    background: var(--pos-gray-100);
    font-size: .8rem;
    font-weight: 700;
}

/* Tiles: the same shape the order screen's menu uses, so the two screens feel like one app.
   max-content rows, never auto - an auto row only grows into free space, and a scrolling
   container never has any, which is what once left the photos out of the menu picker's tiles. */
.stock-grid[b-7dv0t7alq0] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    grid-auto-rows: max-content;
    align-content: start;
    gap: .6rem;
}

.stock-tile[b-7dv0t7alq0] {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    min-height: 5rem;
    padding: .5rem .6rem;
    border: 2px solid var(--pos-gray-300);
    border-radius: .5rem;
    background: #fff;
    color: inherit;
    text-align: left;
}

.stock-tile:hover[b-7dv0t7alq0] {
    border-color: var(--pos-teal);
}

.stock-tile:active[b-7dv0t7alq0] {
    background: var(--pos-teal-light);
}

/* Off the menu, and unmistakably so from across a kitchen. */
.stock-tile.is-off[b-7dv0t7alq0] {
    border-color: var(--pos-red);
    background: var(--pos-red-light);
}

/* Off because something ABOVE it is off. Dashed, because the way to put it back is not here. */
.stock-tile.is-parent-off[b-7dv0t7alq0] {
    border-style: dashed;
}

/* The slot is drawn whether or not there is a photo, so the names line up across a row. */
.stock-tile-photo[b-7dv0t7alq0] {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    margin-bottom: .25rem;
    border-radius: .35rem;
    background: var(--pos-gray-100);
    overflow: hidden;
}

.stock-tile-photo img[b-7dv0t7alq0] {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.stock-tile.is-off .stock-tile-photo img[b-7dv0t7alq0] {
    /* Greyed, so a wall of photos does not go on advertising what the kitchen cannot cook. */
    filter: grayscale(1);
    opacity: .6;
}

.stock-tile-name[b-7dv0t7alq0] {
    font-weight: 600;
    line-height: 1.15;
}

.stock-tile-sub[b-7dv0t7alq0] {
    color: var(--pos-gray-600);
    font-size: .8rem;
    line-height: 1.2;
}

/* Pushed to the foot of the tile, so the badges of a row sit on one line. */
.stock-tile-state[b-7dv0t7alq0] {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    margin-top: auto;
    padding-top: .35rem;
}

/* Gold: worth knowing, and not this row being off. The theme's one scarce colour, used here for
   the two notes that would otherwise be read as an alarm. */
.stock-note-badge[b-7dv0t7alq0] {
    padding: .1rem .4rem;
    border-radius: .3rem;
    background: var(--pos-gold-light);
    color: var(--pos-gold-dark);
    font-size: .75rem;
    font-weight: 600;
    line-height: 1.15;
}

.stock-empty[b-7dv0t7alq0] {
    padding: 3rem 0;
    text-align: center;
}
/* /Components/Pages/UsersPage.razor.rz.scp.css */
/* The person open beside the list (TableBeside's right side): their own header, then the form. */
.user-pane[b-eids4qhfww] {
    padding: .75rem 1rem 1rem;
}

.user-pane-head[b-eids4qhfww] {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    margin-bottom: 1rem;
}

.user-pane-title[b-eids4qhfww] {
    flex: 1 1 auto;
    min-width: 0;
}

/* Wide enough for an eight-digit PIN and its placeholder, and no wider: it sits beside its buttons. */
.user-pin-input[b-eids4qhfww] {
    width: 12rem;
}
/* /Components/Pos/BatchStrip.razor.rz.scp.css */
/* The order's batch chips (BatchStrip). */

.pos-batch-chip[b-y70yj1f3jg] {
    min-height: 2rem;
}

/* The print-problem chip is its glyph and nothing else, so it needs a width of its own: a .btn-sm
   wrapped round one 1em triangle is a target narrower than the gap beside it. Square, which is
   also what tells it apart from the numbered chips it sits among. */
.pos-print-problem-chip[b-y70yj1f3jg] {
    min-width: 2rem;
}

/* Slips still at the printer: the chip is quiet and not tappable, but must not look broken
   (Bootstrap greys a disabled button out). */
.pos-batch-printing:disabled[b-y70yj1f3jg] {
    opacity: 1;
    font-style: italic;
}
/* /Components/Pos/BillAdjustmentDialog.razor.rz.scp.css */
/* Two columns: the presets, which nearly every press uses, and the one-off pad beside them. They
   stack under 700px, where a dialog is most of a phone and a row of two would leave the pad four
   keys wide. */
.adj[b-on62uk1p5h] {
    display: flex;
    gap: 1rem;
    align-items: flex-start;
}

.adj-main[b-on62uk1p5h] {
    flex: 1 1 auto;
    min-width: 0;
}

.adj-oneoff[b-on62uk1p5h] {
    flex: 0 0 15rem;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    padding-left: 1rem;
    border-left: 1px solid var(--pos-gray-200);
}

@media (max-width: 700px) {
    .adj[b-on62uk1p5h] {
        flex-direction: column;
    }

    .adj-oneoff[b-on62uk1p5h] {
        flex: 1 1 auto;
        width: 100%;
        padding-left: 0;
        padding-top: .75rem;
        border-left: 0;
        border-top: 1px solid var(--pos-gray-200);
    }
}

/* What the bill comes to, which is the question the whole dialog is about, so it is the biggest
   thing in it. */
.adj-total[b-on62uk1p5h] {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    padding-bottom: .5rem;
    border-bottom: 1px solid var(--pos-gray-200);
}

.adj-total-label[b-on62uk1p5h] {
    font-size: .85rem;
    color: var(--pos-gray-600);
    margin-right: auto;
}

.adj-total-was[b-on62uk1p5h] {
    font-size: 1.1rem;
}

/* ::deep, because the arrow is SvgIcon's <svg> and carries SvgIcon's scope, not this one. */
.adj-total[b-on62uk1p5h]  .adj-total-arrow {
    color: var(--pos-gray-400);
}

.adj-total-now[b-on62uk1p5h] {
    font-size: 1.6rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* What is already on the bill. Each row carries who applied it, because this is money somebody
   decided to give away and the bill is the only place that is visible while it is still open. */
.adj-applied[b-on62uk1p5h] {
    margin: .6rem 0;
    display: flex;
    flex-direction: column;
    gap: .35rem;
}

.adj-applied-row[b-on62uk1p5h] {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .35rem .5rem;
    background: var(--pos-gray-50);
    border: 1px solid var(--pos-gray-200);
    border-radius: .375rem;
}

.adj-applied-name[b-on62uk1p5h] {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.adj-applied-figure[b-on62uk1p5h],
.adj-applied-by[b-on62uk1p5h] {
    margin-left: .4em;
    font-size: .8em;
    color: var(--pos-gray-500);
}

.adj-applied-amount[b-on62uk1p5h] {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* The presets. Two across on anything but a phone, so a name has room to be read - these are the
   shop's own words and may be two languages long. */
.adj-presets[b-on62uk1p5h] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: .5rem;
}

.adj-preset[b-on62uk1p5h] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .15rem;
    min-height: 3.25rem;
    padding: .5rem .7rem;
    text-align: left;
    border: 1px solid var(--pos-gray-300);
    background: #fff;
}

.adj-preset:hover:not(:disabled)[b-on62uk1p5h] {
    background: var(--pos-gray-50);
}

.adj-preset-name[b-on62uk1p5h] {
    font-weight: 500;
    line-height: 1.2;
}

.adj-preset-figure[b-on62uk1p5h] {
    font-size: 1.05rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* A discount takes money off and a surcharge puts it on, and which one a button is has to be
   readable before it is pressed - the figure alone says 20%, not which way. */
.adj-preset.is-discount .adj-preset-figure[b-on62uk1p5h] {
    color: var(--pos-teal-dark);
}

.adj-preset.is-surcharge .adj-preset-figure[b-on62uk1p5h] {
    color: var(--pos-gray-700);
}

.adj-empty[b-on62uk1p5h] {
    padding: 1rem;
    text-align: center;
    color: var(--pos-gray-600);
    font-size: .9rem;
}

.adj-oneoff-head[b-on62uk1p5h] {
    font-size: .8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--pos-gray-500);
}

/* Two halves of one choice, so they read as a switch rather than as two buttons. */
.adj-toggle[b-on62uk1p5h] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .35rem;
}

.adj-toggle .btn[b-on62uk1p5h] {
    min-height: 2.5rem;
}

.adj-figure[b-on62uk1p5h] {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    padding: .35rem .5rem;
    background: var(--pos-gray-50);
    border: 1px solid var(--pos-gray-200);
    border-radius: .375rem;
}

.adj-figure-value[b-on62uk1p5h] {
    font-size: 1.5rem;
    line-height: 1.2;
}

/* Nothing keyed yet: the zero is a placeholder, not a figure somebody typed. */
.adj-figure-note[b-on62uk1p5h] {
    font-size: .8rem;
    color: var(--pos-gray-600);
}

.adj-name[b-on62uk1p5h] {
    font-size: .9rem;
}

.adj-apply[b-on62uk1p5h] {
    min-height: 2.75rem;
}
/* /Components/Pos/BillCharges.razor.rz.scp.css */
/* The bill's arithmetic - a group's subtotal, its charges, the shop's rounding - on the SAME grid
   as the items above it, so its amounts land in the totals column and its names start at the item
   names. Muted rather than smaller: it is a row of the bill, not a detail hanging off one. */
.bill-charge[b-vuwiw5mn4t] {
    display: grid;
    grid-template-columns: var(--bill-cols);
    align-items: baseline;
    padding: .18em 0;
    color: var(--pos-gray-600);
}

.bill-charge-name[b-vuwiw5mn4t] {
    grid-column: 2 / 5;
    min-width: 0;
}

/* A discount is the one row on a bill where money goes the other way, and the one row somebody
   may query at the counter. Darker than the arithmetic around it, so a customer's eye lands on
   it - not coloured, because this bill is read on a thermal-paper-coloured screen beside a
   printed one and the two should say the same thing. */
.bill-adjustment[b-vuwiw5mn4t] {
    color: var(--pos-gray-800);
    font-weight: 500;
}

.bill-charge-amount[b-vuwiw5mn4t] {
    grid-column: 5;
    min-width: 0;
    padding-left: .6em;
    text-align: right;
    font-variant-numeric: tabular-nums;
}
/* /Components/Pos/BillLine.razor.rz.scp.css */
/* A GRID, so every row of a line shares one set of columns and nothing has to be indented by hand.
   It was three flex rows with three different left edges - the name at 2.1em, the sub-rows at 1.92em
   (2.4em of a .8em font), the charges at 3em - close enough that the eye read them as a mistake
   rather than as levels. Columns cannot drift.

   Everything is in em, so a consumer sets one font-size and the whole block scales with it: the
   order panel is a dense touch list, the payment dialog is small type beside a numpad, and the
   customer screen is read across a counter. */
.bill-line[b-lyb50wmvgl] {
    display: grid;
    grid-template-columns: var(--bill-cols);
    align-items: baseline;
    row-gap: .12em;
    padding: .18em 0;
}

.bill-line-qty[b-lyb50wmvgl] {
    grid-column: 1;
    color: var(--pos-gray-600);
    font-variant-numeric: tabular-nums;
}

/* An item's name is the shop's OWN text, and this shop types both languages into the one field
   ("R6 特色炸水饺 Fried Dumpling (4pcs)"). Wrapped, one such dish took three rows of a panel that
   has to show a whole bill, and the rows stopped being one height. So it is cut with an ellipsis
   and the whole name is the row's tooltip. Not a <T> pair: nothing here is translated, which is
   why cutting it is safe. */
.bill-line-name[b-lyb50wmvgl] {
    grid-column: 2;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The kitchen mark, between the name and the money. Its own column so the prices do not shift
   sideways on the one screen that shows it. */
.bill-line-mark[b-lyb50wmvgl] {
    grid-column: 3;
    padding-left: .5em;
    line-height: 1;
}

/* PER-UNIT money: the item's own price, and what each modifier adds to one of them. One column, so
   the things that are added together are stacked on top of each other. */
.bill-line-unit[b-lyb50wmvgl] {
    grid-column: 4;
    min-width: 0;
    padding-left: .6em;
    text-align: right;
    font-size: .8em;
    color: var(--pos-gray-500);
    font-variant-numeric: tabular-nums;
}

/* The menu's price on a line somebody typed over, struck through in front of the new one. Quieter
   again than the unit price it sits beside: it is context for the figure, not a second figure. */
.bill-line-was[b-lyb50wmvgl] {
    margin-right: .4em;
}

/* WHAT THE LINE COSTS, and the only bold number in the bill's body. There used to be no such
   column: the total sat on the item's row when the line was a single plain one and on a row
   underneath when it was not, so reading down the right-hand edge gave bold and muted numbers
   alternating at two different heights. One column, one weight, one place to look. */
.bill-line-total[b-lyb50wmvgl] {
    grid-column: 5;
    min-width: 0;
    padding-left: .6em;
    text-align: right;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.bill-line-detail-name[b-lyb50wmvgl] {
    grid-column: 2 / 4;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: .8em;
    color: var(--pos-gray-500);
}

.bill-line-note[b-lyb50wmvgl] {
    grid-column: 2 / -1;
    font-size: .8em;
    font-style: italic;
    color: var(--pos-gray-500);
}

/* A line the kitchen already has. */
.bill-line-quiet[b-lyb50wmvgl] {
    color: var(--pos-gray-600);
}

/* A line taken off the bill after the kitchen had it: crossed out, name and money alike, and
   faded further than a sent line. Not hidden - the cashier who took it off, and the one after
   them, both want to see that it was there. */
.bill-line-voided[b-lyb50wmvgl] {
    color: var(--pos-gray-400);
    text-decoration: line-through;
}

.bill-line-voided .bill-line-total[b-lyb50wmvgl],
.bill-line-voided .bill-line-unit[b-lyb50wmvgl],
.bill-line-voided .bill-line-detail-name[b-lyb50wmvgl],
.bill-line-voided .bill-line-note[b-lyb50wmvgl] {
    color: var(--pos-gray-400);
    font-weight: 400;
}
/* /Components/Pos/BillToolsMenu.razor.rz.scp.css */
/* The bill's tools menu (BillToolsMenu). The menu's own chrome and the look of an item are
   PosMenu's; what is here is what only this menu has. */

/* The bill has already been printed: the state the old button carried as .active. */
.pos-tool-item.done[b-v1w498h95y] {
    color: var(--pos-teal-dark);
    font-weight: 600;
}

/* A bill at the printer, or one that did not come out. It reported itself on its own button
   until that button moved into the menu, and a state nobody can see is not a state. */
.pos-tools-state[b-v1w498h95y] {
    position: absolute;
    top: -.15rem;
    right: -.15rem;
    width: .6rem;
    height: .6rem;
    border: 2px solid #fff;
    border-radius: 50%;
    pointer-events: none;
}

.pos-tools-state.printing[b-v1w498h95y] {
    background: var(--pos-gold);
}

.pos-tools-state.failed[b-v1w498h95y] {
    background: var(--bs-danger);
}
/* /Components/Pos/BillView.razor.rz.scp.css */
/* The size is a variable, because the two screens showing this read it from different distances:
   the payment dialog is small type beside a numpad, the customer screen is read across a counter.
   Everything under it - BillLine included - is in em, so one number scales the whole bill. */
.bill-view[b-o96wo91fhr] {
    font-size: var(--bill-size, .9rem);
}

.bill-group + .bill-group[b-o96wo91fhr] {
    margin-top: .75em;
    padding-top: .75em;
    border-top: 1px solid var(--pos-gray-200);
}

.bill-group-name[b-o96wo91fhr] {
    font-size: .75em;
    font-weight: 600;
    letter-spacing: .04em;
    color: var(--pos-gray-500);
    margin-bottom: .25em;
}
/* /Components/Pos/CustomerScreenStatus.razor.rz.scp.css */
/* The one strip on the till about ANOTHER screen. Gold, because it is the one thing on the page
   that must be seen and the theme keeps gold for exactly that - and it is only here while the
   customer screen is gone, which is rare enough that it never becomes wallpaper.

   It sits ABOVE the dock and pushes it down rather than floating over it: anything laid over the
   till covers a tile, a line or a button somebody is about to press. Sizes are em of the till's
   own type, like everything else on this screen; the buttons are rem, because a finger is the
   same size on every till. */
.screen-offline[b-329dihql2h] {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: .75em;
    padding: .35em .75em;
    background: var(--pos-gold-light);
    border-bottom: 1px solid var(--pos-gold);
    color: var(--pos-gray-900);
    font-size: var(--pos-type, 1rem);
}

.screen-offline-glyph[b-329dihql2h] {
    flex: 0 0 auto;
    color: var(--pos-gold-dark);
    font-size: 1.35em;
    line-height: 1;
}

.screen-offline-text[b-329dihql2h] {
    flex: 1 1 auto;
    min-width: 0;
    font-weight: 600;
}

.screen-offline-button[b-329dihql2h] {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    min-width: 2.5rem;
    min-height: 2.5rem;
}

.screen-offline-forget[b-329dihql2h] {
    color: var(--pos-gray-600);
}

.screen-offline-forget:hover[b-329dihql2h] {
    color: var(--pos-gray-900);
}
/* /Components/Pos/LinePriceDialog.razor.rz.scp.css */
.lp[b-qyr62aef6d] {
    display: flex;
    flex-direction: column;
    gap: .6rem;
}

/* What the line costs now, and what the menu had if somebody has already typed over it. */
.lp-now[b-qyr62aef6d] {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    padding-bottom: .5rem;
    border-bottom: 1px solid var(--pos-gray-200);
}

.lp-now-label[b-qyr62aef6d] {
    font-size: .85rem;
    color: var(--pos-gray-600);
    margin-right: auto;
}


.lp-now-price[b-qyr62aef6d] {
    font-size: 1.2rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* What is being typed, in the biggest type in the dialog: it is the one thing being decided. */
.lp-new[b-qyr62aef6d] {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    padding: .35rem .5rem;
    background: var(--pos-gray-50);
    border: 1px solid var(--pos-gray-200);
    border-radius: .375rem;
}

.lp-new-label[b-qyr62aef6d] {
    font-size: .85rem;
    color: var(--pos-gray-600);
    margin-right: auto;
}

.lp-new-value[b-qyr62aef6d] {
    font-size: 1.75rem;
    line-height: 1.1;
}

/* Only on a line of more than one, where the price each and the line's total differ. */
.lp-line-total[b-qyr62aef6d] {
    text-align: right;
    font-size: .85rem;
    color: var(--pos-gray-600);
}
/* /Components/Pos/MenuPicker.razor.rz.scp.css */
/* THE WHOLE PICKER IS SIZED FROM ONE NUMBER, and that number is the page's (--pos-type, declared
   on .pos-page and shrunk there on a small screen). Everything below is an em of it, so the tiles,
   the dish names, the prices and the category chips step down TOGETHER rather than one of them
   being tuned on its own and the rest left behind. The fallback is the 1rem this used to inherit,
   for any host that ever renders the picker outside the POS screen. */
.menu-picker[b-giexa61usm] {
    background: #fff;
    font-size: var(--pos-type, 1rem);
}

.menu-picker-target[b-giexa61usm] {
    background: var(--pos-gray-50);
}

.menu-picker-cats[b-giexa61usm] {
    background: var(--pos-gray-50);
    scrollbar-width: thin;
    /* A flex child shrinks to fit. With the grid below wanting more height than the panel has,
       the strip gave up part of its own and clipped its chips behind a scrollbar. */
    flex: 0 0 auto;
}

/* THE BAR UNDER THE STRIP IS FOR A MOUSE, so a finger is not given one. It is a few pixels nobody
   can grab, and all it does on a touch screen is take strip height off a panel that was already
   clipping its chips for want of it. What says there is more to the right is a chip cut off at the
   edge, and what gets there is a swipe.

   POINTER, not width, which is the same call `AllowTouchDocking` makes: the till is a LARGE touch
   screen and wants this every bit as much as a tablet does, while a narrow desktop window still has
   a mouse to drive the bar with. The customer's own page hides the same strip's bar outright
   (`CustomerOrderPage.razor.css`), because that one is only ever a phone. */
@media (pointer: coarse) {
    .menu-picker-cats[b-giexa61usm] {
        scrollbar-width: none;
    }

    .menu-picker-cats[b-giexa61usm]::-webkit-scrollbar {
        display: none;
    }
}

/* Constant classes, because js/menuNav.js owns which one is lit and Bootstrap's btn-primary /
   btn-outline-secondary pair cannot be toggled from there without the two fighting over the class
   attribute. The outline state is written out here instead, and is-on fills it. */
.menu-picker-cat[b-giexa61usm] {
    /* THE HEIGHT STAYS A REM. A finger does not get smaller with the screen, so only the label
       shrinks - which is what takes a long bilingual category name off a second line. */
    min-height: 2.75rem;
    font-size: 1em;
    border: 1px solid var(--pos-gray-400);
    background: #fff;
    color: var(--pos-gray-700);
}

.menu-picker-cat:hover[b-giexa61usm] {
    border-color: var(--pos-teal);
    color: var(--pos-teal-dark);
}

.menu-picker-cat.is-on[b-giexa61usm] {
    border-color: var(--pos-teal);
    background: var(--pos-teal);
    color: #fff;
}

.menu-picker-section[b-giexa61usm] {
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: .7rem;
}

/* The whole menu, one category after another. This is the scroll the strip drives, and the strip
   sits ABOVE it rather than over it - so menuNav.js finds no [data-menu-sticky] here and measures
   its reading line from this box's own top. */
.menu-picker-scroll[b-giexa61usm] {
    background: var(--pos-gray-50);
    scrollbar-width: thin;
}

.menu-picker-group + .menu-picker-group[b-giexa61usm] {
    margin-top: 1rem;
}

/* The LAST category has to be able to reach the reading line, or the scroll runs out while its
   heading is still halfway down: its tab never lights, and a tap on it looks like it half worked.
   This shop's Beverages stopped 200px short. The room is a min-height on that one group rather than
   a padding under the whole scroll, so it appears only where it is needed and a last category
   already taller than the panel pays nothing for it. Same load-bearing trailing space as
   settingsNav.js's, for the same reason. */
.menu-picker-group:last-child[b-giexa61usm] {
    min-height: 100%;
}

/* Sticky, so the heading answers "what am I looking at" all the way down a long category rather
   than only at its start. It spans the grid's own gutter (the negative margin) and paints the
   pane's background back in, or tiles would slide out from under it. */
.menu-picker-group-title[b-giexa61usm] {
    position: sticky;
    top: 0;
    z-index: 2;
    margin: 0 -0.5rem 0.5rem;
    padding: 0.5rem;
    background: var(--pos-gray-50);
    font-size: 0.9em;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--pos-gray-600);
}

/* Tiles: a grid that reflows with the panel, each tile a finger target. */
.menu-picker-grid[b-giexa61usm] {
    display: grid;
    /* --tile-min is the one number that says how big a tile is. 6.5rem, so an iPad-sized panel
       takes three or four tiles across and a till six or seven; the photo is still recognisable
       at the width that leaves, and more dishes in view beats a bigger picture.
       SMALLER IS ALSO STEADIER, which is the half of it that is easy to miss. auto-fill hands
       every leftover pixel to the columns that DID fit, so the fewer of them there are the more
       each one swells - at 8rem an iPad Mini's panel fell to TWO columns and every tile came out
       half again as wide as the 8rem it was asking for. That is what made the photos look
       enormous: a photo is square, so a tile that grows sideways grows just as much downward.
       Three or four columns split the same slack three or four ways, and a tile stays near its
       minimum whatever width the panel happens to be.
       The page hands this down (--pos-tile-min on .pos-page) and shrinks it on a small screen,
       where the panel holding these tiles is a fraction of the room it has on a till and the
       photo has to give something back. A rem and NOT an em of the picker's own number: how
       small a tile may get is a separate question from how big its writing is, and shrinking the
       two in step left the tile a hair too wide to gain a column. The fallback is the 6.5rem it
       has always been, for any host outside the POS screen. */
    --tile-min: var(--pos-tile-min, 6.5rem);
    grid-template-columns: repeat(auto-fill, minmax(var(--tile-min), 1fr));
    /* max-content, not auto. An auto row is left at its minimum wherever the grid has no free
       space to grow into, and a tile's minimum leaves out its photo - so the photos overlapped the
       tiles below on every screen width, back when this grid was itself the scroll container.
       max-content sizes a row to what the tile actually holds and cannot be caught out that way. */
    grid-auto-rows: max-content;
    gap: .6em;
    align-content: start;
}

.menu-tile[b-giexa61usm] {
    position: relative;
    min-height: 5.5em;
    padding: .45em .5em;
    /* Every size inside a tile is em from here, so the text shrinks with the tile rather than a
       narrow tile spending most of its width on padding and a name wrapped over three lines.
       And this one is an em of the PICKER's number, so the tile shrinks with the screen too. */
    font-size: .85em;
    border: 2px solid var(--pos-gray-300);
    border-radius: .5em;
    background: #fff;
    color: inherit;
    display: flex;
    flex-direction: column;
    gap: .15em;
}

.menu-tile:hover[b-giexa61usm] {
    border-color: var(--pos-teal);
}

.menu-tile:active[b-giexa61usm] {
    background: var(--pos-teal-light);
}

/* Out of stock: the same red-edged, greyed tile the out-of-stock screen draws, and it refuses
   the tap. Driven by the ITEM's own state and never by :disabled - the picker is also disabled
   for the length of every write, and a tile that changed colour on each of those would flicker
   on the tap a cashier repeats most. */
.menu-tile.is-off[b-giexa61usm],
.menu-tile.is-off:hover[b-giexa61usm] {
    border-color: var(--pos-red);
    background: var(--pos-red-light);
    color: var(--pos-gray-600);
    cursor: not-allowed;
}

.menu-tile.is-off .menu-tile-photo[b-giexa61usm] {
    filter: grayscale(1);
    opacity: .6;
}

.menu-tile.is-off .menu-tile-price[b-giexa61usm] {
    color: var(--pos-gray-500);
}

.menu-tile-photo[b-giexa61usm] {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: .35rem;
    margin-bottom: .3em;
}

.menu-tile-name[b-giexa61usm] {
    font-weight: 600;
    line-height: 1.15;
}

/* The bottom row: the price, and the stock badge when there is one. Sharing a line is what keeps
   a tile that has a badge exactly as tall as one that has not. */
.menu-tile-foot[b-giexa61usm] {
    margin-top: auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .25rem;
    min-width: 0;
}

/* The everyday price, beside the one actually being charged. Quiet and struck through: the cashier
   needs to SEE that a dish is not on its usual price, not to read the old number. It is the LOWER
   of the two wherever a channel marks prices up, which is what stops the strike reading as a
   discount. Shown only where the two differ, so an ordinary tile is exactly as wide as it was. */
.menu-tile-base[b-giexa61usm] {
    font-size: .72em;
    font-weight: 400;
    margin-right: .25em;
}

.menu-tile-price[b-giexa61usm] {
    white-space: nowrap;
    font-size: 1.1em;
    color: var(--pos-teal-dark);
    font-weight: 600;
}

.menu-tile[b-giexa61usm]  .menu-tile-asks {
    position: absolute;
    top: .4rem;
    right: .5rem;
    color: var(--pos-gray-500);
    font-size: .95em;
}

/* The badge sizes with the tile like everything else inside one, and is allowed to shrink so a
   narrow tile gives the price its room first. ::deep, because the span is StockBadge's markup and
   never carries this component's scope attribute. */
.menu-tile-foot[b-giexa61usm]  .stock-badge {
    font-size: .8em;
    min-width: 0;
}
/* /Components/Pos/ModifierPickerDialog.razor.rz.scp.css */
/* Finger-sized choices. */
.mod-btn[b-o5cl3u53e5] {
    min-height: 3rem;
    min-width: 5rem;
    font-size: 1.05rem;
}

/* Out of stock: still there to be read, struck through so what it means needs no legend, and
   dead to the touch. Its own class rather than Bootstrap's outline style, because a disabled
   outline button merely looks faded and reads as "wait" rather than as "we have run out". */
/* The shop's own upsell line under the group that holds the unlocking answer: gold, because it
   is the one thing on this dialog asking to be looked at, and the theme keeps gold for that. */
.mod-upsell[b-o5cl3u53e5] {
    color: var(--pos-gold-dark);
    font-weight: 600;
}

/* A dependent group still waiting for its answer: there, readable, and plainly not open. */
.mod-locked[b-o5cl3u53e5] {
    color: var(--pos-gray-500);
}

.mod-btn.is-off[b-o5cl3u53e5] {
    border: 1px solid var(--pos-gray-300);
    background: var(--pos-gray-100);
    color: var(--pos-gray-500);
    text-decoration: line-through;
    cursor: not-allowed;
}

/* The picked dish whose questions are on screen, and the set group it is for. */
.mod-step-head[b-o5cl3u53e5] {
    margin-bottom: .9rem;
    padding-bottom: .5rem;
    border-bottom: 1px solid var(--pos-gray-200);
}

/* A dish picked by answering it, under its group: what it is and how it was answered, with its own
   way out. A button can only count a dish, and two Barleys answered two ways are two things. */
.mod-chips[b-o5cl3u53e5] {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    margin-top: .5rem;
}

.mod-chip[b-o5cl3u53e5] {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    min-height: 2.25rem;
    padding: .15rem .25rem .15rem .7rem;
    border: 1px solid var(--pos-teal);
    border-radius: 1.2rem;
    background: var(--pos-teal-light);
    color: var(--pos-teal-dark);
    font-size: .95rem;
}

.mod-chip-x[b-o5cl3u53e5] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.9rem;
    height: 1.9rem;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
}

.mod-chip-x:hover[b-o5cl3u53e5] { background: rgba(0, 0, 0, .08); }

.mod-qty-btn[b-o5cl3u53e5] {
    min-width: 3rem;
    min-height: 3rem;
    font-size: 1.2rem;
}

.mod-qty[b-o5cl3u53e5] {
    min-width: 2.5rem;
    text-align: center;
    font-size: 1.25rem;
    font-weight: 600;
}

.mod-action-btn[b-o5cl3u53e5] {
    min-height: 3rem;
    min-width: 5.5rem;
    font-size: 1.05rem;
}

/* What a countdown has left, beside the stepper it caps. Gold, because it is the one thing on this
   dialog worth looking at twice - and because red already means "cannot be sold". */
.mod-left[b-o5cl3u53e5] {
    padding: .1rem .45rem;
    border-radius: .35rem;
    background: var(--pos-gold-light);
    color: var(--pos-gray-800);
    font-size: .85rem;
    font-weight: 600;
    white-space: nowrap;
}
/* /Components/Pos/OrderCard.razor.rz.scp.css */
/* An open bill as a card to tap (OrderCard). Everything is an em of the number the grid or the
   strip around it sets (--pos-type), so a small screen gets more cards across at a smaller size.
   Three rules it shares with the order panel - .pos-chip, .pos-badge-billed and .pos-ref - stay in
   OrderScreen.razor.css and reach in with ::deep. The rules below keep the order they had there:
   the candidate ring comes before :hover and .selected, which win over it. */

/* No padding here: .pos-card sets it further down and wins on source order, so the
   roomier padding this once asked for has never been what was drawn. */
.pos-order-card[b-zlc6kuco3k] {
    min-width: 0;
    min-height: 8.5em;
}

/* The two figures a card is read for, across the room: which bill it is, and what it comes to.
   They were Bootstrap's .fs-5 and .fs-4, which are rem (and .fs-4 carries a vw of its own), so
   they were the two things on a card that would NOT have come down with the rest of it - a
   shrunken card with a full-sized total on it. */
.pos-card-title[b-zlc6kuco3k] {
    font-size: 1.25em;
}

.pos-order-card .pos-card-total[b-zlc6kuco3k] {
    font-size: 1.5em;
}

/* A card that is not a candidate, in the same mode; and one that is, ringed the way the map
   rings its table, carrying its rank and evidence in the gold badge. */
.pos-card.pos-dim[b-zlc6kuco3k] {
    opacity: .35;
    filter: grayscale(.7);
}

.pos-card.pos-candidate[b-zlc6kuco3k] {
    border-color: var(--pos-gold);
    box-shadow: 0 0 0 3px rgba(var(--pos-gold-rgb), .35);
}

/* em, like the card's other badges: a rem here stayed full size while the card around it came
   down with --pos-type. */
.pos-badge-pay[b-zlc6kuco3k] {
    background: var(--pos-gold);
    color: #fff;
    font-size: .8em;
}

.pos-badge-unsent[b-zlc6kuco3k] {
    background: var(--pos-gold);
    color: #fff;
}

/* Set to go to the kitchen by itself: teal outlined, quieter than the gold that asks for a press. */
.pos-badge-later[b-zlc6kuco3k] {
    background: #fff;
    color: var(--pos-teal-dark);
    border: 1px solid var(--pos-teal);
}

/* The kitchen's badge and a held round's time, side by side, wrapping under a narrow card. */
.pos-badges[b-zlc6kuco3k] {
    display: inline-flex;
    flex-wrap: wrap;
    gap: .25rem;
}

.pos-badge-sent[b-zlc6kuco3k] {
    background: var(--pos-teal-light);
    color: var(--pos-teal-dark);
}

/* Cooked and waiting to be carried: teal, filled, because something is waiting on somebody.
   Served: the quietest of the three, the order's food is nobody's work any more. */
.pos-badge-ready[b-zlc6kuco3k] {
    background: var(--pos-teal);
    color: #fff;
}

.pos-badge-served[b-zlc6kuco3k] {
    background: var(--pos-gray-200);
    color: var(--pos-gray-700);
}

/* The reference and the cutlery mark share one line under a card. min-width on the row is what
   lets the reference truncate rather than push the mark off the end. */
.pos-tags[b-zlc6kuco3k] {
    display: flex;
    align-items: center;
    gap: .4rem;
    min-width: 0;
}

.pos-card[b-zlc6kuco3k] {
    flex: 0 0 auto;
    min-width: 12em;
    padding: .5em .75em;
    border: 2px solid var(--pos-gray-300);
    border-radius: .5em;
    background: #fff;
    color: inherit;
}

.pos-card:hover[b-zlc6kuco3k] {
    border-color: var(--pos-teal);
}

.pos-card.selected[b-zlc6kuco3k] {
    border-color: var(--pos-gold);
    box-shadow: 0 0 0 3px var(--pos-gold-light);
}

.pos-card.billed[b-zlc6kuco3k] {
    border-style: dashed;
}

.pos-card-total[b-zlc6kuco3k] {
    font-weight: 600;
    color: var(--pos-teal-dark);
}
/* /Components/Pos/OrderScreen.razor.rz.scp.css */
/* The screen fills the layout's article (a flex column): the map and the order panel get the
   viewport height and scroll inside their own panes, never the page. */
.pos-page[b-johag1b995] {
    flex: 1 1 auto;
    min-height: 0;

    /* HOW BIG THE TILL'S OWN TEXT IS, and the one number the whole screen reads: the order panel,
       the order cards, the strip of orders without a table, and the menu picker in its own
       stylesheet (it reads this through the cascade, with a fallback for any host outside this
       page). Full size from 1500px of screen up, and down to 80% of it by 800px.

       FLUID rather than a breakpoint, for the same reason the customer display's --bill-size is:
       there is no width at which a till suddenly becomes a tablet, and a step means a cashier who
       resizes or rotates sees everything jump. The one thing a step would buy - a size chosen per
       device - is not worth a screen that changes under somebody mid-service.

       IT IS THE VIEWPORT, not the panel, and that is the known limit. The dock's splitter is the
       cashier's to drag, so a panel dragged narrow on a big screen still gets big-screen type. A
       container query would answer that, but the number has to be declared ABOVE everything that
       reads it and a container cannot style itself, so it would have to move onto the dock's own
       markup - and the tools menu's backdrop is position: fixed and would be trapped inside the
       containment. The device is what actually varies here; the splitter is a preference. */
    --pos-type: clamp(.8rem, .57rem + .46vw, 1rem);

    /* HOW SMALL A MENU TILE MAY GET, which is a different question from how big the text is and
       so gets a number of its own. A tile is mostly a PHOTO, and a photo gives up far more than
       a line of prices can: shrunk in step with the text the tile stayed a hair too wide, and a
       576px panel went on showing the same five dishes across it that it showed before.
       It falls faster and bottoms out sooner - 5rem by about 1020px, where the type scale is
       still only a sixth of the way down - which is what turns that panel into six across. */
    --pos-tile-min: clamp(5rem, 1.8rem + 5vw, 6.5rem);
}

/* The dock fills the rest of the page; dock.css sizes the host at 100% of it. */
.pos-dock[b-johag1b995] {
    min-height: 0;
    position: relative;
}

.pos-left[b-johag1b995] {
    background: #fff;
}

/* Orders View: filter bar and the list of every open order. */
.pos-orders[b-johag1b995] {
    background: #fff;
}

.pos-orders-filters[b-johag1b995] {
    background: var(--pos-gray-50);
}

/* One card per order, sized for a finger: a grid that reflows with the panel width.
   Everything about a card is an em of the page's one number, the card's own minimum included, so
   a small screen gets MORE cards across at a smaller size rather than the same three cards with
   the writing running out of room. */
.pos-orders-grid[b-johag1b995] {
    font-size: var(--pos-type);
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15em, 1fr));
    /* max-content, not auto - the same trap the menu tiles hit, and worse here because the card
       is a <button>. An auto row in a SCROLLING grid is left at its minimum, since the container's
       height is definite and there is never free space to grow into; and a button under-reports
       that minimum, so the row came out at exactly the card's min-height while the card held more.
       The badge and the total were then DRAWN BELOW THE CARD'S OWN BORDER, at every panel width
       where a bilingual badge stacked onto two lines. */
    grid-auto-rows: max-content;
    gap: .75em;
    align-content: start;
    background: var(--pos-gray-50);
}

.pos-orders-empty[b-johag1b995] {
    grid-column: 1 / -1;
}

.pos-tab-count[b-johag1b995] {
    background: rgba(255, 255, 255, .25);
    font-weight: 500;
}

.btn-outline-secondary .pos-tab-count[b-johag1b995] {
    background: var(--pos-teal-light);
    color: var(--pos-teal-dark);
}

/* Order state on the map. The canvas draws the tables; this page only colours them.
   Free = the canvas's grey, open = teal, bill printed = dark with a teal edge. Gold stays the
   selection ring the canvas already draws. */
.pos-map[b-johag1b995]  .room-table.pos-open {
    background: var(--pos-teal);
    border-color: var(--pos-teal-dark);
}

.pos-map[b-johag1b995]  .room-table.pos-billed {
    background: var(--pos-gray-800);
    border-color: var(--pos-teal);
    border-style: dashed;
}

.pos-map[b-johag1b995]  .pos-table-total {
    font-size: calc(var(--cell) * .34);
    font-weight: 500;
    opacity: .95;
}

/* Kitchen state. The gold count in a table's corner is the one thing a cashier must not miss:
   items that have not gone to the kitchen. Once everything is sent the table turns dark teal. */
.pos-map[b-johag1b995]  .room-table.pos-sent {
    background: var(--pos-teal-dark);
    border-color: var(--pos-teal-dark);
}

/* Every item cooked: one step darker than "in the kitchen", one step lighter than "bill asked
   for". No new hue - the map already carries teal, dark teal, dark, and gold twice over, and a
   fifth colour would turn a busy room into a paint chart. The reading it enables is done by the
   Ready-to-pay mode instead, which removes the other tables rather than recolouring this one. */
.pos-map[b-johag1b995]  .room-table.pos-served {
    background: var(--pos-gray-700);
    border-color: var(--pos-gray-700);
}

/* Ready-to-pay mode. Narrowing beats colouring: a colour still leaves the cashier scanning forty
   tables for a shade, while this takes the others out of the running. */
.pos-map[b-johag1b995]  .room-table.pos-dim {
    opacity: .28;
    filter: grayscale(.7);
}

.pos-map[b-johag1b995]  .room-table.pos-candidate {
    box-shadow: 0 0 0 3px var(--pos-gold), 0 0 12px rgba(var(--pos-gold-rgb), .5);
    z-index: 2;
}

.pos-map[b-johag1b995]  .pos-table-pay {
    display: block;
    font-size: calc(var(--cell) * .28);
    font-weight: 700;
    color: var(--pos-gold-light);
    line-height: 1.2;
}

.pos-map[b-johag1b995]  .pos-table-unsent {
    position: absolute;
    top: 2px;
    right: 2px;
    min-width: 1.4em;
    padding: 0 .3em;
    border-radius: 1em;
    background: var(--pos-gold);
    color: #fff;
    font-size: calc(var(--cell) * .3);
    font-weight: 700;
    line-height: 1.4em;
    text-align: center;
}

/* Orders without a table: one card per order, in a horizontal strip. It sits under the map and is
   the same card, so it takes the same number - otherwise the strip would be the one part of the
   screen still at full size. */
.pos-unseated[b-johag1b995] {
    font-size: var(--pos-type);
    background: var(--pos-gray-50);
}

/* An order's external reference (a Grab order number): the one thing on a card a rider reads out,
   so it is set apart from the grey around it. Teal and not gold - gold is for the one selected thing.
   ::deep, like .pos-chip and .pos-badge-billed, because OrderCard draws it as well as this panel. */
[b-johag1b995] .pos-ref {
    color: var(--pos-teal-dark);
    font-weight: 600;
    /* "GF-4471" broke at its hyphen in a narrow panel, which reads as two numbers. */
    white-space: nowrap;
}

/* The order panel: header, scrolling lines, totals, actions.

   It is the one panel a cashier reads all day and the one that ran out of room first, so it
   sets its OWN type scale rather than the page's: every size below is an em of this, as is
   Bootstrap's .small, so the whole panel is tuned by this single number. It also gives up the
   dock's header (DockPanelDef.HideHeader) - its first line already names the bill.

   Nine tenths of the page's number, which is the .9rem it has always been on a full-sized screen
   and less on a small one. What does NOT follow it is anything a finger lands on - the steppers,
   the icon buttons, the split tick - and the two or three labels already at the smallest size
   worth reading. Those stay in rem: a hand is the same size on every till. */
.pos-order[b-johag1b995] {
    background: var(--pos-gray-50);
    font-size: calc(var(--pos-type) * .9);
}

.pos-order-header[b-johag1b995] {
    background: #fff;
}

/* The bill's name. Big enough to find at a glance, and nothing like the heading it was. */
.pos-order-title[b-johag1b995] {
    font-size: 1.2em;
    font-weight: 600;
    line-height: 1.25;
}

/* So a long table name shortens rather than shoving the tool buttons off the row. */
.pos-order-head-text[b-johag1b995] {
    min-width: 0;
}

/* The things done TO the bill: one hamburger and the X, and nothing else ever joins them. A
   sixth glyph goes in the menu. */
.pos-order-tools[b-johag1b995] {
    display: flex;
    align-items: center;
    gap: .25rem;
}

.pos-order-lines[b-johag1b995] {
    background: #fff;
}

.pos-group-header[b-johag1b995] {
    background: var(--pos-gray-100);
    border-bottom: 1px solid var(--pos-gray-200);
}

/* ::deep: OrderCard draws a chip per group too. */
[b-johag1b995] .pos-chip {
    display: inline-block;
    padding: .05rem .5rem;
    border-radius: 1rem;
    background: var(--pos-teal-light);
    color: var(--pos-teal-dark);
    font-size: .8rem;
    font-weight: 600;
}

/* Lines are tap targets: a row tall enough for a finger, a readable size, and the tools open
   inside the row. Tighter than they were - more of the bill in view beats air around it. */
.pos-line[b-johag1b995] {
    border-bottom: 1px solid var(--pos-gray-100);
    cursor: pointer;
    padding-top: .4rem;
    padding-bottom: .4rem;
    font-size: 1.05em;
}

.pos-line-tools[b-johag1b995] {
    margin-top: .4rem;
    cursor: default;
}

.pos-sent-tag[b-johag1b995] {
    color: var(--pos-teal-dark);
}

.pos-unsent-tag[b-johag1b995] {
    color: var(--pos-gold-dark);
    font-weight: 600;
}

/* Held for a later send: teal, the colour of food that is coming, with the time it goes. */
.pos-held-tag[b-johag1b995] {
    display: inline-flex;
    align-items: center;
    gap: .15rem;
    color: var(--pos-teal-dark);
    font-weight: 600;
    font-size: .85em;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* A line taken off the bill after the kitchen had it. Gray like the line itself: it is history,
   not a warning, and the panel's red is kept for a slip that did not print. */
.pos-void-tag[b-johag1b995] {
    color: var(--pos-gray-500);
}

/* A print problem sits under the chips it belongs to. Small and tight: it is a note about the
   hardware in a panel that is about the bill. */
.pos-print-problem[b-johag1b995] {
    font-size: .75rem;
    line-height: 1.3;
    color: var(--bs-danger);
    margin-top: .15rem;
}

.pos-line-qty-big[b-johag1b995] {
    min-width: 2.2rem;
    text-align: center;
    font-size: 1.2em;
    font-weight: 600;
}

/* The split stepper holds TWO numbers where the plain one holds a quantity, so it takes a size
   down and a slash. "2 of 2" at the plain stepper's size wrapped onto two lines inside the box
   and made every part-split row half as tall again as the rows around it. */
.pos-split-qty[b-johag1b995] {
    min-width: 2.6rem;
    font-size: 1em;
    white-space: nowrap;
}

/* Controls a finger lands on. The steppers and the "Charge as" buttons keep the bigger size:
   they are pressed mid-order with the other hand holding a plate. */
.pos-touch-btn[b-johag1b995] {
    min-width: 2.75rem;
    min-height: 2.75rem;
    font-size: 1.05rem;
}

/* A glyph-only button in the order's header row is .pos-icon-btn, in app.css: the bill's tools
   menu and the adjustment dialog carry it too, and a rule scoped here never reached them. */

.pos-cat-strip .btn[b-johag1b995] {
    min-height: 2.5rem;
    font-size: 1em;
}

/* One row, however many buttons are in it: the draft's three destinations, the order's Send /
   Pay / Void, and Add beside them while the Menu is behind another tab. A flex row rather than
   a fixed grid, so adding a column is adding a button and nothing else. */
.pos-action-row[b-johag1b995] {
    display: flex;
    gap: .4rem;
}

/* Spelled with .btn so it OUTRANKS app.css's rule for a button carrying a bilingual pair. That
   rule puts the glyph beside the label, which is right everywhere else and wrong here: this row
   is one line across a panel that may be a third of a tablet, so the glyph goes above. */
.btn.pos-action-btn[b-johag1b995] {
    flex: 1 1 0;
    min-width: 0;
    min-height: 2.9rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .05rem;
    padding: .3rem .2rem;
    line-height: 1.1;
}

.pos-action-btn[b-johag1b995]  .svg-icon {
    font-size: 1.15rem;
}

.pos-action-btn span[b-johag1b995] {
    font-size: .8rem;
}

.pos-line:hover[b-johag1b995] {
    background: var(--pos-gray-50);
}

.pos-line.selected[b-johag1b995] {
    background: var(--pos-teal-light);
}

/* ::deep: OrderCard draws it too. */
[b-johag1b995] .pos-badge-billed {
    background: var(--pos-gray-800);
}

/* The bar over the map while an order is being seated at a table, or a bill combined into another. */
.pos-seating[b-johag1b995] {
    background: var(--pos-gold-light);
    border-bottom: 1px solid var(--pos-gold);
}

/* Several bills on one table: the count under the total on the map, the tab strip in the panel. */
.pos-map[b-johag1b995]  .pos-table-bills {
    font-size: calc(var(--cell) * .22);
    opacity: .9;
}

/* The layout the markup used to carry as utilities. It lives here so the media query below can
   turn the row off: Bootstrap's .d-flex is display: flex !important and would have beaten it. */
.pos-bill-tabs[b-johag1b995] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .25rem;
}

.pos-bill-tabs .btn[b-johag1b995] {
    min-height: 2rem;
}

/* The caret that says a row opens something. It exists ONLY where something is folded: on a
   full-sized screen nothing is, the tap changes nothing, and so the row must offer nothing.
   One class for both folds, and for any that follow. */
.pos-fold-caret[b-johag1b995] {
    display: none;
}

/* TWO ROWS FOLD AWAY ON A SMALL SCREEN, and these are the only things on this page decided by a
   breakpoint rather than by the fluid scale above - a row is shown or it is not, and there is no
   halfway to clamp to.

   THE BILLS STRIP is already the rarest row in the panel (only a table with a SECOND party draws
   it), and on a tablet it is a row of chrome over a panel that has a whole bill to show. THE
   TOTAL'S BREAKDOWN is the arithmetic between the bill and its figure, three or four rows of it,
   and the figure is what the panel is read for.

   Both are FOLDED and not taken away, and in both the row that stays is the one that opens the
   rest: the header that names the bill, which is what somebody looking for another bill is already
   reading, and the total, which is what somebody querying a service charge is already pointing at.
   (The bills were still reachable one tap further out - a card each in the Orders list, "2 bills"
   on the table - but that is a trip out of the panel to do something the panel is for.)

   1100px covers a 1024 tablet and a 768 one held upright, and leaves a 1280 landscape tablet and
   every till alone; it is one number to move if that is the wrong line. */
@media (max-width: 1100px) {
    .pos-bill-tabs[b-johag1b995] {
        display: none;
    }

    .pos-bill-tabs.is-open[b-johag1b995] {
        display: flex;
    }

    .pos-total-breakdown[b-johag1b995] {
        display: none;
    }

    .pos-total-breakdown.is-open[b-johag1b995] {
        display: block;
    }

    .pos-fold-caret[b-johag1b995] {
        display: inline;
    }

    .pos-fold-toggle[b-johag1b995] {
        cursor: pointer;
    }
}

/* THE DRAWER'S FACE, held upright: what the Order panel says about itself while it is shut
   behind the handle at the right edge. The dock draws the tab, the chevron and the movement; this
   is only what goes inside it. The face and the count are this component's own markup and carry
   this scope's attribute wherever the dock renders them - but the GLYPH is SvgIcon's <svg>, which
   carries SvgIcon's scope and never this one, so its rule needs ::deep. Without it the size and the
   colour never reached the icon, and nothing looked wrong enough to say so.

   REM and not em, like every other thing on this screen a finger lands on or reads at the
   smallest size worth reading. The handle is three characters wide down the edge of a screen
   somebody is holding, and shrinking it with --pos-type would take it below what a hand can hit
   at exactly the width where it matters most. */
.pos-drawer-face[b-johag1b995] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .15rem;
    line-height: 1.1;
}

.pos-drawer-face[b-johag1b995]  .pos-drawer-glyph {
    font-size: 1.15rem;
    color: var(--pos-gray-600);
}

.pos-drawer-count[b-johag1b995] {
    font-size: .95rem;
    font-weight: 600;
    color: var(--pos-gray-700);
}

/* GOLD is items the kitchen has not got - the same pill the map puts on a table and the cards put
   on a bill, and the one thing on this handle that has to be seen without being looked for. It
   carries the send glyph, because gold alone would only say that one of the two numbers above it
   was special and not which. A draft never lights it: nothing on a draft has been sent, because
   there is no order yet, so it would be on from the first tap to the last. */
.pos-drawer-unsent[b-johag1b995] {
    display: inline-flex;
    align-items: center;
    gap: .15rem;
    padding: .05rem .3rem;
    border-radius: .75rem;
    background: var(--pos-gold);
    color: #fff;
    font-size: .7rem;
    font-weight: 700;
    line-height: 1.3;
}

.pos-drawer-total[b-johag1b995] {
    font-size: .8rem;
    font-weight: 600;
    color: var(--pos-teal-dark);
}

/* Split mode: every line carries a tick box on the left; a ticked line is highlighted. */
.pos-line.splitting[b-johag1b995] {
    position: relative;
    padding-left: 2.6rem;
}

.pos-line[b-johag1b995]  .pos-split-mark {
    position: absolute;
    left: .5rem;
    top: .35rem;
    font-size: 1.4rem;
    line-height: 1;
    color: var(--pos-gray-500);
}

.pos-line.taking[b-johag1b995] {
    background: var(--pos-teal-light);
}

.pos-line.taking[b-johag1b995]  .pos-split-mark {
    color: var(--pos-teal-dark);
}

/* The group the next tapped item lands in, on a mixed order. */
.pos-group-header[b-johag1b995] {
    cursor: pointer;
}

.pos-group-header.target[b-johag1b995] {
    background: var(--pos-teal-light);
}

.pos-target-mark[b-johag1b995] {
    color: var(--pos-teal-dark);
    font-weight: 600;
}

.pos-order-totals[b-johag1b995] {
    background: #fff;
}

/* The one figure anybody reads from across the counter. */
.pos-total-line[b-johag1b995] {
    font-size: 1.45em;
    font-weight: 600;
}

/* The mark on the Total row saying this bill has been discounted. Gold, which on this screen
   means the one thing worth looking at, and ::deep because the <svg> is SvgIcon's own markup. */
.pos-total-line[b-johag1b995]  .pos-total-adjusted {
    margin-left: .25em;
    color: var(--pos-gold);
}

/* The menu's price on the Price button of a line somebody typed over, so the way back is readable
   without opening the dialog. */
.pos-line-was[b-johag1b995] {
    margin-left: .4em;
    font-size: .85em;
}

/* The lines of a sent bill flying from the panel to the Orders list (js/orderFlight.js). The
   clone is the lines block itself, copied and pinned to the viewport - it keeps this scope's
   attribute, so every rule above still dresses it - and the original is hidden for the flight,
   or the bill would be seen twice. The landing target may be the dock's own tab, which carries
   no scope attribute, hence ::deep. */
.pos-flight-away > *[b-johag1b995] {
    visibility: hidden;
}

/* The flying copy is dressed by js/flight.js - pinned above everything, inert, a white card with a
   shadow - which the customer's page shares. The landing is drawn on an overlay pinned over the
   target rather than as a class on the card: the circuit rewrites the card's class attribute as the
   bill is deselected, which cut a class-driven animation off a few frames in. */
/* /Components/Pos/PaymentDialog.razor.rz.scp.css */
.pay[b-b6k4nuu35r] {
    display: flex;
    align-items: stretch;
    min-height: 26rem;
}

/* ---- The methods, as vertical tabs ---- */

.pay-methods[b-b6k4nuu35r] {
    flex: 0 0 11rem;
    border-right: 1px solid var(--pos-gray-200);
    padding-right: .5rem;
}

.pay-method[b-b6k4nuu35r] {
    display: flex;
    align-items: center;
    gap: .6rem;
    width: 100%;
    padding: .85rem .75rem;
    border: 0;
    border-left: 4px solid transparent;
    border-radius: .25rem;
    background: none;
    text-align: left;
    font-size: 1rem;
    color: var(--pos-gray-800);
}

.pay-method:hover:not(:disabled)[b-b6k4nuu35r] {
    background: var(--pos-gray-100);
}

.pay-method.active[b-b6k4nuu35r] {
    border-left-color: var(--pos-teal);
    background: var(--pos-teal-light);
    font-weight: 600;
    color: var(--pos-teal-dark);
}

.pay-method:disabled[b-b6k4nuu35r] {
    opacity: .55;
}

.pay-method[b-b6k4nuu35r]  .svg-icon {
    font-size: 1.15rem;
}

/* ---- The middle: what the chosen method needs ---- */

.pay-main[b-b6k4nuu35r] {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0 1rem;
    display: flex;
    flex-direction: column;
}

.pay-due[b-b6k4nuu35r] {
    display: flex;
    align-items: baseline;
    gap: .6rem;
    flex-wrap: wrap;
    padding-bottom: .5rem;
    border-bottom: 1px solid var(--pos-gray-200);
}

.pay-due-label[b-b6k4nuu35r] {
    color: var(--pos-gray-600);
}

.pay-due-amount[b-b6k4nuu35r] {
    font-size: 2rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.pay-due-note[b-b6k4nuu35r] {
    font-size: .8rem;
    color: var(--pos-gray-500);
}

.pay-instructions[b-b6k4nuu35r] {
    padding-top: .5rem;
    font-size: .85rem;
    color: var(--pos-gray-600);
}

.pay-tendered[b-b6k4nuu35r] {
    padding: .6rem 0;
}

.pay-tendered-row[b-b6k4nuu35r] {
    display: flex;
    align-items: baseline;
    gap: .75rem;
}

.pay-field-label[b-b6k4nuu35r] {
    color: var(--pos-gray-600);
}

.pay-field-amount[b-b6k4nuu35r] {
    margin-left: auto;
    font-size: 1.6rem;
}

/* Nothing keyed means the exact amount; show it, but not as if it had been typed. */
.pay-field-amount.muted[b-b6k4nuu35r] {
    font-weight: 400;
}

.pay-tendered-row.short .pay-field-amount[b-b6k4nuu35r],
.pay-tendered-row.short .pay-field-label[b-b6k4nuu35r] {
    color: var(--bs-danger);
}

.pay-quick[b-b6k4nuu35r] {
    display: flex;
    gap: .4rem;
    padding-bottom: .5rem;
}

.pay-quick-btn[b-b6k4nuu35r] {
    flex: 1 1 0;
    font-size: 1rem;
    padding: .5rem .25rem;
}

.pay-qr[b-b6k4nuu35r] {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    padding: 1rem 0;
}

.pay-qr img[b-b6k4nuu35r] {
    max-width: 100%;
    max-height: 17rem;
    border: 1px solid var(--pos-gray-200);
    border-radius: .5rem;
}

.pay-qr-missing[b-b6k4nuu35r] {
    color: var(--pos-gray-600);
    text-align: center;
}

.pay-qr-account[b-b6k4nuu35r] {
    font-weight: 600;
}

.pay-reference[b-b6k4nuu35r] {
    padding-top: .75rem;
}

/* ---- Settled elsewhere: the pane with nothing to do in it ---- */

.pay-elsewhere[b-b6k4nuu35r] {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .75rem;
    padding: 1rem 0;
    color: var(--pos-gray-600);
    text-align: center;
}

/* The glyph stands in for the QR picture's bulk, so the pane is not a tall empty box. */
.pay-elsewhere[b-b6k4nuu35r]  .svg-icon {
    font-size: 3.5rem;
    color: var(--pos-gray-400);
}

.pay-elsewhere-note[b-b6k4nuu35r] {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    max-width: 22rem;
}

/* ---- Settled: what the cashier reads at the open drawer ---- */

.pay-settled[b-b6k4nuu35r] {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: .25rem;
}

.pay-settled-label[b-b6k4nuu35r] {
    font-size: 1rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--pos-gray-500);
}

.pay-settled-amount[b-b6k4nuu35r] {
    font-size: 4.5rem;
    line-height: 1.05;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--pos-teal-dark);
}

.pay-settled-note[b-b6k4nuu35r] {
    color: var(--pos-gray-600);
}

.pay-receipt[b-b6k4nuu35r] {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: .5rem;
    margin-top: 1.25rem;
    font-size: .85rem;
}

/* ---- The bill, on the right ---- */

.pay-bill[b-b6k4nuu35r] {
    flex: 0 0 20rem;
    display: flex;
    flex-direction: column;
    border-left: 1px solid var(--pos-gray-200);
    padding-left: 1rem;
}

.pay-bill-head[b-b6k4nuu35r] {
    font-weight: 600;
    padding-bottom: .35rem;
    border-bottom: 1px solid var(--pos-gray-200);
}

.pay-bill-lines[b-b6k4nuu35r] {
    flex: 1 1 auto;
    overflow-y: auto;
    max-height: 24rem;
    padding: .5rem 0;
}

.pay-bill-total[b-b6k4nuu35r] {
    display: flex;
    font-size: 1.25rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    border-top: 1px solid var(--pos-gray-300);
    padding-top: .4rem;
}

.pay-action[b-b6k4nuu35r] {
    font-size: .95rem;
}
/* /Components/Pos/PosMenu.razor.rz.scp.css */
/* A menu behind one button (PosMenu). The trigger's size is .pos-icon-btn, which it shares with the
   X beside it in the order panel's header, in app.css. */

.pos-menu[b-7x1ploxrzm] {
    position: relative;
    display: inline-flex;
}

/* At the end of the bottom row: as tall as the row's buttons, narrower than any of them. */
.pos-menu--footer[b-7x1ploxrzm] {
    flex: 0 0 auto;
}

    .pos-menu--footer .pos-menu-trigger[b-7x1ploxrzm] {
        min-width: 3rem;
        min-height: 2.9rem;
        font-size: 1.15rem;
    }

/* Transparent, and over everything: it is what closes the menu on a tap anywhere else, and it
   eats that tap so the tap cannot also do something to the bill underneath. No dim - this is a
   menu over a live bill, not a dialog (see "Overlays that sit OVER a live surface" in CLAUDE.md). */
.pos-menu-backdrop[b-7x1ploxrzm] {
    position: fixed;
    inset: 0;
    z-index: 20;
}

/* Hung from the trigger's right edge, so it stays inside the panel however narrow it is: below it in
   the header, above it at the foot. */
.pos-menu-list[b-7x1ploxrzm] {
    position: absolute;
    top: calc(100% + .25rem);
    right: 0;
    z-index: 21;
    min-width: 13rem;
    padding: .25rem;
    border: 1px solid var(--pos-gray-300);
    border-radius: .5rem;
    background: #fff;
    box-shadow: 0 .5rem 1.25rem rgba(0, 0, 0, .18);
}

.pos-menu--footer .pos-menu-list[b-7x1ploxrzm] {
    top: auto;
    bottom: calc(100% + .25rem);
    box-shadow: 0 -.5rem 1.25rem rgba(0, 0, 0, .18);
}

/* The items are the caller's markup and never carry this component's scope attribute, hence ::deep. */
.pos-menu-list[b-7x1ploxrzm]  .pos-tool-item {
    display: flex;
    align-items: center;
    gap: .6rem;
    width: 100%;
    min-height: 2.6rem;
    padding: .35rem .6rem;
    border: 0;
    border-radius: .35rem;
    background: transparent;
    color: inherit;
    text-align: left;
}

    .pos-menu-list[b-7x1ploxrzm]  .pos-tool-item:hover:not(:disabled) {
        background: var(--pos-teal-light);
    }

    .pos-menu-list[b-7x1ploxrzm]  .pos-tool-item:disabled {
        opacity: .45;
    }

    /* Something that destroys, such as voiding the whole bill: red, as it was on its own button. */
    .pos-menu-list[b-7x1ploxrzm]  .pos-tool-item.danger {
        color: var(--pos-red);
    }

        .pos-menu-list[b-7x1ploxrzm]  .pos-tool-item.danger:hover:not(:disabled) {
            background: var(--pos-red-light);
        }

    .pos-menu-list[b-7x1ploxrzm]  .pos-tool-item .svg-icon {
        flex: 0 0 auto;
        font-size: 1.15rem;
    }
/* /Components/Pos/SendLaterDialog.razor.rz.scp.css */
/* "Send later" (SendLaterDialog). Every button is a thumb's size: this is pressed at a till, often
   with the other hand holding the customer's phone or a Grab ticket. */

/* The time chosen, big, and how far away it is under it. */
.sl-readout[b-dpl93rexgg] {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 1rem;
}

.sl-time[b-dpl93rexgg] {
    font-size: 2.6rem;
    font-weight: 700;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
    color: var(--pos-teal-dark);
}

.sl-time--none[b-dpl93rexgg] {
    color: var(--pos-gray-400);
}

.sl-in[b-dpl93rexgg] {
    color: var(--pos-gray-600);
}

.sl-none[b-dpl93rexgg] {
    text-align: center;
    color: var(--pos-gray-600);
}

/* One big button per order type with food waiting: a finger's worth, its name, and how many. */
.sl-groups[b-dpl93rexgg] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: .5rem;
    margin-bottom: .75rem;
}

.sl-group[b-dpl93rexgg] {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-height: 3.25rem;
    text-align: left;
}

.sl-group-name[b-dpl93rexgg] {
    flex: 1 1 auto;
    min-width: 0;
    font-weight: 600;
}

.sl-group-count[b-dpl93rexgg] {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    font-size: .85em;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.sl-group-held[b-dpl93rexgg] {
    display: inline-flex;
    align-items: center;
    gap: .15rem;
}

.sl-label[b-dpl93rexgg] {
    margin: .75rem 0 .35rem;
    font-size: .8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--pos-gray-500);
}

.sl-row[b-dpl93rexgg],
.sl-quick[b-dpl93rexgg] {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: .4rem;
}

.sl-row[b-dpl93rexgg] {
    margin-bottom: .5rem;
}

/* As many hours as are left in the day, wrapping: six across fits a phone-width dialog. */
.sl-hours[b-dpl93rexgg] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(3.4rem, 1fr));
    gap: .4rem;
}

/* The minutes in fives, four across and three down: the same place for :30 every time. */
.sl-minutes[b-dpl93rexgg] {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: .4rem;
}

.sl-row .btn[b-dpl93rexgg],
.sl-quick .btn[b-dpl93rexgg],
.sl-hours .btn[b-dpl93rexgg],
.sl-minutes .btn[b-dpl93rexgg] {
    min-height: 2.9rem;
    font-size: 1.05rem;
    font-variant-numeric: tabular-nums;
}
/* /Components/Pos/TouchNumpad.razor.rz.scp.css */
/* Three columns of tap targets. The size is in REM and not em, because a finger is the same size
   on every till - the rule the POS screen already follows for everything a hand lands on. */
.pad-keys[b-brafi8f3gm] {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: .4rem;
}

.pad-key[b-brafi8f3gm] {
    padding: .7rem 0;
    font-size: 1.35rem;
    font-weight: 500;
    background: var(--pos-gray-50);
    border: 1px solid var(--pos-gray-300);
    color: var(--pos-gray-900);
}

.pad-key:hover[b-brafi8f3gm] {
    background: var(--pos-gray-100);
}
/* /Components/Printing/PrinterPicker.razor.rz.scp.css */
.printer-picker[b-qukbps6vt5] {
    max-width: 28rem;
    flex-wrap: nowrap;
}

/* A long printer name must shrink the list, not push the button out of the group. */
.printer-picker .form-select[b-qukbps6vt5] {
    min-width: 0;
}

.printer-picker .btn[b-qukbps6vt5] {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    white-space: nowrap;
}
/* /Components/Printing/SlipBlockProperties.razor.rz.scp.css */
/* Monospace the text fields, so a space is the same width on screen as on the paper and an indent
   can be counted. ::deep, because the <input> is LiveInputText's markup and never carries this
   component's scope attribute - written plain on the page, the rule matched nothing and the
   fields were drawn in the ordinary font. */
[b-bnwy96fml5] .slip-text-input {
    font-family: "Cascadia Mono", "Consolas", monospace;
}

/* The placeholder buttons. Many of them, so they wrap and stay small. */
.slip-tokens[b-bnwy96fml5] {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
}

.slip-tokens .btn[b-bnwy96fml5] {
    font-family: "Cascadia Mono", "Consolas", monospace;
    font-size: .7rem;
    padding: .1rem .3rem;
}
/* /Components/Printing/SlipPreview.razor.rz.scp.css */
/* The slip preview. Widths come from the API in columns; this file only turns a column into
   pixels. Nothing here may depend on how the browser measures a glyph. */

.slip-frame[b-u4bhns83kf] {
    display: inline-block;
    max-width: 100%;
    overflow-x: auto;
}

/* Paper is white in both themes: it is paper. The frame around it carries the theme. */
.slip-paper[b-u4bhns83kf] {
    display: block;
    width: calc(var(--cell) * var(--cols) + 2rem);
    padding: 1rem;
    background: #fff;
    color: #111;
    border: 1px solid var(--pos-gray-300);
    border-radius: 2px;
    box-shadow: 0 1px 4px rgb(0 0 0 / 0.15);
    font-family: "Cascadia Mono", "Consolas", "DejaVu Sans Mono", "Noto Sans Mono CJK SC", monospace;
    font-variant-ligatures: none;

    /* One printed line, in grid units. DERIVED, not measured: a normal character is 4 units
       wide and .slip-ch sets it at (cell * 4 / 0.6) with line-height 1, so that expression is
       exactly how tall a row of normal text comes out. Anything wanting "one line" of room
       must use this, or it will be quietly wrong the day the glyph sizing changes. */
    --line: calc(4 / 0.6);
}

.slip-line[b-u4bhns83kf] {
    display: grid;
    grid-template-columns: repeat(var(--cols), var(--cell));
    /* Two cells of height per line of text, so a double-height run has room to grow into. */
    min-height: calc(var(--cell) * 1.9 * var(--h, 1));
    align-items: center;
    /* The line's own spacing, as the gap it ADDS after the line - which is what the setting is
       called and what someone changing it is looking for. Folding it into the height instead
       would let a tall glyph swallow it: a double-height heading is already two lines tall, so
       asking for double spacing there would show nothing at all.

       At the printer's own pitch this is exactly zero, so a design nobody has touched draws
       precisely as it did. Down the paper the preview has always been approximate - a line's
       height is a fixed multiple of the grid unit, because across and down are measured in
       different units on this printer - and this keeps to that bargain rather than pretending
       to millimetres. */
    margin-bottom: calc(var(--cell) * var(--line) * (var(--sp, 1) - 1));
}

.slip-ch[b-u4bhns83kf] {
    /* Explicit row because the highlight box sits in the same cells. Auto-placement would see
       those cells taken and push the characters onto a second row. */
    grid-row: 1;
    /* Size follows the character's OWN cell width, which the API gives in grid units. A
       monospace advance is about 0.6em, so this makes a glyph fill the cells allotted to it -
       and a small-font character comes out three quarters the size of a normal one without the
       stylesheet knowing anything about fonts. A hanzi is 1em wide, so it is set from its
       height instead and simply sits centred in its wider cell. */
    font-size: calc(var(--cell) * var(--cw, 4) / 0.6);
    line-height: 1;
    text-align: center;
    white-space: pre;
    overflow: visible;
}

/* A Chinese glyph is as wide as it is tall, so sizing it by its cell width would make it tower
   over the letters beside it. Eight units wide is the same height as a four-unit letter. */
.slip-ch.w[b-u4bhns83kf] {
    font-size: calc(var(--cell) * var(--cw, 8) / 2 / 0.6);
}

.slip-ch.b[b-u4bhns83kf] {
    font-weight: 700;
}

/* The block being edited, boxed on the paper.

   Gold, which the theme keeps for the one thing that has to be found at a glance - and on a page
   whose whole job is telling a design and its paper apart, this is that thing. The fill stays
   faint because the ink underneath is what is being judged; the border is what actually says
   where the block begins and ends.

   Sides on every line, top and bottom only at the ends of a run, so a Repeat's rows come out as
   one box rather than a stack of them.

   It lies OVER the characters, so the fill has to stay faint enough to read the ink through -
   a highlighter, not a cover. Under them it would be painted out by any reversed run, which is
   how a kitchen ticket draws its quantities. */
.slip-box[b-u4bhns83kf] {
    grid-row: 1;
    align-self: stretch;
    background: rgba(var(--pos-gold-rgb), .2);
    border-left: 2px solid var(--pos-gold);
    border-right: 2px solid var(--pos-gold);
    border-radius: 1px;
    pointer-events: none;
}

.slip-box.box-top[b-u4bhns83kf] {
    border-top: 2px solid var(--pos-gold);
}

.slip-box.box-bottom[b-u4bhns83kf] {
    border-bottom: 2px solid var(--pos-gold);
}

/* GS B: white on black. The printer's one way of boxing text. */
.slip-ch.r[b-u4bhns83kf] {
    background: #111;
    color: #fff;
}

.slip-cut[b-u4bhns83kf] {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: .35rem 0;
    color: var(--pos-gray-500);
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .08em;
}

.slip-cut[b-u4bhns83kf]::before,
.slip-cut[b-u4bhns83kf]::after {
    content: "";
    flex: 1;
    border-top: 1px dashed var(--pos-gray-400);
}

/* A Cut block has no characters to box, so its own tear-off rule carries the mark instead. */
.slip-cut.boxed[b-u4bhns83kf] {
    color: var(--pos-gold);
    font-weight: 600;
}

.slip-cut.boxed[b-u4bhns83kf]::before,
.slip-cut.boxed[b-u4bhns83kf]::after {
    border-top-color: var(--pos-gold);
}

.slip-placeholder[b-u4bhns83kf] {
    padding: 1.5rem;
    color: var(--pos-gray-600);
    font-style: italic;
}

.slip-notes[b-u4bhns83kf] {
    margin: .5rem 0 0;
    padding-left: 1.1rem;
    color: var(--pos-gray-600);
    font-size: .8rem;
}

/* A picture the printer rasters: a logo, a QR.

   No grid here. Every other line is placed on exact columns because the browser must never be
   trusted to measure a glyph - but a picture is not text, it is the dots themselves, so it is
   simply laid across the paper under the justification it printed with. */
.slip-image[b-u4bhns83kf] {
    display: flex;
    align-items: flex-start;
}

.slip-image img[b-u4bhns83kf] {
    display: block;
    /* The dots are meant to be SEEN as dots. Smoothing would hide exactly the roughness somebody
       is checking for before they let a logo onto a roll of paper. */
    image-rendering: pixelated;
}

/* A picture has no characters to draw a box around, so the whole of it carries the mark. */
.slip-image.boxed[b-u4bhns83kf] {
    outline: 2px solid var(--pos-gold);
    background: rgba(var(--pos-gold-rgb), .2);
}

/* One band of a picture with slip text beside it.

   The row is exactly 24 printer dots - eight grid units - and carries NO gap under it, so
   consecutive bands butt together. That is not tidiness: a seam of white between the strips would
   run straight across a QR code, and a QR with lines through it does not scan.

   It is the one place the preview is exact down the paper as well as across it. Everywhere else a
   line's height is a fixed multiple of the grid unit, because the two axes are measured
   differently on this printer - but a band IS dots, so it can be drawn as dots. */
.slip-line-banded[b-u4bhns83kf] {
    min-height: 0;
    height: calc(var(--cell) * 8);
    align-items: stretch;
    margin-bottom: 0;
}

.slip-band[b-u4bhns83kf] {
    grid-row: 1;
    display: block;
    width: 100%;
    height: 100%;
    image-rendering: pixelated;
}

/* A sticker job: the stickers on a strip of their backing, the way they hang off the tear bar.
   The backing is the pale blue-green of a real roll's liner in both themes, because it IS the
   liner; a sticker is white for the same reason paper is. */
.sticker-strip[b-u4bhns83kf] {
    display: inline-flex;
    flex-direction: column;
    gap: .5rem;
    padding: .5rem .6rem;
    background: #d7e6e4;
    border-radius: 3px;
    box-shadow: 0 1px 4px rgb(0 0 0 / 0.15);
}

.sticker[b-u4bhns83kf] {
    display: block;
    background: #fff;
    border-radius: 4px;
    /* The dots are meant to be SEEN as dots, as on the slip's pictures. */
    image-rendering: pixelated;
}

/* The box a block's outline is placed in: the sticker itself, so a box in the sticker's own dots
   lands on the picture exactly. */
.sticker-wrap[b-u4bhns83kf] {
    position: relative;
}

/* The block being edited, outlined on the sticker - gold, as it is on a slip, and for the same
   reason. An outline and a faint wash rather than a fill, because the ink underneath is what is
   being judged. */
.sticker-box[b-u4bhns83kf] {
    position: absolute;
    border: 2px solid var(--pos-gold);
    background: rgba(var(--pos-gold-rgb), .15);
    border-radius: 2px;
    pointer-events: none;
}

/* The characters keep their own size and sit centred in the band beside the picture. */
.slip-line-banded .slip-ch[b-u4bhns83kf] {
    align-self: center;
}

/* The picture in a band, when its own block is the one being edited. An outline rather than the
   translucent fill the text gets: a wash over a QR would hide exactly the thing being judged. */
.slip-band.boxed[b-u4bhns83kf] {
    outline: 2px solid var(--pos-gold);
    outline-offset: -2px;
}
/* /Components/Sales/BillPane.razor.rz.scp.css */
/* The pane beside the Sales list (TableBeside's right side): its own header, then the bill. */
.bill-pane[b-gvl9sw73h9] {
    padding: .75rem 1rem 1rem;
}

.bill-pane-head[b-gvl9sw73h9] {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    margin-bottom: .75rem;
}

.bill-pane-title[b-gvl9sw73h9] {
    flex: 1 1 auto;
    min-width: 0;
}

.bill-pane-tools[b-gvl9sw73h9] {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: .35rem;
}

/* The statement and the rest side by side when the pane has the room, one above the other when
   it has not. By the PANE's width, which a media query cannot see: the person drags the split. */
.bill-pane-grid[b-gvl9sw73h9] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
    gap: 1.5rem;
    align-items: start;
}

/* The bill's own total, under the statement, in the weight the eye lands on first. */
.sale-total[b-gvl9sw73h9] {
    display: flex;
    justify-content: space-between;
    margin-top: .5rem;
    padding-top: .5rem;
    border-top: 2px solid var(--pos-gray-400);
    font-size: 1.25rem;
    font-weight: 700;
}

/* One tender: what was taken, or what went back. */
.sale-payment[b-gvl9sw73h9] {
    padding: .75rem;
    border: 1px solid var(--pos-gray-300);
    border-radius: .375rem;
    background: var(--pos-gray-100);
}

.sale-payment + .sale-payment[b-gvl9sw73h9] {
    margin-top: .75rem;
}

/* Money leaving reads differently from money arriving, at a glance. */
.sale-payment-refund[b-gvl9sw73h9] {
    border-color: var(--bs-danger-border-subtle, #f1aeb5);
    background: var(--bs-danger-bg-subtle, #f8d7da);
}

.sale-payment-head[b-gvl9sw73h9] {
    display: flex;
    align-items: baseline;
    gap: .5rem;
}

.sale-payment-amount[b-gvl9sw73h9] {
    margin-left: auto;
    font-size: 1.15rem;
    font-weight: 700;
}

.sale-payment-foot[b-gvl9sw73h9] {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin-top: .5rem;
}

.sale-payment-foot > .btn[b-gvl9sw73h9] {
    margin-left: auto;
}

.sale-payment-foot > .btn + .btn[b-gvl9sw73h9] {
    margin-left: 0;
}

/* One reopening: what the bill was worth before somebody changed it. Shaped like a tender
   because it is read the same way - an amount, when, who - but gold rather than red: money
   did not leave here, the bill did. */
.sale-reopen[b-gvl9sw73h9] {
    padding: .75rem;
    border: 1px solid var(--pos-gold);
    border-radius: .375rem;
    background: var(--pos-gold-light);
}

.sale-reopen + .sale-reopen[b-gvl9sw73h9] {
    margin-top: .75rem;
}

/* Facts about the bill: label left, value right, one row each. */
.sale-facts[b-gvl9sw73h9] {
    display: grid;
    grid-template-columns: 9rem 1fr;
    row-gap: .35rem;
    margin: 0;
}

.sale-facts dt[b-gvl9sw73h9] {
    font-weight: 500;
    color: var(--pos-gray-600);
}

.sale-facts dd[b-gvl9sw73h9] {
    margin: 0;
}
/* /Components/Sales/ReportCards/DrawerCard.razor.rz.scp.css */
/* The cash-up, under the expected figure it is checked against. */
.cash-up[b-353yor29h2] {
    border-top: 1px solid var(--pos-gray-200);
    padding-top: .75rem;
    margin-top: .25rem;
}

/* Square is not a success and short is not a disaster - both are facts. Over and short are
   coloured only enough to be told apart at a glance, with short the one that reads as a warning
   because it is the direction somebody has to explain. */
.cash-up-variance[b-353yor29h2] {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.cash-up-variance.is-square[b-353yor29h2] {
    color: var(--pos-teal);
}

.cash-up-variance.is-over[b-353yor29h2] {
    color: var(--pos-gold-dark);
}

.cash-up-variance.is-short[b-353yor29h2] {
    color: var(--bs-danger);
}

/* Said out loud when the drawer figure spans more days than the report does - it is the one number
   on the page that is not about this period, and it must not be mistaken for one that is. */
.report-carried[b-353yor29h2] {
    border-left: 3px solid var(--pos-gold);
    background: var(--pos-gold-light);
    padding: .5rem .6rem;
    border-radius: 0 .375rem .375rem 0;
    color: var(--pos-gray-700);
}
/* /Components/Sales/ReportCards/ExceptionsCard.razor.rz.scp.css */
/* Gold, matching the Reopened badge on the sales list: money did not leave, the bill did. */
.day-reopen[b-2pdy5idzbe] {
    color: var(--pos-gold-dark);
}
/* /Components/Sales/ReportCards/ItemsSoldCard.razor.rz.scp.css */
/* A category's heading row carries its subtotal, so a category is read at a glance and its dishes
   are read only when somebody wants them. Shaded rather than bordered, because a table of forty
   dishes ruled off every few rows reads as a grid of boxes. */
.items-category th[b-lemzfm0puu] {
    background: var(--pos-gray-100);
    font-weight: 600;
    border-top: 1px solid var(--pos-gray-300);
}

/* The section, when the period's categories come from more than one. Muted: it only tells two
   same-named categories apart. */
.items-section[b-lemzfm0puu] {
    font-weight: 400;
    color: var(--pos-gray-500);
}

/* The shop types both languages into one name field, so a name is long. It wraps rather than
   pushing the figures off a tablet's screen. */
.items-name[b-lemzfm0puu] {
    white-space: normal;
}

/* A dish sits one step in from its category's heading, which is the only thing that says it
   belongs to it once the heading has scrolled out of sight. */
.items-table tbody td.items-name[b-lemzfm0puu] {
    padding-left: 1.25rem;
}

/* A department's glyph, before its name as on the departments page. Muted, because it decorates
   the shop's own word and never replaces it. */
.items-glyph[b-lemzfm0puu] {
    color: var(--pos-gray-500);
    margin-right: .35rem;
}
/* /Components/Sales/ReportCards/OrderTypesView.razor.rz.scp.css */
/* The glyph and the name side by side, each its own flex item, so a long name that has to wrap
   on a narrow screen wraps beside its glyph rather than dropping under it. */
.order-type-name[b-jtovq4fhlp] {
    display: inline-flex;
    align-items: baseline;
    gap: .35rem;
}

/* Eight columns in half the page: a heading breaks between its two languages (they are Stacked),
   never inside a word of either. Chinese otherwise breaks between any two characters, and a
   squeezed column read "已退" over "款". */
thead th[b-jtovq4fhlp] {
    word-break: keep-all;
}
/* /Components/Sales/ReportCards/RevenueByDayCard.razor.rz.scp.css */
/* The three figures above the bars, on one line that wraps on a narrow card. */
.revenue-summary[b-9cq6cf1tnu] {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem 1.5rem;
    margin-bottom: .75rem;
    font-size: .9rem;
    color: var(--pos-gray-600);
}

.revenue-summary strong[b-9cq6cf1tnu] {
    color: var(--pos-gray-800);
    font-variant-numeric: tabular-nums;
}
/* /Components/Sales/ReportCards/TrafficCard.razor.rz.scp.css */
/* The row above the graph that picks what the day is compared with. It wraps on a narrow card, and
   its buttons are the span filter's size, so the two rows of date controls on the page read alike. */
.traffic-compare[b-tbzbb3d594] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem;
    margin-bottom: .9rem;
}

.traffic-compare-label[b-tbzbb3d594] {
    font-size: .875rem;
    font-weight: 600;
    color: var(--pos-gray-600);
    margin-right: .15rem;
}

.traffic-compare-hint[b-tbzbb3d594] {
    font-size: .875rem;
    color: var(--pos-gray-500);
}
/* /Components/Settings/SlipPrintMatrix.razor.rz.scp.css */
/* ---- Who prints a slip ---- */

/* A chip per department, lit when it has subscribed. Chips rather than a multi-select because the
   answer is usually one or two out of five and the whole set is worth seeing at once - a closed
   select would hide the very thing the setting is about. */
.slip-subscribers[b-qyyyhyppyx] {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
}

/* Its own line under the chips, not one more item in their row. Gold, because a slip nobody
   prints is the one thing on this page worth looking at: it reads exactly like a row nobody has
   got round to, and the difference matters. Under .slip-row, so it beats the page's .setting-help
   on the same line by specificity rather than by which stylesheet happens to load last. */
.slip-row .slip-none[b-qyyyhyppyx] {
    flex-basis: 100%;
    color: var(--pos-gold-dark);
}

/* ---- What the shop prints: one row per slip, one column per question ---- */

/* The three questions that decide a slip - who prints it, which orders get one, what it looks
   like - have three different homes, and are ANDed rather than overriding. Shown one at a time
   that was unreadable: a lit chip looked like a slip that would print. So the rows keep the
   page's own .setting shape for their first cell and lay the three answers out beside it.

   The template is a custom property because the header row and every slip row have to agree on
   it while staying separate boxes - a single grid with display:contents rows would line up too,
   but then a row could not carry the search highlight. */
/* The GOES TO column carries seven chips where the other two carry a phrase, so it is given the
   room and they are trimmed to what they need. */
.slip-matrix[b-qyyyhyppyx] {
    --slip-cols: minmax(9rem, 1.2fr) minmax(12rem, 2.2fr) minmax(7rem, .9fr) minmax(7rem, .9fr);
    --slip-gap: .9rem;
}

.slip-matrix-head[b-qyyyhyppyx] {
    display: grid;
    grid-template-columns: var(--slip-cols);
    gap: var(--slip-gap);
    margin: .25rem -.6rem 0;
    padding: 0 .6rem .4rem;
    border-bottom: 1px solid var(--pos-gray-200);
    font-size: .75rem;
    font-weight: 600;
    color: var(--pos-gray-500);
}

/* Grid rather than the flex .setting sets, and one class more specific so it wins whichever
   stylesheet loads first - the page's .setting rules are in another file. Everything else a
   setting row has - the padding, the bleed, the rule between rows, the gold match bar - is
   inherited as it stands. */
.setting.slip-row[b-qyyyhyppyx] {
    display: grid;
    grid-template-columns: var(--slip-cols);
    gap: var(--slip-gap);
    align-items: start;
}

.slip-cell[b-qyyyhyppyx] {
    min-width: 0;
}

/* The "?" card's containing block is the row's FIRST CELL, which here is one narrow column rather
   than the 46rem of prose an ordinary row gives it - so min(30rem, 100%) resolved to 248px and a
   three-paragraph note was drawn in a ribbon. It is let across the row instead, which is where the
   room is. The viewport guard is what keeps it off the ordinary rule's trap: a card wider than the
   pane is scrollable overflow, and a horizontal scrollbar under the whole page. */
.slip-row[b-qyyyhyppyx]  .setting-hint-card {
    width: min(30rem, calc(100vw - 6rem));
}

/* The column headings say it once at full width, so the per-cell label is hidden THERE - but
   hidden by clipping rather than display:none, because a grid gives a screen reader no
   heading-to-cell association and these labels are the only thing naming a cell. */
.slip-cell-label[b-qyyyhyppyx] {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* An answer that is not a control. Where the answer is set on another screen the SENTENCE is the
   link - it already names that screen - so a cell is one line rather than a phrase with a "go
   here" repeated under it. A cell with nothing behind it stays plain text, which is what tells
   the two kinds apart without a word about it. */
.slip-answer[b-qyyyhyppyx] {
    font-size: .8125rem;
    color: var(--pos-gray-700);
    line-height: 1.35;
}

.slip-answer a[b-qyyyhyppyx] {
    text-decoration: none;
}

.slip-answer a:hover[b-qyyyhyppyx] {
    text-decoration: underline;
}

.slip-chip[b-qyyyhyppyx] {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    border: 1px solid var(--pos-gray-300);
    background: #fff;
    border-radius: 2rem;
    padding: .3rem .7rem;
    font-size: .8125rem;
    color: var(--pos-gray-700);
    line-height: 1.2;
}

.slip-chip:hover:not(:disabled)[b-qyyyhyppyx] {
    border-color: var(--pos-teal);
    color: var(--pos-teal-dark);
}

.slip-chip:disabled[b-qyyyhyppyx] {
    opacity: .6;
}

.slip-chip.is-on[b-qyyyhyppyx] {
    background: var(--pos-teal-light);
    border-color: var(--pos-teal);
    color: var(--pos-teal-dark);
    font-weight: 600;
}

/* Subscribed with no printer behind it. Gold, because it is the one thing on the row worth
   looking at - the send skips such a department in silence, so this is where a shop finds out. */
.slip-chip[b-qyyyhyppyx]  .slip-chip-warn {
    color: var(--pos-gold-dark);
}

/* The matrix gives way EARLIER than an ordinary row, at its own width: four columns want about
   40rem between them where a setting row wants 22rem of control and a description. Below it the
   headings go and every cell says its own name, which is the same information in a column. */
@media (max-width: 76rem) {
    .slip-matrix-head[b-qyyyhyppyx] {
        display: none;
    }

    .setting.slip-row[b-qyyyhyppyx] {
        grid-template-columns: 1fr;
        gap: .6rem;
    }

    .slip-cell-label[b-qyyyhyppyx] {
        position: static;
        display: block;
        width: auto;
        height: auto;
        overflow: visible;
        clip-path: none;
        white-space: normal;
        margin-bottom: .15rem;
        font-size: .75rem;
        font-weight: 600;
        color: var(--pos-gray-500);
    }
}
/* /Components/Shared/AutoSaveHint.razor.rz.scp.css */
.auto-save-hint[b-xt9rnvb0ga] {
    min-height: 1.25rem;
}

.auto-save-hint .spinner-border[b-xt9rnvb0ga] {
    width: 0.75rem;
    height: 0.75rem;
    border-width: 0.12em;
}
/* /Components/Shared/CardNotes.razor.rz.scp.css */
.card-notes[b-r6p4tl9uf9] {
    position: relative;
}

.card-notes > summary[b-r6p4tl9uf9] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    list-style: none;
    cursor: pointer;
    font-size: 1.1rem;
    color: var(--pos-gray-500);
}

.card-notes > summary[b-r6p4tl9uf9]::-webkit-details-marker {
    display: none;
}

.card-notes > summary:hover[b-r6p4tl9uf9],
.card-notes[open] > summary[b-r6p4tl9uf9] {
    background: var(--pos-gray-100);
    color: var(--pos-gray-700);
}

/* A note says the card is not showing everything. Gold, the theme's colour for the one thing
   that must be seen. */
.card-notes.has-warning > summary[b-r6p4tl9uf9] {
    color: var(--pos-gold-dark);
}

/* The box: every note one under the other, each a sentence of its own, over the card rather than
   pushing it down. Its own weight, because the header it hangs from is bold. */
.card-notes-panel[b-r6p4tl9uf9] {
    position: absolute;
    top: calc(100% + .35rem);
    right: 0;
    z-index: 20;
    display: flex;
    flex-direction: column;
    gap: .35rem;
    width: min(30rem, calc(100vw - 2rem));
    padding: .75rem 1rem;
    border: 1px solid var(--pos-gray-200);
    border-radius: .5rem;
    background: #fff;
    box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .12);
    font-size: .875rem;
    font-weight: 400;
    color: var(--pos-gray-700);
}

/* The note that turned the (i) gold, in the same gold. It is the caller's markup, so ::deep. */
.card-notes-panel[b-r6p4tl9uf9]  .note-warn,
.card-notes-panel[b-r6p4tl9uf9]  .note-warn .t-1 {
    color: var(--pos-gold-dark);
    font-weight: 600;
}
/* /Components/Shared/ChartLegend.razor.rz.scp.css */
/* The legend sits above the chart it names, one row of entries that wraps on a narrow card. */
.chart-legend[b-s1g5e213yc] {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem 1rem;
    margin: 0 0 .75rem;
}

/* Each entry is a switch, so it is a button a finger can hit, drawn as plainly as a legend: no
   border until the pointer is on it. */
.legend-key[b-s1g5e213yc] {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-height: 2.25rem;
    padding: .2rem .6rem;
    border: 1px solid transparent;
    border-radius: .375rem;
    background: transparent;
    color: inherit;
    font: inherit;
}

.legend-key:hover[b-s1g5e213yc] {
    border-color: var(--pos-gray-200);
}

/* A hidden entry keeps its place and its colour, faded, so it is plain what is off and where to
   tap to have it back. */
.legend-key.is-off[b-s1g5e213yc] {
    opacity: .4;
}

/* A short stroke of the entry's own colour and weight, so it reads as the line or the shape's
   edge rather than a box. */
.legend-swatch[b-s1g5e213yc] {
    flex: 0 0 auto;
    width: 1.25rem;
    height: 3px;
    border-radius: 2px;
}

.legend-figure[b-s1g5e213yc] {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* The compared figure: quieter than the line's own, behind a stroke drawn as its line is. */
.legend-compared[b-s1g5e213yc] {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    color: var(--pos-gray-500);
    font-variant-numeric: tabular-nums;
}
/* /Components/Shared/ContainerMark.razor.rz.scp.css */
/* ::deep because the <svg> is SvgIcon's markup and never carries this component's scope
   attribute. Sizing works off the surrounding font-size - the glyph is 1em square - so a card,
   a panel heading and a board tile each get a mark in proportion to what it sits beside.

   GOLD, where the cutlery mark beside it is teal. This one is on screen only when the bill is
   being packed differently from every other bill, and is exactly the "one thing that must be
   seen" the theme keeps gold for. */
.container-mark[b-hffjlac88i]  .svg-icon {
    color: var(--pos-gold-dark);
}
/* /Components/Shared/CutleryMark.razor.rz.scp.css */
/* ::deep because the <svg> is SvgIcon's markup and never carries this component's scope
   attribute. Sizing works off the surrounding font-size - the glyph is 1em square - so a card,
   a panel heading and a board tile each get a mark in proportion to what it sits beside. */
.cutlery-mark[b-4l2lsq08hp]  .svg-icon {
    color: var(--pos-teal-dark);
}

/* "No cutlery" is an ANSWER, not a blank, so it is drawn rather than left out - dimmed, with a
   line through it. A packer scanning a column of cards has to be able to tell it from a bill
   nobody was asked about, which shows no mark at all. */
.cutlery-mark.none[b-4l2lsq08hp] {
    position: relative;
    color: var(--pos-gray-500);
}

.cutlery-mark.none[b-4l2lsq08hp]  .svg-icon {
    color: var(--pos-gray-500);
}

.cutlery-mark.none[b-4l2lsq08hp]::after {
    content: "";
    position: absolute;
    left: -.1em;
    right: -.1em;
    top: 50%;
    border-top: 2px solid currentColor;
    transform: rotate(-20deg);
}
/* /Components/Shared/IconPicker.razor.rz.scp.css */
.icon-tiles[b-7poi2k1jer] {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
}

/* A tile big enough for a thumb: these pickers are used on a tablet as well as at a desk. */
.icon-tile[b-7poi2k1jer] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.6rem;
    height: 2.6rem;
    padding: 0;
    border: 1px solid var(--pos-gray-300);
    border-radius: .35rem;
    background: #fff;
    color: var(--pos-gray-700);
    cursor: pointer;
}

/* ::deep, because the <svg> is SvgIcon's own markup and never carries this component's scope. */
.icon-tile[b-7poi2k1jer]  .svg-icon { font-size: 1.25rem; line-height: 1; }

/* A heading in a LONG set. flex-basis: 100% takes a whole line of the wrapping row, which breaks
   the row without a box round each group - so every tile on the page still sits on one grid. */
.icon-group[b-7poi2k1jer] {
    flex: 0 0 100%;
    margin: .55rem 0 -.05rem;
    font-size: .78rem;
    font-weight: 600;
    color: var(--pos-gray-600);
}

.icon-group:first-of-type[b-7poi2k1jer] { margin-top: .3rem; }

/* The tabs of a TABBED set. The menu picker's category chips, drawn smaller: on the recipe
   designer they sit a panel away from that strip, and two kinds of tab on one screen would read as
   two kinds of thing. Filled when open, like a lit category. */
.icon-tabs[b-7poi2k1jer] {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    margin-bottom: .6rem;
}

.icon-tab[b-7poi2k1jer] {
    display: inline-flex;
    align-items: center;
    min-height: 2.25rem;
    padding: .2rem .65rem;
    border: 1px solid var(--pos-gray-400);
    border-radius: .375rem;
    background: #fff;
    color: var(--pos-gray-700);
    font-size: .85rem;
    line-height: 1.2;
    cursor: pointer;
}

.icon-tab:hover[b-7poi2k1jer] {
    border-color: var(--pos-teal);
    color: var(--pos-teal-dark);
}

.icon-tab:focus-visible[b-7poi2k1jer] { outline: 2px solid var(--pos-teal); outline-offset: 2px; }

.icon-tab--on[b-7poi2k1jer],
.icon-tab--on:hover[b-7poi2k1jer] {
    border-color: var(--pos-teal);
    background: var(--pos-teal);
    color: #fff;
}

/* "No icon" shows letters rather than an empty box, which would read as an icon that failed to
   load rather than as the answer somebody chose. */
.icon-tile-none[b-7poi2k1jer] {
    font-size: .95rem;
    font-weight: 600;
    color: var(--pos-gray-500);
}

.icon-tile:hover[b-7poi2k1jer] { border-color: var(--pos-teal); }

.icon-tile:focus-visible[b-7poi2k1jer] { outline: 2px solid var(--pos-teal); outline-offset: 2px; }

/* Chosen. Teal ring plus an inset, because on a wall of tiles a border colour alone is easy to miss. */
.icon-tile--on[b-7poi2k1jer] {
    border-color: var(--pos-teal);
    box-shadow: inset 0 0 0 2px var(--pos-teal);
    color: var(--pos-teal-dark);
}
/* /Components/Shared/LineChart.razor.rz.scp.css */
/* What the full-strength and the faint lines are, under the legend while a chart compares two
   things. In the page's own gray, because it is about every line at once rather than one colour. */
.compare-key[b-crd66bcj0x] {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem 1.25rem;
    margin: -.4rem 0 .75rem;
    padding-left: .6rem;
    font-size: .85rem;
    color: var(--pos-gray-600);
}

.compare-key-item[b-crd66bcj0x] {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
}

.compare-key-solid[b-crd66bcj0x],
.compare-key-faint[b-crd66bcj0x] {
    flex: 0 0 auto;
    width: 1.5rem;
    height: 3px;
    border-radius: 2px;
    background: var(--pos-gray-600);
}

/* The same strength the faint lines are drawn at (ChartTheme.SeriesFaint). */
.compare-key-faint[b-crd66bcj0x] {
    opacity: .45;
}
/* /Components/Shared/PrinterDownStatus.razor.rz.scp.css */
/* The till's and the board's one strip about the printers. RED, because the theme keeps red for
   what is off or has gone wrong, and a printer the kitchen's tickets cannot reach is exactly that.
   It sits ABOVE the page and pushes it down, like the customer screen's strip. On the till its type
   follows the till's own (--pos-type); the board has no such number and takes the page's. */
.printer-down[b-lstya6opt2] {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: .75em;
    padding: .35em .75em;
    background: var(--pos-red-light);
    border-bottom: 1px solid var(--pos-red-border);
    color: var(--pos-red-dark);
    font-size: var(--pos-type, 1rem);
}

/* Several lines: the glyph and the button beside the FIRST of them, not halfway down. */
.printer-down-list[b-lstya6opt2] {
    align-items: flex-start;
}

.printer-down-glyph[b-lstya6opt2] {
    flex: 0 0 auto;
    color: var(--pos-red);
    font-size: 1.35em;
    line-height: 1;
}

/* One printer to a line when they are all shown. Run together across the strip, seven of them read
   as one long sentence, and the name somebody is looking for is lost in the middle of it. */
.printer-down-text[b-lstya6opt2] {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .15em;
    font-weight: 600;
}

/* "+6 more" / "Fewer": the way into the rest when the strip is stacked. A finger's height, because
   it is on the till. */
.printer-down-more[b-lstya6opt2] {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    min-height: 2.25rem;
    border: 1px solid var(--pos-red-border);
    background: #fff;
    color: var(--pos-red-dark);
    font-weight: 600;
}

    .printer-down-more:hover[b-lstya6opt2],
    .printer-down-more:focus-visible[b-lstya6opt2] {
        background: var(--pos-red-light);
        color: var(--pos-red-dark);
    }
/* /Components/Shared/QtyOfStepper.razor.rz.scp.css */
/* Thumb targets: the till and the pass are touch screens, often used with the other hand full. */
.qty-of[b-qangyrmaoi] {
    display: flex;
    align-items: center;
    gap: .6rem;
}

/* Big enough to hit while holding a plate. A number input's spinner arrows are the wrong control
   for this entirely - they are a mouse affordance and all but invisible on a wall screen. */
.qty-of .btn[b-qangyrmaoi] {
    width: 3rem;
    height: 3rem;
    font-size: 1.1rem;
}

.qty-of-value[b-qangyrmaoi] {
    min-width: 2.5rem;
    text-align: center;
    font-size: 1.6rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--pos-gray-900);
}

.qty-of-max[b-qangyrmaoi] {
    font-size: .9rem;
    color: var(--pos-gray-500);
}
/* /Components/Shared/SpanFilter.razor.rz.scp.css */
/* The span filter: the calendar first, then the one-click spans.

   STRETCH, not centre, so every button on a line is one height. A button holding a bilingual pair
   is inline-flex (app.css, .btn:has(.t)) and takes the pair's tighter line height, 26px, while an
   arrow button keeps the ordinary one, 31px - so Today and Last 7 days sat shorter than the
   stepping groups beside them. */
.span-filter[b-ygsmcfjp8x] {
    display: flex;
    align-items: stretch;
    flex-wrap: wrap;
    gap: .4rem;
}

.span-filter-sep[b-ygsmcfjp8x] {
    align-self: center;
    color: var(--pos-gray-400);
    margin: 0 .25rem;
}

/* EVERY BUTTON IN THE ROW KEEPS ONE WIDTH, whatever span is on show, so pressing one never moves
   the others out from under the finger. The calendar comes first, so it mattered most: it was as
   wide as its span, and "1 Oct 2026" against "21 Sept - 27 Sept 2026" shifted the whole row.

   Each floor is the widest label that button really shows, measured in both language orders at
   its own font size, so these are em: the calendar's "28 Sept - 29 Sept 2026" is 14.4em, and the
   steppers' are "99 days ago" (9.8), "52 weeks ago" (10.5) and "12 months ago" (11.7) with their
   Chinese beside them. A MIN-width rather than a width, so a label past those (101 days ago)
   grows the button instead of wrapping onto a second line.

   The calendar's button is drawn by FreeCalendar, so its class reaches it through ::deep. */
.span-filter[b-ygsmcfjp8x]  .span-filter-trigger {
    min-width: 14.75em;
}

.span-step-day .span-step-label[b-ygsmcfjp8x] {
    min-width: 10em;
}

.span-step-week .span-step-label[b-ygsmcfjp8x] {
    min-width: 10.75em;
}

.span-step-month .span-step-label[b-ygsmcfjp8x] {
    min-width: 12em;
}
/* /Components/Shared/StaffPinDialogHost.razor.rz.scp.css */
/* The PIN dialog. Everything a finger lands on is sized in rem, because a hand is the same size on
   every till; the keys are the size of a calculator's, and the names are rows a thumb can pick. */

.pin-ask[b-at9e4f2qa7] {
    border-left: 4px solid var(--pos-gold);
    background: var(--pos-gray-50);
    border-radius: .375rem;
    padding: .6rem .8rem;
    margin-bottom: 1rem;
}

.pin-ask-what[b-at9e4f2qa7] {
    font-weight: 600;
    font-size: 1.05rem;
}

.pin-ask-detail[b-at9e4f2qa7] {
    margin-top: .15rem;
}

.pin-ask-how[b-at9e4f2qa7] {
    margin-top: .35rem;
    font-size: .85rem;
    color: var(--bs-secondary-color);
}

.pin-empty[b-at9e4f2qa7] {
    padding: 1rem 0;
    color: var(--bs-secondary-color);
    text-align: center;
}

.pin-names[b-at9e4f2qa7] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: .5rem;
}

.pin-name[b-at9e4f2qa7] {
    display: flex;
    align-items: center;
    gap: .6rem;
    min-height: 3.5rem;
    padding: .5rem .75rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    background: var(--bs-body-bg);
    text-align: left;
}

    .pin-name:hover[b-at9e4f2qa7],
    .pin-name:focus-visible[b-at9e4f2qa7] {
        border-color: var(--pos-teal);
        background: var(--pos-teal-light);
    }

.pin-name-initial[b-at9e4f2qa7] {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    background: var(--pos-teal);
    color: #fff;
    font-weight: 600;
}

.pin-name-text[b-at9e4f2qa7] {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.pin-name-who[b-at9e4f2qa7] {
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pin-name-role[b-at9e4f2qa7] {
    font-size: .8rem;
    color: var(--bs-secondary-color);
}

.pin-who[b-at9e4f2qa7] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .6rem;
    font-size: 1.1rem;
    margin-bottom: .75rem;
    position: relative;
}

.pin-back[b-at9e4f2qa7] {
    position: absolute;
    left: 0;
    padding: .25rem .5rem;
    font-size: 1.25rem;
}

/* Off screen rather than display: none, or it could not hold the keyboard's focus. */
.pin-capture[b-at9e4f2qa7] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.pin-dots[b-at9e4f2qa7] {
    display: flex;
    justify-content: center;
    gap: .75rem;
    min-height: 1.5rem;
    cursor: text;
}

.pin-dot[b-at9e4f2qa7] {
    width: .9rem;
    height: .9rem;
    border-radius: 50%;
    border: 2px solid var(--pos-gray-500);
}

    .pin-dot.filled[b-at9e4f2qa7] {
        background: var(--pos-gray-800);
        border-color: var(--pos-gray-800);
    }

.pin-dots-wrong .pin-dot[b-at9e4f2qa7] {
    border-color: var(--bs-danger);
}

.pin-problem[b-at9e4f2qa7] {
    min-height: 2.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--bs-danger);
    font-size: .9rem;
    text-align: center;
}

.pin-pad[b-at9e4f2qa7] {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: .5rem;
    max-width: 18rem;
    margin: 0 auto;
}

.pin-key[b-at9e4f2qa7] {
    min-height: 3.5rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    background: var(--bs-body-bg);
    font-size: 1.5rem;
    font-variant-numeric: tabular-nums;
}

    .pin-key:active:not(:disabled)[b-at9e4f2qa7] {
        background: var(--pos-gray-100);
    }

    .pin-key:disabled[b-at9e4f2qa7] {
        opacity: .45;
    }

.pin-key-quiet[b-at9e4f2qa7] {
    background: transparent;
    border-color: transparent;
}

.pin-key-go[b-at9e4f2qa7] {
    background: var(--pos-teal);
    border-color: var(--pos-teal);
    color: #fff;
}
/* /Components/ShopLayout/RoomCanvas.razor.rz.scp.css */
/* RoomCanvas: an unbounded plane of cells seen through a pan / zoom viewport. The canvas fills
   its wrapper and draws the grid; the layer inside it is translated and scaled by the view
   (custom properties the JS module keeps current); each table is an absolutely positioned box
   on the layer whose place and size come from its --x/--y/--w/--h times --cell. Colours follow
   the 70/20/10 theme: gray surfaces and tables, teal for the hover/active affordance, gold
   reserved for the one selected table. */

.room-canvas-wrap[b-n0b21faz1s] {
    position: relative;
    width: 100%;
    height: 100%;
    min-height: 0;
    overflow: hidden;
    background: var(--pos-gray-100);
}

.room-canvas[b-n0b21faz1s] {
    --cell: 24px;
    --zoom: 1;
    --pan-x: 0px;
    --pan-y: 0px;
    position: absolute;
    inset: 0;
    overflow: hidden;
    background-color: #fff;
    outline: none;
    touch-action: none;
}

.room-canvas.pannable[b-n0b21faz1s] {
    cursor: grab;
}

.room-canvas.panning[b-n0b21faz1s] {
    cursor: grabbing;
}

/* The grid is on the viewport, not the layer, so it is endless: its spacing follows the zoom
   and its offset follows the pan, which keeps the lines on the cell boundaries. */
.room-canvas.show-grid[b-n0b21faz1s] {
    background-image:
        linear-gradient(to right, var(--pos-gray-200) 1px, transparent 1px),
        linear-gradient(to bottom, var(--pos-gray-200) 1px, transparent 1px);
    background-size: calc(var(--cell) * var(--zoom)) calc(var(--cell) * var(--zoom));
    background-position: var(--pan-x) var(--pan-y);
}

/* Zoomed far out the lines would be closer than their own width: just noise. */
.room-canvas.show-grid.zoomed-out[b-n0b21faz1s] {
    background-image: none;
}

.room-canvas:focus-visible[b-n0b21faz1s] {
    box-shadow: inset 0 0 0 2px var(--pos-teal);
}

.room-canvas-layer[b-n0b21faz1s] {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
    transform-origin: 0 0;
    transform: translate(var(--pan-x), var(--pan-y)) scale(var(--zoom));
}

.room-table[b-n0b21faz1s] {
    position: absolute;
    left: calc(var(--x) * var(--cell));
    top: calc(var(--y) * var(--cell));
    width: calc(var(--w) * var(--cell));
    height: calc(var(--h) * var(--cell));
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .1em;
    overflow: hidden;
    padding: 2px;
    background: var(--pos-gray-600);
    border: 2px solid var(--pos-gray-800);
    border-radius: 6px;
    color: #fff;
    font-weight: 600;
    text-align: center;
    line-height: 1.1;
    user-select: none;
    cursor: pointer;
    transition: box-shadow .12s, border-color .12s;
}

.room-table.shape-round[b-n0b21faz1s] {
    border-radius: 50%;
}

.room-table:hover[b-n0b21faz1s] {
    border-color: var(--pos-teal);
}

.editable .room-table[b-n0b21faz1s] {
    cursor: grab;
}

.room-table.dragging[b-n0b21faz1s] {
    cursor: grabbing;
    opacity: .9;
    z-index: 10;
    transition: none;
    box-shadow: 0 8px 20px rgba(0, 0, 0, .3);
}

/* The cell under a drag is taken: the drop will be refused, say so before it happens. */
.room-table.dragging.invalid[b-n0b21faz1s] {
    cursor: not-allowed;
    border-color: var(--bs-danger);
    box-shadow: 0 0 0 3px rgba(var(--bs-danger-rgb), .35), 0 8px 20px rgba(0, 0, 0, .3);
}

.room-table.selected[b-n0b21faz1s] {
    border-color: var(--pos-gold);
    box-shadow: 0 0 0 3px var(--pos-gold-light), 0 0 0 5px var(--pos-gold);
    z-index: 5;
}

/* Shift+drag on empty space: the selection box (rendered by Blazor, shown and placed in
   viewport px by the JS module) and the tables it currently covers. The cursor turns into a
   crosshair as soon as Shift is held over the canvas, so the gesture announces itself. */
.room-canvas-marquee[b-n0b21faz1s] {
    position: absolute;
    border: 2px dashed var(--pos-teal);
    background: color-mix(in srgb, var(--pos-teal) 18%, transparent);
    pointer-events: none;
    z-index: 20;
}

.room-canvas.editable.boxable[b-n0b21faz1s],
.room-canvas.boxing[b-n0b21faz1s],
.room-canvas.boxing .room-table[b-n0b21faz1s] {
    cursor: crosshair;
}

.room-table.boxed[b-n0b21faz1s] {
    border-color: var(--pos-teal);
    box-shadow: 0 0 0 3px var(--pos-teal-light);
}

/* Sizes are in layer px and scale with the view along with everything else. */
.room-table-label[b-n0b21faz1s] {
    font-size: calc(var(--cell) * .5);
}

.room-table-seats[b-n0b21faz1s] {
    font-size: calc(var(--cell) * .36);
    font-weight: 400;
    opacity: .85;
    white-space: nowrap;
}

.room-canvas-empty[b-n0b21faz1s] {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--pos-gray-500);
    pointer-events: none;
}

/* Corner view controls: zoom out / readout / zoom in / fit, plus the out-of-view badge. Plain
   buttons the JS module handles; nothing here reaches the circuit. */
.room-canvas-controls[b-n0b21faz1s] {
    position: absolute;
    right: .75rem;
    bottom: .75rem;
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 2px;
    background: rgba(255, 255, 255, .92);
    border: 1px solid var(--pos-gray-300);
    border-radius: 6px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .1);
}

.room-canvas-controls button[b-n0b21faz1s] {
    border: 0;
    background: transparent;
    min-width: 28px;
    height: 26px;
    padding: 0 4px;
    border-radius: 4px;
    color: var(--pos-gray-700);
    line-height: 1;
}

.room-canvas-controls button:hover[b-n0b21faz1s] {
    background: var(--pos-gray-100);
    color: var(--pos-teal-dark);
}

.room-canvas-zoom[b-n0b21faz1s] {
    min-width: 3.2rem;
    text-align: center;
    font-size: .8rem;
    color: var(--pos-gray-600);
    user-select: none;
}

.room-canvas-controls .room-canvas-outside[b-n0b21faz1s] {
    padding: 0 .5rem;
    margin-right: 4px;
    font-size: .75rem;
    white-space: nowrap;
    color: var(--pos-teal-dark);
    background: var(--pos-teal-light);
}
/* /Components/ShopLayout/TableQrPanel.razor.rz.scp.css */
/* ---- Table QR codes -------------------------------------------------------------------------
   The picture is what a shop takes away, so it is shown at a size somebody can actually check by
   eye - a code too small to read on screen is one nobody can tell apart from another table's. On
   WHITE whatever the pane's background, because a QR needs its quiet zone to be light and the
   picture's own margin is the only one it has. */

.qr-img[b-gur2dudos8] {
    display: block;
    width: 100%;
    max-width: 11rem;
    height: auto;
    background: #fff;
    border: 1px solid var(--pos-gray-200);
    border-radius: .25rem;
    padding: .25rem;
}

.qr-single .qr-img[b-gur2dudos8] {
    margin-bottom: .5rem;
}

/* The address, long enough to scroll inside its own box. It is monospace because the one thing
   somebody reads off it by eye is the hostname, character by character, against the one they meant
   to be on. */
.qr-link[b-gur2dudos8] {
    margin-bottom: .5rem;
}

.qr-link input[b-gur2dudos8] {
    font-family: var(--bs-font-monospace);
    font-size: .75rem;
}

/* Printer and Print, above the buttons. The picker takes what is left after the two fixed ends, so
   a long printer name shortens rather than pushing the button off the pane. */
.qr-print[b-gur2dudos8] {
    margin-bottom: .5rem;
}

.qr-actions[b-gur2dudos8] {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

/* One cell per table, as many across as the pane allows. The pane is narrow and can get narrower,
   so the track has a floor rather than a fixed count. */
.qr-grid[b-gur2dudos8] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr));
    gap: .75rem;
}

.qr-cell[b-gur2dudos8] {
    text-align: center;
}

.qr-cell .qr-img[b-gur2dudos8] {
    max-width: 100%;
}

/* Two formats of the same code, side by side under the label. Centred with the cell and spaced by
   a gap rather than a margin, so the pair stays centred whichever of them is wider. */
.qr-cell-actions[b-gur2dudos8] {
    display: flex;
    justify-content: center;
    gap: .5rem;
}

/* The table's own label: the shop's data, so never translated, and the one thing that says which
   picture is which once they are saved. */
.qr-label[b-gur2dudos8] {
    margin-top: .25rem;
    font-size: .8125rem;
    font-weight: 600;
    color: var(--pos-gray-700);
}
/* /Customer/CustomerLayout.razor.rz.scp.css */
/* A customer's phone, not a till. One column, generous touch targets, and the app's own colours so
   the page plainly belongs to the shop whose sticker was just scanned.

   It does NOT use app.css's locked-viewport assumptions: this page scrolls normally, because a
   customer reading a menu on a phone scrolls, where every staff screen is pinned to the viewport. */

.cx-shell[b-t6wp8owvny] {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--pos-gray-100);
}

.cx-top[b-t6wp8owvny] {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .75rem 1rem;
    background: var(--pos-gray-700);
    color: #fff;
}

.cx-brand[b-t6wp8owvny] {
    font-size: 1.125rem;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--pos-gold);
}

.cx-lang[b-t6wp8owvny] {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    /* A finger's worth of target, the same reason every POS button has a minimum. */
    min-height: 2.5rem;
    padding: .25rem .6rem;
    border: 1px solid rgba(255, 255, 255, .25);
    border-radius: .375rem;
    background: transparent;
    color: inherit;
    font-size: .8125rem;
    line-height: 1.1;
}

.cx-lang-1[b-t6wp8owvny] { font-weight: 600; }
.cx-lang-2[b-t6wp8owvny] { opacity: .65; font-size: .78em; }

.cx-body[b-t6wp8owvny] {
    flex: 1 1 auto;
    /* A side gutter that survives a narrow phone, set once here rather than per page. The bottom is
       generous because the basket bar floats over the page: without it the last dish on the menu
       would sit under the bar and be untappable. */
    padding: 1.25rem 1rem 6rem;
    max-width: 40rem;
    width: 100%;
    margin-inline: auto;
}
/* /Customer/CustomerOrderPage.razor.rz.scp.css */
/* Phone-first. Everything here is one column and sized for a person standing up holding a phone at
   arm's length, not for a cashier leaning over a till. */

.cx-card[b-drm5ctty6y] {
    background: #fff;
    border: 1px solid var(--pos-gray-200);
    border-radius: .5rem;
    padding: 1.25rem;
    margin-bottom: 1rem;
}

.cx-eyebrow[b-drm5ctty6y] {
    margin: 0 0 .25rem;
    font-size: .8125rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--pos-gray-500);
}

/* EVERYTHING ABOVE THE MENU IN ONE CARD, and tighter than the rest: the table, how the order is
   charged and what is already on the bill were two cards of four lines and two, which is most of a
   phone screen spent before the first dish. All of it answers "am I in the right place", which is
   read once and scrolled past. */
.cx-head[b-drm5ctty6y] {
    padding: .875rem 1rem;
}

/* The table and the order type share a line, and give way onto two only when a long pair of names
   will not fit. Baselines rather than centres, so the big table label and the small order type sit
   on one line of text rather than on a shared middle. */
.cx-head-row[b-drm5ctty6y] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: .25rem .75rem;
}

/* The eyebrow's margin is for a label sitting OVER its value; on this row it sits beside it. */
.cx-head-row > .cx-eyebrow[b-drm5ctty6y] {
    margin-bottom: 0;
}

/* The table's name is the one thing a customer must be able to check at a glance against the table
   they are sitting at - so it is still the biggest thing on the card, just no longer twice the size
   of anything near it. It is the shop's own data, never translated. */
.cx-table[b-drm5ctty6y] {
    margin: 0;
    font-size: 1.5rem;
    line-height: 1.2;
    font-weight: 600;
}

/* The room follows the table on its own line rather than under it: it is the quieter half of one
   address, and a line of its own said so at the same weight as everything else. */
.cx-room[b-drm5ctty6y] {
    margin-left: .4rem;
    font-size: .9375rem;
    font-weight: 400;
    color: var(--pos-gray-500);
}

.cx-muted[b-drm5ctty6y] { color: var(--pos-gray-500); }

.cx-note[b-drm5ctty6y] {
    margin: 0 0 1rem;
    padding: .75rem 1rem;
    border-left: 3px solid var(--pos-teal);
    background: #fff;
    font-size: .9375rem;
}

.cx-problem[b-drm5ctty6y] {
    text-align: center;
    color: var(--pos-gray-700);
}

.cx-problem-title[b-drm5ctty6y] {
    margin: .75rem 0 .5rem;
    font-size: 1.25rem;
    font-weight: 600;
}

/* A send that did not go through: the card above, floated over the basket in the middle of the
   screen. Above the question sheet (20, 21) and everything else on the page, because nothing should
   be tapped past it unread. */
.cx-dialog-backdrop[b-drm5ctty6y] {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .45);
    z-index: 30;
}

.cx-dialog[b-drm5ctty6y] {
    position: fixed;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 31;
    width: min(26rem, calc(100% - 2rem));
    max-height: calc(100% - 2rem);
    overflow-y: auto;
    margin: 0;
    box-shadow: 0 .75rem 2.5rem rgba(0, 0, 0, .25);
}

/* Gold, the theme's "look at this one thing": a warning the customer has to act on, not a fault. */
.cx-dialog[b-drm5ctty6y]  .svg-icon {
    color: var(--pos-gold-dark);
}

/* ---- The menu ------------------------------------------------------------------------------- */

/* Scrolls sideways rather than wrapping. A strip that grows to three rows pushes the food off a
   phone screen, which is the opposite of what a menu is for. */
.cx-tabs[b-drm5ctty6y] {
    display: flex;
    gap: .5rem;
    overflow-x: auto;
    padding-bottom: .25rem;
    scrollbar-width: none;
}

.cx-tabs[b-drm5ctty6y]::-webkit-scrollbar { display: none; }

.cx-tab[b-drm5ctty6y] {
    flex: 0 0 auto;
    /* A finger's worth of target, the same minimum every POS button keeps. */
    min-height: 2.5rem;
    padding: .4rem .9rem;
    border: 1px solid var(--pos-gray-300);
    border-radius: 1.25rem;
    background: #fff;
    font-size: .9375rem;
    font-weight: 500;
    white-space: nowrap;
    color: var(--pos-gray-700);
}

.cx-tab.is-on[b-drm5ctty6y] {
    background: var(--pos-teal);
    border-color: var(--pos-teal);
    color: #fff;
}

.cx-group[b-drm5ctty6y] { margin-bottom: 1.5rem; }

.cx-group-title[b-drm5ctty6y] {
    margin: 0 0 .5rem;
    font-size: 1rem;
    font-weight: 600;
    color: var(--pos-gray-600);
}

/* The row is a CONTAINER now, not the button. The quantity stepper is not inside its tap area,
   because a button inside a button is not valid markup and changing a quantity must not also reopen
   the dish's questions. Positioned, because the stepper is laid over the tap area's last line. */
.cx-item[b-drm5ctty6y] {
    position: relative;
    display: flex;
    align-items: center;
    gap: .5rem;
    background: #fff;
    border: 1px solid var(--pos-gray-200);
    border-radius: .5rem;
    margin-bottom: .5rem;
}

/* The photo's own tap target, padded out to the row's edge so the whole corner zooms, not only the
   picture inside it. Its right side has no padding. The add button beside it starts .25rem in, and
   with the row's gap that keeps the photo and the name the .75rem apart they always were. */
.cx-item-zoom[b-drm5ctty6y] {
    flex: 0 0 auto;
    display: block;
    padding: .75rem 0 .75rem .75rem;
    border: 0;
    background: none;
    cursor: zoom-in;
}

.cx-item-zoom .cx-item-photo[b-drm5ctty6y] { display: block; }

.cx-item-tap[b-drm5ctty6y] {
    flex: 1 1 auto;
    min-width: 0;
    /* Stretched to the row's full height, which the photo sets now that it sits outside this button.
       Otherwise the strip above and below a one-line name would be a dead zone. */
    align-self: stretch;
    /* A COLUMN: the name and the description, then the price on a line of its own at the foot. The
       price used to sit to the right of the text, and with the stepper beside it the two took
       two-thirds of a phone's row and left the description a word wide. */
    display: flex;
    flex-direction: column;
    gap: .25rem;
    padding: .75rem .75rem .75rem .25rem;
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.cx-item-tap:disabled[b-drm5ctty6y] { cursor: default; }

/* A stepper on the row itself, so a double tap is undone where it happened. Laid over the right
   end of the price's line (.cx-item-foot), which is as tall as this is and exactly as far from the
   row's bottom edge, so the two sit on one line without the stepper taking any width from the text.
   It is drawn over the tap area and so takes the tap; the rest of the line still adds the dish. */
.cx-item-qty[b-drm5ctty6y] {
    position: absolute;
    right: .75rem;
    bottom: .75rem;
    display: inline-flex;
    align-items: center;
    gap: .375rem;
}

/* A dish that has run out is still NAMED and still priced - a customer looking for something they
   had last week needs to be told it is off today, not left wondering. It recedes; it does not go. */
.cx-item.is-off[b-drm5ctty6y] {
    opacity: .55;
}

.cx-item-photo[b-drm5ctty6y] {
    flex: 0 0 auto;
    width: 5.5rem;
    height: 5.5rem;
    object-fit: cover;
    border-radius: .375rem;
    background: var(--pos-gray-100);
}

/* WHILE A PHOTO IS ON ITS WAY, something has to say so. A photo still coming and a photo that is
   never coming are the same grey square otherwise, and on a phone the wait is real: the whole menu
   goes out in one burst and the ones at the back arrive last.

   Whether it has arrived is a CLASS WRITTEN BY js/customerImages.js, which is listening for the
   load anyway - the same trade kanbanClock.js makes about time passing. Asked through the circuit
   this would be a round trip per photo per phone, fifty-three of them landing together.

   The box exists only to hold the ring: a pseudo-element on an <img> never renders, and the button
   around it is padded out to the row's edge, so a ring centred on THAT sits off the photo. */
.cx-item-photo-box[b-drm5ctty6y] {
    position: relative;
    display: block;
}

.cx-item-photo-box[b-drm5ctty6y]::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 1.5rem;
    height: 1.5rem;
    /* Centred by NEGATIVE MARGINS and not by a transform, which the rotation below would overwrite. */
    margin: -.75rem 0 0 -.75rem;
    border: 2px solid var(--pos-gray-300);
    border-right-color: transparent;
    border-radius: 50%;
    /* Bootstrap's own rotation, the one every other spinner in the app turns on. The second
       animation is the DELAY: a photo already in the browser's cache draws before .35s is up, and
       a ring that flashes on every row of a menu that loaded perfectly is worse than no ring. */
    animation: spinner-border .75s linear infinite, cx-photo-wait-b-drm5ctty6y .2s ease-out .35s both;
}

/* Settled is arrived, OR failed for the last time - js/customerImages.js says which, because only
   it knows whether another attempt is coming. A ring still turning over a photo that is never
   coming is a worse lie than the empty square it replaced. */
.cx-item-photo-box.is-settled[b-drm5ctty6y]::after {
    content: none;
}

@keyframes cx-photo-wait-b-drm5ctty6y {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* Slowed rather than stopped, the way Bootstrap's own spinners answer this: the ring is the only
   thing saying the photo is still coming, so taking it away says nothing at all. */
@media (prefers-reduced-motion: reduce) {
    .cx-item-photo-box[b-drm5ctty6y]::after {
        animation-duration: 1.5s, .2s;
    }
}

/* Drawn even with no photo, so the names stay in one column down the list instead of stepping in
   and out around the dishes that have one. */
.cx-item-photo-none[b-drm5ctty6y] {
    border: 1px dashed var(--pos-gray-200);
}

.cx-item.is-off .cx-item-photo[b-drm5ctty6y] {
    filter: grayscale(1);
}

.cx-item-text[b-drm5ctty6y] {
    flex: 1 1 auto;
    min-width: 0;
}

/* BLOCK, because on a menu row these are SPANS. A button may only hold phrasing content, so the row
   cannot use a div, and an inline span let the description run straight on after the name on the
   same line - a long bilingual name and a long bilingual description read as one paragraph. The
   basket and the bill use divs, where this changes nothing. */
.cx-item-name[b-drm5ctty6y] {
    display: block;
    font-weight: 600;
    line-height: 1.25;
}

.cx-item-desc[b-drm5ctty6y],
:where(.cx-sheet-host)[b-drm5ctty6y]  .cx-item-desc {
    display: block;
    margin-top: .25rem;
    font-size: .8125rem;
    line-height: 1.35;
    color: var(--pos-gray-500);
}

/* ONE LINE of each paragraph on a menu row, and two when there is only one. The shop writes a
   paragraph per language, so this shows the start of each; the whole text is behind the photo.
   Shown in full, one dish took more than a phone's screen. */
.cx-item-para[b-drm5ctty6y],
:where(.cx-sheet-host)[b-drm5ctty6y]  .cx-item-para {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 1;
    line-clamp: 1;
    overflow: hidden;
}

.cx-item-para:only-child[b-drm5ctty6y],
:where(.cx-sheet-host)[b-drm5ctty6y]  .cx-item-para:only-child {
    -webkit-line-clamp: 2;
    line-clamp: 2;
}

.cx-item-off[b-drm5ctty6y] {
    display: inline-block;
    margin-top: .25rem;
    padding: .0625rem .375rem;
    border-radius: .25rem;
    background: var(--pos-gray-200);
    font-size: .75rem;
    font-weight: 600;
    color: var(--pos-gray-600);
}

.cx-item-price[b-drm5ctty6y] {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

/* The price's own line at the foot of a menu row. Pushed to the bottom so every row's price lines
   up with the bottom of its photo, and read down a column at the text's left edge. It is as tall
   as the stepper even when there is none, so a dish going into the basket does not grow its row. */
.cx-item-foot[b-drm5ctty6y] {
    display: flex;
    align-items: center;
    min-height: 2.5rem;
    margin-top: auto;
}

.cx-fineprint[b-drm5ctty6y] {
    margin: 0;
    font-size: .8125rem;
    color: var(--pos-gray-500);
}

/* ---- Choosing, the basket, and the bar ------------------------------------------------------ */

.cx-note-warn[b-drm5ctty6y] {
    border-left-color: var(--pos-gold);
}

.cx-item-in-cart[b-drm5ctty6y] {
    display: inline-block;
    margin-top: .25rem;
    padding: .0625rem .375rem;
    border-radius: .25rem;
    background: var(--pos-teal-light);
    font-size: .75rem;
    font-weight: 600;
    color: var(--pos-teal-dark);
}

/* ---- Buttons --------------------------------------------------------------------------------- */

/* The question sheet is a component of its own (CustomerQuestionSheet), drawn inside this box. The
   box draws nothing; it is what lets the shared rules below - the buttons, the stepper, a
   description's paragraphs - reach the sheet's markup, through a :where() that adds nothing to
   their specificity, so the sheet's own rules still win exactly where they did. */
.cx-sheet-host[b-drm5ctty6y] {
    display: contents;
}

.cx-btn[b-drm5ctty6y],
:where(.cx-sheet-host)[b-drm5ctty6y]  .cx-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* A finger's worth of target, the minimum every POS button keeps. */
    min-height: 3rem;
    padding: .5rem 1rem;
    border: 1px solid var(--pos-gray-300);
    border-radius: .5rem;
    background: #fff;
    font-size: 1rem;
    font-weight: 600;
    color: var(--pos-gray-700);
}

.cx-btn-primary[b-drm5ctty6y],
:where(.cx-sheet-host)[b-drm5ctty6y]  .cx-btn-primary {
    background: var(--pos-teal);
    border-color: var(--pos-teal);
    color: #fff;
}

.cx-btn-primary:disabled[b-drm5ctty6y],
:where(.cx-sheet-host)[b-drm5ctty6y]  .cx-btn-primary:disabled {
    background: var(--pos-gray-300);
    border-color: var(--pos-gray-300);
    color: var(--pos-gray-600);
}

.cx-btn-wide[b-drm5ctty6y] {
    width: 100%;
    margin-top: .5rem;
}

/* The order-type gate. The answers were full-width rows, because a wide short button takes its
   height from its own label and the shop types its own words into them - "Take Away" beside a name
   in two languages came out as two buttons of different heights. A GRID does not have that problem:
   the row sizes to the tallest tile and both stretch to match, so making them bigger is what let
   them sit side by side. */
.cx-type-grid[b-drm5ctty6y] {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: .5rem;
}

/* An odd one out takes the whole width rather than sitting alone in the left column, where the gap
   beside it reads as a tile that failed to load. */
.cx-type-grid > .cx-type:last-child:nth-child(odd)[b-drm5ctty6y] { grid-column: 1 / -1; }

/* The first thing a scan puts in front of somebody standing at a table, so it is sized for a thumb
   and a glance rather than for the page. */
.cx-type[b-drm5ctty6y] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    min-height: 7.5rem;
    padding: 1rem .75rem;
    border: 1px solid var(--pos-gray-300);
    border-radius: .75rem;
    background: #fff;
    color: var(--pos-gray-700);
    font: inherit;
    text-align: center;
    cursor: pointer;
}

.cx-type:active[b-drm5ctty6y] {
    border-color: var(--pos-teal);
    background: var(--pos-gray-100);
}

/* Teal, which is the app's own colour and not the shop's. The icon is a decoration on somebody
   else's word, so it never competes with the name under it. */
.cx-type-icon[b-drm5ctty6y] {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 2.75rem;
    color: var(--pos-teal);
}

/* ::deep, because the <svg> is SvgIcon's markup and never carries this page's scope attribute. */
.cx-type-icon[b-drm5ctty6y]  .svg-icon { font-size: 2.75rem; line-height: 1; }

/* Big enough to read at arm's length, and allowed to wrap: this is the shop's own text and it is
   often two languages long. */
.cx-type-name[b-drm5ctty6y] {
    font-size: 1.125rem;
    font-weight: 600;
    line-height: 1.25;
}

/* The answer, read back under the table's name. Quiet, because it is a confirmation and not the
   thing the customer came to look at. */
.cx-chosen[b-drm5ctty6y] {
    font-size: .9375rem;
    font-weight: 600;
    color: var(--pos-gray-700);
}

/* The same mark that was on the tile they tapped, so the line reads as the answer to the question
   rather than as a new piece of information. */
.cx-chosen[b-drm5ctty6y]  .svg-icon {
    margin-right: .3rem;
    color: var(--pos-teal);
}

/* A button that reads as a link. It is a <button> and not an <a> because it changes what is on
   screen rather than going anywhere, and a customer's back gesture must not undo it. */
.cx-link[b-drm5ctty6y] {
    margin-left: .5rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-weight: 400;
    color: var(--pos-teal);
    text-decoration: underline;
}

.cx-icon-btn[b-drm5ctty6y],
:where(.cx-sheet-host)[b-drm5ctty6y]  .cx-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.5rem;
    min-height: 2.5rem;
    border: 1px solid var(--pos-gray-300);
    border-radius: .375rem;
    background: #fff;
    font-size: 1.125rem;
    line-height: 1;
    color: var(--pos-gray-700);
}

/* The way BACK from the basket and the bill: a tap-sized button with its arrow. It shared the name
   .cx-link with the inline text link above, and the two rules merged, so "Change" grew a 2.5rem
   height in the middle of a line and the back buttons came out underlined. */
.cx-back[b-drm5ctty6y] {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    min-height: 2.5rem;
    border: 0;
    background: none;
    padding: 0;
    font-size: .9375rem;
    color: var(--pos-teal-dark);
}

.cx-stepper[b-drm5ctty6y],
:where(.cx-sheet-host)[b-drm5ctty6y]  .cx-stepper {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
}

.cx-stepper-qty[b-drm5ctty6y],
:where(.cx-sheet-host)[b-drm5ctty6y]  .cx-stepper-qty {
    min-width: 1.5rem;
    text-align: center;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* ---- The basket ------------------------------------------------------------------------------ */

.cx-cart-head[b-drm5ctty6y] { margin-bottom: .5rem; }

.cx-cart-line[b-drm5ctty6y] {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    padding: .75rem;
    background: #fff;
    border: 1px solid var(--pos-gray-200);
    border-radius: .5rem;
    margin-bottom: .5rem;
}

.cx-cart-text[b-drm5ctty6y] { flex: 1 1 auto; min-width: 0; }

.cx-cart-right[b-drm5ctty6y] {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: .5rem;
}

/* The price sits on the DISH'S OWN LINE, so it has to share that line's box. The rows are
   top-aligned (a line can run to three lines of text and the money belongs beside the first), and
   top-aligning two boxes of different line-heights leaves the two texts 2px apart - not obviously
   wrong, just never quite right. The menu's own rows are centred and need none of this. */
.cx-cart-line .cx-item-price[b-drm5ctty6y] {
    line-height: 1.25;
}

/* What the shop adds to a line - packaging. It reads as part of the line rather than as another
   line: same quiet size as a chosen answer, and its amount sits with the words instead of in the
   price column, where it would line up under the dish's own figure and read as a second dish. */
.cx-item-added[b-drm5ctty6y] {
    display: flex;
    gap: .5rem;
    margin-top: .125rem;
    font-size: .8125rem;
    color: var(--pos-gray-500);
}

.cx-added-price[b-drm5ctty6y] {
    font-variant-numeric: tabular-nums;
}

.cx-cart-note[b-drm5ctty6y] {
    margin-top: .125rem;
    font-size: .8125rem;
    font-style: italic;
    color: var(--pos-gray-500);
}

/* The extra pixel is the LINE CARD'S BORDER. The rows above are bordered cards and these are
   not, so a plain .75rem here left every figure a pixel inside the prices it is totalling. */
.cx-cart-total[b-drm5ctty6y] {
    display: flex;
    justify-content: space-between;
    padding: .75rem calc(.75rem + 1px);
    font-size: 1.125rem;
    font-weight: 600;
    border-top: 1px solid var(--pos-gray-300);
    margin-bottom: .5rem;
}

/* ---- Ordered so far ---------------------------------------------------------------------------- */

/* A ROW of the head card, not a card of its own: it is about this table like everything else up
   there. The WHOLE row is the tap target - it says one thing and does one thing, and a phone has no
   hover to go hunting for a link inside it with - so it is a full-width button ruled off from the
   line above. It wraps onto two lines on a narrow phone rather than being measured for. */
.cx-placed[b-drm5ctty6y] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .1rem .5rem;
    width: 100%;
    margin-top: .625rem;
    padding: .625rem 0 0;
    border: 0;
    border-top: 1px solid var(--pos-gray-200);
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

/* The label keeps its own margin off, because on this row it sits BESIDE the figure rather than
   over it. */
.cx-placed .cx-eyebrow[b-drm5ctty6y] {
    margin: 0;
}

.cx-placed-sum[b-drm5ctty6y] {
    font-size: 1.125rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* Hard against the right edge whether the row wrapped or not, so the row reads as one thing to
   tap. */
.cx-placed[b-drm5ctty6y]  .cx-placed-more {
    margin-left: auto;
    align-self: center;
    color: var(--pos-gray-400);
}

/* The quantity, ahead of the name on a line nothing can change. Muted, because the NAME is what a
   customer reads down this list for - the figures are checked afterwards, in one column. */
.cx-bill-qty[b-drm5ctty6y] {
    color: var(--pos-gray-500);
    font-variant-numeric: tabular-nums;
}

/* The bill's arithmetic under its lines: subtotal, each charge, the shop's rounding. Muted and
   tighter than the total below them, which is the figure somebody actually came to read. */
.cx-bill-row[b-drm5ctty6y] {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    /* The same pixel as .cx-cart-total: these rows carry no border and the lines above them do. */
    padding: .25rem calc(.75rem + 1px);
    color: var(--pos-gray-500);
}

.cx-bill-row > span:last-child[b-drm5ctty6y] {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
}

/* ---- The basket bar -------------------------------------------------------------------------- */

/* Always in reach, because the basket is the thing a customer loses track of on a long menu. Fixed
   rather than sticky so it survives the page scrolling, and the shell keeps a matching gap at the
   bottom so the last dish is never hidden under it. */
.cx-bar[b-drm5ctty6y] {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: calc(.75rem + env(safe-area-inset-bottom, 0px));
    z-index: 15;
    display: flex;
    align-items: center;
    gap: .75rem;
    width: calc(100% - 2rem);
    max-width: 38rem;
    min-height: 3.25rem;
    padding: .5rem 1rem;
    border: 0;
    border-radius: .625rem;
    background: var(--pos-teal);
    color: #fff;
    font-size: 1rem;
    font-weight: 600;
    box-shadow: 0 .25rem 1rem rgba(0, 0, 0, .25);
}

.cx-bar-count[b-drm5ctty6y] {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.75rem;
    height: 1.75rem;
    padding: 0 .375rem;
    border-radius: .875rem;
    background: rgba(255, 255, 255, .22);
    font-variant-numeric: tabular-nums;
}

.cx-bar-label[b-drm5ctty6y] { flex: 1 1 auto; text-align: left; }

.cx-bar-total[b-drm5ctty6y] { flex: 0 0 auto; font-variant-numeric: tabular-nums; }

/* ---- A dish flying into the basket (js/customerFlight.js) -------------------------------------- */

/* The layer the clone lives in. NOT positioned: a fixed ancestor would become the containing block
   for the fixed clone inside it, and the flight's coordinates are the viewport's. It draws nothing
   and takes no room; it exists so this stylesheet can reach the clone at all, which a clone
   appended to <body> would be beyond. */
.cx-flight[b-drm5ctty6y] {
    display: contents;
}

/* The dish flying to the bar, and the landing drawn over the bar, are js/flight.js's to dress: it
   pins the copy above everything and makes it inert, as it already places it. This page and the
   till each carried the same rules for it. */

/* ---- The confirmation ------------------------------------------------------------------------ */

.cx-done[b-drm5ctty6y] {
    text-align: center;
    color: var(--pos-teal-dark);
}

.cx-done-title[b-drm5ctty6y] {
    margin: .75rem 0 .5rem;
    font-size: 1.25rem;
    font-weight: 600;
}

/* ---- The sticky header: search and the category strip ---------------------------------------- */

/* Both are about getting somewhere in a long menu, so both stay in reach. The background is opaque
   because the dishes scroll UNDER it. Its height is measured by js/menuNav.js (it is the
   data-menu-sticky header) rather than assumed - a long category name wraps the strip onto a second
   row on a narrow phone. */
.cx-sticky[b-drm5ctty6y] {
    position: sticky;
    top: 0;
    z-index: 10;
    /* Pulled out to the shell's gutter and padded back, so the strip can scroll edge to edge rather
       than starting and stopping inside a 1rem margin. */
    margin: 0 -1rem .75rem;
    padding: .5rem 1rem .25rem;
    background: var(--pos-gray-100);
    border-bottom: 1px solid var(--pos-gray-200);
}

/* The box and its magnifier are .search-box's (app.css), which the staff pages share. The input
   keeps padding on BOTH sides here, for the clear button at the far end. */
.cx-search[b-drm5ctty6y] {
    display: flex;
    align-items: center;
    margin-bottom: .5rem;
}

.cx-search-input[b-drm5ctty6y] {
    width: 100%;
    min-height: 2.75rem;
    padding: .5rem 2.5rem;
    border: 1px solid var(--pos-gray-300);
    border-radius: .5rem;
    /* 1rem, because anything smaller makes iOS zoom the page on focus - and this page is meant to be
       zoomable, so there is no viewport lock to stop it. */
    font-size: 1rem;
    background: #fff;
}

/* The browser's own clear cross is inconsistent and tiny; this one is a finger's worth. */
.cx-search-input[b-drm5ctty6y]::-webkit-search-cancel-button { display: none; }

.cx-search-clear[b-drm5ctty6y] {
    position: absolute;
    right: .25rem;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.25rem;
    min-height: 2.25rem;
    border: 0;
    background: none;
    color: var(--pos-gray-500);
}

/* A muted label before a section's own run of category pills, the shape the till's strip uses. */
.cx-tabs-section[b-drm5ctty6y] {
    flex: 0 0 auto;
    align-self: center;
    padding-left: .25rem;
    font-size: .75rem;
    white-space: nowrap;
    color: var(--pos-gray-500);
}


/* How many the shop has left of a dish it is counting down. The same pill as the two beside it,
   in gold: it is neither "you cannot have this" (gray) nor "you already have some" (teal) - it is
   the one thing on the row worth hurrying over. */
.cx-item-left[b-drm5ctty6y] {
    display: inline-block;
    margin-top: .25rem;
    padding: .0625rem .375rem;
    border-radius: .25rem;
    background: var(--pos-gold-light);
    font-size: .75rem;
    font-weight: 600;
    color: var(--pos-gray-800);
}
/* /Customer/CustomerPhotoZoom.razor.rz.scp.css */
/* ---- A dish's photo, full-screen -------------------------------------------------------------- */

/* Over everything, the question sheet and the basket bar included. touch-action: none stops a swipe
   on it from scrolling the menu underneath, because the whole promise is that closing it lands the
   customer where they were. A tap still reaches it and closes it. */
.cx-zoom[b-vikqqzad91] {
    position: fixed;
    inset: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    border: 0;
    background: rgba(0, 0, 0, .85);
    cursor: zoom-out;
    touch-action: none;
    animation: cx-zoom-in-b-vikqqzad91 .15s ease-out;
}

/* The photo with the dish's name and whole description under it, as one card. Never taller than
   the screen: nothing in this overlay scrolls, so a caption pushed off the bottom could not be read. */
.cx-zoom-card[b-vikqqzad91] {
    display: flex;
    flex-direction: column;
    width: min(100%, 40rem);
    max-height: 100%;
    overflow: hidden;
    border-radius: .5rem;
    background: #fff;
    text-align: left;
}

/* Every photo is square, because the cropper exports squares, so the box is one while there is
   room. Where the caption and a full square will not both fit, the PHOTO gives way - it shrinks in
   height and is cropped, because the words cannot be cropped. The thumbnail behind it is cropped
   the same way, which is what lets it stand in until the full photo has loaded. */
.cx-zoom-photo[b-vikqqzad91] {
    flex: 0 1 auto;
    min-height: 0;
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    background-size: cover;
    background-position: center;
    background-color: var(--pos-gray-200);
}

.cx-zoom-caption[b-vikqqzad91] {
    flex: 0 0 auto;
    display: block;
    padding: .875rem 1rem 1rem;
}

.cx-zoom-name[b-vikqqzad91] {
    display: block;
    font-weight: 600;
    line-height: 1.25;
    color: var(--pos-gray-800);
}

/* A paragraph per language, as the shop typed them. The row shows only the first line of each. */
.cx-zoom-para[b-vikqqzad91] {
    display: block;
    margin-top: .5rem;
    font-size: .9375rem;
    line-height: 1.45;
    color: var(--pos-gray-600);
}

/* A phone turned on its side has no height for a square AND a caption under it, so they sit side
   by side instead. Only on a SHORT landscape screen: a tablet or a desktop has room for the column. */
@media (orientation: landscape) and (max-height: 32rem) {
    .cx-zoom-card[b-vikqqzad91] {
        flex-direction: row;
        width: min(100%, 52rem);
    }

    .cx-zoom-photo[b-vikqqzad91] {
        flex: 0 0 auto;
        width: auto;
        height: calc(100dvh - 2rem);
        max-width: 55%;
    }

    .cx-zoom-caption[b-vikqqzad91] {
        flex: 1 1 auto;
        min-width: 0;
        overflow: hidden;
    }
}

@keyframes cx-zoom-in-b-vikqqzad91 {
    from { opacity: 0; }
    to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .cx-zoom[b-vikqqzad91] { animation: none; }
}
/* /Customer/CustomerQuestionSheet.razor.rz.scp.css */
/* ---- The question sheet ---------------------------------------------------------------------- */

.cx-sheet-backdrop[b-isx9x07is0] {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .4);
    z-index: 20;
}

/* Anchored to the BOTTOM, where a thumb is. Capped at most of the screen and scrolling inside, so a
   dish with four questions cannot push its own Add button off the bottom. */
.cx-sheet[b-isx9x07is0] {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 21;
    display: flex;
    flex-direction: column;
    max-height: 85vh;
    max-width: 40rem;
    margin-inline: auto;
    background: #fff;
    border-radius: .75rem .75rem 0 0;
    box-shadow: 0 -.25rem 1.5rem rgba(0, 0, 0, .25);
}

.cx-sheet-head[b-isx9x07is0] {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .875rem 1rem;
    border-bottom: 1px solid var(--pos-gray-200);
}

.cx-sheet-name[b-isx9x07is0] {
    flex: 1 1 auto;
    font-size: 1.0625rem;
    font-weight: 600;
}

.cx-sheet-body[b-isx9x07is0] {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 1rem;
}

/* The dish's description at the top of the sheet: cut short like the menu row's, and the whole of
   it on a tap. The chevron sits at the end of the last line and turns over when it is open. */
.cx-about[b-isx9x07is0] {
    display: flex;
    align-items: flex-end;
    gap: .5rem;
    width: 100%;
    margin: 0 0 1rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.cx-about .cx-item-desc[b-isx9x07is0] {
    flex: 1 1 auto;
    min-width: 0;
    margin-top: 0;
}

.cx-about.is-open .cx-item-para[b-isx9x07is0] {
    display: block;
}

.cx-about.is-open .cx-item-para + .cx-item-para[b-isx9x07is0] {
    margin-top: .375rem;
}

/* ::deep, because the <svg> is SvgIcon's markup and never carries this page's scope attribute. */
.cx-about[b-isx9x07is0]  .cx-about-more {
    flex: 0 0 auto;
    margin-bottom: .125rem;
    color: var(--pos-gray-400);
    transition: transform .15s ease-out;
}

.cx-about.is-open[b-isx9x07is0]  .cx-about-more {
    transform: rotate(180deg);
}

@media (prefers-reduced-motion: reduce) {
    .cx-about[b-isx9x07is0]  .cx-about-more { transition: none; }
}

.cx-sheet-foot[b-isx9x07is0] {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .75rem 1rem;
    border-top: 1px solid var(--pos-gray-200);
    /* Clear of a phone's home indicator. */
    padding-bottom: calc(.75rem + env(safe-area-inset-bottom, 0px));
}

.cx-qgroup[b-isx9x07is0] { margin-bottom: 1.25rem; }

.cx-qhead[b-isx9x07is0] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
    margin-bottom: .375rem;
}

.cx-qname[b-isx9x07is0] {
    font-weight: 600;
    font-size: .9375rem;
}

.cx-qrule[b-isx9x07is0] {
    font-size: .8125rem;
    color: var(--pos-gray-500);
}

/* A required question not yet answered says so where the eye already is - beside its name - rather
   than only by the Add button being dead. */
.cx-qrule.is-needed[b-isx9x07is0] {
    color: var(--pos-gold-dark);
    font-weight: 600;
}

/* The shop's own upsell line, under the question whose answer unlocks the next one. Gold for
   the same reason the unanswered rule is: it is the one thing on the sheet asking to be seen. */
.cx-upsell[b-isx9x07is0] {
    color: var(--pos-gold-dark);
    font-weight: 600;
    font-size: .9375rem;
    margin: .125rem 0 .375rem;
}

/* A question still waiting for its add-on: named, its rule shown, and plainly not open. */
.cx-qgroup.is-locked .cx-qname[b-isx9x07is0] {
    color: var(--pos-gray-500);
}

.cx-answer[b-isx9x07is0] {
    display: flex;
    align-items: center;
    gap: .625rem;
    width: 100%;
    min-height: 3rem;
    padding: .5rem .75rem;
    margin-bottom: .375rem;
    border: 1px solid var(--pos-gray-200);
    border-radius: .5rem;
    background: #fff;
    font-size: .9375rem;
    text-align: left;
    color: inherit;
}

.cx-answer.is-on[b-isx9x07is0] {
    border-color: var(--pos-teal);
    background: var(--pos-teal-light);
}

/* An answer that has run out is struck through and dead to the touch - the till's treatment, so a
   customer and a cashier see the same thing. */
.cx-answer.is-off[b-isx9x07is0] {
    opacity: .5;
    text-decoration: line-through;
}

.cx-answer-mark[b-isx9x07is0] {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border: 1px solid var(--pos-gray-300);
    border-radius: .25rem;
    background: #fff;
    color: var(--pos-teal-dark);
}

.cx-answer-name[b-isx9x07is0] { flex: 1 1 auto; }

/* A piece picked more than once: the row holds its own stepper, so it is not a button itself. Its
   tap area is a button inside it, and takes over the row's padding on every side but the stepper's,
   so the whole row up to the stepper is one target. */
.cx-answer-repeat[b-isx9x07is0] {
    padding: 0 .75rem 0 0;
}

.cx-answer-tap[b-isx9x07is0] {
    flex: 1 1 auto;
    min-width: 0;
    align-self: stretch;
    display: flex;
    align-items: center;
    gap: .625rem;
    padding: .5rem 0 .5rem .75rem;
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.cx-answer-repeat .cx-stepper[b-isx9x07is0] {
    flex: 0 0 auto;
}

/* How a picked dish was answered, under its name. */
.cx-answer-said[b-isx9x07is0] {
    display: block;
    font-size: .8125rem;
    color: var(--pos-teal-dark);
}

/* The picked dish whose questions are on the sheet, with the way back to the set's. */
.cx-step-head[b-isx9x07is0] {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin-bottom: 1rem;
    padding-bottom: .75rem;
    border-bottom: 1px solid var(--pos-gray-200);
}

.cx-answer-price[b-isx9x07is0] {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    color: var(--pos-gray-600);
}

.cx-input[b-isx9x07is0] {
    width: 100%;
    min-height: 3rem;
    padding: .5rem .75rem;
    border: 1px solid var(--pos-gray-300);
    border-radius: .5rem;
    font-size: 1rem;
}
