  /* Tokens live in design/tokens.css, which every application loads first.
     This file had its own :root and dark block; the platform console had a second,
     narrower one inline. Two token models is why the three applications did not look
     like one product. The names below are unchanged — they are aliases over the shared
     tokens now, so a screen migrates when it is touched rather than all at once. */

  *{box-sizing:border-box}
  html,body{margin:0;height:100%}
  body{background:var(--bg);color:var(--text);font:15px/1.5 var(--font);-webkit-font-smoothing:antialiased}
  [dir="rtl"] body{font-family:var(--font-ar)}
  button{font:inherit;cursor:pointer;border:0;border-radius:var(--radius-md);transition:background .12s,border-color .12s,box-shadow .12s,transform .04s}
  button:active{transform:translateY(1px)}
  input,select,textarea{font:inherit;color:var(--text);background:var(--panel);border:1px solid var(--line);border-radius:var(--radius-md);padding:12px 13px;transition:border-color .12s,box-shadow .12s;outline:none}
  input:focus,select:focus,textarea:focus{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 20%,transparent)}
  input::placeholder,textarea::placeholder{color:var(--muted);opacity:.7}
  .hidden{display:none !important}
  .muted{color:var(--muted)}

  /* login */
  #login{min-height:100%;display:flex;align-items:center;justify-content:center;padding:24px}
  .card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:28px 24px;width:100%;max-width:380px;box-shadow:0 8px 30px rgba(20,33,61,.08)}
  .card h1{margin:0 0 4px;font-size:24px;font-weight:800}
  .card p{margin:0 0 20px;color:var(--muted);font-size:13px}
  .field{display:block;width:100%;margin-bottom:12px}
  input.field,select.field,textarea.field{background:var(--panel);border:1px solid var(--line);color:var(--text);padding:12px 13px;border-radius:11px}
  /* A colour input draws its value as the control's own swatch. input.field sets a
     white background, which Safari paints straight over it — so a field holding
     #C0522F rendered as an empty white box and the colour looked lost. The padding
     made it worse: what little swatch showed was inset to nothing. */
  input[type="color"].field{-webkit-appearance:none;appearance:none;padding:4px;height:46px;cursor:pointer}
  input[type="color"].field::-webkit-color-swatch-wrapper{padding:0}
  input[type="color"].field::-webkit-color-swatch{border:1px solid var(--line);border-radius:8px}
  input[type="color"].field::-moz-color-swatch{border:1px solid var(--line);border-radius:8px}
  /* the hex beside the swatch: a colour you can read, copy and paste between fields */
  .cpair{display:flex;gap:8px;align-items:center}
  .cpair input[type="color"]{flex:0 0 68px;margin-bottom:0}
  .cpair input[type="text"]{flex:1 1 auto;margin-bottom:0;font-family:ui-monospace,Menlo,monospace;text-transform:uppercase}
  .btn{background:var(--accent);color:#fff;padding:12px 18px;width:100%;font-weight:700;border-radius:11px;box-shadow:0 1px 2px rgba(20,33,61,.06)}
  /* A disabled button LOOKS disabled (7.72). `.btn` had no disabled state at all, so the Till's
     three pay-outs with no shift open were full-colour buttons that did nothing when pressed. One
     rule here covers every `.btn` in the till and the back office. */
  .btn:disabled,.btn[aria-disabled="true"]{opacity:.45;cursor:not-allowed;box-shadow:none;filter:saturate(.4)}
  .btn:hover{background:var(--accent2)}
  .btn.secondary{background:var(--panel);color:var(--text);border:1px solid var(--line);box-shadow:none}
  .btn.secondary:hover{border-color:var(--accent);color:var(--accent)}
  .btn.good{background:var(--good)} .btn.good:hover{filter:brightness(.95)}
  .btn.danger{background:var(--danger)} .btn.danger:hover{filter:brightness(.95)}
  .err{color:var(--danger-text);font-size:13px;margin-top:8px;min-height:18px}

  /* app shell */
  #app{display:flex;flex-direction:column;height:100vh;height:100dvh;overflow:hidden}
  /* `viewport-fit=cover` lets the page use the full screen, which on an installed iOS app
     means the header sits UNDER the status bar — the clock over the wordmark in the
     screenshot. The inset is added to the padding rather than replacing it, so a browser
     with no notch is unaffected (env() is 0 there). */
  header{display:flex;align-items:center;gap:10px;
    padding:calc(12px + env(safe-area-inset-top)) calc(16px + env(safe-area-inset-right)) 12px calc(16px + env(safe-area-inset-left));
    background:var(--panel);border-bottom:1px solid var(--line);flex:0 0 auto}
  .brand{font-weight:800;font-size:17px;color:var(--text)}
  [data-theme="dark"] .brand{color:var(--text)}
  @media(max-width:700px){
    /* ONE NAVIGATION MECHANISM. The drawer.
     *
     * A header that scrolls sideways was here from before the ☰ existed, and both real headers
     * had already overridden it one at a time — each with its own comment describing the same
     * fix, because the rule kept doing the same damage in a new place. The sticky brand it
     * needed was pinned with a physical `left:0`, which parked it over the hamburger and on the
     * wrong side in RTL.
     *
     * A scroll strip nobody can see the end of is not a menu. Removed, rather than overridden a
     * third time when somebody adds a header. */
    /* 4.55: the phone shell scrolls the document, so the bar scrolled away with it — and with it
       the ☰, the branch and any way back. It stays put now. The branch selector is the thing a
       person checks mid-scroll ("am I looking at Main?"), so hiding it was the wrong economy. */
    /* 5.56: this overrode the inset padding set above with a flat 10px, which is invisible in a
       browser — Safari's own chrome pushes the page down — and wrong in an INSTALLED app, where
       the page owns the whole screen. The header then sat under the status bar: the clock over
       the wordmark, and the ☰ half inside a strip where iOS takes the touch. The menu did not
       open because the tap never reached the button. */
    header{flex-wrap:nowrap;gap:8px;overflow-x:hidden;
      padding:calc(10px + env(safe-area-inset-top,0px)) calc(12px + env(safe-area-inset-right,0px))
              10px calc(12px + env(safe-area-inset-left,0px));
      position:sticky;top:0;z-index:var(--z-sticky)}
    header > *{flex:0 0 auto;min-width:0}
    header .sp{display:none}
    header .who{max-width:none}
    header .brand{position:static;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    header select{flex:1 1 auto;min-width:0}
    .deskonly{display:none !important}
    /* identity + actions, pinned to the bottom of the drawer */
    .side-foot{margin-top:auto;padding-top:12px;border-top:1px solid var(--line);display:grid;gap:8px}
    .side-foot .who{font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .side-foot .btn{width:100%;padding:11px 12px;text-align:center;text-decoration:none}
  }
  @media(min-width:701px){ .side-foot{display:none} }
  header .brand{font-weight:800;font-size:17px;letter-spacing:.2px;color:var(--text)}
  [data-theme="dark"] header .brand{color:#fff}
  header .sp{flex:1}
  header select{padding:8px 10px}
  header .who{font-size:12px;color:var(--muted);max-width:40vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  nav{display:flex;gap:6px;padding:8px 14px;background:var(--nav);border-bottom:1px solid var(--line)}
  nav button{background:transparent;color:var(--on-nav-muted);padding:8px 12px;font-weight:600}
  nav button.active{color:var(--on-nav);background:var(--nav-active)}
  main{flex:1;overflow:auto}

  /* POS layout */
  .pos{display:grid;grid-template-columns:1fr;gap:0;height:100%}
  @media(min-width:820px){.pos{grid-template-columns:1fr 360px}}
  .poscol{display:flex;flex-direction:column;min-height:0}
  .possearch{margin:0 0 12px;padding:12px 14px;border:1px solid var(--line);border-radius:12px;background:var(--panel);color:var(--text);width:100%}
  .grid{padding:14px;display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px;align-content:start;overflow:auto}
  .cat{background:linear-gradient(135deg,var(--accent2),var(--accent));border:0;border-radius:14px;padding:18px 14px;text-align:start;min-height:96px;display:flex;flex-direction:column;justify-content:space-between;color:#fff}
  .cat:active{filter:brightness(1.1)}
  .cat.back{background:var(--chip);color:var(--text)}
  .cat .cn{font-weight:700;font-size:16px;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}
  .cat .cc{font-size:12px;opacity:.85;margin-top:8px}
  .prod{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:10px;text-align:start;display:flex;flex-direction:column;gap:6px;min-height:140px}
  .prod:active{border-color:var(--accent)}
  .prod .pimg{height:56px;width:100%;border-radius:8px;background:var(--chip);background-size:cover;background-position:center;display:flex;align-items:center;justify-content:center;font-size:24px;flex:0 0 56px}
  .prod .pimg.noimg{color:var(--muted);opacity:.5}
  .prod .p{color:var(--accent);font-weight:700;font-size:14px;flex:0 0 auto}
  .prod .n{font-weight:600;font-size:13px;line-height:1.3;color:var(--text);flex:0 0 auto;height:2.6em;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;word-break:break-word}
  .pthumb{width:40px;height:40px;border-radius:8px;background:var(--chip);background-size:cover;background-position:center;display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0}
  .pthumb.noimg{opacity:.5}

  /* cart */
  /* `border-inline-start`, not `border-left`.
   *
   * The cart sits at the inline END of the till — the right in English, the LEFT in Arabic — and
   * a physical `border-left` kept its divider on the English side after the layout mirrored, so
   * the rule drew a line down the middle of the products and left the cart's own edge bare. */
  .cart{background:var(--panel2);border-inline-start:1px solid var(--line);display:flex;flex-direction:column;min-height:280px}
  .cart h3{margin:0;padding:14px;border-bottom:1px solid var(--line);font-size:14px}
  .lines{flex:1;overflow:auto;padding:6px 0}
  .line{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px 14px;flex-wrap:wrap}
  .line .ln{flex:1}
  .line .ln .nm{font-weight:600;font-size:14px}
  .line .ln .mt{color:var(--muted);font-size:12px}
  .qty{display:flex;align-items:center;gap:6px}
  .qty button{background:var(--chip);color:var(--text);width:30px;height:30px;font-size:18px;line-height:1}
  .qin{width:52px;height:30px;text-align:center;padding:2px;border:1px solid var(--line);border-radius:8px;background:var(--panel2);color:var(--text)}
  .lctrl{display:flex;align-items:center;gap:8px}
  .discbtn{background:var(--chip);color:var(--muted);width:30px;height:30px;border-radius:8px;font-weight:700}
  .badge{background:var(--good);color:var(--on-success);border-radius:6px;padding:1px 6px;font-size:11px;font-weight:700}
  .paidstamp{text-align:center;color:var(--good);font-weight:800;letter-spacing:2px;border:2px solid var(--good);border-radius:8px;padding:4px;margin:8px auto;width:120px}
  .rbtns{display:flex;gap:8px;margin-top:14px}
  .rbtns .btn{flex:1}
  .shiftwrap{padding:0}
  .shiftwrap .admin{padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:16px;align-items:start}
  .shiftwrap .ri,#tillBody .ri{display:flex;justify-content:space-between;padding:6px 0;border-bottom:1px solid var(--line)}
  .shiftwrap .ri.g{font-weight:700;border-bottom:0;margin-top:6px}
  .stocklist{padding:0 14px 14px}
  .strow{display:flex;align-items:center;gap:12px;background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:12px;margin-bottom:8px}
  .strow .si{flex:1;min-width:0}
  .strow .si .nm{font-weight:600}
  .strow .si .mt{color:var(--muted);font-size:12px}
  .strow .soh{font-weight:800;font-size:20px;min-width:44px;text-align:center}
  .strow .soh.low{color:var(--danger-text)}
  .strow .sact{display:flex;align-items:center;gap:6px}
  .strow .sact .qin{width:64px}
  .postrip{display:flex;align-items:center;gap:10px;padding:12px 14px}
  .popick{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0;max-height:140px;overflow:auto}
  .pchip{background:var(--panel);color:var(--text);border:1px solid var(--line);border-radius:999px;padding:8px 14px;font-size:13px;font-weight:600;transition:all .12s}
  .pchip:hover{border-color:var(--accent);color:var(--accent)}
  .modgrp{border-top:1px solid var(--line);padding-top:10px;margin-top:10px}
  .modh{font-weight:700;font-size:14px;margin-bottom:6px}
  .modopt{display:flex;justify-content:space-between;align-items:center;padding:7px 0;font-size:14px}
  .modopt input{width:auto}
  .availrow{border-top:1px solid var(--line);padding:8px 0;display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:space-between}
  .availdays{display:flex;flex-wrap:wrap;gap:4px}
  .daychip{display:flex;align-items:center;gap:3px;font-size:11px;background:var(--chip);padding:3px 6px;border-radius:6px}
  .daychip input{width:auto}
  .availtime{display:flex;align-items:center;gap:6px}
  .availtime .field{margin:0;width:auto;padding:6px}
  .tenders{display:flex;flex-wrap:wrap;gap:8px}
  .tenders .btn{flex:1 1 auto;min-width:90px;width:auto}

  .rcp-head{display:flex;justify-content:space-between;align-items:baseline;flex-wrap:wrap;gap:8px}
  .rcp-money{display:flex;gap:10px;flex-wrap:wrap;margin:10px 0}
  .rcp-money .mv{flex:1 1 auto;min-width:90px;background:var(--panel2);border-radius:10px;padding:10px}
  .rcp-money .mv span{display:block;font-size:11px;color:var(--muted);text-transform:uppercase}
  .rcp-money .mv b{font-size:18px}
  .rcp-yield{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;margin:8px 0}
  .rcp-scale{display:flex;gap:4px;align-items:center;flex-wrap:wrap}
  .rcp-line{display:flex;align-items:center;gap:8px;padding:7px 0;border-bottom:1px solid var(--line)}
  .rcp-line .rcp-ing{flex:1;font-weight:600}
  .rcp-line .rcp-lc{min-width:64px;text-align:right;direction:ltr;color:var(--muted)}
  .rcp-method textarea{width:100%;margin-top:4px}
  .invtabs{display:flex;gap:6px;flex-wrap:wrap}
  .invtabs .pchip.on{background:var(--accent);color:var(--on-brand)}
  .pchip.on{background:var(--accent);color:var(--on-brand)}

  .stepcard{border:1px solid var(--line);border-radius:10px;padding:10px;margin:8px 0;background:var(--panel2)}
  .stephdr{display:flex;justify-content:space-between;font-weight:700;font-size:13px;margin-bottom:6px}
  .stepphotos{display:flex;flex-wrap:wrap;align-items:center;gap:4px;margin-top:6px}
  .wbadge{background:var(--warning);color:var(--on-warning);border-radius:5px;padding:0 5px;font-size:10px;font-weight:700}
  .tbadge{display:inline-block;background:var(--panel2);color:var(--muted);border-radius:999px;padding:2px 9px;font-size:11px;font-weight:600}
  /* Settings screen. Classed rather than styled inline because this is one component
     rendered for every domain — a font size written into the markup here would be a font
     size written into every settings screen the product will ever have. */
  .tbadge.risk{background:var(--danger);color:var(--on-danger)}
  .set-note{font:var(--type-label);color:var(--muted)}
  .set-caption{font:var(--type-caption);color:var(--muted)}
  .set-scope-label{font:var(--type-label);color:var(--muted);align-self:center}
  /* Which level is being edited must be visible (7.68): with three levels a pale chip for each
     left nobody sure whether they were changing the company or the whole business. */
  #setScopeRow .tog.on,.set-tabs .tog.on{background:var(--accent);color:var(--on-brand)}
  .set-tabs{margin-top:8px}
  .set-pick{width:auto}
  .set-override{display:inline-flex;gap:var(--sp-2);align-items:center;font:var(--type-caption);color:var(--muted);margin-top:var(--sp-2)}

  /* Service type on the till. Two taps wide, sitting under the customer row where the cashier
     is already looking, and hidden entirely where a branch serves only one kind. */
  .svc{display:flex;gap:8px;padding:0 12px 8px}
  .svc-opt{flex:1;min-height:40px;border:1px solid var(--line);border-radius:var(--radius-md);
    background:transparent;color:var(--text);font:var(--type-label)}
  .svc-opt.on{background:var(--accent);color:var(--on-brand);border-color:var(--accent)}

  /* ── the numeric contract ────────────────────────────────────────────────
     Text mirrors. Numbers do not.
     
     Arabic reverses layout, navigation and prose. It does not reverse a debit column, a
     quantity, a rate, an invoice number or a date — and `text-align:end`, which is right in
     almost every other context, resolves to the LEFT under dir=rtl. A column of amounts then
     flips sides and the decimal points stop lining up with the totals beneath them.
     
     Right alignment for figures is a typesetting convention older than the web and it has no
     direction. `direction:ltr` on the cell keeps the digits, the separators and the sign in
     the order they were written, whatever surrounds them. */
  .num,.money,.qty,.rate{text-align:right;direction:ltr;unicode-bidi:isolate;font-variant-numeric:tabular-nums}
  .ref,.datecell{direction:ltr;unicode-bidi:isolate;text-align:start}

  /* A negative in an accounting column is red AND parenthesised. Colour alone fails for the
     colour-blind and fails entirely on a printed statement. */
  .num.neg,.money.neg{color:var(--danger-text)}

  /* Table headers follow their column. A right-aligned amount under a start-aligned heading
     is the commonest small wrongness in a bilingual report. */
  th.num,th.money,th.qty,th.rate{text-align:right}

  /* Employee app. One column, large targets, and one dominant control — it is used one
     handed, at a door, often in a hurry. */
  .emp-app{max-width:520px;margin:0 auto;padding:16px}
  .emp-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius-xl);padding:18px;margin-bottom:12px}
  .emp-title{font:var(--type-page);margin:0 0 8px}
  .emp-h2{font:var(--type-section);margin:0 0 8px}
  /* A row in this app is a label and a figure, and it had no layout at all here: `.ri` was
     styled inside `.shiftwrap` and `.receipt` only, so "2026-09-14" and "0h 00m" ran together
     into one word on every phone (5.86). */
  .emp-punches{margin-top:10px;display:grid;gap:2px}
  .emp-punches .ri{display:flex;justify-content:space-between;font:var(--type-small);
    color:var(--text-secondary);padding:4px 0;border-bottom:1px solid var(--line)}
  .emp-punches .ri:last-child{border-bottom:0}
  .emp-card .ri{display:flex;justify-content:space-between;align-items:baseline;gap:12px;
    padding:6px 0;border-bottom:1px solid var(--line)}
  .emp-card .ri:last-child{border-bottom:0}
  /* The app's own header: one bar, the person, and the way into everything that is not clocking
     in — which is most of what an employee does rarely and needs to find at all. */
  .emp-top{position:sticky;top:0;z-index:var(--z-sticky);display:flex;align-items:center;gap:8px;
    background:var(--panel);border-bottom:1px solid var(--line);
    padding:calc(10px + env(safe-area-inset-top,0px)) 12px 10px}
  .emp-top .sp{flex:1}
  /* The ☰ is a control, not a form button: `.btn` is full-width in this stylesheet, which is why
     it stretched across the bar and pushed the name onto two lines (5.89). */
  .emp-burger{flex:0 0 auto;width:44px;height:44px;border:1px solid var(--line);
    border-radius:var(--radius-md);background:var(--panel);color:var(--text);font-size:20px;line-height:1}
  .emp-top strong{font:var(--type-section);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

  /* A drawer from the inline start, like the till and the back office. */
  /* `nav{display:flex}` at the top of this file is the till's tab strip, and it caught this
     drawer because it is also a <nav> (5.90): the items laid out in a row and the selected one
     stretched into a tall pill. Said explicitly here rather than renaming the element — a drawer
     IS navigation, and the next <nav> somebody writes should not inherit a tab strip either. */
  .emp-nav{display:block;background:var(--panel);
    position:fixed;top:0;bottom:0;inset-inline-start:0;width:min(280px,80vw);
    z-index:var(--z-drawer);border-inline-end:1px solid var(--line);
    box-shadow:2px 0 20px rgba(20,33,61,.15);overflow-y:auto;
    padding:calc(12px + env(safe-area-inset-top,0px)) 0 calc(12px + env(safe-area-inset-bottom,0px));
    transform:translateX(-105%);transition:transform .22s ease}
  [dir="rtl"] .emp-nav{transform:translateX(105%)}
  body.emp-nav-open .emp-nav{transform:translateX(0)}
  .emp-backdrop{display:none}
  body.emp-nav-open .emp-backdrop{display:block;position:fixed;inset:0;
    background:rgba(0,0,0,.4);z-index:var(--z-backdrop)}
  .emp-navhead{padding:8px 16px 12px;color:var(--text-muted);font:var(--type-label);
    text-transform:uppercase;letter-spacing:.04em}
  .emp-navitem{display:block;width:100%;text-align:start;background:none;border:0;
    padding:14px 16px;font:var(--type-body);color:var(--text)}
  .emp-navitem.is-on{background:var(--accent-subtle);color:var(--brand-strong);font-weight:var(--fw-semibold)}
  .emp-navrule{height:1px;background:var(--line);margin:8px 0}
  .emp-who{font:var(--type-display)}
  .emp-state{font:var(--type-section);margin:14px 0}
  .emp-code{text-align:center;letter-spacing:2px;text-transform:uppercase}
  .emp-primary{width:100%;min-height:64px;font:var(--type-section)}
  .emp-primary.emp-out{background:var(--danger)}
  .emp-msg{margin-top:10px;font:var(--type-label);color:var(--muted)}
  /* `90vh` ignores the keyboard, so the buttons at the bottom of an editor went behind it the
     moment somebody typed (6.9). `--vvh` is the visual viewport, set from JS. */
  .editor{background:var(--panel);border:1px solid var(--line);border-radius:18px;max-width:460px;width:100%;padding:22px;max-height:calc(var(--vvh, 90vh) - 24px);overflow:auto;box-shadow:0 24px 60px rgba(20,33,61,.25);animation:editorin .18s ease}
  /* And the buttons stay reachable while the rest scrolls, rather than being the part that
     scrolls away. */
  .editor .rbtns{position:sticky;z-index:var(--z-sticky);bottom:calc(var(--kb) - 22px);background:var(--panel);padding:12px 0 0;margin-top:4px}
  @keyframes editorin{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
  .editor h2{margin:0 0 16px;font-size:19px;font-weight:800;color:var(--text)}
  [data-theme="dark"] .editor h2{color:var(--text)}
  .editor label{display:block;font-size:12px;color:var(--muted);margin-bottom:10px}
  .editor .field{display:block;width:100%;margin-top:4px}
  .editor .erow{display:flex;gap:10px}
  .editor .erow label{flex:1}
  /* `.erow` was only ever styled INSIDE `.editor`, and twenty-one of them are not — they
     sit in `.admincard` on Reconcile, Production, Catalog and Channels, where the caption
     stayed inline with the control and the fields did not share the row. Same defect as
     the reports filter, different class, so the rule is unscoped and the layout matched.
     `.chk` is excluded: a checkbox and its caption belong on one line. */
  .erow{display:flex;flex-wrap:wrap;gap:10px}
  .erow > label:not(.chk){display:flex;flex-direction:column;gap:4px;
    flex:1 1 150px;min-width:0;font-size:12px;color:var(--muted)}
  .erow > label:not(.chk) > .field{width:100%;min-width:0;margin-top:0}
  .erow .btn{flex:0 0 auto;align-self:end}
  .editor .chk{display:flex;align-items:center;gap:8px;color:var(--text);font-size:14px;margin:8px 0}
  .editor .chk input{width:auto}
  .recipebox{margin:12px 0;border-top:1px solid var(--line);padding-top:12px}
  .rectitle{font-weight:700;font-size:14px;margin-bottom:8px}
  .recline{display:flex;justify-content:space-between;align-items:center;padding:6px 0;border-bottom:1px solid var(--line);font-size:14px}
  .recadd{display:flex;gap:6px;align-items:center;margin:8px 0}
  .recadd .field{margin:0}
  .recadd #rec_qty{width:90px}
  .recbtns{display:flex;gap:8px;margin-top:8px}
  .recbtns .btn{flex:1}
  .tot{padding:14px;border-top:1px solid var(--line)}
  .tot .row{display:flex;justify-content:space-between;margin-bottom:6px}
  .tot .grand{font-size:20px;font-weight:700}
  /* 11.48.16 (QA-037): ONE COLUMN. `.pay` was a two-column grid from the days of two fixed buttons; its only child is now
     the tender row, which sat in the first half, wrapped every tender onto a line of its own and pushed the totals so high
     that on a 1440×900 till the basket's lines were left 12 px. The row takes the cart's width; the lines keep room for
     at least two (and scroll), whatever the number of tenders. */
  .pay{display:grid;grid-template-columns:1fr;gap:8px;margin-top:10px}
  .cart > .lines{min-height:96px}
  .pay button{padding:14px;font-weight:700}
  .clear{width:100%;margin-top:8px;background:transparent;color:var(--muted)}

  /* dashboard */
  .dash{padding:16px;display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px}
  .stat{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px}
  .stat .k{color:var(--muted);font-size:12px}
  .stat .v{font-size:26px;font-weight:700;margin-top:6px}
  .list{padding:0 16px 16px}
  .list .h{color:var(--muted);font-size:12px;margin:8px 0}
  .row2{display:flex;justify-content:space-between;padding:10px 0;border-bottom:1px solid var(--line)}
  .hrow{width:100%;background:transparent;color:var(--text);border:0;border-bottom:1px solid var(--line);text-align:start;cursor:pointer;font:inherit;padding:12px 2px}
  .hrow:active{background:var(--chip)}

  /* receipt modal */
  /* A MODAL WITH NO LAYER IS NOT A MODAL (6.18).
   *
   * `.modal` had no z-index at all, so it stacked wherever the document put it — underneath the
   * workspace's sticky toolbar, which HAS one. Editing a product showed the product list's
   * header, its search box and its quick views painted across the dialog, and the dialog is the
   * thing that is supposed to be covering them. `--z-dialog` is the scale's own answer: above a
   * drawer, below a popover opened from inside one. */
  .modal{position:fixed;inset:0;z-index:var(--z-dialog);background:rgba(0,0,0,.6);display:flex;align-items:center;justify-content:center;
    padding:calc(20px + env(safe-area-inset-top,0px)) 20px calc(20px + env(safe-area-inset-bottom,0px))}
  /* theme-safe: a receipt is paper. It is white with black ink in both appearances
     because that is what it is a picture of, and what it prints as. */
  .receipt{background:#fff;color:#111;border-radius:12px;max-width:340px;width:100%;padding:20px;font-family:ui-monospace,Menlo,Consolas,monospace} /* theme-safe: paper */
  .receipt h2{margin:0 0 2px;font-size:16px;text-align:center}
  .receipt .c{text-align:center;color:#555;font-size:12px;margin-bottom:12px} /* theme-safe: paper */
  .receipt .ri{display:flex;justify-content:space-between;font-size:13px;padding:3px 0}
  .receipt .rm{font-size:11px;color:#555;padding:0 0 3px 12px} /* theme-safe: paper — 9.11 modifiers under their line */
  /* 9.13.1 (RTL review): Arabic on the on-screen receipt and shift report in a joined face, as on paper
     (9.11) — a monospace font sets Arabic letter by letter where it has the glyphs at all. */
  html[lang="ar"] .receipt{font-family:"Noto Naskh Arabic","Noto Sans Arabic",Tahoma,"Segoe UI",sans-serif;font-variant-numeric:tabular-nums}
  .receipt hr{border:0;border-top:1px dashed #bbb;margin:10px 0} /* theme-safe: paper */
  .receipt .g{font-weight:700;font-size:15px}
  .receipt .done{margin-top:16px}
  /* No z-index at all before: a toast is feedback about what just happened and was
     painted over by whatever it was reporting on. */
  .toast{position:fixed;bottom:calc(18px + var(--kb));left:50%;transform:translateX(-50%);z-index:var(--z-toast);background:var(--inverse-surface);border:1px solid var(--line);color:var(--inverse-text);padding:10px 16px;border-radius:10px;opacity:0;transition:opacity .2s;pointer-events:none}
  /* 11.70.0: a refusal's reference and next step, each on a line of its own under the words (clickable, small) */
  .toast .toast-ref{display:flex;gap:var(--sp-2);align-items:center;margin-top:var(--sp-1);font-size:.78em;opacity:.85;pointer-events:auto}
  .toast .toast-copy,.toast .toast-next{pointer-events:auto;font:inherit;border:1px solid currentColor;background:transparent;color:inherit;border-radius:var(--radius-sm);padding:0 var(--sp-2);cursor:pointer}
  .toast .toast-next{margin-top:var(--sp-1);font-weight:600}
  .toast.show{opacity:1}
  /* 11.72.0 (A11Y-01): the message can be dismissed (✕), holds while pointed at or focused, and an error stays put — so it
     takes the pointer; an empty one takes nothing. The two regions never sit on top of each other: the error is above. */
  .toast{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-1) var(--sp-3);max-inline-size:min(92vw,560px)}
  .toast:empty{padding:0;border:0}
  .toast.show{pointer-events:auto}
  .toast .toast-msg{flex:1 1 auto;min-inline-size:0}
  .toast .toast-x{pointer-events:auto;font:inherit;line-height:1;border:0;background:transparent;color:inherit;cursor:pointer;min-inline-size:32px;min-block-size:32px;border-radius:var(--radius-sm)}
  .toast .toast-x:focus-visible,.toast .toast-next:focus-visible,.toast .toast-copy:focus-visible{outline:none;box-shadow:var(--focus-ring)}
  .toast--error{border-color:var(--danger);border-inline-start-width:4px;bottom:calc(72px + var(--kb))}
  @media (max-width:700px){ .toast{bottom:calc(var(--ws-tabbar-h,84px) + 12px + var(--kb))} .toast--error{bottom:calc(var(--ws-tabbar-h,84px) + 64px + var(--kb))} }

  /* products admin */
  .admin{padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:16px;align-items:start}
  .admincard{background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:18px;align-self:start;box-shadow:0 1px 3px rgba(20,33,61,.04)}
  .admincard h3{margin:0 0 14px;font-size:15px;font-weight:700;color:var(--text)}
  .admincard .field{margin-bottom:10px}
  .adminlist .h{color:var(--muted);font-size:12px;margin:4px 0 8px}
  .prow{display:flex;align-items:center;gap:10px;background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:12px;margin-bottom:8px}
  .prow .pi{flex:1}
  .prow .pi .nm{font-weight:600}
  .prow .pi .mt{color:var(--muted);font-size:12px}
  .prow .pp{font-weight:600}
  .prow .tog{background:var(--chip);color:var(--muted);padding:6px 10px;border-radius:8px;font-size:12px}
  /* 3.74.0: four lines of a JavaScript print template sat here — `+'.ri{…}'` and friends, left
     behind when the receipt printer moved into pos.js and overview.js, where the real print
     styles live. In a stylesheet they are a parse error, and CSS error recovery swallowed the
     next rule: `.adminshell{flex:1 1 auto}` never applied, so the shell was only as tall as its
     content and the sidebar stopped short of the window on every short screen. */

  /* admin shell (back office) — sidebar + scrollable content, robust on iPad/desktop */
  /* Always a left sidebar + content, at ANY width. Never stacks (that was hiding
     content on narrow iPads). Sidebar narrows on small screens but stays a column. */
  /* Desktop / tablet: left sidebar + content. (inline display:flex on .adminshell) */
  .adminshell{flex:1 1 auto;min-height:0;flex-direction:row}
  .side{width:190px;flex:0 0 190px;background:var(--panel);border-inline-end:1px solid var(--line);padding:8px;display:flex;flex-direction:column;gap:3px;overflow-y:auto}
  /* The stamp sits at the very bottom of the sidebar rather than immediately after the
     last group: `.side` is a flex column, so it needs to claim the remaining space
     rather than float up under the navigation. */
  .side > .o-version{margin-top:auto;flex:0 0 auto}
  .sidebtn{display:flex;align-items:center;gap:8px;background:transparent;color:var(--muted);padding:11px 10px;border-radius:10px;text-align:start;font:inherit;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .sidebtn.active{background:var(--chip);color:var(--text)}
  .content{flex:1 1 0%;min-width:0;padding:16px;overflow-y:auto}
  /* Every screen's title, from the page token (3.74.0) — global chrome, applied globally. It was
     22px at weight 800, a size and a weight nothing else in the product used. */
  .ptitle{margin:0 0 var(--sp-6);font:var(--type-page);color:var(--text);letter-spacing:-.01em}
  [data-theme="dark"] .ptitle{color:var(--text)}
  /* nav groups (collapsible) */
  .navgroup{margin-bottom:2px}
  .navgroup-h{display:flex;align-items:center;gap:6px;width:100%;background:transparent;border:0;color:var(--muted);font:inherit;font-weight:700;font-size:11px;text-transform:uppercase;letter-spacing:.04em;padding:10px 10px 6px;cursor:pointer;text-align:start}
  .navchevron{display:inline-block;transition:transform .15s;font-size:14px}
  .navgroup-h.open .navchevron{transform:rotate(90deg)}
  [dir="rtl"] .navchevron{transform:rotate(180deg)}
  [dir="rtl"] .navgroup-h.open .navchevron{transform:rotate(90deg)}
  .navgroup-items{display:flex;flex-direction:column;gap:2px}
  /* display:flex above beats the [hidden] attribute's display:none, so a collapsed
     group kept rendering its items while its chevron said otherwise — the state was
     right and the screen disagreed with it. */
  .navgroup-items[hidden]{display:none}
  .hamburger{display:none;background:var(--panel2);border:1px solid var(--line);border-radius:10px;width:40px;height:40px;font-size:18px;cursor:pointer;color:var(--text);margin-inline-end:8px}
  .nav-backdrop{display:none}
  /* Phone (<=700px): hamburger drawer instead of horizontal strip */
  @media(max-width:700px){
    #app{height:auto;min-height:100vh;overflow:visible}
    .adminshell{flex-direction:column;min-height:0}
    .hamburger{display:inline-flex;align-items:center;justify-content:center}
    .side{position:fixed;top:0;inset-inline-start:0;height:100vh;height:100dvh;width:min(270px,74vw);z-index:var(--z-drawer);
      transform:translateX(-105%);transition:transform .22s ease;flex-direction:column;flex-wrap:nowrap;gap:2px;
      border-inline-end:1px solid var(--line);border-bottom:0;overflow-y:auto;box-shadow:2px 0 20px rgba(0,0,0,.12);
      /* Installed, the drawer covers the whole screen including the status bar and the home
         indicator: its first entry was under the clock and its last under the bar you swipe. */
      padding:calc(12px + env(safe-area-inset-top,0px)) 8px calc(12px + env(safe-area-inset-bottom,0px))}
    /* same double-flip as the shop drawer: the logical property mirrors itself, the
       transform does not. Only the transform is overridden. */
    [dir="rtl"] .side{transform:translateX(105%)}
    body.nav-open .side{transform:translateX(0)}
    body.nav-open .nav-backdrop{display:block;position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:var(--z-backdrop)}
    /* 11.72.2 (QA-163): the bottom bar stays above the backdrop while the menu is open, so its Menu button closes the menu it opened (a tap on it landed on the backdrop, which closed the menu, and the click then opened it again) */
    body.nav-open .ws-tabbar{z-index:calc(var(--z-backdrop) + 1)}
    .sidebtn{flex:0 0 auto;padding:12px 12px}
    .sidebtn .lbl{display:inline}
    /* ONE scroller on a phone: the document. The pane kept its own `overflow-y:auto` from a
       later stylesheet, so it was a scroll container that never scrolled — and a sticky header
       inside a scroll container that does not move can never stick. The rule is written against
       both of its classes so it cannot be quietly out-specified again. */
    .content.o-content, .content{overflow-y:visible;overflow:visible}
    /* The screen's own header stays while its rows scroll under. It is pinned to the TOP OF THE
       SCROLLING PANE, not to the window: on a phone the content pane is what scrolls, and an
       offset measured from the window would leave it floating in the middle of the list. The
       description is dropped here — it is the least useful line to keep pinned. */
    .o-page > .o-wshead{position:sticky;top:var(--app-bar, calc(56px + env(safe-area-inset-top)));z-index:2;background:var(--bg);
      margin-inline:calc(var(--sp-4) * -1);padding:var(--sp-2) var(--sp-4) 0;gap:var(--sp-2)}
    /* Pinned, it has to earn every pixel: the breadcrumb repeats the menu, and the description is
       read once. What stays is what a scrolling person needs — where they are, what they can do,
       the search, and which view they are in. */
    .o-page > .o-wshead .o-crumbs,
    .o-page > .o-wshead .o-wshead__desc{display:none}
    .o-page > .o-wshead .o-wshead__title{font-size:var(--fs-section)}
  }

  /* reports */
  /* A filter row, and the reason it was misaligned: each label held its caption and its
     input as inline text, so the caption sat on the baseline of a 40px control and the
     control could not shrink — the inputs overflowed their own flex items and the Apply
     button landed on top of the second one.
     Each label is its own column now, captions align across the row, and every control
     may shrink to nothing rather than pushing its neighbour. */
  .reprange{display:flex;flex-wrap:wrap;gap:10px 12px;align-items:end;margin-bottom:14px}
  .reprange label{display:flex;flex-direction:column;gap:4px;
    font-size:12px;color:var(--muted);flex:1 1 150px;min-width:0}
  .reprange .field{margin-top:0;width:100%;min-width:0}
  /* The action keeps its size while the fields give way, and stays on the control line
     rather than the caption line. */
  .reprange .btn{flex:0 0 auto;align-self:end}
  /* The quick ranges are a second thought, not a fourth field: they take the whole next
     line rather than being squeezed in beside Apply. */
  .repquick{display:flex;gap:6px;flex:1 0 100%}
  .repgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px;margin-top:14px}

  .repcard{background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:16px;box-shadow:0 1px 3px rgba(20,33,61,.04)}
  .reph{font-weight:700;font-size:14px;margin-bottom:10px}
  /* The bars stretch to fill the card; the LABELS must not. `preserveAspectRatio:none`
     scales the viewBox unevenly, which stretched the axis text horizontally — so the
     labels are HTML underneath the chart, on the same column grid as the bars. */
  .bars{width:100%;height:170px;overflow:visible;display:block}
  .barlabels{display:grid;gap:2px;margin-top:6px}
  .barlabels span{font-size:11px;color:var(--muted);text-align:center;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .rtable{display:flex;flex-direction:column}
  .rtr{display:flex;justify-content:space-between;gap:8px;padding:11px 2px;border-bottom:1px solid var(--line);font-size:14px}
  .rtr .rnum{color:var(--muted);min-width:70px;text-align:right;direction:ltr}

/* ---- Recipe module: Meez/Paprika-grade design (on-brand navy/teal) ---- */
.rcpcards{display:flex;flex-direction:column;gap:8px}
.rcpcard{display:flex;align-items:center;gap:12px;width:100%;text-align:start;background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:10px;cursor:pointer;transition:border-color .15s,box-shadow .15s}
.rcpcard:hover{border-color:var(--accent);box-shadow:0 2px 12px rgba(0,169,157,.10)}
.rcpcard-img{width:52px;height:52px;border-radius:10px;object-fit:cover;flex-shrink:0}
.rcpcard-mono{width:52px;height:52px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:22px;font-weight:800;flex-shrink:0}
.rcpcard-body{flex:1;min-width:0}
.rcpcard-name{font-weight:700;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rcpcard-price{font-size:13px;color:var(--muted);margin-top:2px}
.rcpcard-go{color:var(--muted);font-size:22px;opacity:.5}
.empty{padding:28px 12px;text-align:center;color:var(--muted)}

/* editor sheet */
.rcp-hero{padding:4px 2px 12px}
.rcp-hero-title{font-size:22px;font-weight:800;color:var(--text);line-height:1.2}
[data-theme="dark"] .rcp-hero-title{color:var(--text)}
.rcp-hero-price{color:var(--muted);font-size:14px;margin-top:4px}
.rcp-hero-price b{color:var(--text)}

/* the one bold element: cost/margin strip */
.rcp-strip{display:grid;grid-template-columns:1fr 1fr 1.3fr;gap:1px;background:var(--line);border-radius:16px;overflow:hidden;margin-bottom:16px}
.rcp-stat{background:var(--panel);padding:14px 14px 12px;display:flex;flex-direction:column;gap:3px}
.rcp-stat span{font-size:11px;color:var(--muted);letter-spacing:.02em}
.rcp-stat b{font-size:20px;font-weight:800;color:var(--text);font-variant-numeric:tabular-nums}
.rcp-stat-margin{background:linear-gradient(135deg,var(--panel),var(--panel2))}
.rcp-margin-bar{height:5px;border-radius:999px;background:var(--line);overflow:hidden;margin-top:6px}
.rcp-margin-bar i{display:block;height:100%;border-radius:999px;transition:width .3s}

.rcp-yield{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:10px;margin-bottom:14px}
.rcp-makes{font-weight:600;color:var(--text)}
.rcp-makes input{width:72px;text-align:center;border:1px solid var(--line);border-radius:10px;padding:9px;font:inherit;background:var(--panel);margin:0 4px}
.rcp-scale{display:flex;gap:6px;flex-wrap:wrap}
.scalechip{border:1px solid var(--line);background:var(--panel);color:var(--text);border-radius:999px;padding:8px 14px;font:inherit;font-weight:600;cursor:pointer;transition:all .12s}
.scalechip.on{background:var(--accent);color:#fff;border-color:var(--accent)}

.rcp-sectlabel{font-size:12px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin:6px 2px 8px}

/* ingredient rows */
.rcp-line{display:flex;align-items:center;gap:10px;padding:11px 12px;background:var(--panel);border:1px solid var(--line);border-radius:12px;margin-bottom:6px}
.rcp-line .rcp-ing{flex:1;font-weight:600;color:var(--text)}
.rcp-line .qin{width:74px;text-align:center;border:1px solid var(--line);border-radius:9px;padding:8px;font:inherit;background:var(--bg)}
.rcp-line .rcp-lc{min-width:60px;text-align:right;direction:ltr;color:var(--muted);font-variant-numeric:tabular-nums}
.rcp-line .tog{border:0;background:transparent;color:var(--danger-text);cursor:pointer;font-size:16px}

.recadd{display:flex;gap:8px;align-items:center;margin:8px 0 4px;flex-wrap:wrap}
.recadd .field{flex:1;min-width:120px}
.recadd input.field{max-width:110px}

/* method */
.rcp-method{margin-top:16px}
.rcp-method textarea{width:100%;border:1px solid var(--line);border-radius:12px;padding:12px;font:inherit;background:var(--panel);min-height:110px;resize:vertical}

/* action buttons */
.rbtns{display:flex;gap:10px;margin-top:16px;flex-wrap:wrap}
.rbtns .btn{flex:1;min-width:130px}

@media(max-width:640px){ .rcp-strip{grid-template-columns:1fr 1fr} .rcp-stat-margin{grid-column:1/-1} }

/* ---- Recipe master-detail: two screens on mobile, side-by-side on desktop ---- */
.rcp-back{display:none}
@media(min-width:701px){
  /* desktop/tablet: both panes visible, list narrower + sticky */
  .rcp-wrap{grid-template-columns:320px 1fr}
  .rcp-wrap .rcp-pane-list{position:sticky;z-index:var(--z-sticky);top:8px;align-self:start;max-height:calc(100vh - 120px);overflow-y:auto}
}
@media(max-width:700px){
  /* mobile: show list OR detail, not both stacked */
  .rcp-wrap .rcp-pane-detail{display:none}
  .rcp-wrap.show-detail .rcp-pane-list{display:none}
  .rcp-wrap.show-detail .rcp-pane-detail{display:block}
  .rcp-back{display:inline-flex;align-items:center;gap:4px;background:var(--panel2);color:var(--text);border:1px solid var(--line);border-radius:999px;padding:8px 16px;font:inherit;font-weight:600;cursor:pointer;margin-bottom:12px}
}

/* ---- Reusable data grid ---- */
.dg-toolbar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px}
.dg-search{width:100%;border:1px solid var(--line);border-radius:12px;padding:12px 14px;font:inherit;background:var(--panel);margin-bottom:10px}
.dg-scroll{overflow-x:auto;border:1px solid var(--line);border-radius:14px;background:var(--panel)}
table.dg{width:100%;border-collapse:collapse;font-size:14px}
.dg-th{position:sticky;z-index:var(--z-sticky);top:0;background:var(--panel2);color:var(--muted);font-weight:600;text-align:start;padding:12px 14px;cursor:pointer;white-space:nowrap;user-select:none;border-bottom:1px solid var(--line)}
.dg-th.end{text-align:end}
.dg-td{padding:12px 14px;border-bottom:1px solid var(--line);color:var(--text)}
.dg-td.end{text-align:end;font-variant-numeric:tabular-nums;white-space:nowrap}
.dg-tr{cursor:pointer;transition:background .1s}
.dg-tr:hover{background:var(--panel2)}
.dg-tr:last-child .dg-td{border-bottom:0}
.dg-empty{padding:28px;text-align:center;color:var(--muted)}
.dg-foot{display:flex;justify-content:space-between;align-items:center;margin-top:10px;flex-wrap:wrap;gap:8px}
.dg-pager{display:flex;gap:4px;align-items:center}
.dg-pg{border:1px solid var(--line);background:var(--panel);color:var(--text);border-radius:9px;min-width:38px;height:38px;font:inherit;cursor:pointer}
.dg-pg:disabled{opacity:.4;cursor:default}
.dg-pgn{padding:0 10px;color:var(--muted);font-variant-numeric:tabular-nums}
.dg-namecell{display:flex;align-items:center;gap:10px}
.dg-thumb{width:36px;height:36px;border-radius:8px;object-fit:cover;flex-shrink:0}
.dg-mono{width:36px;height:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:15px;flex-shrink:0}
.dg-chip{display:inline-block;font-size:11px;padding:2px 8px;border-radius:999px;background:var(--panel2);color:var(--muted);margin-inline-start:6px}

/* ---- data grid: select + filters + column chooser + bulk ---- */
.dg-selc{width:44px;text-align:center}
.dg-selc input{width:18px;height:18px}
.dg-colbtn{width:44px;text-align:center}
.dg-cols{border:0;background:transparent;font-size:18px;cursor:pointer;color:var(--muted)}
.dg-filters{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:10px}
.dg-filter{display:flex;flex-direction:column;gap:4px;font-size:12px;color:var(--muted)}
.dg-filter select{border:1px solid var(--line);border-radius:10px;padding:9px 12px;font:inherit;background:var(--panel);color:var(--text);min-width:130px}
.dg-bulk{display:flex;align-items:center;gap:10px;flex-wrap:wrap;background:var(--brand);color:var(--on-brand);border-radius:12px;padding:10px 14px;margin-bottom:10px}
[data-theme="dark"] .dg-bulk{background:var(--panel2);color:var(--text)}
.dg-bulk span{font-weight:600}
.dg-bulk-btn{border:0;background:var(--nav-active);color:var(--on-brand);border-radius:8px;padding:8px 14px;font:inherit;font-weight:600;cursor:pointer}
[data-theme="dark"] .dg-bulk-btn{background:var(--accent);color:#04211f}
.dg-bulk-btn.danger{background:var(--danger);color:#fff}
.dg-bulk-x{margin-inline-start:auto;border:0;background:transparent;color:inherit;font-size:16px;cursor:pointer;opacity:.8}
.dg-colmenu{position:fixed;z-index:var(--z-menu);background:var(--panel);border:1px solid var(--line);border-radius:12px;box-shadow:0 8px 30px rgba(0,0,0,.15);padding:8px;min-width:200px;max-height:70vh;overflow:auto}
.dg-colmenu-h{font-size:12px;font-weight:700;color:var(--muted);text-transform:uppercase;padding:6px 10px}
.dg-colopt{display:flex;align-items:center;gap:8px;padding:9px 10px;border-radius:8px;cursor:pointer;color:var(--text)}
.dg-colopt:hover{background:var(--panel2)}

/* ---- Dashboard KPI cards ---- */
.kpigrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px;margin-bottom:8px}
.kpi{background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:16px}
.kpi-label{font-size:12px;color:var(--muted);margin-bottom:8px}
.kpi-value{font-size:22px;font-weight:800;color:var(--text);font-variant-numeric:tabular-nums;line-height:1.1}
.kpi-big{grid-column:span 2}
.kpi-accent{background:linear-gradient(135deg,var(--brand),var(--brand-strong));border-color:transparent}
.kpi-accent .kpi-label{color:rgba(255,255,255,.7)}
.kpi-accent .kpi-value{color:var(--on-brand);font-size:26px}
[data-theme="dark"] .kpi-accent{background:linear-gradient(135deg,var(--accent),var(--accent2))}
[data-theme="dark"] .kpi-accent .kpi-value,[data-theme="dark"] .kpi-accent .kpi-label{color:#04211f}
.kpi-methods{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:12px 14px;margin-top:8px}
@media(max-width:520px){ .kpigrid{grid-template-columns:1fr 1fr} .kpi-big{grid-column:span 2} }

/* ---- utility classes (reduce inline-style drift; consistent spacing) ---- */
.u-auto{width:auto !important}
.mt-0{margin-top:0}.mt-1{margin-top:6px}.mt-2{margin-top:12px}.mt-3{margin-top:18px}
.mb-2{margin-bottom:12px}
.row-between{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}
.stack{display:flex;flex-direction:column;gap:10px}
.section-label{font-size:12px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin:14px 2px 8px}
.hint{color:var(--muted);font-size:13px}

/* ---- page head + toolbar (list-first layout) ---- */
.page-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:16px}
.toolbar{display:flex;gap:8px;flex-wrap:wrap}
.tbtn{background:var(--panel);color:var(--text);border:1px solid var(--line);border-radius:11px;padding:10px 16px;font-weight:600;font-size:14px;box-shadow:0 1px 2px rgba(20,33,61,.05);transition:all .12s}
.tbtn:hover{border-color:var(--accent);color:var(--accent)}
.tbtn.primary{background:var(--accent);color:#fff;border-color:var(--accent)}
.tbtn.primary:hover{background:var(--accent2);color:#fff}
@media(max-width:520px){ .page-head{align-items:stretch} .toolbar{width:100%} .toolbar .tbtn{flex:1;text-align:center;padding:11px 8px} }

/* ---- PIN pad (POS login) ---- */
.pin-dots{display:flex;justify-content:center;gap:12px;margin:14px 0}
.pin-dot{width:14px;height:14px;border-radius:50%;border:2px solid var(--line);background:transparent}
.pin-dot.on{background:var(--accent);border-color:var(--accent)}
.pin-pad{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;max-width:260px;margin:0 auto}
.pin-key{height:64px;border-radius:14px;border:1px solid var(--line);background:var(--panel);font-size:24px;font-weight:700;color:var(--text)}
.pin-key:hover{border-color:var(--accent);color:var(--accent)}
.pin-key:active{background:var(--panel2)}

/* the payment-split group on the daily entry: the four tenders read as one block */
.repsub{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:10px 12px;margin:8px 0}

.cust-row{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;
  background:var(--panel2);border:1px dashed var(--line);color:var(--muted);border-radius:11px;
  padding:11px 13px;margin-bottom:10px;font-size:14px;text-align:start;cursor:pointer}
.cust-row:hover{border-color:var(--accent);color:var(--accent)}
.cust-row.on{border-style:solid;border-color:var(--accent);color:var(--text);background:var(--panel)}
.cust-row .x{font-weight:700;opacity:.6;padding:0 4px}

.fstats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin:10px 0}
.fstat{background:var(--panel);border:1px solid var(--line);border-top:3px solid var(--line);border-radius:12px;padding:11px 13px;display:flex;flex-direction:column;gap:4px}
.fstat-l{font-size:11px;color:var(--muted);letter-spacing:.3px}
.fstat-v{font-size:19px;font-weight:800;font-variant-numeric:tabular-nums}
.fstat.pos{border-top-color:var(--good)} .fstat.neg{border-top-color:var(--danger)} .fstat.warn{border-top-color:var(--warning)}
/* .fintabs removed in 3.71.0: no screen carries a menu of its own any more. */

/* ---- POS header drawer ---- */
/* Anchored to the inline START — the same edge the ☰ sits on, and the same edge
   the admin sidebar uses. It was anchored to the inline END, so in English the
   button was on the left and the panel arrived from the right. */
.pos-drawer{position:fixed;top:0;inset-inline-start:0;height:100vh;height:100dvh;width:min(280px,74vw);background:var(--panel);z-index:var(--z-drawer);
  transform:translateX(-105%);transition:transform .22s ease;box-shadow:2px 0 20px rgba(20,33,61,.15);
  padding:calc(16px + env(safe-area-inset-top,0px)) 16px calc(16px + env(safe-area-inset-bottom,0px));
  display:flex;flex-direction:column;gap:10px;overflow-y:auto}
[dir="rtl"] .pos-drawer{transform:translateX(105%);box-shadow:-2px 0 20px rgba(20,33,61,.15)}
body.pos-menu-open .pos-drawer{transform:translateX(0)}
.pos-drawer-backdrop{display:none}
body.pos-menu-open .pos-drawer-backdrop{display:block;position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:var(--z-backdrop)}
.pos-drawer-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;padding-bottom:10px;border-bottom:1px solid var(--line)}
.pos-drawer-head .who{color:var(--muted);font-size:13px}
.pos-drawer-x{border:0;background:var(--panel2);width:34px;height:34px;border-radius:50%;font-size:15px;cursor:pointer}
.pos-drawer-lbl{font-size:12px;color:var(--muted);margin-top:4px}
.pos-drawer-field{width:100%}
.pos-drawer-item{width:100%;text-align:center;margin:0}

/* POS is touch-first: show the header hamburger up to tablet width */
/* The till's menu is reachable at EVERY width (7.76, UX-765-16). It was hidden above 900px on the
   assumption that a desktop header had the controls — it has not since the drawer took Till,
   Inventory, the pay-outs, language and sign-out, so a desktop till could reach none of them. */
#app > header #posMenuBtn{display:inline-flex;align-items:center;justify-content:center}
@media(max-width:900px){ .posonly-desktop{display:none} }

/* ---- online order alert popup + badge ---- */
.oo-pop{max-width:400px;text-align:center}
.oo-flash{font-size:20px;font-weight:800;color:var(--accent);margin-bottom:8px}
.oo-flash.pulse{animation:ooPulse .8s ease infinite}
@keyframes ooPulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.06);opacity:.7}}
.oo-src{font-weight:700;margin-bottom:4px}
.oo-cust{color:var(--text);margin-bottom:2px}
.oo-total{font-size:20px;font-weight:800;margin:12px 0}
.oo-acts{display:flex;gap:8px;flex-wrap:wrap}
.oo-acts .btn{flex:1;min-width:100px}
.oo-badge{position:fixed;bottom:calc(18px + var(--kb));inset-inline-end:18px;background:var(--accent);color:#fff;border-radius:999px;padding:12px 18px;font-weight:800;box-shadow:0 6px 24px rgba(0,169,157,.4);z-index:var(--z-sheet);display:flex;align-items:center;gap:6px;cursor:pointer}

/* the till's own figures, shown live above the day's fields */
.poslive{background:var(--panel2);border:1px solid var(--line);border-radius:11px;
  padding:10px 12px;margin:8px 0;font-size:12.5px;color:var(--muted);line-height:1.7}
.poslive b{color:var(--text);font-size:14px}

/* ---- floor plan ---- */

/* ---- kitchen display ---- */

/* ============================================================
   INTEGRATIONS
   ------------------------------------------------------------
   The default treatment for this screen is a grid of provider
   logos with an on/off switch, which frames an integration as a
   feature you enable. It is not: it is a connection with a
   health state and a list of unmet prerequisites. So the screen
   is a readiness ledger, ordered by what needs attention.

   The lifecycle track is the one bold element. Everything else
   stays quiet — no gradients, no shadow kit — because the brand
   guidelines are explicit that the back office prioritises
   density and clarity over marketing treatments.
   ============================================================ */

.int-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 14px;margin:0 0 4px}
.int-head h2{margin:0}
.int-scope{color:var(--muted);font-size:13px}
.int-scope b{color:var(--text);font-weight:600}
.int-intro{color:var(--muted);font-size:13px;max-width:62ch;margin:6px 0 18px}

/* The ledger. Rows, not cards: an integration is a line item in a
   list of things that are or are not working. */
.int-list{border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;background:var(--panel)}
.int-row{display:grid;grid-template-columns:1fr auto;gap:4px 16px;
  padding:14px 16px;border-bottom:1px solid var(--line);cursor:pointer;
  background:none;border-inline:0;border-top:0;width:100%;text-align:start;color:inherit}
.int-row:last-child{border-bottom:0}
.int-row:hover{background:var(--panel2)}
.int-row[aria-current="true"]{background:var(--panel2);
  box-shadow:inset 3px 0 0 var(--accent)}
[dir="rtl"] .int-row[aria-current="true"]{box-shadow:inset -3px 0 0 var(--accent)}
.int-row:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.int-name{font-weight:600;font-size:15px}
.int-sub{grid-column:1;color:var(--muted);font-size:12px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Explicit placement: without a column the browser auto-places this into
   column 1 and pushes the provider name to the right, which reads as though
   the state is the subject and the name is a footnote. */
.int-right{grid-column:2;grid-row:1 / span 2;align-self:center;
  display:flex;align-items:center;gap:10px}

/* The readiness track. Four stages, because that is the actual
   state machine — not decoration, and not a progress bar, which
   would imply it advances on its own. */
.int-track{display:flex;align-items:center;gap:3px}
.int-seg{width:16px;height:5px;border-radius:2px;background:var(--line)}
.int-seg.on{background:var(--accent)}
.int-seg.warn{background:var(--warning)}
.int-seg.stop{background:var(--danger)}

/* State never rests on colour alone: every one carries a word.
   That is a brand rule and an accessibility one. */
/* Right-aligned with a floor, so the tracks line up down the column instead of
   drifting with the length of each label. */
.int-state{font-size:12px;font-weight:600;white-space:nowrap;
  min-width:8.5em;text-align:end}
.int-state.live{color:var(--good)}
/* "Ready to go live" is a state of the business, not a piece of branding. It read in the
   brand colour, which is the misuse a design review will always find first: brand and
   success become the same fact on screen. */
.int-state.ready{color:var(--info)}
.int-state.part{color:var(--muted)}
.int-state.stop{color:var(--danger-text)}

.int-empty{padding:28px 20px;text-align:center;color:var(--muted);font-size:13px}
.int-empty b{display:block;color:var(--text);font-size:15px;margin-bottom:6px;font-weight:600}

/* Detail. On a wide screen it sits beside the ledger; on a phone
   it replaces it, because scrolling past twelve integrations to
   reach the one you opened is the thing that makes these screens
   unusable on a till. */
.int-split{display:grid;gap:18px}
@media(min-width:1000px){
  .int-split{grid-template-columns:minmax(300px,380px) 1fr;align-items:start}
  /* The detail runs far longer than the ledger, so the ledger follows rather
     than stranding the reader beside empty space. */
  .int-split > .int-list{position:sticky;z-index:var(--z-sticky);top:12px}
}
/* No `overflow` here, deliberately: clipping the pane would make the sticky header
   stick to a box that does not scroll, which looks like a header that has stopped
   working. The header rounds its own top corners instead. */
.int-detail{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel);
  padding:0 0 20px}
.int-detail-sub{color:var(--muted);font-size:12px;margin:0 0 16px}
.int-back{display:none;margin-bottom:12px}

/* Identity, and it stays put.
   Which integration this is and whether it is working are the two facts that stop being
   true the moment you have scrolled past them — and a credentials form with no provider
   name above it is how a production key goes into the wrong row. */
.int-id{position:sticky;top:0;z-index:2;display:flex;align-items:center;gap:12px;
  padding:16px 18px 14px;background:var(--panel);border-bottom:1px solid var(--line);
  border-radius:var(--radius) var(--radius) 0 0}
.int-id h3{margin:0;font-size:19px;line-height:1.25;letter-spacing:-.01em;font-weight:650}

/* The state, as a word in a shape. Colour carries it a second time and never alone. */
.int-pill{margin-inline-start:auto;font-size:12px;font-weight:600;line-height:1;
  padding:6px 10px;border-radius:999px;white-space:nowrap;
  border:1px solid var(--line);color:var(--muted);background:var(--panel2)}
.int-pill.live{color:var(--good);border-color:color-mix(in srgb,var(--good) 40%,var(--line));
  background:color-mix(in srgb,var(--good) 10%,transparent)}
.int-pill.ready{color:var(--info);border-color:color-mix(in srgb,var(--info) 40%,var(--line));
  background:color-mix(in srgb,var(--info) 10%,transparent)}
.int-pill.stop{color:var(--danger-text);border-color:color-mix(in srgb,var(--danger) 40%,var(--line));
  background:color-mix(in srgb,var(--danger) 10%,transparent)}

/* ── the stage rail ──────────────────────────────────────────────────────────
   The one loud element on the screen, and loud because it answers the only question
   anybody opens it with: where has this got to, and what is next.

   Four stops, because that is the state machine. Deliberately not a progress bar: a bar
   implies something is advancing on its own, and nothing here advances until a person
   does the next thing. */
.int-rail{list-style:none;display:grid;grid-auto-flow:column;grid-auto-columns:1fr;
  gap:0;margin:0;padding:18px 18px 4px}
.int-stop{position:relative;display:grid;justify-items:center;gap:8px;
  font-size:11.5px;color:var(--muted);text-align:center}
/* The connector is drawn from each stop to the next, so it inherits that stop's state:
   the line fills behind you and stays grey ahead. */
.int-stop::before{content:"";position:absolute;top:5px;height:2px;background:var(--line);
  inset-inline-start:50%;width:100%}
.int-stop:last-child::before{display:none}
.int-stop.done::before{background:var(--accent)}
.int-dot{width:12px;height:12px;border-radius:50%;background:var(--panel);
  border:2px solid var(--line);position:relative;z-index:1}
.int-stop.done .int-dot{background:var(--accent);border-color:var(--accent)}
.int-stop.done{color:var(--text)}
/* Where you are standing: amber, which is the brand's attention colour and is used on
   this screen for that and nothing else. */
.int-stop.here .int-dot{background:var(--panel);border-color:var(--warning);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--warning) 22%,transparent)}
.int-stop.here{color:var(--text);font-weight:600}
.int-stop.stop .int-dot{border-color:var(--danger);background:var(--danger)}
.int-stop-label{max-width:12ch}

/* One sentence under the stop you are standing on, rather than a list under a heading.
   A list of blockers is a list; the next thing to do is an instruction. */
.int-next{margin:10px 18px 0;font-size:13.5px;line-height:1.5;color:var(--text)}
.int-next.ok{color:var(--good);font-weight:600}
.int-then{display:block;margin-top:3px;color:var(--muted);font-size:12px}
@media(max-width:999px){
  /* Master-detail, not master-then-detail. Rendering both stacked means
     scrolling past every integration to reach the one you opened, which is the
     pattern that makes these screens unusable on a phone behind a till. */
  .int-split:not(.detail-open) > #intDetail{display:none}
  .int-split.detail-open .int-list{display:none}
  .int-split.detail-open .int-back{display:inline-flex}

  /* Four labels across 390px is four truncations. The rail keeps its dots — the shape is
     the information — and drops to the label of the stop you are standing on, which is
     the only one being read on a phone anyway. */
  .int-rail{padding:14px 14px 2px}
  .int-stop-label{display:none}
  .int-stop.here .int-stop-label,.int-stop:last-child .int-stop-label{display:block}
  .int-id{padding:14px 14px 12px}
  .int-id h3{font-size:17px}
  .int-sect{padding:18px 14px 0}
  .int-next{margin-inline:14px}

  /* A three-column table at 390px truncates every value it holds. The same
     information stacks: our field, then theirs, then the action. */
  .map-tbl,.map-tbl tbody,.map-tbl tr,.map-tbl td{display:block;width:100%}
  .map-tbl thead{display:none}
  .map-tbl tr{padding:10px 0;border-bottom:1px solid var(--line)}
  .map-tbl td{border:0;padding:2px 0}
  .map-tbl td .btn{margin-top:6px}
}

/* Sections are separated by a rule and not boxed into cards. Identical rounded cards
   with the same shadow under each is the house style of every admin template; a rule
   costs one pixel and says the same thing, and it keeps the density the brand
   guidelines ask of the back office. */
.int-sect{margin:0;padding:20px 18px 0;border-top:1px solid var(--line)}
.int-sect:first-of-type{border-top:0}
.int-sect > h4{margin:0 0 3px;font-size:13px;font-weight:650;letter-spacing:.01em}

/* An integration that needs work says so in the ledger, in the one colour this screen
   reserves for it. A marker on every row is a marker that says nothing. */
.int-row.int-attn{box-shadow:inset 3px 0 0 var(--warning)}
[dir="rtl"] .int-row.int-attn{box-shadow:inset -3px 0 0 var(--warning)}
.int-row.int-attn[aria-current="true"]{box-shadow:inset 3px 0 0 var(--accent)}
[dir="rtl"] .int-row.int-attn[aria-current="true"]{box-shadow:inset -3px 0 0 var(--accent)}

/* Counts, prices and durations line up in a column or they are harder to compare than
   the same numbers written on paper. */
.int-detail,.int-list{font-variant-numeric:tabular-nums}

/* Catalog panel.
   The stage line is a statement of fact, not a status pill: green for "this works" would
   be a claim nothing has verified, so an unactivated connection reads as a note. */
.cat-stage{padding:10px 0 10px 12px;margin:0 0 12px;font-size:13.5px;line-height:1.5;
  border-inline-start:2px solid var(--line);color:var(--text)}
[dir="rtl"] .cat-stage{padding:10px 12px 10px 0}
.cat-stage-off{border-inline-start-color:var(--warning)}
.cat-stage b{font-weight:650}

/* The payload is a document, not a card.
   It is the one thing on this screen a person reads line by line, so it is set as a
   listing: a header strip naming the request, hairline frame, and a monospaced body that
   scrolls sideways rather than wrapping JSON into something unreadable. */
.cat-op{border:1px solid var(--line);border-radius:8px;margin:12px 0;overflow:hidden;
  background:var(--panel)}
.cat-op-head{background:var(--panel2);padding:7px 10px;font-size:12px;font-weight:600;
  border-bottom:1px solid var(--line);color:var(--muted)}
.cat-op-head code{color:var(--text)}
.cat-op pre{margin:0;padding:12px;overflow-x:auto;font-size:12.5px;line-height:1.55;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  background:var(--panel);color:var(--text);tab-size:2}

/* Why an item is not on the menu is the question people actually ask here, so the answer
   sits beside the payload rather than in a log. Quiet: it is context, not a failure. */
.cat-excl{margin-top:12px;padding-inline-start:12px;font-size:13px;
  border-inline-start:2px solid var(--line);color:var(--muted)}
.cat-excl b{color:var(--text);font-weight:650}
.cat-excl ul{margin:5px 0 0;padding-inline-start:16px;list-style:none}
.cat-excl li{margin:3px 0;position:relative}
.cat-excl li::before{content:"";position:absolute;inset-inline-start:-12px;top:8px;
  width:4px;height:4px;border-radius:50%;background:var(--line)}

.int-sect > p{margin:0 0 12px;color:var(--muted);font-size:12px;max-width:60ch}

/* Environments as a segmented control. One is active; the others
   are switchable if they have credentials of their own. */
.env-switch{display:flex;gap:0;border:1px solid var(--line);border-radius:11px;overflow:hidden;width:fit-content;max-width:100%}
.env-opt{padding:9px 14px;font-size:13px;font-weight:600;background:var(--panel);
  border:0;border-inline-end:1px solid var(--line);color:var(--muted);cursor:pointer;
  display:flex;flex-direction:column;gap:2px;align-items:flex-start;min-width:120px}
.env-opt:last-child{border-inline-end:0}
.env-opt[aria-pressed="true"]{background:var(--accent);color:#fff}
.env-opt:disabled{cursor:not-allowed;opacity:.55}
.env-opt:not(:disabled):not([aria-pressed="true"]):hover{background:var(--panel2);color:var(--text)}
.env-opt:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.env-meta{font-size:11px;font-weight:500;opacity:.85}

.int-fields{display:grid;gap:10px;margin-top:12px}
.int-field label{display:block;font-size:12px;color:var(--muted);margin-bottom:4px}
.int-field input{width:100%}

/* A URL, a secret name and a JSON path are Latin technical values. In an Arabic
   interface they must still read left to right — right-aligning
   "https://talabat.partner.deliveryhero.io" puts the scheme at the wrong end and
   moves the trailing punctuation, which is exactly the mixed-script case the
   brand guidelines say to test. */
.ltr-value{direction:ltr;text-align:left;unicode-bidi:isolate}
.int-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
/* Back-office toolbar, not a call to action: these are quieter and smaller
   than the primary buttons elsewhere in the product. */
.int-actions .btn{width:auto;padding:9px 14px;font-size:13px;font-weight:600}

/* Blockers are the working content of this screen, so they read as
   a checklist of things to do rather than an error panel. */
.int-blockers{list-style:none;padding:0;margin:8px 0 0;display:grid;gap:6px}
.int-blockers li{display:flex;gap:8px;font-size:13px;align-items:flex-start}
.int-blockers li::before{content:"";flex:0 0 auto;width:6px;height:6px;border-radius:50%;
  background:var(--warning);margin-top:7px}
.int-ok{color:var(--good);font-size:13px;font-weight:600}

/* Credentials read as a key list rather than a table of two things: the name is the
   subject, and the mask and its history are the detail underneath it. */
#secBox .map-tbl td:first-child{padding-block:8px}
#secBox code{font-size:13px;font-weight:600}
#secBox .int-detail-sub{font-size:11.5px}
#secBox .int-fields{margin-top:14px;padding-top:14px;border-top:1px dashed var(--line)}

/* Mapping editor. A table, because it is tabular — and editable,
   because the whole point is that a tenant can change it. */
.map-tbl{width:100%;border-collapse:collapse;font-size:13px}
.map-tbl th{text-align:start;font-weight:600;font-size:12px;color:var(--muted);
  padding:0 8px 8px;border-bottom:1px solid var(--line)}
.map-tbl td{padding:7px 8px;border-bottom:1px solid var(--line);vertical-align:middle}
.map-tbl tr:last-child td{border-bottom:0}
.map-path{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;
  direction:ltr;text-align:left;unicode-bidi:isolate;display:inline-block}
.map-tbl td .btn{width:auto;padding:6px 10px;font-size:12px;font-weight:600}
.map-tbl input.map-in{width:100%;padding:6px 8px;border-radius:8px;font-size:12px;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  direction:ltr;text-align:left;unicode-bidi:isolate}
.map-origin{font-size:11px;color:var(--muted)}
.map-origin.custom{color:var(--accent);font-weight:600}
.map-missing{border:1px solid var(--warning);background:color-mix(in srgb,var(--warning) 12%,transparent);
  border-radius:10px;padding:10px 12px;font-size:13px;margin-bottom:12px}

/* Outlets, master-detail on small screens for the same reason as
   the integrations list. */
.outlet-list{display:grid;gap:8px}
.outlet-card{border:1px solid var(--line);border-radius:11px;padding:12px 14px;background:var(--panel)}
.outlet-card.warn{border-color:var(--warning)}
.outlet-top{display:flex;justify-content:space-between;align-items:baseline;gap:10px}
.outlet-name{font-weight:600}
.outlet-meta{display:flex;flex-wrap:wrap;gap:4px 14px;margin-top:6px;font-size:12px;color:var(--muted)}
.outlet-meta b{color:var(--text);font-weight:600}

.int-vendor{border:1px solid var(--line);border-radius:11px;padding:12px 14px;background:var(--panel2)}
.int-vendor summary{cursor:pointer;font-size:13px;font-weight:600}
.int-vendor pre{white-space:pre-wrap;font-size:12px;margin:10px 0 0;color:var(--muted);
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;line-height:1.6}

@media (prefers-reduced-motion:reduce){
  .int-row,.env-opt{transition:none}
}

/* POS at the top of the drawer: the way back to the till should not be under a
   scroll of every other screen in the product. */
.side-pos{display:block;text-align:center;margin:0 0 14px}
.side-foot-btns{display:grid;gap:8px}
.side-foot-btns .btn{width:100%}

/* The webhook address is a value to copy, not prose. */
.int-endpoint{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.int-endpoint code{flex:1 1 260px;min-width:0;overflow-x:auto;white-space:nowrap;
  background:var(--panel2);border:1px solid var(--line);border-radius:9px;
  padding:9px 11px;font-size:12px;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.int-endpoint .btn{width:auto;padding:9px 14px;font-size:13px;font-weight:600}

/* ============================================================
   POS CART ON A PHONE
   ------------------------------------------------------------
   The cart was a column stacked under the product grid, so with
   a long menu it sat a full scroll away and a cashier could not
   see what they were building. It is now a sheet anchored to the
   bottom: a handle that stays put while browsing, expanding over
   the grid when there is something to check or take payment for.

   Desktop is untouched — above 820px the cart is a column beside
   the products, which is the right shape when there is room.
   ============================================================ */
.cart-handle,.cart-backdrop,.cart-grab{display:none}

@media(max-width:819px){
  .cart-handle{
    display:grid;grid-template-columns:auto 1fr auto auto;align-items:center;gap:10px;
    /* Above the keyboard, not behind it (7.02) — the handle is how a cashier reaches the cart,
       and a cashier typing a quantity is exactly when the keyboard is up. */
    position:fixed;inset-inline:0;bottom:var(--kb);z-index:var(--z-sheet-handle);
    background:var(--nav);color:#fff;border:0;
    padding:14px 16px calc(14px + env(safe-area-inset-bottom,0px));
    font-size:15px;font-weight:600;text-align:start;
    box-shadow:0 -4px 20px rgba(20,33,61,.18)}
  .cart-handle:focus-visible{outline:2px solid var(--accent);outline-offset:-3px}

  /* The count is the thing a cashier glances at mid-service, so it leads. */
  .cart-handle-count{
    min-width:26px;height:26px;border-radius:13px;background:var(--accent);
    display:inline-flex;align-items:center;justify-content:center;
    font-size:13px;font-weight:700;padding:0 8px}
  .cart-handle-lbl{color:rgba(255,255,255,.75);font-weight:500;font-size:14px}
  .cart-handle-total{font-variant-numeric:tabular-nums;font-weight:700}
  .cart-handle-chev{opacity:.7;transition:transform .18s}
  .cart-handle[aria-expanded="true"] .cart-handle-chev{transform:rotate(180deg)}

  /* An empty cart still shows the bar — it is the anchor a cashier reaches for —
     but reads as an instruction rather than a total of nothing. */
  .cart-handle.empty .cart-handle-count{background:rgba(255,255,255,.18)}
  .cart-handle.empty .cart-handle-total{opacity:.55;font-weight:500}

  /* The grid ends above the bar. Without this the last row of products sits
     underneath it and cannot be tapped, which is the classic bottom-bar bug. */
  .poscol{padding-bottom:78px}

  .cart{
    position:fixed;inset-inline:0;bottom:var(--kb);z-index:var(--z-sheet);
    /* Shorter as well as lifted: a sheet that only rises pushes its own top off the screen. */
    max-height:min(78vh,640px);
    border-inline-start:0;border-top:1px solid var(--line);
    border-radius:16px 16px 0 0;
    transform:translateY(101%);transition:transform .22s ease;
    box-shadow:0 -10px 40px rgba(20,33,61,.22);
    overflow:hidden}
  .cart.open{transform:translateY(0)}

  /* The grab bar. Expanded, the handle is underneath the sheet, so this is the way
     back — and it is the affordance people already reach for on a bottom sheet. */
  .cart-grab{display:flex;align-items:center;justify-content:center;
    width:100%;padding:10px 0 6px;background:none;border:0;cursor:pointer}
  .cart-grab span{width:38px;height:4px;border-radius:2px;background:var(--line)}
  .cart-grab:focus-visible{outline:2px solid var(--accent);outline-offset:-4px;border-radius:8px}
  /* The lines scroll; the totals and payment buttons stay in view, because
     scrolling to find Pay is the last thing anyone wants at a counter. */
  .cart .lines{overflow-y:auto;-webkit-overflow-scrolling:touch}
  .cart .tot{padding-bottom:calc(12px + env(safe-area-inset-bottom,0px))}

  .cart-backdrop{
    display:block;position:fixed;inset:0;z-index:var(--z-sheet-backdrop);
    background:rgba(20,33,61,.35);opacity:0;pointer-events:none;
    transition:opacity .22s}
  .cart-backdrop.open{opacity:1;pointer-events:auto}

  body.cart-open{overflow:hidden}
}

@media (prefers-reduced-motion:reduce){
  .cart,.cart-backdrop,.cart-handle-chev{transition:none}
}

/* ============================================================
   DIALOGS
   ------------------------------------------------------------
   Replacing prompt/confirm/alert, which could not be translated,
   could not lay out right-to-left, blocked the event loop, and
   are suppressed entirely by some embedded webviews — so a POS
   running in one did nothing at all when a cashier tapped
   Refund.
   ============================================================ */
/* A map is a third-party widget with opinions about stacking: Leaflet's panes are 400,
   its controls 800 and its corner containers 1000, all set in its own stylesheet. Those
   numbers were competing with ours — which is why the delivery zone map painted over the
   navigation drawer.

   `isolation:isolate` gives the map its own stacking context, so everything Leaflet does
   internally is contained beneath whatever the container itself sits at. It stops being a
   contest, and the fix does not depend on our numbers being bigger than a library's. */
.leaflet-container{isolation:isolate;position:relative;z-index:var(--z-base)}

/* The dialog rules moved to `design/dialog.css` in 5.24 — see the note there. `app.css` kept
   them while only this shell used them, and the platform console proved that was never true. */


/* Money must not be reordered by the bidi algorithm — see the note in shop.css.
   "12.00 - 15.00 SAR" renders as "SAR 15.00 - 12.00" in an Arabic page without this,
   which reverses a price range rather than merely moving the currency code. */
/* Both properties, always: an isolate inherits its base direction, so isolation alone
   leaves the neutral space between the number and the currency code resolving RTL. */
.price, .pill, .money, .amount, .cart-handle-total,
.tot .row span:last-child, .grand span:last-child{
  unicode-bidi:isolate; direction:ltr;
}

/* Ask Orvia (3.72.0): an answer keeps the line breaks the model wrote. */
.ai-answer{white-space:pre-wrap;margin-top:8px}
  /* The cart's own actions, side by side: park, what is parked, and clear. */
  .cart-acts{display:flex;gap:var(--sp-2)}
  .cart-acts .clear{flex:1 1 0}
/* 9.9: workplaces on one phone — which one this is, and adding another. */
.emp-wpbar{display:flex;gap:var(--sp-2);align-items:center;justify-content:flex-end;padding:var(--sp-2) var(--sp-3)}
.emp-wpbar select{min-height:40px;border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--surface);color:var(--text);padding-inline:var(--sp-2)}
.emp-link{background:none;border:0;color:var(--brand-strong);font-weight:600;min-height:40px;cursor:pointer}

/* ---- 11.02.0 (POS-1): booking from the till — the panels, the holds in the basket, the embedded mode ----
   Touch first: every target is at least --control-lg (48px) high, slots are a grid a thumb can hit, the day strip
   scrolls sideways. Logical sides only, so the sheet mirrors in Arabic; times are isolated LTR runs (<bdi dir=ltr>). */
.bk-entry{border-style:solid;color:var(--text);min-height:var(--control-lg)}
.bk-entry .bk-chev{margin-inline-start:auto;opacity:.6}
html[dir="rtl"] .bk-chev{display:inline-block;transform:scaleX(-1)}
.cat.bk-cat{background:var(--accent-subtle);color:var(--text);border:1px solid var(--accent)}
.bk-modal .bk-sheet{max-width:var(--dialog-lg);width:100%;display:flex;flex-direction:column;gap:var(--sp-3)}
.bk-head{display:flex;align-items:center;gap:var(--sp-2)}
.bk-head h2{flex:1;margin:0;font-size:var(--fs-section);overflow:hidden;text-overflow:ellipsis}
.bk-icon{min-width:var(--control-lg);min-height:var(--control-lg);border:1px solid var(--line);border-radius:var(--radius-md);
  background:var(--panel);color:var(--text);font-size:var(--fs-section);cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
.bk-icon:disabled{opacity:.4;cursor:default}
.bk-sub,.bk-hint{margin:0;font-size:var(--fs-small)}
.bk-msg{padding:var(--sp-4) 0;margin:0}
.bk-lbl{font-size:var(--fs-caption);color:var(--muted);font-weight:var(--fw-semibold)}
.bk-list{display:grid;gap:var(--sp-2)}
.bk-big{min-height:var(--row-touch);display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);text-align:start;
  padding:var(--sp-3) var(--sp-4);border:1px solid var(--line);border-radius:var(--radius-md);background:var(--panel);color:var(--text);cursor:pointer}
.bk-big:hover,.bk-big:focus-visible{border-color:var(--accent)}
.bk-big-t{font-weight:var(--fw-semibold);font-size:var(--fs-body)}
.bk-big-s{color:var(--muted);font-size:var(--fs-small)}
.bk-days{display:flex;gap:var(--sp-2);overflow-x:auto;padding-bottom:var(--sp-1);scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch}
.bk-day{flex:0 0 auto;min-width:var(--row-touch);min-height:var(--row-touch);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--sp-1);
  padding:var(--sp-2) var(--sp-3);border:1px solid var(--line);border-radius:var(--radius-md);background:var(--panel);color:var(--text);cursor:pointer;scroll-snap-align:start}
.bk-day.on{background:var(--accent);border-color:var(--accent);color:var(--on-brand)}
.bk-dw{font-size:var(--fs-caption);font-weight:var(--fw-semibold)}
.bk-dn{font-size:var(--fs-small)}
.bk-chips{display:flex;flex-wrap:wrap;gap:var(--sp-2)}
.bk-chip{min-height:var(--control-lg);padding:0 var(--sp-4);border:1px solid var(--line);border-radius:var(--radius-pill);background:var(--panel);color:var(--text);cursor:pointer}
.bk-chip.on{background:var(--accent);border-color:var(--accent);color:var(--on-brand)}
.bk-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(88px,1fr));gap:var(--sp-2)}
.bk-slot{min-height:var(--row-touch);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--sp-1);
  border:1px solid var(--line);border-radius:var(--radius-md);background:var(--panel);color:var(--text);cursor:pointer;font-variant-numeric:tabular-nums}
.bk-slot .bk-t{font-weight:var(--fw-bold);font-size:var(--fs-body)}
.bk-slot .bk-s{font-size:var(--fs-caption);color:var(--muted)}
.bk-slot.free{border-color:var(--success)}
.bk-slot.taken,.bk-slot.blocked{background:var(--surface-2);color:var(--text-disabled);cursor:not-allowed}
.bk-slot.mine{background:var(--accent-subtle);border-style:dashed;border-color:var(--accent);cursor:not-allowed}
.bk-slot.held{background:var(--surface-2);border-style:dashed;border-color:var(--warning);color:var(--text-muted);cursor:not-allowed}
.bk-slot.blocked .bk-t{text-decoration:line-through}
.bk-slot.sel{background:var(--accent);border-color:var(--accent);color:var(--on-brand)}
.bk-slot.sel .bk-s{color:var(--on-brand)}
.bk-slot:disabled{opacity:1}
.bk-acts{position:sticky;bottom:0;z-index:var(--z-sticky);background:var(--panel);display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2);padding-top:var(--sp-2)}
.bk-acts .btn{flex:1 1 12rem;min-height:var(--control-lg)}
.bk-when{flex:1 1 100%;font-weight:var(--fw-semibold);font-size:var(--fs-small);unicode-bidi:plaintext}
.bk-sum{padding:var(--sp-3);border-radius:var(--radius-md);background:var(--surface-2);font-weight:var(--fw-semibold)}
.bk-step{display:inline-flex;align-items:center;gap:var(--sp-3)}
.bk-n{min-width:var(--control-md);text-align:center;font-size:var(--fs-section);font-weight:var(--fw-bold);font-variant-numeric:tabular-nums}
.bk-cust{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2)}
.bk-cust-n{flex:1 1 auto;font-weight:var(--fw-semibold)}
.bk-badge{font-size:var(--fs-caption);padding:var(--sp-1) var(--sp-2);border-radius:var(--radius-pill);background:var(--surface-2)}
.bk-badge.on{background:var(--accent-subtle);color:var(--text)}
.bk-badge.bad{color:var(--danger-text);background:var(--surface-2)}
.bk-guest{display:grid;grid-template-columns:1fr 1fr auto;gap:var(--sp-2);margin-bottom:var(--sp-2)}
.bk-guest .field{margin:0;min-height:var(--control-lg)}
.bk-quote{display:flex;justify-content:space-between;align-items:center;gap:var(--sp-3);padding:var(--sp-3);border:1px solid var(--line);border-radius:var(--radius-md)}
.bk-amt{font-weight:var(--fw-bold);font-size:var(--fs-section);unicode-bidi:isolate;direction:ltr}
.bk-err:empty{display:none}
@media (max-width:520px){
  .bk-modal{align-items:flex-end;padding:0}
  .bk-modal .bk-sheet{max-width:none;border-end-start-radius:0;border-end-end-radius:0;max-height:calc(var(--vvh, 100vh) - var(--sp-6))}
  .bk-guest{grid-template-columns:1fr auto}
  .bk-guest [data-gphone]{grid-column:1}
}
/* A hold in the basket: its line says it is held and for how long; when time runs out it says so and offers to book again. */
.line.hold-line{border-inline-start:3px solid var(--accent);padding-inline-start:var(--sp-2)}
.hold-cd{font-size:var(--fs-caption);color:var(--accent);font-weight:var(--fw-semibold);font-variant-numeric:tabular-nums}
.line.hold-line.expired{border-inline-start-color:var(--danger)}
.line.hold-line.expired .nm,.line.hold-line.expired .mt{opacity:.55}
.line.hold-line.expired .hold-cd{color:var(--danger-text)}
.bk-again{min-height:var(--control-md);padding:0 var(--sp-3);border:1px solid var(--accent);border-radius:var(--radius-md);background:var(--panel);color:var(--accent);font-weight:var(--fw-semibold);cursor:pointer}
/* Embedded in the Windows till: only the panel, the whole window. */
body.pos-embed{background:var(--bg)}
.bk-embed{position:fixed;inset:0;z-index:var(--z-base);overflow:auto;background:var(--bg);padding:var(--sp-4)}
.bk-embed .bk-sheet{max-width:var(--width-form-wide);margin:0 auto;display:flex;flex-direction:column;gap:var(--sp-3)}
/* 11.03.0 (POS-2): cinema, admissions, memberships, passes and packages in the same panel. Touch-sized, logical sides only. */
.bk-big.on{border-color:var(--accent);background:var(--accent-subtle)}
.pn-big-b{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}
.bk-big .bk-amt{flex:0 0 auto;font-size:var(--fs-body)}
.pn-screen{margin:0 var(--sp-6);padding:var(--sp-1) 0;text-align:center;font-size:var(--fs-caption);color:var(--muted);border-top:3px solid var(--line);border-radius:var(--radius-md) var(--radius-md) 0 0}
.pn-seatmap{display:flex;flex-direction:column;gap:var(--sp-1);overflow-x:auto;padding-bottom:var(--sp-1);-webkit-overflow-scrolling:touch}
.pn-row{display:flex;align-items:center;gap:var(--sp-1);margin:0 auto}
.pn-rl{flex:0 0 auto;min-width:1.5rem;text-align:center;font-size:var(--fs-caption);font-weight:var(--fw-semibold);color:var(--muted)}
.pn-seat{flex:0 0 auto;width:var(--control-md);height:var(--control-md);display:inline-flex;align-items:center;justify-content:center;padding:0;
  border:1px solid var(--success);border-radius:var(--radius-sm);background:var(--panel);color:var(--text);font-size:var(--fs-caption);font-variant-numeric:tabular-nums;cursor:pointer}
.pn-seat.held{background:var(--surface-2);border-style:dashed;border-color:var(--warning);color:var(--text-muted);cursor:not-allowed}
.pn-seat.sold{background:var(--surface-2);border-color:var(--line);color:var(--text-disabled);cursor:not-allowed}
.pn-seat.k-wheelchair,.pn-seat.k-companion{border-width:2px;border-color:var(--info)}
.pn-seat.k-premium{border-width:2px}
.pn-seat.sel{background:var(--accent);border-color:var(--accent);color:var(--on-brand)}
.pn-seat:disabled{opacity:1}
.pn-legend{display:flex;flex-wrap:wrap;gap:var(--sp-3);font-size:var(--fs-caption);color:var(--muted)}
.pn-legend span{display:inline-flex;align-items:center;gap:var(--sp-1)}
.pn-legend .pn-seat{width:1rem;height:1rem;cursor:default}
.pn-tts{display:flex;flex-direction:column;gap:var(--sp-2)}
.pn-tt{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-2) 0;border-bottom:1px solid var(--line)}
.pn-tt-n{flex:1 1 auto;font-weight:var(--fw-semibold);min-width:0}
.pn-note{padding:var(--sp-2) 0;color:var(--text-muted)}
.pn-holder{margin:0;min-height:var(--control-lg)}
.pn-tickets .pn-slip{padding:var(--sp-2) 0}
.pn-tickets .pn-code{font-weight:var(--fw-bold);letter-spacing:.05em}
.rm.rc{opacity:.8}

/* 11.02.0: the basket's seat chooser — one scrolling row of chips (9.62.0 put it in a column of unstyled buttons). */
.seat-bar{display:flex;align-items:center;gap:var(--sp-1);overflow-x:auto;padding:var(--sp-1) var(--sp-2);border-bottom:1px solid var(--line)}
.seat-bar .tog{flex:0 0 auto;min-width:var(--row-touch);border:1px solid var(--line);background:var(--panel);color:var(--text);border-radius:var(--radius-pill);padding:var(--sp-1) var(--sp-2);font-size:var(--fs-small);cursor:pointer}
.seat-bar .tog.on{background:var(--accent);border-color:var(--accent);color:var(--on-brand)}
/* 11.32.0 (T1): the table a basket's bill is at, and the floor. A free table plain; a busy one its bill, its guests, its
   minutes; waiting at the table (amber) or open on a till (blue); this basket's own outlined. */
.table-bar{display:flex;align-items:center;gap:var(--sp-1);flex-wrap:wrap;padding:var(--sp-1) var(--sp-2);border-bottom:1px solid var(--line);background:var(--panel)}
.table-bar__name{font-weight:600;margin-inline-end:auto}
.table-bar .tog{border:1px solid var(--line);background:var(--panel);color:var(--text);border-radius:var(--radius-pill);padding:var(--sp-1) var(--sp-2);font-size:var(--fs-small);cursor:pointer;min-height:var(--row-touch)}
.floor-sheet{max-width:min(920px,96vw)}
.fsec{margin:var(--sp-3) 0 var(--sp-1)}
.floor{display:grid;grid-template-columns:repeat(auto-fill,minmax(130px,1fr));gap:var(--sp-2)}
.ftile{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-height:96px;padding:var(--sp-2);border:1px solid var(--line);border-radius:var(--radius-md);background:var(--panel);color:var(--text);cursor:pointer;text-align:start;font-size:var(--fs-small)}
.ftile b{font-size:var(--fs-body)}
.ftile:disabled{opacity:.45;cursor:not-allowed}
.ftile--free .ftile__free{color:var(--good)}
.ftile--waiting{border-color:var(--warning);border-inline-start-width:4px}
.ftile--busy{border-color:var(--accent);border-inline-start-width:4px}
.ftile--mine{outline:2px solid var(--accent);outline-offset:2px}

/* 11.02.0: a hidden button stays hidden — .btn set display and overrode the attribute, so the member-account and advance
   tenders showed as blank buttons at every till. */
.btn[hidden],.cust-row[hidden]{display:none}

/* 11.04.0 (POS-3): the front desk, parking, laundry, rentals and gift-card panels — the POS-1/POS-2 sheet (.bk-*), with
   cards for a stay, a car, a ticket or a rental, and short forms. Logical properties only; touch-sized controls. */
.p3-in{margin:0;min-height:var(--control-lg);width:100%;box-sizing:border-box}
.p3-search{display:flex;gap:var(--sp-2);align-items:stretch}
.p3-search .p3-in{flex:1 1 auto;min-width:0;margin:0}
.p3-search .btn{flex:0 0 auto;width:auto;min-height:var(--control-lg)}   /* 11.04.0: .btn is full width by default */
.p3-two{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-2)}
.p3-two>div{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}
.p3-card{display:flex;flex-direction:column;gap:var(--sp-2);padding:var(--sp-3);border:1px solid var(--line);border-radius:var(--radius-md);background:var(--panel)}
.p3-card-h{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2)}
.p3-who{font-weight:var(--fw-medium)}
.p3-money{display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-4);font-size:var(--fs-small);color:var(--text-secondary)}
.p3-acts{display:flex;flex-wrap:wrap;gap:var(--sp-2)}
.p3-acts .btn{flex:1 1 10rem;min-height:var(--control-lg)}
.p3-row{display:flex;justify-content:space-between;align-items:baseline;gap:var(--sp-3);padding:var(--sp-1) 0;border-bottom:1px solid var(--line);font-size:var(--fs-small)}
.p3-row:last-child{border-bottom:0}
.p3-row>span:last-child{text-align:end;font-variant-numeric:tabular-nums}
.p3-note{margin:0;padding:var(--sp-2) var(--sp-3);border-radius:var(--radius-md);background:var(--accent-subtle);color:var(--text);font-size:var(--fs-small)}
.p3-note:empty{display:none}
.p3-result{display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-3);border:1px solid var(--success);border-radius:var(--radius-md);background:var(--surface-2)}
.p3-form{display:flex;flex-direction:column;gap:var(--sp-2);padding-block-start:var(--sp-2);border-top:1px dashed var(--line)}
.p3-form .btn{min-height:var(--control-lg)}
.p3-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(10rem,1fr));gap:var(--sp-2)}
.p3-svc{flex-direction:column;align-items:flex-start;justify-content:center}
.p3-items{display:flex;flex-direction:column;gap:var(--sp-2)}
.p3-item{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.2fr) auto;align-items:center;gap:var(--sp-2)}
.p3-item-n{font-weight:var(--fw-semibold);overflow:hidden;text-overflow:ellipsis}
.p3-slips{max-height:18rem;overflow:auto;padding:var(--sp-2);border:1px dashed var(--line);border-radius:var(--radius-md);background:var(--surface-2)}
.p3-slips .pn-slip{padding:var(--sp-2) 0;text-align:center}
.p3-slips .rq svg{width:7rem;height:7rem}
.p3-dep{display:flex;flex-direction:column;gap:var(--sp-3)}
.bk-big:disabled{opacity:.55;cursor:not-allowed}
@media (max-width:520px){
  .p3-two{grid-template-columns:1fr}
  .p3-item{grid-template-columns:minmax(0,1fr) auto}
  .p3-item .p3-in{grid-column:1 / -1;grid-row:2}
}

