/* Aloke POS on the web — the till's own look.
   ═════════════════════════════════════════════════════════════════════════
   WHY IT DOES NOT LOAD console-theme.css. That sheet says so itself: «the
   admin/super consoles, the till and the customer pages do not load it and
   keep their own look». A console is read; a till is HIT — by somebody
   standing up, in a hurry, often with a queue watching. The two want opposite
   things from the same brand, so this sheet re-values the tokens rather than
   inheriting a reading layout.

   THE THREE RULES EVERYTHING HERE FOLLOWS:

     1. NOTHING A CASHIER PRESSES IS SMALLER THAN 44px, and the things they
        press hundreds of times a day are bigger than that.
     2. EVERY NUMBER IS TABULAR AND LTR-ISOLATED. Arabic is RTL and a price is
        not; a column of prices that shifts by a pixel per digit is a column
        nobody can scan, and «36.00 ر.س» rendered without isolation puts the
        currency on the wrong side of the amount.
     3. THE TICKET IS ALWAYS VISIBLE. Every register layout keeps the running
        total on screen at every width — a total you have to scroll to is a
        total that gets read wrong.

   IT IS BUILT FOR A 1366×768 WINDOWS TILL FIRST, which is the machine the
   founder actually named, and reflows down to a tablet. Below 900px the
   ticket becomes a bottom sheet rather than a column, because a 40 %-width
   ticket on a narrow screen leaves no room for the thing being sold. */

:root {
  --bg: #F6F4FA;
  --surface: #FFFFFF;
  --surface-2: #FBFAFE;
  --ink: #1E1729;
  --muted: #6B6379;
  --line: #E7E2F0;
  --line-strong: #D6CEE6;

  --accent: #5B2C91;
  --accent-press: #43206B;
  --accent-weak: #F2ECFA;
  --accent-ink: #FFFFFF;

  --ok: #1B7A4B;
  --ok-weak: #E8F6EE;
  --warn: #96591A;
  --warn-weak: #FDF3E4;
  --bad: #A3242B;
  --bad-weak: #FCECEC;

  --r-card: 14px;
  --r-btn: 10px;
  --r-pill: 999px;

  --shadow: 0 1px 2px rgba(30, 23, 41, .05), 0 6px 18px rgba(30, 23, 41, .06);
  --shadow-lift: 0 10px 34px rgba(30, 23, 41, .16);
  --ring: 0 0 0 3px rgba(91, 44, 145, .18);

  --rail: 176px;
  --topbar: 60px;

  --font: "Readex Pro", system-ui, -apple-system, "Segoe UI", Tahoma, sans-serif;
  --num: "Inter", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0; height: 100%;
  background: var(--bg); color: var(--ink);
  font-family: var(--font);
  font-size: 15px; line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  /* A till is not a document. Rubber-banding the whole page while a cashier
     drags a long product list is how a tap lands on the wrong row. */
  overscroll-behavior: none;
}

.hidden { display: none !important; }

/* NUMBERS. Applied by class, never inherited: an Arabic name inside an LTR
   isolate would be laid out backwards. */
.num, .money, td.num, .ticket-total b, .stat-num {
  font-family: var(--num);
  font-variant-numeric: tabular-nums;
  direction: ltr; unicode-bidi: isolate;
}

/* ══════════════════════════════════════════════════════════════ shell */

#posShell { display: grid; grid-template-rows: var(--topbar) 1fr; height: 100dvh; }

.pos-top {
  display: flex; align-items: center; gap: 12px;
  padding: 0 14px; background: var(--surface);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 1px 0 rgba(30, 23, 41, .03);
}
/* THE CORNER. The rail's purple runs up through the header for exactly the
   rail's width, so the two are one piece of chrome and not a white bar laid
   across a purple column. The 1px overhang covers the header's own bottom
   border, which would otherwise draw a hairline seam across the block. */
.pos-brand {
  display: flex; align-items: center; gap: 10px; flex: none;
  width: var(--rail); height: calc(100% + 1px); position: relative;
  margin-inline-start: -14px; padding-inline-start: 14px;
  background: linear-gradient(180deg, #57298F 0%, #4E2682 100%);
  color: #fff;
}
.pos-brand .mark {
  width: 32px; height: 32px; border-radius: 8px; flex: none;
  background: rgba(255, 255, 255, .16);
  display: grid; place-items: center; color: #fff; font-weight: 700;
}
.pos-brand h1 {
  font-size: 15px; margin: 0; font-weight: 600; letter-spacing: -.01em;
  color: #fff; white-space: nowrap;
}
.pos-top .spacer { flex: 1; }

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 34px; padding: 4px 12px; border-radius: var(--r-pill);
  background: var(--accent-weak); color: var(--accent-press);
  font-size: 13px; font-weight: 500; white-space: nowrap;
  border: 1px solid transparent;
}
.chip.warn { background: var(--warn-weak); color: var(--warn); }
.chip.bad  { background: var(--bad-weak);  color: var(--bad); }
.chip.ok   { background: var(--ok-weak);   color: var(--ok); }
.chip.mute { background: var(--surface-2); color: var(--muted); border-color: var(--line); }
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }

/* A standing condition, not an event — so it is a bar the screen makes room
   for, never a toast that scrolls away while the cashier is looking elsewhere. */
.warnbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0 0 10px; padding: 10px 14px;
  background: var(--warn-weak); color: var(--warn);
  border: 1px solid color-mix(in srgb, var(--warn) 26%, transparent);
  border-radius: 10px; font-size: 14px; line-height: 1.5;
}
.warnbar .note { margin: 0; color: inherit; opacity: .85; }
.warnbar button { margin-inline-start: auto; }
button.chip { cursor: pointer; font-family: inherit; }
button.chip:hover { filter: brightness(.97); }

/* A CHOSEN CHIP HAS TO LOOK CHOSEN — and until this rule existed it did not.
   `aria-pressed` was set correctly on every order-type and payment-method chip
   and styled NOWHERE outside `.reg-sections`, so the pay screen's two most
   consequential choices rendered byte-identically whether or not they were
   selected. Caught by comparing the computed backgrounds of a pressed and an
   unpressed chip, because at a glance both simply look like chips. */
button.chip[aria-pressed="true"] {
  background: var(--accent); color: var(--accent-ink); font-weight: 600;
  border-color: var(--accent-press);
}
button.chip[aria-pressed="true"]:hover { background: var(--accent-press); filter: none; }
button.chip:disabled { opacity: .42; cursor: not-allowed; }

.pos-body { display: grid; grid-template-columns: var(--rail) 1fr; min-height: 0; }