/* 11.07.0: the Demo / QA badge in the header of a demo or QA business (app.js sandboxBadge) — admin and till alike.
   Amber for a demo, blue for QA; never red or green, which the till uses for money states. */
.sandbox-badge{display:inline-flex;align-items:center;margin-inline-start:var(--sp-2);padding:2px var(--sp-2);
  border-radius:var(--radius-pill);font:var(--type-caption);font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  background:var(--warning);color:var(--on-warning);white-space:nowrap}
.sandbox-badge[data-kind="qa"]{background:var(--info);color:var(--on-brand)}
/* 11.22.0 (DS1): a test, development or training business — a scrambled copy or a non-production business. The brand
   colour, so it is never taken for a demo's amber or QA's blue; striped, so it is seen at a glance on every screen. */
.sandbox-badge[data-kind^="env-"]{background:repeating-linear-gradient(135deg,var(--brand) 0 8px,color-mix(in srgb,var(--brand) 80%,var(--surface)) 8px 16px);color:var(--on-brand)}

/* 11.08.0: THE CONFIGURATION GUIDE (admin/config.js) — the area tree beside the activity list, the activity panel, the
   change log, consultant access and integration monitoring. Tokens only; every direction is logical, so Arabic mirrors. */
.cfg-ws .o-grid tbody td{white-space:normal;max-width:none;height:auto;padding-block:var(--sp-2);vertical-align:middle}
.cfg-ws .o-grid tbody td .o-grid__sub{white-space:normal}
.cfg-ws--guide .o-page{display:grid;grid-template-columns:minmax(200px,264px) minmax(0,1fr);grid-template-rows:auto auto auto auto 1fr;column-gap:var(--sp-4);align-items:start}
.cfg-ws--guide .o-wshead{grid-column:1 / -1}
.cfg-ws--guide .o-wsnotice{display:contents}
.cfg-ws--guide .cfg-tree{grid-column:1;grid-row:2 / 6}   /* the list's row takes what the tree's height leaves over */
.cfg-ws--guide .cfg-areahead{grid-column:2;grid-row:2}
.cfg-ws--guide .cfg-areahead__note{grid-column:2;grid-row:3;margin-block-end:var(--sp-3)}
.cfg-ws--guide #wsBulk{grid-column:2;grid-row:4}
.cfg-ws--guide #wsGrid{grid-column:2;grid-row:5;min-inline-size:0}
.cfg-tree{display:grid;gap:2px;align-content:start;padding:var(--sp-2);border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface)}
.cfg-tree__head{padding:var(--sp-2) var(--sp-3) var(--sp-1);font:var(--type-label);font-weight:var(--fw-semibold);letter-spacing:.04em;text-transform:uppercase;color:var(--text-muted)}
.cfg-tree__item{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:var(--sp-1) var(--sp-2);padding:var(--sp-2) var(--sp-3);
  border-radius:var(--radius-md);color:var(--text-secondary);font:var(--type-small);text-decoration:none}
.cfg-tree__item:hover{background:var(--surface-subtle);color:var(--text)}
.cfg-tree__item[aria-current="page"]{background:var(--accent-subtle);color:var(--text);font:var(--type-body-strong)}
.cfg-tree__name{min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cfg-tree__count{display:inline-flex;align-items:center;gap:var(--sp-1);font:var(--type-caption);color:var(--text-muted);font-variant-numeric:var(--num-figures)}
.cfg-tree__dot{inline-size:var(--sp-2);block-size:var(--sp-2);border-radius:var(--radius-pill);background:var(--warning)}
.cfg-tree__bar{grid-column:1 / -1;block-size:3px;border-radius:var(--radius-pill);background:var(--border);overflow:hidden}
.cfg-tree__bar i{display:block;block-size:100%;background:var(--success)}
.cfg-areahead{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--sp-2) var(--sp-4);margin:0 0 var(--sp-3);color:var(--text)}
.cfg-areahead__title{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--sp-1) var(--sp-3)}
.cfg-areahead h2{margin:0;font:var(--type-section)}
.cfg-areahead__title span{font:var(--type-caption);color:var(--text-muted)}
.cfg-scope{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2)}
.cfg-scope__label{font:var(--type-caption);color:var(--text-muted)}
/* The level being looked at, and a setting's value being set, are the choice on the page: solid, not a tint the changed row
   shares (7.68's rule for the settings screen's level chips). */