/* THE RAIL IS CHROME, AND IT HAS TO LOOK LIKE IT.
 *
 * It was pure white — the same colour as the product cards it sits beside — so
 * it read as one more panel of content rather than as the frame around it. The
 * Aloke purple fixes that in one move and does two other things for free: an
 * icon inheriting `currentColor` turns white without a rule, and a selected row
 * can be told from an unselected one across a counter, which a pale lilac fill
 * on white could not manage.
 *
 * AND IT HAD TO FIT. Fifteen entries at 44px overflowed a 1366×768 till by
 * 57px with no scroll affordance — «الإعدادات», «الأجهزة» and «الموظفون» simply
 * below the fold on the machine pos.css names as the target, with nothing on
 * screen to say so. The row height is NOT what gave way (nothing a cashier
 * presses goes under 44px); the first group's heading did. See `POS.render`.
 */
.pos-rail {
  background: linear-gradient(180deg, #4E2682 0%, #3A1A5E 100%);
  padding: 10px 8px 14px;
  overflow-y: auto;
  display: flex; flex-direction: column; gap: 1px;
  /* The scrollbar is the only thing here that would draw a light-mode
     scrollbar over a dark ground. */
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, .28) transparent;
}
.pos-rail::-webkit-scrollbar { width: 6px; }
.pos-rail::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, .28); border-radius: 3px;
}

.pos-rail button {
  display: flex; align-items: center; gap: 10px; width: 100%;
  min-height: 44px; padding: 6px 12px; border: 0; border-radius: 9px;
  background: transparent; color: rgba(255, 255, 255, .78);
  font: inherit; font-size: 14px; cursor: pointer; text-align: start;
  /* THE INDICATOR IS ALWAYS THERE, transparent until selected — so a row does
     not shift sideways by 3px when it becomes the current one. */
  border-inline-start: 3px solid transparent;
  transition: background-color .12s ease, color .12s ease;
}
.pos-rail button > span.label {
  /* A LABEL NEVER WRAPS TO A SECOND LINE. «الأصناف والقائمة» is the longest and
     an uneven row in a list of fifteen is what makes a rail look unconsidered;
     the full text is on the button's `title` for anyone who needs it. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.pos-rail button:hover { background: rgba(255, 255, 255, .09); color: #fff; }
.pos-rail button[aria-current="true"] {
  background: rgba(255, 255, 255, .16);
  color: #fff; font-weight: 600;
  border-inline-start-color: #C9A9FF;
}
.pos-rail button:focus-visible { outline: 2px solid #C9A9FF; outline-offset: -2px; }

.pos-rail .rail-group {
  font-size: 10.5px; color: rgba(255, 255, 255, .5); letter-spacing: .08em;
  padding: 14px 12px 6px; font-weight: 600;
  margin-top: 6px; border-top: 1px solid rgba(255, 255, 255, .14);
}
/* «ALOKE BY HWE» (2026-10-05): the company's line at the rail's foot — pushed
   down by `margin-top: auto`, counted in the 1366×768 fit (test_pos_web_till). */
.pos-rail .rail-byline {
  margin: auto 0 0; padding: 12px 4px 0; color: rgba(255, 255, 255, .5);
  font-size: 11px; line-height: 14px; font-weight: 600; letter-spacing: .02em;
  text-align: center; unicode-bidi: isolate;
}
.pos-rail .rail-badge {
  margin-inline-start: auto; min-width: 22px; padding: 0 6px; height: 20px;
  border-radius: var(--r-pill); background: #FF6B6B; color: #3A1A5E;
  font-size: 11px; font-weight: 700; display: grid; place-items: center;
  font-family: var(--num); font-variant-numeric: tabular-nums;
}

.pos-main { min-width: 0; min-height: 0; overflow: auto; padding: 16px; }
.pos-main.flush { padding: 0; overflow: hidden; }

/* ══════════════════════════════════════════════════════════ primitives */

.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); box-shadow: var(--shadow); padding: 16px;
}
/* A card a panel row opened (`POS.revealPart`): lit for a moment, then itself again. */
.card[data-part] { scroll-margin-top: 16px; transition: box-shadow .6s cubic-bezier(0.23, 1, 0.32, 1); }
.card.part-lit { box-shadow: 0 0 0 3px var(--accent); }
@media (prefers-reduced-motion: reduce) { .card[data-part] { transition: none; } }
.card + .card { margin-top: 14px; }
.card > h2 { font-size: 17px; margin: 0 0 4px; font-weight: 600; }
.card > .sub { color: var(--muted); font-size: 13.5px; margin: 0 0 14px; }

.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
/* A LANGUAGE IS PICKED FROM A LIST OF FULL-WIDTH ROWS, not a two-letter pill.
   The 44px floor is the same one the rail keeps: this is pressed on a till
   screen by somebody who cannot read the label on the button beside it. */
button.lang-row { width: 100%; min-height: 44px; margin-bottom: 8px; padding: 10px 14px;
                  background: var(--surface-2); border: 1px solid var(--line);
                  border-radius: var(--r-btn); font-size: 17px; text-align: start; }
button.lang-row[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-weak); }
.row.end { justify-content: flex-end; }
.grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
.grid3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }

label.field { display: block; margin-bottom: 12px; }
label.field > span { display: block; font-size: 13px; color: var(--muted); margin-bottom: 5px; }

input, select, textarea {
  width: 100%; min-height: 44px; padding: 8px 12px;
  border: 1px solid var(--line-strong); border-radius: var(--r-btn);
  background: var(--surface); color: var(--ink); font: inherit; font-size: 15px;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: var(--ring);
}
input[type="checkbox"] { width: 20px; height: 20px; min-height: 0; accent-color: var(--accent); }
textarea { min-height: 84px; resize: vertical; }
input[inputmode="decimal"], input.num { font-family: var(--num); direction: ltr; text-align: start; }
input:disabled, select:disabled, button:disabled { opacity: .55; cursor: not-allowed; }