.cfg-scope .o-segmented > button[aria-pressed="true"],.cfg-set .o-segmented > button[aria-pressed="true"]{background:var(--brand);color:var(--on-brand)}
.cfg-ws--guide .o-grid thead th:first-child{inline-size:30%}
.cfg-ws--ops .o-grid thead th:first-child{inline-size:20%}
.cfg-note{padding:var(--sp-2) var(--sp-3);border:1px solid var(--border);border-inline-start:3px solid var(--warning);border-radius:var(--radius-md);
  background:var(--surface-subtle);color:var(--text);font:var(--type-small)}
.cfg-note--info{border-inline-start-color:var(--brand)}
.cfg-ws .o-wsnotice > .cfg-note{margin-block-end:var(--sp-3)}
.cfg-badge{display:inline-block;padding:0 var(--sp-2);margin-inline-start:var(--sp-1);border:1px solid var(--brand);border-radius:var(--radius-pill);
  color:var(--brand-strong);font:var(--type-caption);white-space:nowrap}
.cfg-badge--warn{border-color:var(--warning);color:var(--text)}
.cfg-badge--header{align-self:center;margin-inline-end:var(--sp-2)}
.cfg-badge[hidden]{display:none}
.cfg-hit{color:var(--brand-strong)}
.cfg-desc{margin:0;font:var(--type-small);color:var(--text-secondary)}
.cfg-doc{font:var(--type-small);color:var(--text-secondary)}
.cfg-doc > summary{cursor:pointer;color:var(--brand-strong)}
.cfg-doc > p{margin:var(--sp-1) 0 0}
.cfg-sets{display:grid;gap:var(--sp-2)}
.cfg-sets .strow{margin:0}
.cfg-set .sact{flex-wrap:wrap;justify-content:flex-end}
.cfg-set .sact .o-input,.cfg-set .sact .o-select{inline-size:auto;min-inline-size:10ch;max-inline-size:22ch}
.cfg-set--changed{border-color:var(--brand);background:var(--accent-subtle)}
.cfg-hist{display:grid;gap:var(--sp-1);margin:var(--sp-2) 0 0;padding:0;list-style:none}
.cfg-hist li{display:flex;flex-wrap:wrap;justify-content:space-between;gap:var(--sp-1) var(--sp-3);padding-block:var(--sp-1);border-block-end:1px solid var(--border)}
.cfg-why{inline-size:100%;min-block-size:64px;box-sizing:border-box}
.cfg-filters{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--sp-2) var(--sp-3);margin-block-end:var(--sp-2)}
.cfg-filters .o-field{flex:1 1 9rem;min-inline-size:9rem;margin:0}
.cfg-pre{max-block-size:18rem;overflow:auto;margin:var(--sp-2) 0 0;padding:var(--sp-2);border-radius:var(--radius-md);background:var(--surface-subtle);font:var(--type-caption)}
.cfg-losses{display:grid;gap:var(--sp-2);margin-block-end:var(--sp-3)}
.cfg-losses ul{display:grid;gap:var(--sp-1);margin:0;padding:0;list-style:none}
.cfg-losses li{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--sp-2)}
.cfg-losses > .o-btn{justify-self:start}
.cfg-wrap{white-space:normal}
.cfg-fieldset{margin:var(--sp-2) 0 0;padding:0;border:0;display:grid;gap:var(--sp-2)}
.cfg-legend{padding:0;font:var(--type-label);font-weight:var(--fw-semibold);color:var(--text)}
.cfg-areas{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp-1) var(--sp-4);padding:var(--sp-3);border:1px solid var(--border);border-radius:var(--radius-md)}
.cfg-groups{margin-block-start:var(--sp-3)}
#cgSum[hidden],#cgDateBox[hidden]{display:none}
@media (max-width:900px){
  /* The consultant badge stays in a phone's header: it gives way to the menu and the pickers, and ends in an ellipsis
     rather than pushing the page wider than the screen. */
  .cfg-badge--header{flex:0 1 auto;min-inline-size:0;max-inline-size:40vw;overflow:hidden;text-overflow:ellipsis;margin-inline-end:0}
  .cfg-scope .o-segmented{flex-wrap:wrap}
  .cfg-ws--guide .o-page{display:block}
  .cfg-tree{display:flex;gap:var(--sp-2);overflow-x:auto;margin-block-end:var(--sp-3)}
  .cfg-tree__head{display:none}
  .cfg-tree__item{flex:0 0 auto;min-inline-size:11rem}
  .cfg-areas{grid-template-columns:minmax(0,1fr)}
}
/* 11.08.0 (security review): a key that cannot be changed here says why, under it. */
.cfg-set--locked{background:var(--surface-subtle)}
.cfg-locked{margin-block-start:var(--sp-1);font:var(--type-caption);color:var(--text-secondary)}
.cfg-set--locked .sact .o-icon{color:var(--text-muted)}
.cfg-lost{display:block;font:var(--type-caption);color:var(--text-secondary)}

/* 11.09.0: GUIDED CONFIGURATION — Configuration › Quick start (admin/guided.js): the ways in, the wizard with its progress,
   the plan grouped by area, the result. Touch-sized controls, tokens only, every direction logical so Arabic mirrors. */
.cfg-badge--guided{border-color:var(--success);color:var(--success-text)}
.cfg-ws--guide .cfg-qs{grid-column:2;grid-row:3;margin-block-end:var(--sp-3)}
.cfg-qs{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-3) var(--sp-4);
  border:1px solid var(--border);border-inline-start:3px solid var(--brand);border-radius:var(--radius-lg);background:var(--surface)}
.cfg-qs__text{flex:1 1 18rem;min-inline-size:0}
.cfg-qs__text h3{margin:0;font:var(--type-card)}
.cfg-qs__text p{margin:var(--sp-1) 0 0;font:var(--type-small);color:var(--text-secondary)}
.cfg-qs__actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2)}
.gd-ws{display:grid;gap:var(--sp-4);min-inline-size:0}
/* 11.43.0 (DW4, measured): a grid item's minimum is its content — the setup guide's change list (a table wider than a phone)
   stretched its item to 610 px inside a 358 px column, so the page scrolled sideways (in Arabic, off the start). The item
   may now be as narrow as its column; the list scrolls in its own frame, as lists do everywhere else. */