button {
  font-family: inherit; font-size: 15px; cursor: pointer;
  border-radius: var(--r-btn); min-height: 44px; padding: 8px 18px;
  border: 1px solid transparent; background: var(--surface-2); color: var(--ink);
}
button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
button.primary { background: var(--accent); color: var(--accent-ink); font-weight: 600; }
button.primary:hover:not(:disabled) { background: var(--accent-press); }
button.ghost { background: transparent; border-color: var(--line-strong); }
button.ghost:hover:not(:disabled) { background: var(--surface-2); }
button.danger { background: var(--bad); color: #fff; font-weight: 600; }
button.link { background: none; border: 0; color: var(--accent); padding: 4px 6px; min-height: 34px; }
button.sm { min-height: 36px; padding: 4px 12px; font-size: 14px; }
button:active:not(:disabled) { transform: translateY(1px); }

table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
th { text-align: start; font-weight: 600; color: var(--muted); font-size: 13px;
     padding: 8px 10px; border-bottom: 1px solid var(--line); white-space: nowrap; }
td { padding: 10px; border-bottom: 1px solid var(--line); vertical-align: middle; }
tbody tr:hover { background: var(--surface-2); }
td.num, th.num { text-align: end; }
.table-wrap { overflow-x: auto; }

.empty { color: var(--muted); text-align: center; padding: 34px 16px; font-size: 14.5px; }
.err  { color: var(--bad); background: var(--bad-weak); border-radius: var(--r-btn);
        padding: 10px 12px; margin: 10px 0; font-size: 14px; }
.ok   { color: var(--ok);  background: var(--ok-weak);  border-radius: var(--r-btn);
        padding: 10px 12px; margin: 10px 0; font-size: 14px; }
.note { color: var(--muted); font-size: 13.5px; }

/* A REFUSAL THE SERVER NAMED. `X-POS-Reason` is a machine word and it is shown
   in a monospace pill beside the Arabic, because when a cashier reads it out
   over the phone the person on the other end needs the word, not the sentence. */
.reason-pill {
  font-family: var(--num); font-size: 11.5px; padding: 1px 7px;
  border-radius: var(--r-pill); background: rgba(0,0,0,.06); color: var(--muted);
  margin-inline-start: 8px; direction: ltr; unicode-bidi: isolate;
}

/* ══════════════════════════════════════════════════════════════ register */

.reg { display: grid; grid-template-columns: 1fr 380px; height: 100%; min-height: 0; }
.reg-left { display: grid; grid-template-rows: auto auto 1fr; min-height: 0; min-width: 0; }

.reg-search { padding: 12px 14px; background: var(--surface); border-bottom: 1px solid var(--line);
              display: flex; gap: 10px; align-items: center; }
.reg-search input { font-size: 16px; }
/* «نفذ اليوم» — the register's switchboard sheet (2026-09-20). */
.avail-list { display: flex; flex-direction: column; gap: 2px; max-height: 60vh; overflow-y: auto; margin-top: 10px; }
.avail-sec { font-weight: 600; color: var(--accent); padding: 12px 0 4px; }
.avail-row { display: flex; align-items: center; gap: 10px; padding: 8px 4px; border-bottom: 1px solid var(--line); cursor: pointer; }
.avail-row .aname { flex: 1; }
.avail-row.off .aname { color: var(--muted); }
.avail-row input[type="checkbox"] { width: 22px; height: 22px; accent-color: var(--accent); }

.reg-sections { display: flex; gap: 6px; padding: 10px 14px; overflow-x: auto;
                background: var(--surface); border-bottom: 1px solid var(--line); }
.reg-sections button { white-space: nowrap; min-height: 38px; padding: 4px 14px;
                       border-radius: var(--r-pill); background: var(--surface-2); font-size: 14px; }
.reg-sections button[aria-pressed="true"] { background: var(--accent); color: #fff; font-weight: 600; }

.reg-grid { padding: 14px; overflow-y: auto; display: grid; align-content: start;
            grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); gap: 10px;
            /* Every row as tall as its tiles (2026-10-07). This grid has a
               fixed height and scrolls; with a full menu the browser shrank
               every row to make them all fit, cutting each tile at its photo
               and hiding the name and the price. The founder saw images only. */
            grid-auto-rows: max-content; }

.prod {
  display: flex; flex-direction: column; justify-content: space-between; gap: 6px;
  min-height: 92px; padding: 12px; text-align: start;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card);
  box-shadow: var(--shadow); color: var(--ink);
}
.prod:hover:not(:disabled) { border-color: var(--accent); }
.prod .pname { font-weight: 600; font-size: 14.5px; line-height: 1.3; }
/* The same add-on picked more than once: a stepper in the tile. */
.prod.mod-rep { cursor: default; }
/* One option of a dish under its row on the «نفذ اليوم» sheet. */
.avail-row.avail-opt { padding-inline-start: 28px; font-size: 14px; }
.prod.mod-rep.on { border-color: var(--accent); background: var(--accent-weak); }
.prod.mod-rep.off { opacity: .55; }
.mod-step { display: inline-flex; align-items: center; justify-content: space-between; gap: 4px; margin-top: 6px; width: 100%; }
.mod-step button { width: 44px; height: 44px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface);
  color: var(--accent-press); font-size: 20px; font-weight: 700; cursor: pointer; }
.mod-step button:disabled { opacity: .35; cursor: default; }
.mod-step b { min-width: 24px; text-align: center; font-family: var(--num); font-variant-numeric: tabular-nums; font-size: 16px; }
.prod .pprice { font-family: var(--num); font-variant-numeric: tabular-nums;
                direction: ltr; unicode-bidi: isolate; color: var(--accent-press); font-weight: 600; }
.prod .pflags { display: flex; gap: 4px; flex-wrap: wrap; }
.prod .tag { font-size: 11px; padding: 1px 7px; border-radius: var(--r-pill);
             background: var(--surface-2); color: var(--muted); }
.prod .tag.offer { background: var(--ok-weak); color: var(--ok); }
.prod:disabled { opacity: .48; }
.prod.out { border-style: dashed; }

/* THE REGISTER'S TILE IS A PICTURE WITH ITS NAME UNDER IT (2026-10-07): the
   photo on top at 4:3, cropped to fill and bled to the tile's edges; the name
   centred under it (two lines at most); the price under that. A dish with no
   photo shows its first letter on a tint in the same frame, so every tile in
   the grid is the same shape. Scoped to the register's grid: the option,
   order-type, place and package pickers keep the plain `.prod` card. */