.gd-ws>*{min-inline-size:0}
.gd-ways{display:grid;grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));gap:var(--sp-3);margin-block-end:var(--sp-2)}
.gd-way{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:var(--sp-2) var(--sp-3);padding:var(--sp-3) var(--sp-4);
  border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface)}
.gd-way > .o-icon{color:var(--brand-strong)}
.gd-way > .o-btn{grid-column:1 / -1;justify-self:start;min-block-size:var(--control-lg)}
.gd-way--main{border-color:var(--brand);background:var(--accent-subtle)}
.gd-way__text{display:grid;gap:var(--sp-1)}
.gd-way__text b{font:var(--type-body-strong)}
.gd-way__text span{font:var(--type-small);color:var(--text-secondary)}
.gd-src{display:inline-block;padding:0 var(--sp-2);border:1px solid var(--border);border-radius:var(--radius-pill);font:var(--type-caption);
  color:var(--text-secondary);background:var(--surface-subtle);white-space:nowrap}
.gd-src--answer{border-color:var(--brand);color:var(--brand-strong)}
.gd-src--country,.gd-src--industry{border-color:var(--info);color:var(--info-text)}
.gd-src--existing{color:var(--text-muted)}
.gd-progress{display:flex;gap:var(--sp-1);margin:0;padding:0;list-style:none;overflow-x:auto}
.gd-progress__step{flex:1 1 0;min-inline-size:6.5rem;display:grid;justify-items:center;gap:var(--sp-1);padding:var(--sp-2) var(--sp-1);
  border-block-end:3px solid var(--border);color:var(--text-muted);font:var(--type-caption);text-align:center}
.gd-progress__n{display:inline-grid;place-items:center;inline-size:var(--control-sm);block-size:var(--control-sm);border-radius:var(--radius-pill);
  border:1px solid var(--border-strong);font-variant-numeric:var(--num-figures)}
.gd-progress__step--done{border-block-end-color:var(--success);color:var(--text-secondary)}
.gd-progress__step--done .gd-progress__n{background:var(--success);border-color:var(--success);color:var(--on-success)}
.gd-progress__step[aria-current="step"]{border-block-end-color:var(--brand);color:var(--text);font:var(--type-label);font-weight:var(--fw-semibold)}
.gd-progress__step[aria-current="step"] .gd-progress__n{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}
.gd-step{display:grid;gap:var(--sp-3)}
.gd-step__title{margin:0;font:var(--type-section)}
.gd-step__body{display:grid;gap:var(--sp-3)}
.gd-card{padding:var(--sp-3) var(--sp-4);border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface)}
.gd-card__head{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2)}
.gd-card__head h3,.gd-card__head h4{margin:0;font:var(--type-card)}
.gd-card__head h4{font:var(--type-body-strong)}
.gd-card__head > .o-btn{margin-inline-start:auto}
.gd-sub{padding:var(--sp-3);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface-subtle)}
.gd-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(14rem,1fr));align-items:start;gap:var(--sp-3) var(--sp-4)}
.gd-grid > .o-field,.gd-bank > .o-field{margin:0}
.gd-ws .o-input,.gd-ws .o-select{min-block-size:var(--control-lg)}
.gd-fixed{padding:var(--sp-2) 0;font:var(--type-body-strong)}
.gd-choices{display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-4)}
.gd-ws .o-check{min-block-size:var(--control-md);align-items:center}
.gd-hours{display:grid;gap:var(--sp-2)}
.gd-hours__day{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2) var(--sp-3)}
.gd-hours__day .o-input{inline-size:auto;min-inline-size:8rem}
.gd-hours__name{inline-size:6rem;font:var(--type-body-strong)}
.gd-hours__err{flex-basis:100%}
.gd-hours > .o-btn{justify-self:start}
.gd-chosen{display:flex;flex-wrap:wrap;gap:var(--sp-2)}
.gd-pick{display:inline-flex;align-items:center;gap:var(--sp-1);padding:var(--sp-1) var(--sp-3);border:1px solid var(--brand);border-radius:var(--radius-pill);
  background:var(--accent-subtle);font:var(--type-small)}