.reg-grid .prod {
  /* WHY THE TILE SHOWED A PHOTO AND NOTHING UNDER IT (2026-10-07, third
     cut). The grid above has a fixed height and scrolls, and this tile said
     `min-height: 0`; with a full menu the browser was free to shrink every
     row until all of them fit the screen, so each tile was cut at its photo
     and its own clipping hid the name and the price. Now the rows are
     `max-content` (above), the tile's minimum is its content (`auto`), the
     photo's frame is a fixed pixel height (no percentage for any engine to
     resolve against nothing; an older iPad Safari had already failed on a
     4:3 `aspect-ratio`), and the tile no longer clips its own content.
     The column stays flex because WebKit shrink-wraps a <button>'s block
     content, and a stretched flex item is full width. */
  display: -webkit-box; display: -webkit-flex; display: flex;
  -webkit-flex-direction: column; flex-direction: column; -webkit-align-items: stretch; align-items: stretch;
  -webkit-justify-content: flex-start; justify-content: flex-start; gap: 0;
  min-height: auto; padding: 0 0 10px; text-align: center; overflow: visible;
  -webkit-transition: -webkit-transform 160ms cubic-bezier(0.23, 1, 0.32, 1), border-color 160ms ease;
  transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1), border-color 160ms ease;
}
@media (hover: none), (pointer: coarse) {
  .reg-grid .prod:hover:not(:disabled) { border-color: var(--line); }
}
.reg-grid .prod:active:not(:disabled) { -webkit-transform: scale(0.97); transform: scale(0.97); }
@media (prefers-reduced-motion: reduce) {
  .reg-grid .prod { transition: border-color 160ms ease; }
  .reg-grid .prod:active:not(:disabled) { -webkit-transform: none; transform: none; }
}
.reg-grid .prod > span { display: block; width: 100%; -webkit-flex: none; flex: none; box-sizing: border-box; }
.reg-grid .prod .pimg { position: relative; height: 112px; padding: 0;
                        background: var(--surface-2); overflow: hidden;
                        /* the tile's top corners, inside its 1px border */
                        border-radius: 9px 9px 0 0; }
@media (min-width: 1181px) { .reg-grid .prod .pimg { height: 128px; } }
.reg-grid .prod .pimg img { position: absolute; top: 0; left: 0; width: 100%; height: 100%;
                            object-fit: cover; display: block; }
.reg-grid .prod .pinit { display: none; }
.reg-grid .prod .pimg.noimg { background: var(--accent-weak, rgba(91,44,145,.08)); }
.reg-grid .prod .pimg.noimg .pinit { position: absolute; top: 0; left: 0; width: 100%; height: 100%;
                                     display: flex; align-items: center; justify-content: center;
                                     font-size: 34px; font-weight: 700; color: var(--accent); }
.reg-grid .prod .pname { margin-top: 8px; padding: 0 10px; display: -webkit-box; -webkit-line-clamp: 2;
                         -webkit-box-orient: vertical; overflow: hidden;
                         min-height: calc(14.5px * 1.3 * 2); }
.reg-grid .prod .pprice { margin-top: 4px; }
.reg-grid .prod .pflags { position: absolute; top: 6px; right: 6px; left: 6px;
                          display: flex; gap: 4px; flex-wrap: wrap; }
.reg-grid .prod .tag { background: var(--surface); box-shadow: 0 1px 3px rgba(0,0,0,.14); }
.reg-grid .prod .tag.offer { background: var(--ok-weak); }
.reg-grid .prod:disabled { opacity: .55; }
.reg-grid .prod.out .pimg img { -webkit-filter: grayscale(1); filter: grayscale(1); }

/* THE TICKET. Its own scroll region with the totals pinned under it, so a
   twenty-line order never pushes the payable off the screen. */
.ticket { display: grid; grid-template-rows: auto 1fr auto; background: var(--surface);
          border-inline-start: 1px solid var(--line); min-height: 0; }
.ticket-head { padding: 12px 14px; border-bottom: 1px solid var(--line);
               display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ticket-lines { overflow-y: auto; padding: 6px 0; }
/* «A123» — THE NUMBER THE CASHIER READS BACK ACROSS THE COUNTER. Bigger than
   the chips beside it because it is read aloud from a metre away, and it
   inherits `.num`'s `direction: ltr; unicode-bidi: isolate` rather than
   redeclaring it: a Latin code dropped bare into an RTL run reorders. */
.ticket-head .ordercode { font-size: 20px; font-weight: 700; letter-spacing: .5px; }
.ticket-head .ordercode-label { color: var(--muted); font-size: 12.5px; }
.tline { display: grid; grid-template-columns: 1fr auto; gap: 2px 10px;
         padding: 10px 14px; border-bottom: 1px solid var(--line); cursor: pointer; }
.tline:hover { background: var(--surface-2); }
.tline[aria-selected="true"] { background: var(--accent-weak); }
.tline .tname { font-weight: 600; font-size: 14.5px; }
.tline .tmeta { grid-column: 1; color: var(--muted); font-size: 12.5px; }
.tline .tamt { grid-row: 1 / span 2; align-self: center; font-family: var(--num);
               font-variant-numeric: tabular-nums; direction: ltr; unicode-bidi: isolate;
               font-weight: 600; }
.tline.void { opacity: .5; text-decoration: line-through; }

.ticket-foot { border-top: 1px solid var(--line); padding: 12px 14px; background: var(--surface-2); }
.ticket-total { display: flex; justify-content: space-between; font-size: 14px; padding: 3px 0;
                color: var(--muted); }
.ticket-total.big { font-size: 21px; color: var(--ink); font-weight: 700; padding-top: 8px;
                    border-top: 1px dashed var(--line-strong); margin-top: 6px; }
/* CASHBACK IS A PAYMENT (2026-09-24): the invoice total struck through, the
   cashback that paid it, then «المطلوب» — what the drawer still takes. */
.ticket-total.cb-total s { text-decoration-thickness: 1.5px; }
.ticket-total.cb-paid { color: var(--ok); font-weight: 600; }
.pay-covered { color: var(--ok); font-weight: 600; margin-top: 6px; }
.ticket-actions { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 10px; }
.ticket-actions button { min-height: 44px; padding: 4px 6px; font-size: 13.5px; }
/* A DISABLED BUTTON DISPATCHES NO POINTER EVENTS, so a `title` on it
   never opens. The wrapper is the grid cell and carries the sentence;
   the button hands the pointer through to it so the tooltip appears
   over a control whose greyness would otherwise have no cause. */
.ticket-actions > .act-hint { display: grid; }
.ticket-actions > .act-hint > button { width: 100%; }
.ticket-actions > .act-hint > button:disabled { pointer-events: none; }
.pay-btn { width: 100%; min-height: 60px; font-size: 20px; margin-top: 10px; font-weight: 700; }

/* keypad — used by the pay sheet and the quantity editor alike */
.keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
/* `hidden` beats a display rule (2026-09-25): the keypad and the tender block
   hide when the cashback pays the whole bill, and `display: grid` above would
   otherwise keep drawing them. */
.keypad[hidden], #payTender[hidden] { display: none; }
.keypad button { min-height: 56px; font-size: 21px; font-family: var(--num); font-weight: 600; }
.keypad button.wide { grid-column: span 2; }

/* ══════════════════════════════════════════════════════════════ dialogs */

.sheet-back {
  position: fixed; inset: 0; background: rgba(30, 23, 41, .45);
  display: grid; place-items: center; padding: 20px; z-index: 60;
}
.sheet {
  background: var(--surface); border-radius: 18px; box-shadow: var(--shadow-lift);
  width: min(560px, 100%); max-height: 90dvh; display: grid;
  grid-template-rows: auto 1fr auto; overflow: hidden;
}
.sheet.wide { width: min(900px, 100%); }
.sheet-head { padding: 16px 18px 10px; border-bottom: 1px solid var(--line);
              display: flex; align-items: center; gap: 10px; }
.sheet-head h3 { margin: 0; font-size: 18px; font-weight: 600; }
.sheet-body { padding: 16px 18px; overflow-y: auto; }
.sheet-foot { padding: 12px 18px 16px; border-top: 1px solid var(--line);
              display: flex; gap: 10px; justify-content: flex-end; }

/* ══════════════════════════════════════════════════════════ permissions */

.perm-group { border: 1px solid var(--line); border-radius: var(--r-card); padding: 12px; margin-bottom: 12px; }
.perm-group h4 { margin: 0 0 8px; font-size: 14px; color: var(--muted); font-weight: 600; }
.perm-row { display: flex; gap: 10px; align-items: flex-start; padding: 8px 4px; border-radius: 8px; }
.perm-row:hover { background: var(--surface-2); }
.perm-row input { margin-top: 3px; flex: none; }
.perm-row .pdesc { color: var(--muted); font-size: 12.5px; }
.perm-row.locked { opacity: .5; }
.preset-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }

/* ═════════════════════════════════════════════════════ the receipt logo */

/* THE PLATE IS THE PAPER. The mark is previewed on WHITE whatever the console's
   own surface colour is, because white is what it will actually be printed on
   — a preview on a tinted card would hide exactly the failure this slot exists
   to prevent (a white logo that prints as nothing). The box carries the
   printer's own drawn shape, 316×240 dots, so an owner sees the proportion the
   paper gives them rather than one this page invented. */
.logo-slot { display: flex; gap: 14px; align-items: flex-start; flex-wrap: wrap; }
.logo-plate {
  flex: none; width: 158px; height: 120px; display: grid; place-items: center;
  background: #fff; border: 1px solid var(--line-strong); border-radius: var(--r-btn);
  padding: 6px; overflow: hidden;
}
.logo-plate img { max-width: 100%; max-height: 100%; object-fit: contain; }
.logo-plate span { color: var(--muted); font-size: 13px; text-align: center; }
.logo-side { flex: 1; min-width: 200px; }
.logo-side .note { margin: 0 0 10px; }

/* A FILE INPUT THAT LOOKS LIKE THE BUTTONS AROUND IT. The input itself is
   hidden (the shared cropper intercepts its change), so the label IS the
   control and has to carry the same 44px target every other control on a till
   screen keeps. */
label.filebtn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 8px 18px; cursor: pointer; font-size: 15px;
  border: 1px solid var(--line-strong); border-radius: var(--r-btn);
  background: transparent; color: var(--ink);
}
label.filebtn:hover { background: var(--surface-2); }
label.filebtn:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }

/* «صورة تحت الشعار» (2026-10-18, docs/receipt-promo-contract.md): the
   picture's own section of «شكل الفاتورة المطبوعة», folded until opened —
   opening it IS editing it (the preview then shows the picture). The plate is
   paper-white like the logo's, a little larger: it holds a photo. */
.rp-box { border: 1px solid var(--line); border-radius: var(--r-btn); padding: 0 12px; background: var(--surface-2); }
.rp-box[open] { background: var(--surface); padding-bottom: 12px; }
.rp-box > summary { cursor: pointer; min-height: 44px; padding: 10px 0; line-height: 24px; }
.rp-box > summary .chip { min-height: 26px; padding: 2px 10px; vertical-align: middle; margin-inline-start: 6px; }
.rp-box .logo-plate.rp-plate { width: 200px; height: 150px; }

/* ══════════════════════════════════════════════════════════════ kitchen */

.kds { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.kot { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card);
       box-shadow: var(--shadow); overflow: hidden; }
.kot header { padding: 10px 12px; background: var(--accent-weak); color: var(--accent-press);
              display: flex; justify-content: space-between; align-items: center; font-weight: 600; }
.kot.late header { background: var(--bad-weak); color: var(--bad); }
.kot ul { list-style: none; margin: 0; padding: 10px 12px; }
.kot li { padding: 5px 0; border-bottom: 1px solid var(--line); font-size: 15px; }
.kot li:last-child { border: 0; }
.kot footer { padding: 10px 12px; }
/* The picks and the notes (2026-10-13): each its own line under the dish, and
   the customer's note for the whole order in a box nobody can miss. */
.kot .kot-pick { display: block; padding-inline-start: 18px; font-size: 14px; font-weight: 600; color: var(--ink); }
.kot .kot-note { display: block; padding-inline-start: 18px; font-size: 14px; color: var(--accent-press); }
.kot .kot-cnote { margin: 0 12px 10px; padding: 8px 10px; border-radius: 10px; background: var(--warn-weak);
                  color: var(--ink); font-size: 14px; line-height: 1.45; overflow-wrap: anywhere; }
.kot .kot-cnote b { display: block; font-size: 12px; color: var(--warn); }

/* ══════════════════════════════════════════════════════════════ toasts */

/* «طلب مسبق جديد» (2026-09-24): stays until somebody looks — a toast that
   fades in three seconds is an order nobody saw. */
.po-alert { position: fixed; inset-block-start: 12px; inset-inline-start: 50%; z-index: 60;
            transform: translateX(50%); display: flex; align-items: center; gap: 10px;
            padding: 10px 12px 10px 14px; border-radius: 14px; background: var(--ink); color: var(--surface);
            box-shadow: 0 10px 30px rgba(20, 10, 40, .28); max-width: calc(100vw - 32px);
            font-size: 15px; font-weight: 600; }
html[dir="ltr"] .po-alert { transform: translateX(-50%); }
.po-alert .po-alert-text { min-width: 0; overflow-wrap: anywhere; }
.po-alert .po-alert-dot { width: 10px; height: 10px; border-radius: 50%; background: #FF6B6B; flex: none;
                          animation: po-pulse 1.2s ease-in-out infinite; }
.po-alert button { min-height: 40px; }
.po-alert .ghost { color: var(--surface); border-color: rgba(255, 255, 255, .3); }
/* The kind wears its dot (2026-09-24): a table's bell and a car's horn are
   told apart at a glance as well as by ear. */