.gd-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(12rem,1fr));gap:var(--sp-2)}
.gd-tile{display:flex;align-items:center;gap:var(--sp-2);min-block-size:var(--control-lg);padding:var(--sp-2) var(--sp-3);border:1px solid var(--border);
  border-radius:var(--radius-md);background:var(--surface);cursor:pointer;font:var(--type-small)}
.gd-tile:hover{background:var(--surface-subtle)}
.gd-tile--on{border-color:var(--brand);background:var(--accent-subtle)}
.gd-tile__name{flex:1 1 auto;min-inline-size:0}
.gd-mods{display:grid;gap:var(--sp-1);margin:0;padding:0;list-style:none}
.gd-mod{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2);min-block-size:var(--control-md);padding-block:var(--sp-1);border-block-end:1px solid var(--border)}
.gd-mod__name{font:var(--type-body)}
.gd-bank{display:grid;grid-template-columns:repeat(auto-fit,minmax(14rem,1fr));align-items:end;gap:var(--sp-2) var(--sp-3);padding:var(--sp-3);
  border:1px solid var(--border);border-radius:var(--radius-md)}
.gd-bank > .o-field-error{grid-column:1 / -1}
.gd-bank > .o-btn{justify-self:start}
.gd-presets{display:grid;grid-template-columns:repeat(auto-fit,minmax(16rem,1fr));gap:var(--sp-3)}
.gd-preset{display:flex;align-items:flex-start;gap:var(--sp-3);padding:var(--sp-3) var(--sp-4);border:1px solid var(--border);border-radius:var(--radius-lg);
  background:var(--surface);cursor:pointer}
.gd-preset input{margin-block-start:var(--sp-1);inline-size:var(--icon-sm);block-size:var(--icon-sm)}
.gd-preset--on{border-color:var(--brand);background:var(--accent-subtle)}
.gd-preset__body{display:grid;gap:var(--sp-2);min-inline-size:0}
.gd-switches{display:grid;gap:var(--sp-1);margin:0;padding:0;list-style:none;font:var(--type-small)}
.gd-switches li{display:flex;justify-content:space-between;gap:var(--sp-3);padding-block:var(--sp-1);border-block-end:1px solid var(--border)}
.gd-nav{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--sp-3);padding-block:var(--sp-3);border-block-start:1px solid var(--border)}
.gd-nav .o-btn{min-block-size:var(--control-lg);min-inline-size:8rem}
.gd-nav__where{font:var(--type-caption);color:var(--text-muted)}
.gd-review{display:grid;gap:var(--sp-3)}
.gd-review__bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--sp-2)}
.gd-review .o-segmented > button[aria-pressed="true"]{background:var(--brand);color:var(--on-brand)}
.gd-group{display:grid;gap:var(--sp-2)}
.gd-group__title{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--sp-2);margin:0;padding-block-end:var(--sp-1);border-block-end:1px solid var(--border-strong);font:var(--type-card)}
.gd-items{display:grid;gap:var(--sp-2);margin:0;padding:0;list-style:none}
.gd-item{display:grid;gap:var(--sp-1);padding:var(--sp-2) var(--sp-3);border:1px solid var(--border);border-inline-start:3px solid var(--brand);
  border-radius:var(--radius-md);background:var(--surface)}
.gd-item--keep,.gd-item--info,.gd-item--skip{border-inline-start-color:var(--border-strong);background:var(--surface-subtle)}
.gd-item--upgrade{border-inline-start-color:var(--warning)}
.gd-item--ro{background:var(--surface-subtle)}
.gd-item__head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--sp-2)}
.gd-item__what{font:var(--type-body-strong);min-inline-size:0;overflow-wrap:anywhere}
.gd-item__change{font:var(--type-small);color:var(--text);overflow-wrap:anywhere}
.gd-item__change:empty{display:none}
.gd-item__meta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2)}
.gd-fields{display:grid;gap:var(--sp-1);margin:0;padding:0;list-style:none}
.gd-fields li > span:first-child{color:var(--text-secondary)}
.gd-warn{display:flex;align-items:flex-start;gap:var(--sp-2);padding:var(--sp-1) var(--sp-2);border-radius:var(--radius-sm);background:var(--surface-subtle);
  color:var(--warning-text);font:var(--type-small)}
.gd-warn .o-icon{flex:0 0 auto;margin-block-start:2px}
.gd-list{margin:var(--sp-1) 0 0;padding-inline-start:var(--sp-4)}
.gd-apply{padding:var(--sp-3) var(--sp-4);border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface)}
.gd-run{display:grid;gap:var(--sp-2);margin:0;padding:0;list-style:none}
.gd-run__step{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2) var(--sp-3);padding:var(--sp-2) var(--sp-3);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface)}
.gd-run__step > .gd-warn{flex-basis:100%}
.gd-run__name{flex:1 1 10rem;font:var(--type-body-strong)}
.gd-run__step--waiting{background:var(--surface-subtle);color:var(--text-muted)}
@media (max-width:900px){
  .cfg-qs{padding:var(--sp-3)}
  .gd-card{padding:var(--sp-3)}
  .gd-progress__step{min-inline-size:5.5rem}
  .gd-nav{position:sticky;inset-block-end:0;z-index:var(--z-sticky);background:var(--bg);padding-inline:var(--sp-1)}
  .gd-nav .o-btn{flex:1 1 auto}
  .gd-nav__where{flex-basis:100%;order:-1;text-align:center}
  .gd-hours__name{inline-size:100%}
}
/* 11.48.31 (QA-C24): the till lock — covers the till; the shift and the basket stay underneath. */
.till-lock{position:fixed;inset:0;z-index:var(--z-dialog);background:var(--bg);display:flex;align-items:center;justify-content:center;padding:var(--sp-4)}
.till-lock__box{width:100%;max-width:340px;text-align:center}
.till-lock__box h2{margin:0 0 var(--sp-2);font-size:var(--fs-record)}
.till-lock__who{margin:0 0 var(--sp-2);color:var(--muted)}
.till-lock__err{min-height:1.4em;color:var(--danger-text);margin:var(--sp-3) 0 0}
.till-lock__acts{display:flex;justify-content:center;margin-top:var(--sp-3)}

/* 11.64.0: a print that failed, expired or went to the backup printer — at the top of the till until someone looks */
.fh-alert{position:sticky;top:0;z-index:var(--z-drawer);display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:space-between;padding:8px 12px;background:var(--danger);color:var(--on-danger);font-weight:600}
.fh-alert .btn{min-height:36px}
/* 11.72.0 (A11Y-14): pinch-zoom is allowed on the till; a quick double tap on a tile or a button is not a zoom. */
button, .cat, .pcard, .tile, .key, [role="button"] { touch-action: manipulation; }
/* 11.72.0 (A11Y-07): the till's category tiles show where the keyboard is. */
.cat:focus-visible, .pcard:focus-visible { outline: none; box-shadow: var(--focus-ring); }
/* 11.72.0 (A11Y-13, WCAG 1.4.10): on a phone the till's branch takes a row of its own under the bar — it was squeezed to a
   bare chevron and the cashier's name cut off. */
@media (max-width: 600px) {
  .pos-header { flex-wrap: wrap; row-gap: var(--sp-1); }
  .pos-header #branchSel, .pos-header #posStore { order: 20; flex: 1 1 100%; min-width: 0; max-width: none; }
  .pos-header #posWho { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
}

/* 11.72.1 (the till rule; web POS audit) ------------------------------------------------------------------------------ */
/* "This device is not a till" — the only screen an unregistered device shows */
.not-a-till { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: var(--sp-4); background: var(--panel2); }
.not-a-till .nat-card { max-width: 440px; width: 100%; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--sp-6) var(--sp-4); text-align: center; display: flex; flex-direction: column; gap: var(--sp-3); }
.not-a-till .nat-icon { font-size: var(--fs-display); }
.not-a-till h1 { margin: 0; font-size: var(--fs-record); color: var(--text); }
.not-a-till .nat-ask { color: var(--text); font-weight: 600; }
/* what is on hand, on the tile (P1-6); a tile the shelf cannot cover is off where the branch does not sell below zero */
.prod .stk { font-size: var(--fs-small); color: var(--muted); }
.prod .stk.low { color: var(--warning); font-weight: 600; }
.prod .stk.out { color: var(--danger); font-weight: 700; }
.prod.sold-out { opacity: .55; }
/* the online-order bell sits at the reading START, never over the basket's Clear, Park or tenders (P3-2) */
body:has(#posCart) .oo-badge { inset-inline-end: auto; inset-inline-start: 18px; }
/* no seats or tables at a branch that does not seat people (P2-1) */
.till-no-seats #seatBar, .till-no-tables #tablesBtn, .till-no-tables #tblBar { display: none !important; }
/* 1024×768 (an iPad in landscape, a small Mac window): the basket keeps its lines and its buttons on the screen (P3-3) */
@media (min-width: 820px) and (max-height: 820px) {
  .prod { min-height: 112px; }
  .prod .pimg { height: 40px; flex-basis: 40px; }
  .cart > h3 { margin: var(--sp-1) var(--sp-2); }
  .cart > .lines { min-height: 160px; }
  .cart .tot .row { padding-top: 2px; padding-bottom: 2px; }
  .cart .cart-acts .clear { padding-top: var(--sp-1); padding-bottom: var(--sp-1); }
  .seat-bar { padding-top: 2px; padding-bottom: 2px; }
}