.po-alert[data-kind="table"] .po-alert-dot { background: #F2B84B; }
.po-alert[data-kind="car"] .po-alert-dot { background: #6FC3FF; }
.po-alert[data-kind="kiosk"] .po-alert-dot { background: #B98CF2; }
.po-card .po-table { font-weight: 700; }
@keyframes po-pulse { 50% { transform: scale(1.5); opacity: .55; } }
@media (prefers-reduced-motion: reduce) { .po-alert .po-alert-dot { animation: none; } }
#posToasts { position: fixed; inset-block-end: 18px; inset-inline-start: 50%;
             transform: translateX(50%); z-index: 90; display: grid; gap: 8px; }
html[dir="ltr"] #posToasts { transform: translateX(-50%); }
.toast { background: var(--ink); color: #fff; padding: 12px 18px; border-radius: var(--r-pill);
         box-shadow: var(--shadow-lift); font-size: 14.5px; max-width: 90vw; }
.toast.bad { background: var(--bad); }
.toast.ok  { background: var(--ok); }

/* ══════════════════════════════════════════════════════════ responsive */

@media (max-width: 1180px) { .reg { grid-template-columns: 1fr 330px; } }

@media (max-width: 900px) {
  :root { --rail: 64px; }
  .pos-rail button > span.label { display: none; }
  .pos-rail .rail-group { display: none; }
  /* The icon-only rail is 64px wide: the line shrinks and may take two lines. */
  .pos-rail .rail-byline { font-size: 9px; line-height: 11px; padding: 10px 0 0; letter-spacing: 0; }
  /* Icon-only: the indicator bar is the only thing left saying which section
     is current, so it stays and the padding gives it room. */
  .pos-rail button { justify-content: center; padding: 8px 6px; }
  /* THE TICKET STOPS BEING A COLUMN AND BECOMES THE BOTTOM HALF. A 330px
     ticket beside a 340px product grid is two unusable panes, and the rule
     that matters — the total never leaves the screen — is kept either way. */
  .reg { grid-template-columns: 1fr; grid-template-rows: 1fr minmax(200px, 45%); }
  .ticket { border-inline-start: 0; border-top: 1px solid var(--line-strong); }
  .ticket-actions { grid-template-columns: repeat(4, 1fr); }
}

@media (max-width: 560px) {
  .pos-top h1 { display: none; }
  .pos-main { padding: 10px; }
  .card { padding: 12px; }
}

/* PRINTING. The page itself is never what goes on paper — a receipt is a PDF
   the server rendered — so if somebody hits Ctrl+P on the till, say so rather
   than spooling a screenshot of the register. */
@media print {
  body::after {
    content: "اطبع الفاتورة من زر «طباعة» في الشاشة — هذه الصفحة ليست الإيصال.";
    display: block; padding: 40px; font-size: 18px; text-align: center;
  }
  #posShell, #posLogin, .sheet-back { display: none !important; }
}

/* THE CONFIGURE SHEET (add-ons wave, 2026-09-20): an option or a pick that is
   ON wears the accent; a sold-out pick stays visible and dashed. */
.sheet-h { margin: 12px 0 6px; font-size: 13px; font-weight: 700; color: var(--ink); }
.sheet-h .note { font-weight: 500; color: var(--muted); font-size: 12px; margin-inline-start: 6px; }
.prod.on { border-color: var(--accent); background: var(--accent-weak, rgba(91,44,145,.08)); }
.prod.off { border-style: dashed; opacity: .55; }

/* ═══════════════════════════════════════════════ the Pre-Order queue (2026-09-20) */
.po-card header { display: flex; align-items: center; gap: 8px; }
.po-card .po-code { font-family: var(--num); font-size: 26px; font-weight: 700; letter-spacing: .02em; }
.po-card.ready { border-color: var(--gold, #C89B3C); box-shadow: 0 0 0 1px var(--gold, #C89B3C) inset; }
.po-card.aging header { background: var(--warn-weak); color: var(--warn); }
.po-card.late header { background: var(--bad-weak); color: var(--bad); }
.po-card .po-age { margin-inline-start: auto; }
.po-card .po-money { padding: 4px 12px 10px; display: grid; gap: 4px; }
.po-card .po-due { font-weight: 700; font-size: 15px; }
.po-card .po-acts { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding: 0 12px 12px; }
.po-card .po-acts button { flex: 1 1 auto; }
.po-card .po-acts .danger { color: var(--bad); border-color: var(--bad-weak); }
.po-card .po-left { flex-basis: 100%; }
.po-card .po-count { font-family: var(--num); }
.kit-tabs { display: flex; gap: 6px; margin: 0 0 12px; }
.kit-tabs button { flex: 1 1 auto; min-height: 44px; border: 1px solid var(--line); background: var(--surface);
  color: var(--muted); border-radius: var(--r-card); font-weight: 700; cursor: pointer; }
.kit-tabs button.on { background: var(--accent-weak); color: var(--accent-press); border-color: transparent; }

/* ORDER FROM THE CAR (2026-09-22): the pause bar above the Pre-Order queue,
   and the plate under a card's header. */
.car-bar { margin-top: 12px; }
.car-bar-row { flex-wrap: wrap; gap: 8px; align-items: center; }
.kot .po-car { padding: 8px 12px 0; margin-top: 0; }

/* THE SHOP'S OFFERS ON THE PAY SHEET (2026-09-23) — what the basket gets,
   read as a receipt reads: the name on one side, the amount on the other. */
/* THE CUSTOMER, FIRST ON THE PAY SHEET (2026-09-25). */
/* «تقسيم الفاتورة» (2026-10-07): the recorded payments, the people of an
   even split, and the split by items. */
.pay-split { margin: 0 0 10px; }
.pay-split .chip .ic { width: 16px; height: 16px; }
.pay-people { display: flex; align-items: center; gap: 8px; margin: 8px 0; }
.pay-people b { min-width: 2ch; text-align: center; font-size: 18px; }
.pay-persons { margin: 6px 0 0; }
.pay-person[data-state="paid"] { background: var(--ok-weak); color: var(--ok); }
.pay-person[data-state="now"] { border-color: var(--accent); background: var(--accent-weak, rgba(91,44,145,.08)); font-weight: 600; }
.pay-person[data-state="wait"] { opacity: .7; }
.pay-add { width: 100%; margin: 8px 0 4px; }
.pay-rows { list-style: none; margin: 6px 0; padding: 0; display: grid; gap: 4px; }
.pay-rows li { display: flex; align-items: center; gap: 8px; padding: 6px 10px;
               border: 1px solid var(--line); border-radius: var(--r-card); background: var(--surface); }
.pay-rows li > span { flex: 1; min-width: 0; }
.pay-rows li small { display: block; }
.pay-moved { color: var(--bad, #b42318); }
.pay-split-of { display: flex; align-items: center; gap: 6px; font-weight: 600; color: var(--accent); }
.split-units { list-style: none; margin: 10px 0; padding: 0; display: grid; gap: 4px;
               max-height: 52vh; overflow-y: auto; }
.split-units li { display: flex; align-items: center; justify-content: space-between; gap: 10px;
                  padding: 6px 10px; border-bottom: 1px solid var(--line); }
.split-units li .preset-row { flex-wrap: wrap; justify-content: flex-end; }
.split-totals { margin: 8px 0; }
.pay-customer { margin: 0 0 10px; }
.pay-customer .field { margin: 0; }
.pay-cust-on { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; border-radius: 10px; background: var(--accent-weak, rgba(91,44,145,.08)); }
.pay-cust-on b { unicode-bidi: plaintext; }
/* No customer, or one who holds nothing: no empty box under the number. */
.pay-balance:empty { display: none; }
.pay-offers { margin: 10px 0; padding: 10px 12px; border: 1px solid var(--line, #ddd);
  border-radius: 10px; display: grid; gap: 6px; }
.pay-offers input[type="text"], .pay-offers #payCode { flex: 1; min-width: 0; }
.offer-lines { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.offer-lines li { display: flex; justify-content: space-between; gap: 10px; }
.offer-lines b { color: var(--ok, #127a3a); font-variant-numeric: tabular-nums; }

/* THE SELLER'S PAPER (2026-09-27) — the files on a receipt or a quick purchase,
   and the attach box a form carries (`POS.docs` in pos-core.js). */
.doc-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.doc-chip {
  display: inline-flex; align-items: center; gap: 4px; max-width: 100%;
  border: 1px solid var(--line); border-radius: 999px; padding: 2px 6px;
  background: var(--surface); font-size: 13px;
}
.doc-chip > span, .doc-chip button span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px;
}
.doc-chip.bad { border-color: var(--bad); }
.doc-box em { font-style: normal; margin-inline-start: 6px; }
.pill-warn {
  display: inline-block; border-radius: 999px; padding: 1px 8px; font-size: 12px;
  background: var(--warn-weak); color: var(--warn);
}

/* ═══ «خصومات الكاشير» (2026-10-11) — the discount sheet and the approval code ═══ */
.dsc { display: grid; gap: 10px; }
.dsc-seg { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 4px; padding: 4px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--surface-2, var(--bg)); }
.dsc-seg-b { min-height: 44px; border: 0; border-radius: 9px; background: transparent; font: inherit;
  font-weight: 600; color: var(--ink); cursor: pointer; }
.dsc-seg-b.on { background: var(--surface); color: var(--accent); box-shadow: 0 1px 2px rgba(0, 0, 0, .08); }
.dsc-what { margin: 0; color: var(--muted); font-size: 14px; }
.dsc-quick, .dsc-reasons { display: flex; flex-wrap: wrap; gap: 6px; }
.dsc-quick[hidden] { display: none; }
.dsc-chip { min-height: 40px; padding: 6px 14px; border-radius: 999px; border: 1px solid var(--line);
  background: var(--surface); font: inherit; cursor: pointer; color: var(--ink); }
.dsc-chip.on { border-color: var(--accent); background: var(--accent-weak); color: var(--accent-press, var(--accent));
  font-weight: 600; }
.dsc #dscVal { font-size: 22px; font-variant-numeric: tabular-nums; }
.dsc-vat { margin: 0; font-size: 13px; color: var(--accent-press); }
.dsc-sum { margin: 0; font-weight: 700; font-variant-numeric: tabular-nums; }
.dsc-sum:empty, .dsc-limit:empty { display: none; }
.dsc-limit { margin: 0; font-size: 13px; color: var(--muted); }
.dsc-why { display: grid; gap: 6px; }
.dsc-why-h { font-weight: 600; font-size: 14px; }
.dsc-ask { margin: 0 0 10px; }
.dsc-bad { margin: 0 0 10px; color: var(--bad); font-weight: 600; }
.dsc-code { width: 100%; font-size: 34px; text-align: center; letter-spacing: .3em; font-variant-numeric: tabular-nums;
  padding: 12px; border-radius: 12px; }
.dsc-mycode { display: grid; justify-items: center; gap: 6px; padding: 16px; border-radius: 14px;
  background: var(--accent-weak); }
.dsc-mycode b { font-size: 40px; letter-spacing: .14em; color: var(--accent-press, var(--accent));
  font-variant-numeric: tabular-nums; }

/* ═══ «العروض والخصومات» on the pay sheet (2026-10-11) ═══ */
.pay-offers-h { justify-content: space-between; align-items: center; gap: 8px; }
.pay-offers-h .note { margin: 0; }
.ofr-open { min-height: 44px; display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }
.ofr-count { min-width: 22px; height: 22px; padding: 0 6px; border-radius: 999px; display: inline-grid;
  place-items: center; background: var(--accent); color: #fff; font-size: 12px; }
.ofr { display: grid; gap: 8px; }
.ofr-h { margin: 6px 0 0; font-weight: 700; font-size: 14px; }
.ofr-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.ofr-row { border: 1px solid var(--line); border-radius: 12px; background: var(--surface); }
.ofr-row.pick { cursor: pointer; }
.ofr-row.on { border-color: var(--accent); background: var(--accent-weak); }
.ofr-pick { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 10px;
  padding: 10px 12px; min-height: 52px; cursor: inherit; }
.ofr-row:not(.pick) .ofr-pick { grid-template-columns: 1fr auto; }
.ofr-pick input { width: 20px; height: 20px; accent-color: var(--accent); }
.ofr-txt { display: grid; gap: 2px; min-width: 0; }
.ofr-line { font-size: 13px; color: var(--muted); }
.ofr-hint { font-size: 13px; color: var(--warn); font-weight: 600; }
.ofr-pick .chip { white-space: nowrap; }
.ofr-foot { margin-top: 4px; }
@media (max-width: 520px) {
  .ofr-pick { grid-template-columns: auto 1fr; }
  .ofr-row:not(.pick) .ofr-pick { grid-template-columns: 1fr; }
  .ofr-pick .chip { grid-column: 1 / -1; justify-self: start; }
}

/* ═══ «النقد والخزنة» (2026-10-11, pos-cash.js) ═══ */
.cash-big { font-size: 26px; font-weight: 700; line-height: 1.2; }
.cash-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; margin-bottom: 12px; }
.cash-tile { border: 1px solid var(--line); border-radius: 12px; padding: 12px; display: flex; flex-direction: column; gap: 4px; }
.cash-tile span { color: var(--muted); font-size: 13px; }
.cash-tile b { font-size: 20px; }
.cash-tile.total { border-color: var(--accent); }
.cash-bar { height: 8px; border-radius: 99px; background: var(--line); overflow: hidden; margin: 10px 0 6px; }
.cash-bar i { display: block; height: 100%; background: var(--accent); }
.cash-dens h4 { margin: 10px 0 6px; font-size: 14px; }
.cash-den { display: grid; grid-template-columns: minmax(96px, 1fr) minmax(96px, 140px) minmax(80px, auto); gap: 8px; align-items: center; margin-bottom: 6px; }
.cash-den-n { min-height: 44px; text-align: center; direction: ltr; font-size: 18px; }
.cash-den-sum { color: var(--muted); text-align: end; }
.cash-den-sum.bad { color: var(--bad); }
.cash-den-total { display: flex; justify-content: space-between; align-items: baseline; border-top: 1px solid var(--line); padding-top: 10px; margin-top: 6px; }
.cash-den-total b { font-size: 22px; }
.num.bad { color: var(--bad); }
.num.ok { color: var(--ok); }
@media (max-width: 520px) {
  .cash-den { grid-template-columns: 1fr 96px; }
  .cash-den-sum { grid-column: 1 / -1; text-align: start; font-size: 12px; }
  .cash-den-sum:empty { display: none; }
}

/* ═══ «مكافآت العميل» — the customer's prizes, gifts and packages (2026-10-23) ═══
   One card per thing held: a kind tile, what it is, the dish it is for, what
   is left, and ONE button that does the whole act. Used on this sale sits on
   top with its undo. The pay sheet and the ticket's «المكافآت» draw the same. */
.rw-chip { gap: 6px; background: var(--accent-weak); color: var(--accent); border-color: transparent; }
.rw-chip svg { width: 14px; height: 14px; }
.rw-h { margin: 6px 0 4px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
.rw-grid { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.rw-card { display: grid; grid-template-columns: 44px 1fr; grid-template-areas: "tile body" "act act";
  grid-template-rows: 1fr auto; align-items: start;
  gap: 10px 12px; padding: 12px; border: 1px solid var(--line); border-radius: var(--r-card);
  background: var(--surface); box-shadow: var(--shadow); }
.rw-tile { grid-area: tile; width: 44px; height: 44px; border-radius: 12px; display: grid; place-items: center;
  background: var(--accent-weak); color: var(--accent); }
.rw-tile svg { width: 22px; height: 22px; }
.rw-gift .rw-tile { background: var(--warn-weak); color: var(--warn); }
.rw-bundle .rw-tile { background: var(--ok-weak); color: var(--ok); }
.rw-body { grid-area: body; min-width: 0; display: grid; gap: 3px; }
.rw-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.rw-kind { font-size: 11.5px; font-weight: 700; letter-spacing: 0; color: var(--accent); }
.rw-gift .rw-kind { color: var(--warn); }
.rw-bundle .rw-kind { color: var(--ok); }
.rw-left { font-size: 12px; color: var(--muted); }
.rw-left b { color: var(--ink); }
.rw-title { font-size: 15.5px; font-weight: 700; color: var(--ink); line-height: 1.35; }
.rw-dish { font-size: 13px; color: var(--ink); opacity: .85; }
.rw-meta { font-size: 12px; color: var(--muted); }
.rw-dishes { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.rw-act { grid-area: act; display: grid; }
.rw-act button { min-height: 46px; font-size: 15px; font-weight: 700; border-radius: var(--r-btn);
  transition: transform 120ms ease-out, filter 120ms ease-out; }
.rw-act button.busy { filter: saturate(.6) brightness(1.05); }
@media (hover: hover) and (pointer: fine) {
  .rw-card:hover { border-color: var(--line-strong); }
}
.rw-act button:active { transform: scale(.98); }
@media (prefers-reduced-motion: reduce) { .rw-act button { transition: none; } .rw-act button:active { transform: none; } }
/* THE LADDER, ONE CARD (2026-10-23): the tiers as radio rows — the cost on
   the end, a tier the stamps left cannot pay greyed and not pickable — and
   one button under them. Spans the grid's full width. */
.rw-ladder { grid-column: 1 / -1; }
.rw-act button[disabled] { background: var(--surface-2, #eee); color: var(--muted); box-shadow: none; cursor: not-allowed; }
.rw-tiers { display: grid; gap: 6px; margin-top: 6px; }
.rw-tier { display: grid; grid-template-columns: 18px 1fr auto; align-items: center; gap: 10px; width: 100%;
  min-height: 48px; padding: 8px 12px; text-align: start; border: 1px solid var(--line);
  border-radius: var(--r-btn); background: var(--surface); color: var(--ink); cursor: pointer;
  transition: border-color 120ms ease-out, background-color 120ms ease-out; }
.rw-tier.on { border-color: var(--accent); background: var(--accent-weak); }
.rw-tier.off { opacity: .45; cursor: not-allowed; }
.rw-tier-dot { width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--line-strong); }
.rw-tier.on .rw-tier-dot { border-color: var(--accent); background: radial-gradient(var(--accent) 45%, transparent 50%); }
.rw-tier-body { display: grid; gap: 2px; min-width: 0; }
.rw-tier-title { font-weight: 700; font-size: 14.5px; }
.rw-tier-dish { font-size: 12.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rw-tier-cost { font-size: 13px; font-weight: 700; color: var(--accent); white-space: nowrap; }
.rw-tier.off .rw-tier-cost { color: var(--muted); }
@media (prefers-reduced-motion: reduce) { .rw-tier { transition: none; } }
.rw-used-list { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 6px; }
.rw-used { display: grid; grid-template-columns: 22px 1fr auto auto; align-items: center; gap: 8px;
  padding: 8px 10px; border-radius: var(--r-btn); background: var(--ok-weak); }
.rw-used-mark { color: var(--ok); display: grid; place-items: center; }
.rw-used-mark svg { width: 16px; height: 16px; }
.rw-used-name { font-weight: 600; color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rw-used-how { font-size: 12px; color: var(--ok); }
/* WHAT COVERS THE CHOSEN ITEMS (2026-10-27): what the filter keeps out of
   sight is one quiet tap away; the line says so when nothing on the card
   covers this ticket. */
.rw-all { justify-self: start; margin-top: 8px; min-height: 40px; gap: 6px; }
.rw-all b { font-weight: 700; color: var(--accent); }
.rw-none { margin: 6px 0 0; }
.rw-empty { display: grid; justify-items: center; gap: 8px; padding: 28px 12px; color: var(--muted); text-align: center; }
.rw-empty svg { width: 32px; height: 32px; color: var(--accent); }

/* «متاح اليوم» on the products page: each option's own switch under the dish's. */
.avail-opt-cell { margin-top: 6px; font-size: 13px; color: var(--muted); white-space: nowrap; }
