  /* ── VARIABLES ── */
  :root{
    /* RPR RETAIL ERP theme. --brand is the navy bar; --accent is the ACTION
       colour. They were one token before, which is why the header and the
       buttons could not differ. Navy #12233f is the app's existing brand navy
       and the one already printed on the A4 invoice, so screen and paper match. */
    --brand:#12233f;--brand-dk:#0c1a2e;--brand-l:#1b3557;
    --bg:#f6f8f5;--card:#fff;--border:#e4e8e3;--border-strong:#c9d1c8;
    --text:#16233b;--muted:#66756e;--hint:#96a29b;
    --accent:#3e8e32;--accent-l:#eaf5e5;--accent-b:#bfe0b2;--accent-d:#2c6b23;
    --sprout:#6bbe4a;
    /* One colour per shop, assigned once and used in every list, challan and
       receipt. Names blur at speed; colour does not. */
    --b1:#2f6fed;--b2:#e8a317;--b3:#0f8e83;--b4:#b3261e;--b5:#7a4fbf;--b6:#3e8e32;
    --sans:'IBM Plex Sans',-apple-system,"Segoe UI",Roboto,sans-serif;
    --num:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
    --ok:#155724;--ok-bg:#d4edda;--err:#b91c1c;--err-bg:#fef2f2;
    --warn:#856404;--warn-bg:#fff3cd;
    --asm:#7c3aed;--asm-l:#f5f3ff;--asm-b:#ddd6fe;
    --own:#78350f;--own-l:#fffbeb;--own-b:#fde68a;
    --so:#0f766e;--so-l:#f5fdfb;--so-b:#99f0e0;
    --r:10px;--rs:8px;--sh:0 1px 2px rgba(18,35,63,.05),0 6px 20px -14px rgba(18,35,63,.3);
    --header-h:58px;--tabs-h:40px;
  }

  /* ── RESET ── */
  *{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
  html,body{overflow-x:hidden;width:100%;max-width:100vw}
  body{font-family:var(--sans);background:var(--bg);color:var(--text);min-height:100vh;-webkit-font-smoothing:antialiased;
    /* Every digit the same width, so money columns line up with no class on
       each cell and a wrong total looks wrong. */
    font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}
  .money,.num,td.r,th.r{font-family:var(--num);font-variant-numeric:tabular-nums}
  body.text-large{zoom:1.12}
  body.text-xl{zoom:1.28}

  /* ── LOGIN ── */
  #login-screen{display:flex;align-items:center;justify-content:center;min-height:100vh;padding:1rem;background:#eef0f4}
  #loginSplit{display:flex;width:100%;max-width:900px;border-radius:14px;overflow:hidden;background:#fff;box-shadow:0 12px 38px rgba(15,35,63,.15)}
  #loginBrand{flex:0 0 43%;background:#12233f;padding:36px 30px;display:flex;flex-direction:column}
  #loginSplit>#loginCard{flex:1 1 57%;border-radius:0;box-shadow:none;margin:0;max-width:none;width:auto;display:flex;flex-direction:column;justify-content:center;padding:36px 32px}
  @media(max-width:760px){#loginSplit{flex-direction:column;max-width:430px}#loginBrand{flex:none;padding:24px 22px}#loginSplit>#loginCard{padding:24px 22px}}
  .card{background:var(--card);border-radius:8px;padding:24px;max-width:420px;width:100%;box-shadow:0 2px 12px rgba(0,0,0,.1);border:1px solid var(--border)}
  h1{font-size:22px;text-align:center;color:var(--text)}
  .sub{text-align:center;color:var(--muted);font-size:13px;margin:6px 0 20px}
  label{display:block;font-size:11px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;margin:12px 0 5px}
  input,select{width:100%;border:1px solid var(--border);border-radius:4px;padding:10px 12px;font-size:14px;font-family:inherit;color:var(--text);background:#fff;transition:border-color .15s}
  input:focus,select:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-l)}
  .btn{background:var(--accent);color:#fff;border:none;padding:12px;border-radius:4px;font-size:14px;font-weight:700;cursor:pointer;width:100%;margin-top:16px;transition:opacity .15s}
  .btn:disabled{opacity:.6;cursor:default}
  .btn:active{opacity:.85}
  .msg{padding:10px;border-radius:4px;font-size:13px;font-weight:600;margin-top:12px}
  .error{background:var(--err-bg);color:var(--err)}
  .warn{background:var(--warn-bg);color:var(--warn)}
  .ok{background:var(--ok-bg);color:var(--ok)}

  /* ── APP SHELL ── */
  #app-shell{display:none;min-height:100vh}

  /* ── TOP HEADER — fixed, Veeva style ── */
  .app-header{
    background:var(--brand);
    position:fixed;
    top:0;left:0;right:0;
    z-index:500;
    height:var(--header-h);
    box-shadow:0 2px 6px rgba(0,0,0,.15);
    display:flex;
    flex-direction:column;
    justify-content:center;
  }
  .app-header .top-row{
    display:flex;align-items:center;
    padding:0 12px;gap:8px;
    height:100%;
  }
  .app-header .co-name{
    font-size:9px;font-weight:700;
    color:rgba(255,255,255,.75);
    letter-spacing:.5px;text-transform:uppercase;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  }
  .app-header .role-line{display:flex;align-items:center;gap:6px;margin-top:2px}
  .app-header .sub2{font-size:13px;font-weight:700;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .app-header #headerMeta{font-size:8px;color:rgba(255,255,255,.6);margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .role-badge{font-size:8px;font-weight:700;letter-spacing:.4px;padding:2px 7px;border-radius:3px;text-transform:uppercase;background:rgba(255,255,255,.2);color:#fff;flex-shrink:0}

  /* Header icon buttons */
  .icon-btn{background:rgba(255,255,255,.15);border:none;border-radius:4px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;color:#fff;cursor:pointer;font-size:15px;flex-shrink:0;transition:background .15s;position:relative}
  .icon-btn:active{background:rgba(255,255,255,.3)}

  /* ── STATS STRIP — below header ── */
  #statsStrip{
    background:var(--brand-dk);
    position:fixed;
    top:var(--header-h);left:0;right:0;
    z-index:499;
    display:none;
    flex-direction:row;
    border-top:1px solid rgba(255,255,255,.1);
    height:28px;
  }
  .stat-item{
    flex:1;padding:3px 4px;
    text-align:center;
    border-right:1px solid rgba(255,255,255,.12);
    cursor:pointer;
    min-width:0;
    overflow:hidden;
  }
  .stat-item:last-child{border-right:none}
  .stat-item .stat-n{font-size:13px;font-weight:800;color:#fff;line-height:1}
  .stat-item .stat-l{font-size:7px;color:rgba(255,255,255,.65);text-transform:uppercase;letter-spacing:.3px;margin-top:2px}

  /* ── TAB STRIP — fixed below header/stats ── */
  .nav-tabs{
    display:flex;background:#fff;
    border-bottom:2px solid var(--border);
    overflow-x:auto;scrollbar-width:none;
    position:fixed;
    top:calc(var(--header-h) + 28px);left:0;right:0;
    z-index:498;
    height:var(--tabs-h);
    align-items:stretch;
    box-shadow:0 1px 4px rgba(0,0,0,.06);
  }
  .nav-tabs::-webkit-scrollbar{display:none}
  .nav-tabs .t{
    padding:0 14px;
    font-size:11px;font-weight:600;
    color:var(--muted);
    white-space:nowrap;
    display:flex;align-items:center;gap:5px;
    border-bottom:3px solid transparent;
    flex-shrink:0;cursor:pointer;
    text-transform:uppercase;letter-spacing:.4px;
    transition:color .15s;
  }
  .nav-tabs .t.active{
    color:var(--accent);
    border-color:var(--accent);
    background:var(--accent-l);
    font-weight:700;
  }
  .nav-tabs .t i{font-size:13px}

  /* ── TRIAL BANNER ── */
  #trialMsg{display:none!important}

  /* ── BOTTOM NAV — Salesforce pill style ── */
  .bottom-nav{
    position:fixed;left:0;right:0;bottom:0;
    display:flex;background:#fff;
    border-top:1px solid var(--border);
    padding:4px 0;
    padding-bottom:calc(4px + env(safe-area-inset-bottom,0px));
    z-index:500;
    box-shadow:0 -1px 4px rgba(0,0,0,.06);
  }
  .bottom-nav .b{
    flex:1;display:flex;flex-direction:column;
    align-items:center;gap:2px;
    cursor:pointer;color:var(--hint);
    padding:3px 0;transition:color .15s;
  }
  .bottom-nav .b.active{color:var(--accent)}
  .bottom-nav .b .b-pip{padding:3px 12px;border-radius:99px;transition:background .15s;display:flex;align-items:center;justify-content:center}
  .bottom-nav .b.active .b-pip{background:var(--accent-l)}
  .bottom-nav .b i{font-size:22px}
  .bottom-nav .b .lbl{font-size:8px;font-weight:700;text-transform:uppercase;letter-spacing:.3px;line-height:1}
  .bottom-nav .b .badge{position:absolute;top:0;right:18%;background:var(--err);color:#fff;font-size:9px;font-weight:800;min-width:16px;height:16px;border-radius:99px;display:flex;align-items:center;justify-content:center;padding:0 3px;border:2px solid #fff}

  /* ── DRAWER ── */
  .drawer-section-label{padding:8px 12px 3px;font-size:9px;font-weight:800;color:var(--hint);text-transform:uppercase;letter-spacing:.5px;display:block}
  .drawer-item{display:flex;align-items:center;gap:10px;padding:12px;cursor:pointer;border-bottom:.5px solid var(--border);transition:background .1s}
  .drawer-item:active,.drawer-item:hover{background:var(--accent-l)}
  .drawer-item i{font-size:18px;color:var(--muted);flex-shrink:0;width:20px}
  .drawer-item span{font-size:13px;font-weight:600;color:var(--text);flex:1}
  .drawer-item.active{background:var(--accent-l)}
  .drawer-item.active i,.drawer-item.active span{color:var(--accent)}
  .drawer-sub-item{display:flex;align-items:center;gap:8px;padding:10px 12px 10px 42px;cursor:pointer;border-bottom:.5px solid var(--border);font-size:12px;font-weight:600;color:var(--muted);transition:background .1s}
  .drawer-sub-item:active{background:var(--border)}
  .drawer-sub-item i{font-size:14px}

  /* ── NOTIFICATION PANEL ── */
  .notif-item{padding:12px 14px;border-bottom:.5px solid var(--border)}
  .notif-item .ni-title{font-size:13px;font-weight:700;color:var(--text)}
  .notif-item .ni-body{font-size:11px;color:var(--muted);margin-top:3px;line-height:1.4}
  .notif-empty{padding:32px 14px;text-align:center;color:var(--hint);font-size:13px}

  /* ── MODALS ── */
  .modal-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:600;display:none;align-items:flex-end;justify-content:center}
  .modal-backdrop.open{display:flex}
  @media(min-width:640px){.modal-backdrop.open{align-items:center}}
  .modal{background:var(--card);border-radius:8px 8px 0 0;max-width:900px;width:100%;max-height:92vh;max-height:88dvh;overflow-y:auto;overflow-x:hidden;padding:0 20px 20px;box-shadow:0 -4px 24px rgba(0,0,0,.12)}
  @media(min-width:640px){.modal{border-radius:8px}}
  .modal-header{display:flex;justify-content:space-between;align-items:center;position:sticky;top:0;z-index:5;background:var(--card);padding:16px 0 12px;margin-bottom:10px;border-bottom:1px solid var(--border)}
  .modal-header h2{font-size:16px;font-weight:700}
  .modal-close{background:var(--bg);border:none;border-radius:4px;width:32px;height:32px;cursor:pointer;color:var(--muted);font-size:16px;display:flex;align-items:center;justify-content:center}

  /* ── BUTTONS ── */
  .new-btn{background:var(--accent);color:#fff;border:none;border-radius:var(--rs);padding:9px 16px;font-weight:600;cursor:pointer;font-size:13px;margin-bottom:12px;display:inline-flex;align-items:center;gap:6px;min-height:36px}
  .new-btn:active{opacity:.85}
  .btn-secondary{background:var(--card);color:var(--text);border:1px solid var(--border-strong);padding:8px 14px;border-radius:var(--rs);font-size:13px;font-weight:600;cursor:pointer;min-height:36px}
  .btn-secondary:active{background:var(--bg)}

  /* ── MAIN CONTENT ── */
  .main-content{
    padding:12px;
    padding-top:calc(var(--header-h) + var(--tabs-h) + 12px);
    padding-bottom:calc(68px + env(safe-area-inset-bottom,0px));
    overflow-x:hidden;
    min-height:100vh;
    width:100%;
  }
  .main-content.has-stats{
    padding-top:calc(var(--header-h) + 28px + var(--tabs-h) + 12px);
  }
  @media(max-width:640px){
    .main-content.has-stats{padding-top:calc(var(--header-h) + 28px + var(--tabs-h) + 8px)}
  }

  /* ── CARDS ── */
  .items-card{max-width:900px;margin:0 auto 12px;background:var(--card);border:1px solid var(--border);border-radius:var(--r);padding:16px;box-shadow:var(--sh);overflow:hidden}
  .items-card h2{font-size:15px;font-weight:700;margin-bottom:12px;display:flex;align-items:center;gap:8px}

  /* ── TABLES ── */
  .items-form{display:grid;grid-template-columns:2fr 1fr 1fr 1fr 1fr 1fr auto;gap:8px;margin-bottom:14px;align-items:end}
  .items-form input{padding:8px;font-size:13px}
  .items-form label{margin:0 0 4px}
  .items-form .add-btn,.add-btn{background:var(--accent);color:#fff;border:none;border-radius:var(--rs);padding:9px 14px;font-weight:600;cursor:pointer;font-size:13px;min-height:36px}
  .add-btn:active{opacity:.85}
  /* [stated] 2 Oct: "we can increase the text size of the invoice lines". 13px -> 14px
     and the row a little taller. EVERY list in the app uses this class - items, parties,
     purchases, payments, stock - so they stay consistent; a laptop shows about two rows
     fewer, which is the trade and it is worth it. */
  table.items-table{width:100%;border-collapse:collapse;font-size:14px}
  table.items-table th{text-align:left;color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.4px;padding:8px 10px;border-bottom:1px solid var(--border);font-weight:700;background:var(--bg)}
  table.items-table td{padding:11px 10px;border-bottom:1px solid var(--border);vertical-align:middle}
  table.items-table tr:last-child td{border-bottom:none}
  table.items-table tr:hover td{background:#fafbfc}
  .del-btn{border:none;border-radius:var(--rs);padding:7px 10px;font-size:14px;font-weight:600;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:4px;min-width:36px;min-height:36px}
  .empty-row{color:var(--hint);text-align:center;padding:24px;font-size:13px}
  .node:hover{opacity:.82}

  /* ── ROLE BADGES ── */
  .role-badge-list{font-size:9px;font-weight:700;letter-spacing:.4px;padding:2px 7px;border-radius:3px;text-transform:uppercase}
  .role-badge-list.owner{background:var(--own-l);color:var(--own)}
  .role-badge-list.asm{background:var(--asm-l);color:var(--asm)}
  .role-badge-list.so{background:var(--so-l);color:var(--so)}
  .role-badge-list.distributor{background:#e0e7ff;color:#4338ca}

  /* ── SEGMENTED CONTROL (Doctor submenu) ── */
  .seg-btn{flex:1;padding:6px 3px;border-radius:3px;border:none;background:none;color:var(--muted);font-size:9px;font-weight:600;cursor:pointer;text-transform:uppercase;letter-spacing:.3px;transition:all .15s;white-space:nowrap;min-height:30px}
  .seg-btn.seg-active{background:var(--accent);color:#fff;box-shadow:0 1px 3px rgba(62,142,50,.28);font-weight:700}
  .seg-btn:not(.seg-active):hover{background:var(--accent-l)}

  /* ── TOAST ── */
  .toast{position:fixed;bottom:80px;left:50%;transform:translateX(-50%) translateY(20px);background:var(--text);color:#fff;padding:10px 18px;border-radius:99px;font-size:13px;font-weight:600;z-index:9999;opacity:0;transition:all .25s;pointer-events:none;display:flex;align-items:center;gap:7px;white-space:nowrap;max-width:calc(100vw - 32px);box-shadow:0 4px 14px rgba(0,0,0,.18)}
  .toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
  .toast.success{background:#155724}
  .toast.error{background:var(--err)}
  .toast.warning{background:#856404}

  /* ── REPORT OVERLAY ── */
  #report-overlay{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:#fff;z-index:9999;overflow-y:auto;-webkit-overflow-scrolling:touch}
  #report-overlay.open{display:block}
  #report-overlay-bar{position:sticky;top:0;background:var(--brand);color:#fff;display:flex;align-items:center;gap:10px;padding:10px 14px;z-index:10000}
  #report-overlay-bar button{background:rgba(255,255,255,.2);border:none;color:#fff;padding:7px 12px;border-radius:4px;font-size:13px;font-weight:600;cursor:pointer;display:flex;align-items:center;gap:5px}
  #report-overlay-title{flex:1;font-size:13px;font-weight:600}
  #report-overlay-content{padding:16px}
  #report-overlay-content table{width:100%;border-collapse:collapse;font-size:12px}
  #report-overlay-content th{background:var(--bg);padding:8px 10px;text-align:left;font-size:10px;text-transform:uppercase;color:var(--muted);border-bottom:2px solid var(--border);font-weight:700}
  #report-overlay-content td{padding:7px 10px;border-bottom:1px solid var(--border)}
  @media print{
    body.report-overlay-open #app-shell,body.report-overlay-open #login-screen{display:none!important}
    body.report-overlay-open #report-overlay{position:static!important;overflow:visible!important}
    #report-overlay-bar{display:none!important}
  /* ⚠ ANY CONTROL INSIDE A PRINTED DOCUMENT. The overlay bar was already hidden,
     but buttons placed INSIDE the document body were not, so Print and CSV would
     have appeared on the paper copy. An unstyled class does nothing silently. */
  .no-print{display:none!important}
  }

  /* ── LOGGEDIN ROWS ── */
  .loggedin .row{display:flex;justify-content:space-between;font-size:13px;padding:8px 0;border-bottom:1px solid var(--border)}
  .loggedin .row b{color:var(--text)}

  /* ── MOBILE ── */
  @media(max-width:640px){
    input,select,textarea{font-size:16px!important}
    body,#app-shell,.main-content{overflow-x:hidden;max-width:100vw}
    table.items-table{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch}
    table.items-table thead,table.items-table tbody{display:table;width:100%;min-width:500px}
    .items-card{padding:12px;margin-bottom:8px}
    .main-content{padding:8px;padding-top:calc(var(--header-h) + var(--tabs-h) + 8px);padding-bottom:calc(68px + env(safe-area-inset-bottom,0px))}
    .main-content.has-stats{padding-top:calc(var(--header-h) + var(--tabs-h) + 28px + 8px)}
    .btn,.new-btn,.btn-secondary,.add-btn{min-height:40px}
    .del-btn{min-width:40px;min-height:40px}
    .modal{max-height:95vh;max-height:88dvh;padding:0 14px 14px}
    .toast{bottom:calc(68px + 8px)}
    :root{--header-h:56px;--tabs-h:38px}
  }

  /* ══════════ PHASE 2 — CHROME ══════════
     Appended rather than edited into the rules above, so reverting is one
     deletion. Nothing here changes layout or class names. */

  /* Cards: a little more air, and the softer shadow from the tokens. */
  .items-card{padding:18px}
  @media(max-width:640px){.items-card{padding:13px}}

  /* Tables: taller rows read faster on a shop PC, and a neutral hover so the
     eye follows the row rather than the tint. */
  table.items-table td{padding:10px 11px}
  table.items-table th{padding:9px 11px;letter-spacing:.5px}
  table.items-table tr:hover td{background:#f7f9f6}

  /* MONEY, STOPGAP: most amount cells in this app carry an inline
     text-align:right, so this reaches them with no markup change. The proper
     fix is a class on those cells when the render functions are next touched. */
  table.items-table td[style*="text-align:right"],
  table.items-table td[style*="text-align: right"]{font-family:var(--num);font-size:12.5px}

  /* Buttons: a real hover, not only :active. */
  .new-btn,.add-btn{transition:background .15s,box-shadow .15s}
  .new-btn:hover,.add-btn:hover{background:var(--accent-d)}
  .btn-secondary{transition:background .15s,border-color .15s}
  .btn-secondary:hover{background:var(--bg);border-color:var(--muted)}
  .btn{transition:background .15s,opacity .15s}
  .btn:hover:not(:disabled){background:var(--accent-d)}

  /* Inputs: rounder, and the focus ring matches the accent. */
  input,select,textarea{border-radius:var(--rs)}

  /* Header: the company name and the person were a touch small to read at a
     glance from standing distance at a counter. */
  .app-header .co-name{font-size:10px;letter-spacing:.6px}
  .app-header .sub2{font-size:14px}

  /* Tabs: slightly larger, and the active tab reads as selected rather than
     merely tinted. */
  .nav-tabs .t{font-size:11.5px}
  .nav-tabs .t.active{background:var(--accent-l);border-color:var(--accent)}

  /* Modals: match the card radius. */
  .modal{border-radius:14px 14px 0 0}
  @media(min-width:640px){.modal{border-radius:14px}}
  .modal-close{border-radius:var(--rs)}

  /* Focus visible for keyboard users - an ERP is used without a mouse. */
  :focus-visible{outline:2px solid var(--accent);outline-offset:2px}

  /* ══════════ PHASE 3A — ONE BUTTON SYSTEM ══════════
     Screens were built at different times and each invented its own button
     tints, so the app read as five products. These rules neutralise the
     hand-tinted INLINE styles. !important is required because an inline style
     beats a class - it reaches ~20 sites without editing 20 pieces of markup,
     and deleting this block reverts every one of them.
     The selector matches HEX tints only, so `background:transparent` and the
     deliberate `background:var(--bg)` Cancel buttons are left alone. */
  .btn-secondary[style*="background:#"]{
    background:var(--card)!important;color:var(--text)!important;
    border:1px solid var(--border-strong)!important}
  .btn-secondary[style*="background:#"]:hover{background:var(--bg)!important}

  /* One filled primary per screen. A credit note is a normal document, so red
     was wrong - red means danger or delete. */
  #newCreditNoteBtn{background:var(--card)!important;color:var(--text)!important;
    border:1px solid var(--border-strong)!important;font-weight:600}
  #newCreditNoteBtn:hover{background:var(--bg)!important}

  /* Stray left margins on buttons that already sit in a flex row with a gap. */
  .items-card .btn-secondary[style*="margin-left"]{margin-left:0!important}

  /* Row actions: one compact quiet button on every screen, whatever tint the
     renderer asked for. Destructive intent shows in the TEXT colour, not by
     shouting with a filled background. */
  table.items-table .del-btn{
    background:var(--bg);color:var(--text);border:1px solid var(--border);
    font-size:12px;font-weight:600;padding:5px 10px;min-width:0;min-height:30px}
  table.items-table .del-btn[style*="background:#"]{
    background:var(--bg)!important;color:var(--text)!important;
    border:1px solid var(--border)!important}
  table.items-table .del-btn:hover{background:var(--card);border-color:var(--muted)}
  table.items-table .del-btn[onclick*="delete"],
  table.items-table .del-btn[onclick*="Delete"],
  table.items-table .del-btn[onclick*="hardDelete"]{color:var(--err)!important}

  /* Sub-tabs: pill shape kept - Invoices and Purchases already agree - but one
     size everywhere. The ACTIVE state is set inline by JS in three files, so
     the shape is deliberately not changed here. */
  .invSubTab,.puSubTab,.dcSubTab{
    padding:7px 14px!important;font-size:12.5px!important;
    min-height:32px!important;border-radius:999px!important;margin-bottom:0!important}

  /* ══════════ PHASE 3B — MONEY AND ROW ACTIONS ══════════ */
  table.items-table td.money{font-family:var(--num);text-align:right;white-space:nowrap;font-size:12.5px}
  table.items-table th.r{text-align:right}
  /* Date and document number never wrap - two lines per row wastes the height
     of every other row in the table. */
  #invoicesBody td:first-child,#invoicesBody td:nth-child(2){white-space:nowrap}
  /* Actions as icons in one narrow column. Three text buttons could not fit
     beside eleven data columns, which is what forced the wrapping. */
  table.items-table td.acts{white-space:nowrap;text-align:right}
  table.items-table .del-btn.ico{padding:5px 7px;min-width:30px;font-size:14px;margin-left:4px}
  table.items-table .del-btn.ico:first-child{margin-left:0}
  table.items-table .del-btn.danger{color:var(--err)}
  table.items-table .del-btn.danger:hover{background:var(--err-bg);border-color:var(--err)}

  /* ══════════ PHASE 3C — BUTTON HIERARCHY ══════════
     Three tiers, so a screen reads at a glance:
       1 one filled primary   2 accent outline for other CREATE actions
       3 compact quiet for EXPORTS
     The export selector matches "xport", which catches exportInvoicesCSV,
     exportInvoicesPDF, openTallyExportModal and openMargExportModal in one
     rule - and the same buttons on every other screen. */

  /* Tier 3 - exports recede. Smaller, grey, icon-led. */
  .items-card .btn-secondary[onclick*="xport"]{
    padding:6px 11px!important;font-size:12px!important;min-height:30px!important;
    color:var(--muted)!important;background:var(--card)!important;
    border:1px solid var(--border)!important;font-weight:600!important;
    align-self:center}
  .items-card .btn-secondary[onclick*="xport"]:hover{
    color:var(--text)!important;border-color:var(--border-strong)!important;
    background:var(--bg)!important}
  .items-card .btn-secondary[onclick*="xport"] i{font-size:14px;opacity:.8}

  /* Tier 2 - a credit note CREATES a document, so it belongs to the primary's
     family. Accent outline: related to New Sales Invoice, clearly not it. */
  #newCreditNoteBtn{
    background:var(--accent-l)!important;color:var(--accent-d)!important;
    border:1.5px solid var(--accent-b)!important;font-weight:700!important}
  #newCreditNoteBtn:hover{
    background:var(--card)!important;border-color:var(--accent)!important}

  /* Tier 1 stays as it is - .new-btn, filled --accent. */

  /* Exports live UNDER the table - they are the least important thing on the
     screen and were competing with the primary action at the top. */
  #invExportRow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
    margin-top:14px;padding-top:12px;border-top:1px solid var(--border)}
  #invExportRow .exp-label{font-size:10px;font-weight:700;letter-spacing:.6px;
    text-transform:uppercase;color:var(--hint);margin-right:2px}


  /* ══════════ DESKTOP — THE SIDEBAR IS PINNED ══════════
     The bottom nav and the scrolling tab strip are a phone pattern. On a
     laptop the whole left margin was empty while ten tabs fought for one
     scrolling row. Below 1024px nothing changes. */
  #drawerBrand{display:flex;align-items:center;gap:9px;color:#fff;margin-bottom:14px;
    padding-bottom:12px;border-bottom:1px solid rgba(255,255,255,.16)}
  #drawerBrand span{display:flex;flex-direction:column;line-height:1}
  #drawerBrand b{font-size:17px;font-weight:700;letter-spacing:-.02em}
  #drawerBrand i{font-style:normal;font-size:8.5px;font-weight:600;
    letter-spacing:.16em;text-transform:uppercase;color:var(--sprout);margin-top:3px}

  @media(min-width:1024px){
    #sideDrawer{left:0!important;width:256px;box-shadow:none;
      border-right:1px solid var(--border);transition:none}
    #drawerBackdrop{display:none!important}
    #drawerHead{background:var(--brand)!important}
    .bottom-nav{display:none!important}
    .app-header,#statsStrip,.nav-tabs{left:256px}
    .main-content{padding-left:calc(256px + 14px);padding-right:14px;
      padding-bottom:24px}
    .main-content.has-stats{padding-bottom:24px}
    /* The hamburger has nothing left to open. */
    .app-header .top-row > div:first-child > .icon-btn{display:none}
  }

  /* ══════════ SIDEBAR WIDTH, COLLAPSE AND RESIZE ══════════
     One variable drives the rail and every offset, so nothing can fall out of
     step. Appended after the earlier desktop block so these values win. */
  :root{--sb-w:256px}
  #sbResizer{display:none}

  @media(min-width:1024px){
    #sideDrawer{width:var(--sb-w)}
    .app-header,#statsStrip,.nav-tabs{left:var(--sb-w)}
    .main-content{padding-left:calc(var(--sb-w) + 14px)}

    /* The header already carries the company, the person, the role and the
       date. The sidebar keeps the brand and the menu - nothing twice. */
    #drawerHead > div:not(#drawerBrand){display:none}
    #drawerBrand{margin-bottom:0;padding-bottom:0;border-bottom:none}
    #drawerHead{padding:14px}

    /* The hamburger stays, as the collapse toggle. */
    .app-header .top-row > div:first-child > .icon-btn{display:flex}

    #sbResizer{display:block;position:absolute;top:0;right:0;width:5px;height:100%;
      cursor:col-resize;z-index:5}
    #sbResizer:hover{background:var(--accent-b)}

    /* Collapsed: a 64px icon rail. Labels go, icons centre, tooltips carry the
       names - the menu still works, it just takes less room. */
    body.sb-collapsed{--sb-w:64px}
    body.sb-collapsed .drawer-item span,
    body.sb-collapsed .drawer-sub-item span,
    body.sb-collapsed .drawer-section-label,
    body.sb-collapsed #drawerBrand span{display:none}
    body.sb-collapsed .drawer-item{justify-content:center;padding:12px 0}
    body.sb-collapsed .drawer-item i{width:auto;font-size:20px}
    body.sb-collapsed #drawerBrand{justify-content:center}
    body.sb-collapsed #sideDrawer > div:last-child{display:none}
    body.sb-collapsed #sbResizer{display:none}
  }

  /* ══════════ THE SIDEBAR, PROPERLY ══════════
     Dark ground, no rules between items, a filled pill for the active screen,
     collapsible groups. Every override carries !important because this markup
     is written with INLINE styles, which beat a stylesheet. */
  @media(min-width:1024px){
    #sideDrawer{width:var(--sb-w)!important;background:var(--brand)!important;
      border-right:none!important;box-shadow:none!important}
    #drawerHead{background:transparent!important;padding:18px 16px 14px!important;
      border-bottom:1px solid rgba(255,255,255,.10)!important}
    /* The header already shows the person, company, role and date - the
       sidebar keeps only the brand. */
    #drawerHead > div:not(#drawerBrand){display:none!important}
    #drawerBrand{margin:0!important;padding:0!important;border:none!important}

    #drawerMainNav{padding:10px 8px}
    .sb-group{margin-bottom:2px}
    .sb-group-hd{display:flex;align-items:center;justify-content:space-between;
      padding:9px 10px 6px;cursor:pointer;user-select:none}
    .sb-group-hd span{font-size:9.5px;font-weight:700;letter-spacing:.14em;
      text-transform:uppercase;color:rgba(255,255,255,.45)}
    .sb-group-hd i{font-size:13px;color:rgba(255,255,255,.35);transition:transform .18s}
    .sb-group-hd:hover span,.sb-group-hd:hover i{color:rgba(255,255,255,.75)}
    .sb-group.shut .sb-group-body{display:none}
    .sb-group.shut .sb-group-hd i{transform:rotate(-90deg)}

    /* No dividers. A ruled row per item is what made this look like a list
       rather than a menu. */
    #drawerMainNav .drawer-item{border:none!important;border-radius:8px;
      padding:9px 10px!important;margin:1px 0;color:rgba(255,255,255,.86)!important;
      transition:background .14s}
    #drawerMainNav .drawer-item span{font-size:13px;font-weight:500;
      color:inherit!important}
    #drawerMainNav .drawer-item i{color:rgba(255,255,255,.55)!important;font-size:17px}
    #drawerMainNav .drawer-item:hover{background:rgba(255,255,255,.08)!important}
    #drawerMainNav .drawer-item.active{background:var(--accent)!important;
      color:#fff!important}
    #drawerMainNav .drawer-item.active i,
    #drawerMainNav .drawer-item.active span{color:#fff!important}

    /* My Account, at the foot of the list. */
    #sideDrawer .drawer-section-label{color:rgba(255,255,255,.45)!important;
      font-size:9.5px;letter-spacing:.14em;padding:14px 18px 4px}
    #sideDrawer .drawer-item{border:none!important;color:rgba(255,255,255,.86)!important;
      padding:9px 18px}
    #sideDrawer .drawer-item i{color:rgba(255,255,255,.55)!important}
    #sideDrawer .drawer-item:hover{background:rgba(255,255,255,.08)!important}

    /* The help panel was mint green - wrong on navy. */
    #sideDrawer > div:last-child{background:rgba(255,255,255,.05)!important;
      border-top:1px solid rgba(255,255,255,.10)!important}
    #sideDrawer > div:last-child i{color:var(--sprout)!important}
    #sideDrawer > div:last-child div{color:rgba(255,255,255,.85)!important}

    #sbResizer:hover{background:rgba(255,255,255,.25)}

    body.sb-collapsed .sb-group-hd{display:none}
    body.sb-collapsed #drawerMainNav{padding:10px 6px}
  }

  /* The mark is dark-on-light, so on navy it sits on a white chip - the normal
     answer until a white-text version exists. Margins were trimmed off the
     source first, or it would float small inside its own empty space. */
  #drawerBrand{display:block!important;background:#fff;border-radius:8px;
    padding:10px 12px;margin:0 0 2px!important}
  #drawerBrand img{display:block;width:100%;height:auto}
  @media(min-width:1024px){
    body.sb-collapsed #drawerBrand{display:none!important}
  }

  /* LOGO HEIGHT CAP. Sizing it to 100% of the sidebar meant it grew with the
     rail - at a dragged-out width it became a 250px block. Cap the HEIGHT and
     let the width follow, so it stays right at any sidebar size. */
  #drawerBrand{display:flex!important;justify-content:center;align-items:center;
    background:#fff;border-radius:8px;padding:7px 10px;margin:0!important}
  #drawerBrand img{display:block;height:38px;width:auto;max-width:100%}

  /* MY ACCOUNT labels - these sit OUTSIDE #drawerMainNav, so they kept the base
     dark text colour and disappeared on the navy ground. */
  @media(min-width:1024px){
    #sideDrawer .drawer-item span{color:inherit!important;font-weight:500;
      font-size:13px}
    #sideDrawer .drawer-item.active span{color:#fff!important}
    body.sb-collapsed #drawerBrand{display:none!important}
  }

  /* The logo is now white ink on transparent, so it sits straight on the navy.
     No chip, no sticker. Height capped so it cannot grow with the rail. */
  #drawerBrand{display:flex!important;justify-content:flex-start;align-items:center;
    background:transparent!important;border-radius:0!important;
    padding:2px 4px!important;margin:0!important}
  #drawerBrand img{display:block;height:34px;width:auto;max-width:100%}

  /* A WHITE BRAND BAND, edge to edge. The logo is drawn for light grounds, so
     the interface gives it one instead of the logo being altered. Edge-to-edge
     reads as a brand bar; a floating rounded box reads as a sticker. */
  #drawerHead{background:#fff!important;padding:0!important;
    border-bottom:1px solid var(--border)!important}
  #drawerBrand{display:flex!important;align-items:center;justify-content:center;
    background:transparent!important;border-radius:0!important;
    padding:14px 18px!important;margin:0!important}
  #drawerBrand img{display:block;height:40px;width:auto;max-width:100%}
  @media(min-width:1024px){
    body.sb-collapsed #drawerHead{padding:10px 0!important}
    body.sb-collapsed #drawerBrand{display:none!important}
  }

  /* ══════════ THE PRODUCT MARK ══════════
     No trolley and no gradient - neither belongs at this level. A solid tile,
     three ascending bars for growth and for several shops under one business,
     and a tight wordmark. Flat, so it survives 16px and a 1-bit printer. */
  #drawerHead{background:transparent!important;padding:18px 16px 15px!important;
    border-bottom:1px solid rgba(255,255,255,.10)!important}
  #drawerBrand{display:flex!important;align-items:center;gap:11px;
    background:transparent!important;border-radius:0!important;
    padding:0!important;margin:0!important}
  #drawerBrand .bmark{width:34px;height:34px;border-radius:9px;
    background:var(--accent);display:flex;align-items:center;justify-content:center;
    flex-shrink:0}
  #drawerBrand .bmark svg{width:26px;height:26px;display:block}
  #drawerBrand .btext{display:flex;flex-direction:column;line-height:1;min-width:0}
  #drawerBrand .btext b{font-size:20px;font-weight:700;letter-spacing:-.02em;color:#fff}
  #drawerBrand .btext i{font-style:normal;font-size:8.5px;font-weight:600;
    letter-spacing:.2em;text-transform:uppercase;
    color:rgba(255,255,255,.52);margin-top:5px}
  @media(min-width:1024px){
    body.sb-collapsed #drawerHead{padding:14px 0!important}
    body.sb-collapsed #drawerBrand{display:flex!important;justify-content:center}
    body.sb-collapsed #drawerBrand .btext{display:none}
  }

  /* The old field-force dashboard is HIDDEN, not deleted - its elements still
     exist, so nothing that references them can break, and reverting is one
     line. */
  #homeCard > *:not(#rdWrap){display:none!important}
  #homeCard{padding:0!important;border:none!important;box-shadow:none!important;
    background:transparent!important;max-width:1400px}
  .rd-kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:14px}
  @media(max-width:900px){.rd-kpis{grid-template-columns:repeat(2,1fr)}}
  .rd-kpi{background:var(--card);border:1px solid var(--border);border-radius:var(--r);padding:14px 15px}
  .rd-kpi .k{font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
  .rd-kpi .v{font-family:var(--num);font-size:23px;font-weight:600;margin-top:6px;letter-spacing:-.02em}
  .rd-kpi .d{font-size:11.5px;color:var(--muted);margin-top:3px}
  .rd-card{background:var(--card);border:1px solid var(--border);border-radius:var(--r);margin-bottom:14px;overflow:hidden}
  .rd-card > h4{font-size:14px;font-weight:700;padding:13px 15px;border-bottom:1px solid var(--border);margin:0}
  .rd-card > h4 span{font-weight:400;font-size:12px;color:var(--muted);margin-left:6px}
  .rd-empty{padding:26px 16px;text-align:center;color:var(--muted);font-size:13px}
  .rd-empty b{display:block;color:var(--text);font-size:14px;margin-bottom:4px}
  .rd-bar{height:6px;background:var(--bg);border-radius:3px;margin-top:6px;overflow:hidden}
  .rd-bar i{display:block;height:100%;background:var(--accent);border-radius:3px}
  .rd-att{display:flex;gap:10px;align-items:flex-start;padding:10px 15px;border-bottom:1px solid #f0f2f0;font-size:13px}
  .rd-att:last-child{border-bottom:none}
  .rd-att .pill{font-size:9.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:3px 8px;border-radius:999px;flex-shrink:0}
  .rd-att .pill.neg{background:var(--err-bg);color:var(--err)}
  .rd-att .pill.low{background:var(--warn-bg);color:var(--warn)}
  .rd-att .pill.tr{background:var(--accent-l);color:var(--accent-d)}
  .rd-trend{display:flex;align-items:flex-end;gap:5px;height:110px;padding:16px 15px}
  .rd-trend > div{flex:1;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;height:100%}
  .rd-trend .bar{width:100%;background:var(--accent);border-radius:3px 3px 0 0;min-height:2px}
  .rd-trend .lbl{font-family:var(--num);font-size:8.5px;color:var(--hint);margin-top:5px}

  /* The retail ribbon replaces the field-force one. The old items stay in the
     DOM, hidden, so drawer.js can keep writing to them without harm. */
  #statsStrip .stat-item{display:none!important}
  #statsRetail{display:flex;flex:1}
  #statsRetail .si{flex:1;padding:3px 4px;text-align:center;min-width:0;overflow:hidden;
    border-right:1px solid rgba(255,255,255,.12)}
  #statsRetail .si:last-child{border-right:none}
  #statsRetail .si b{display:block;font-family:var(--num);font-size:13px;font-weight:600;
    color:#fff;line-height:1}
  #statsRetail .si span{display:block;font-size:7px;color:rgba(255,255,255,.62);
    text-transform:uppercase;letter-spacing:.4px;margin-top:3px}
  #statsRetail .si.warn b{color:#ffb4a8}

  /* CARD WIDTH — one rule for every screen.
     .items-card is max-width:900px centred, and individual cards override it
     inline at 900, 1100 and 1400 — so the gap between the menu and the content
     changed as you moved between screens. !important is needed because those
     overrides are inline. Left-aligned, so every screen starts at the same
     edge instead of being centred in whatever space is left. */
  @media(min-width:1024px){
    .items-card{max-width:1320px!important;margin:0 0 14px 0!important;width:100%}
    #homeCard{max-width:1320px!important;margin:0 0 14px 0!important}
  }

  /* MOBILE DRAWER HEADER. The mark block set this to transparent with NO media
     query. Behind it on desktop is the navy sidebar, so it looked right - but
     the MOBILE drawer is white, and a white wordmark on white is invisible,
     leaving only the green tile. Same element, two grounds: check both. */
  #drawerHead{background:var(--brand)!important}

  /* ══════════ FIXED OVERLAYS AND THE SIDEBAR ══════════
     Everything positioned against the VIEWPORT was thrown off by the sidebar:
     a modal centres on the whole screen, and 256px of it is now the menu, so
     every dialog sat too far left and slid underneath. The backdrop keeps
     covering the full screen (it should still read as a modal) - only the
     CENTRING moves, via padding. */
  @media(min-width:1024px){
    .modal-backdrop{padding-left:var(--sb-w)}
    #report-overlay{left:var(--sb-w)}
    #notifBackdrop{left:var(--sb-w)}
    .toast{left:calc(50% + (var(--sb-w) / 2))}

    /* The help panel sat over the last menu items in the collapsed rail. */
    body.sb-collapsed #sideDrawer > div:last-child{display:none!important}
  }

  /* The nav list scrolls; the help panel is pinned below it and never overlaps.
     Applies at every width, because the mobile drawer had the same fault. */
  #sideDrawer{display:flex;flex-direction:column}
  #drawerMainNav{min-height:0}
  #sideDrawer > div:last-child{flex-shrink:0}

  /* ══════════ DIALOGS, FINISHED PROPERLY ══════════ */
  .modal-backdrop{background:rgba(11,25,45,.55)}
  .modal{max-height:88dvh;padding:0 22px 22px;
    box-shadow:0 24px 60px -20px rgba(11,25,45,.45)}
  .modal-header{padding:18px 0 14px;margin-bottom:14px;
    border-bottom:1px solid var(--border)}
  .modal-header h2{font-size:17px;font-weight:700;letter-spacing:-.01em}
  .modal-close{background:var(--bg);border:1px solid var(--border);
    border-radius:8px;width:32px;height:32px;transition:background .15s}
  .modal-close:hover{background:var(--err-bg);color:var(--err);border-color:var(--err)}
  /* A Cancel button belongs beside the action, not stretched across the dialog. */
  .modal .add-btn[id^="cancel"]{width:auto!important;min-width:120px;
    background:var(--card)!important;color:var(--text)!important;
    border:1px solid var(--border-strong)!important}
  .modal .add-btn[id^="cancel"]:hover{background:var(--bg)!important}

  /* ══════════ TABLET ══════════
     Supermarkets bill on 10-inch tablets. Landscape (1024-1280px) gets the
     desktop layout, so the rail narrows to leave the table room. Portrait
     (~800px) keeps the mobile bottom nav, which is the right shape there. */
  @media(min-width:1024px) and (max-width:1279px){
    :root{--sb-w:212px}
    .items-card,#homeCard{max-width:none!important}
    #drawerBrand .btext b{font-size:18px}
    .rd-kpis{grid-template-columns:repeat(2,1fr)}
  }

  /* Touch, at any size. A finger needs 44px; a mouse does not. */
  @media(hover:none) and (pointer:coarse){
    /* Dragging needs mouse events this code does not have - hide it rather
       than leave a dead strip a thumb can catch. */
    #sbResizer{display:none!important}

    table.items-table .del-btn,
    table.items-table .del-btn.ico{min-height:42px!important;min-width:42px!important;
      padding:9px 11px!important;font-size:15px!important}
    table.items-table td{padding:14px 11px}
    .invSubTab,.puSubTab,.dcSubTab{min-height:42px!important;padding:10px 18px!important;
      font-size:13.5px!important}
    #drawerMainNav .drawer-item{padding:13px 11px!important}
    #sideDrawer .drawer-item{padding:13px 18px}
    .sb-group-hd{padding:13px 11px 8px}
    .btn,.new-btn,.add-btn,.btn-secondary{min-height:44px}
    input,select,textarea{min-height:44px}
    .modal-close{width:40px;height:40px}
    /* Hover states do not exist on touch, so the resting state must already
       read as tappable. */
    table.items-table .del-btn{background:var(--card);border-color:var(--border-strong)}
    #statsRetail .si{padding:6px 4px}
    /* Accent swatches were 30px - too small to hit reliably. */
    #pfAccentSwatches [data-accent]{width:40px!important;height:40px!important}
  }

  /* ══════════ WIDE TABLES ON ANY NARROW SCREEN ══════════
     The scroll treatment only existed below 640px, so between 641 and 1279 an
     eleven-column table had nowhere to go and pushed the layout out of shape.
     Written by WIDTH, not by device, so it holds for any tablet or a small
     laptop equally. */
  @media(max-width:1279px){
    table.items-table{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch}
    table.items-table thead,table.items-table tbody,table.items-table tfoot{
      display:table;width:100%;min-width:760px}
    /* ⚠ WAS overflow-x:hidden - the same fault. The table inside already scrolls
       itself; the card must not amputate anything else that is too wide. */
    .items-card{overflow-x:auto;-webkit-overflow-scrolling:touch}
  }
  /* A scrollable table needs to look scrollable, or nobody scrolls it. */
  @media(max-width:1279px) and (pointer:coarse){
    table.items-table{scrollbar-width:thin}
  }

  /* Which shop the till is billing for - always visible, never ambiguous. */
  .ct-branch{display:flex;align-items:center;gap:9px;flex-wrap:wrap;
    background:var(--accent-l);border:1px solid var(--accent-b);
    border-radius:var(--r);padding:9px 13px;margin-bottom:12px}
  .ct-branch .lbl{font-size:10px;font-weight:700;letter-spacing:.1em;
    text-transform:uppercase;color:var(--accent-d)}
  .ct-branch b{font-size:14px;color:var(--text)}
  .ct-branch select{font:inherit;font-size:14px;font-weight:600;padding:6px 10px;
    border:1px solid var(--accent-b);border-radius:var(--rs);background:var(--card);
    width:auto;min-width:200px}
  .ct-branch .hint{font-size:11.5px;color:var(--muted)}

  /* Type-ahead at the till. Stock is shown per shop, because a cashier who can
     see "also at GDK 20" saves a sale instead of losing it. */
  .ct-sug{border:1px solid var(--border);border-radius:var(--r);overflow:hidden;
    margin-top:8px;box-shadow:var(--sh);background:var(--card)}
  .ct-sug-row{display:grid;grid-template-columns:1fr auto auto;gap:4px 14px;
    padding:10px 13px;cursor:pointer;border-bottom:1px solid var(--border)}
  .ct-sug-row:last-child{border-bottom:none}
  .ct-sug-row:hover{background:var(--accent-l)}
  .ct-sug-row .nm{font-weight:600;font-size:14px}
  .ct-sug-row .nm .u{font-weight:400;font-size:11px;color:var(--muted)}
  .ct-sug-row .st{font-family:var(--num);font-size:12.5px;font-weight:600;white-space:nowrap}
  .ct-sug-row .st.ok{color:var(--ok)}
  .ct-sug-row .st.no{color:var(--err)}
  .ct-sug-row .rt{font-family:var(--num);font-size:14px;font-weight:600;white-space:nowrap}
  .ct-sug-row .ot{grid-column:1/-1;font-size:11.5px;color:var(--accent-d)}
  .ct-sug-row .ot.muted{color:var(--hint)}
  @media(hover:none) and (pointer:coarse){.ct-sug-row{padding:14px 13px}}

  /* Suggestion extras: the salt for a pharmacist, rack and bin so a cashier
     knows where the item physically is, and MRP struck through above the rate. */
  .ct-sug-row .gn{font-size:11.5px;color:var(--muted);font-weight:400;margin-top:2px}
  .ct-sug-row .loc{font-family:var(--num);font-size:11px;color:var(--accent-d);
    font-weight:600;margin-top:3px}
  .ct-sug-row .rt .mrp{display:block;font-size:11px;font-weight:400;
    color:var(--hint);text-decoration:line-through;text-align:right}

/* ══════════ EMPLOYEE FORM — layout C, five numbered sections ══════════
   New `emf-` classes only. Nothing here overrides an existing rule, so no
   !important is needed anywhere in this block. */
.emf-sec{border-top:1px solid var(--border);padding:14px 0 2px}
.emf-sec.first{border-top:none;padding-top:0}
.emf-sech{display:flex;align-items:baseline;gap:9px;margin-bottom:12px}
.emf-n{font-family:var(--num);font-size:11px;font-weight:600;color:var(--hint)}
.emf-sech h3{font-size:13.5px;font-weight:700;letter-spacing:.01em}
.emf-why{font-size:11.5px;color:var(--muted);font-weight:400}
.emf-cnt{margin-left:auto;font-family:var(--num);font-size:10.5px;font-weight:600;
  padding:3px 8px;border-radius:999px;white-space:nowrap}
.emf-cnt.need{background:var(--warn-bg);color:var(--warn)}
.emf-cnt.done{background:var(--accent-l);color:var(--accent-d)}
.emf-cnt.opt{background:var(--bg);color:var(--muted);border:1px solid var(--border)}
.emf-r{display:grid;gap:10px;margin-bottom:10px}
.emf-r2{grid-template-columns:1fr 1fr}
.emf-r3{grid-template-columns:1fr 1fr 1fr}
.emf-r4{grid-template-columns:.7fr 1.7fr .9fr 1fr}
@media(max-width:700px){.emf-r2,.emf-r3,.emf-r4{grid-template-columns:1fr}}
.emf-h{font-size:10px;color:var(--muted);text-transform:none;letter-spacing:0;font-weight:500}
.emf-req{color:var(--err)}
.emf-sub{font-size:11.5px;font-weight:700;color:var(--text);text-transform:none;
  letter-spacing:0;margin:2px 0 6px}
details.emf-sec>summary{list-style:none;cursor:pointer}
details.emf-sec>summary::-webkit-details-marker{display:none}
details.emf-sec>summary .emf-sech{margin-bottom:0}
details.emf-sec[open]>summary .emf-sech{margin-bottom:12px}
.emf-chev{color:var(--hint);font-size:12px;margin-left:6px;display:inline-block;transition:transform .15s}
details.emf-sec[open]>summary .emf-chev{transform:rotate(90deg)}
.emf-tick{display:flex;align-items:flex-start;gap:9px;cursor:pointer;
  text-transform:none;font-weight:600;font-size:13px}
.emf-tick input{width:16px;height:16px;min-width:16px;flex:0 0 16px;margin:1px 0 0;accent-color:var(--accent)}
.emf-note{display:block;font-weight:400;font-size:11px;color:var(--muted);margin-top:2px}
.emf-shop{display:flex;align-items:center;gap:9px;flex-wrap:wrap;background:var(--accent-l);
  border:1px solid var(--accent-b);border-radius:var(--rs);padding:9px 11px}
.emf-shop select{flex:1;min-width:190px;border-color:var(--accent-b)}
.emf-shop .lbl{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--accent-d);white-space:nowrap}

/* ══════════ PHASE 4 — THE PHONE ══════════
   Appended rather than edited into the rules above, so reverting is one deletion.
   Nothing here changes markup or class names.

   ⭐⭐ HIS REPORT WAS ELEVEN SCREENS LONG, but it is ONE cause: "irregular sizes of
   fields, dropdowns, search boxes". The forms carry about two hundred INLINE fixed
   widths — style="width:200px" and the like — written for a desktop. Three of those
   side by side do not fit a 380px phone, so they squash, overflow, or line up
   raggedly. Every screen he named is a form-heavy screen.

   ⚠ EDITING TWO HUNDRED INLINE WIDTHS ACROSS EIGHT FILES WOULD BE PATCH WORK, and I
   would miss some, and new ones would keep appearing. One rule that overrides them
   all below 640px fixes every screen at once — including the ones he has not looked
   at yet. That is also what an app looks like: one field per row, full width.

   ⚠ AND IT CANNOT AFFECT A LAPTOP. Everything here is inside max-width:640px. */
@media(max-width:640px){

  /* ── 1. EVERY FORM GRID BECOMES ONE COLUMN ───────────────────────────────
     73 grids in the markup alone, most of them 1fr 1fr or 1fr 1fr 1fr. Two
     labelled fields in 380px leaves about 170px each, which is why the boxes
     looked ragged. The attribute selector catches the inline ones too, which is
     the only way to reach grids built in JS. */
  .items-form,
  [style*="grid-template-columns"]{
    grid-template-columns:1fr!important;
    gap:10px!important;
  }

  /* ── 2. EVERY FIELD FILLS ITS ROW ────────────────────────────────────────
     ⚠ THE EXCLUSIONS MATTER MORE THAN THE RULE. A checkbox stretched across the
     screen, or the counter's quantity box, would be worse than what he has now.
     Checkboxes, radios and anything explicitly narrow keep their size. */
  input:not([type=checkbox]):not([type=radio]):not([type=file]),
  select, textarea{
    width:100%!important;
    max-width:100%!important;
    min-width:0!important;
    box-sizing:border-box;
  }
  /* A number box inside a TABLE ROW stays narrow - a full-width quantity box in a
     five-column row would push the row off the screen sideways. */
  table.items-table input[type=number],
  table.items-table input[type=text]{
    width:auto!important;min-width:64px!important;max-width:120px!important;
  }
  input[type=checkbox],input[type=radio]{width:auto!important;min-width:0!important}

  /* ── 3. FLEX ROWS STACK INSTEAD OF SQUEEZING ─────────────────────────────
     A toolbar of four controls in a row is four unreadable slivers on a phone. */
  [style*="display:flex"]:not(.ct-branch):not([style*="flex-wrap:nowrap"]){
    flex-wrap:wrap!important;
  }
  /* ⛔⛔ AND THEIR CHILDREN STOP RESERVING SPACE. This is the fault he found on the
     items filter bar: I had cleared min-width on the INPUT but the DIV around it
     still demanded 180px, so five wrappers squeezed side by side and overlapped.
     ⇒ CLEARING A WIDTH ON THE CHILD IS USELESS WHILE THE PARENT RESERVES THE SPACE.
     ⚠ 12 such wrappers exist in the markup, two of them at min-width:520px and one
     at 640px - each on its own guarantees a phone cannot lay the row out. */
  [style*="display:flex"] > div[style*="min-width"],
  [style*="display:flex"] > div[style*="flex:"]{
    min-width:0!important;
  }
  /* anything explicitly wider than a phone gives up its floor entirely */
  [style*="min-width:520px"],[style*="min-width:640px"],
  [style*="min-width:900px"],[style*="min-width:1100px"]{
    min-width:0!important;
  }

  /* ── 4. THE SUB-TAB ROWS SCROLL SIDEWAYS, LIKE AN APP ────────────────────
     ⭐ HIS WORDS: "Purchase module not showing full including sub modules". Ten
     tabs with flex-wrap:wrap become four ragged lines that eat half the screen
     before any content appears. One scrolling line is what a phone app does.
     ⚠ The row is an inline style in the markup, so it is reached by the class of
     the buttons inside it rather than by a class of its own. */
  /* ⚠ .subtab-row IS THE FALLBACK. :has() needs Chrome 105 / Safari 15.4, which
     every phone sold since 2022 has - but an old Android WebView does not, and on
     one of those the tabs would silently keep wrapping. The real class costs
     nothing and works everywhere. */
  .subtab-row,
  div:has(> .puSubTab), div:has(> .invSubTab), div:has(> .dcSubTab){
    flex-wrap:nowrap!important;
    overflow-x:auto;
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
    padding-bottom:2px;
  }
  .subtab-row::-webkit-scrollbar,
  div:has(> .puSubTab)::-webkit-scrollbar,
  div:has(> .invSubTab)::-webkit-scrollbar,
  div:has(> .dcSubTab)::-webkit-scrollbar{display:none}
  .puSubTab,.invSubTab,.dcSubTab{flex:0 0 auto!important;white-space:nowrap}

  /* ── 5. STAT AND KPI STRIPS: TWO ACROSS, NOT SIX ─────────────────────────
     ⭐ "Dashboard, Company Financials not showing full" - six figures in a row on
     a phone is six unreadable columns. Two across is readable and still compact. */
  .rd-kpis,[style*="minmax(160px"],[style*="minmax(150px"]{
    grid-template-columns:1fr 1fr!important;
  }

  /* ── 6. THE PAGE NEVER SCROLLS SIDEWAYS ──────────────────────────────────
     A single wide element drags the whole page with it, and then nothing lines up.
     The tables are already handled: they scroll inside themselves. */
  /* ⛔⛔ I HAD overflow-x:hidden HERE AND IT WAS WRONG. He reported the symptom
     exactly: "unable to scroll right side to view remaining part." Hiding content
     that does not fit does not make it fit - it makes it unreachable. There were
     already FIVE such rules in this file (lines 28, 212, 284, 777 and the modal),
     and mine was the sixth.
     ⇒ THE CARD MAY SCROLL SIDEWAYS if something inside it genuinely will not
     shrink. Better an honest scrollbar than a screen with its right half missing. */
  .items-card{max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}
  .items-card > div[style*="display:flex"]{max-width:100%}

  /* ── 7. MODAL FOOTERS: BUTTONS FULL WIDTH, STACKED ───────────────────────
     Two half-width buttons at the foot of a form are a mis-tap waiting to happen. */
  .modal .btn-primary,.modal .btn-secondary{width:100%!important;margin-bottom:6px}
}

/* ══════════ THE COUNTER ON A PHONE ══════════
   ⭐⭐ HIS VERDICT ON THE GENERAL PHONE RULES WAS FAIR: "able but not good, not
   getting an experience of an app." He was right. Making a desktop screen shrink
   is not the same as designing for a phone, and no amount of width overrides
   turns a two-column grid with a thirteen-column table into something that feels
   like an app.

   ⇒ THIS IS ONE SCREEN DONE PROPERLY, so he can judge the approach before three
   weeks are spent on the rest. Same markup and same JS - nothing can drift out of
   step with the desktop - but the cart renders as CARDS, the totals sit in a
   fixed bar at the bottom, and the search box is the biggest thing on screen.

   ⚠ THE CAMERA BUTTON IS THE OTHER HALF. On a phone the camera IS the scanner. */

/* The camera button hides on desktop - a webcam pointed at a shelf is useless,
   and a real scanner gun just types into the box. */
.ct-cam{display:none}

@media(max-width:640px){

  /* ── 1. ONE COLUMN. The 1fr 300px grid is why he saw half a screen. ────── */
  #counterCard > div[style*="1fr 300px"]{
    display:block!important;
  }
  #counterCard{max-width:100%;padding:10px 10px 0}
  #counterCard h2{font-size:17px;margin:0 0 8px}

  /* ── 2. THE SEARCH BOX IS THE SCREEN. Everything else is secondary. ───── */
  #ctScan{font-size:17px!important;padding:14px 12px!important}
  .ct-cam{
    display:inline-flex!important;align-items:center;justify-content:center;
    min-width:52px!important;width:52px!important;padding:0!important;
    font-size:22px!important;
  }

  /* ── 3. THE CART BECOMES CARDS, NOT A TABLE ──────────────────────────────
     ⭐ THIS IS THE PART THAT MAKES IT FEEL LIKE AN APP. A six-column table on a
     380px screen is six unreadable slivers; a card per line is one glance.
     ⚠ Done with CSS on the SAME markup, so the desktop table and the phone cards
     can never disagree about what is in the cart. */
  #counterCard table.items-table{display:block;overflow:visible!important;border:0}
  #counterCard table.items-table thead{display:none}
  #counterCard table.items-table tbody{display:block;width:100%;min-width:0!important}
  #counterCard table.items-table tr{
    display:grid;grid-template-columns:1fr auto;gap:2px 10px;
    border:1px solid var(--border);border-radius:10px;
    padding:10px 12px;margin-bottom:8px;background:var(--card);
  }
  #counterCard table.items-table td{
    display:block;border:0!important;padding:0!important;text-align:left!important;
  }
  /* the item name spans the row and leads */
  #counterCard table.items-table td:first-child{
    grid-column:1 / -1;font-weight:600;font-size:14.5px;line-height:1.3;
  }
  /* the numbers sit under it, small and grey, in one line */
  #counterCard table.items-table td:nth-child(2),
  #counterCard table.items-table td:nth-child(3),
  #counterCard table.items-table td:nth-child(4){
    display:inline-block;font-size:12.5px;color:var(--muted);margin-right:14px!important;
  }
  /* the line total is the one figure that matters, so it is big and right-aligned */
  #counterCard table.items-table td:nth-child(5){
    grid-column:2;text-align:right!important;font-weight:700;font-size:15px;
    font-family:var(--num);
  }
  #counterCard table.items-table .empty-row{
    grid-column:1 / -1;text-align:center!important;color:var(--muted);padding:18px 0!important;
  }

  /* ── 4. THE TOTAL AND THE PAY BUTTON LIVE AT THE BOTTOM ──────────────────
     ⭐ Where a thumb is, and always visible. A cashier should never scroll to
     find out what to charge. */
  #counterCard > div[style*="1fr 300px"] > div:last-child > div:first-child{
    position:sticky;bottom:0;z-index:20;
    margin:12px -10px 0;border-radius:14px 14px 0 0;
    box-shadow:0 -6px 20px rgba(0,0,0,.10);
    padding:12px 14px calc(12px + env(safe-area-inset-bottom,0px))!important;
    background:var(--card)!important;border:0!important;border-top:1px solid var(--border)!important;
  }
  #ctTotal{font-size:26px!important}
  #ctSaveBtn{width:100%!important;min-height:52px!important;font-size:17px!important}

  /* ── 5. THE PAYMENT MODE BUTTONS: three across, thumb-sized ───────────── */
  #ctMode_cash,#ctMode_card,#ctMode_upi{
    flex:1 1 0!important;min-height:46px!important;font-size:14px!important;
  }
}

/* ══════════ THE ITEMS LIST ON A PHONE ══════════
   ⭐ THE SAME PATTERN THAT WORKED ON THE COUNTER, and his verdict there was
   "excellent alignment no issues": the table becomes CARDS, driven by CSS on the
   SAME markup, so the phone view and the desktop table can never disagree.

   ⚠ THIRTEEN COLUMNS: 1 checkbox · 2 name+photo · 3 code · 4 HSN · 5 category ·
   6 unit · 7 buy · 8 sell · 9 margin · 10 GST% · 11 GST type · 12 status ·
   13 actions. On a 380px screen that is thirteen unreadable slivers.

   ⭐ WHAT A SHOPKEEPER ACTUALLY NEEDS AT A GLANCE: the name, the selling price,
   and the buttons. Everything else is secondary, so it goes small and grey on a
   second line — and HSN and GST type are HIDDEN entirely, because nobody opens a
   phone to read an HSN code. They are still there on the desktop. */
@media(max-width:640px){

  #itemsCard table.items-table,
  #itemsCard table.items-table tbody{display:block;width:100%;min-width:0!important}
  #itemsCard table.items-table{overflow:visible!important;border:0}
  #itemsCard table.items-table thead{display:none}

  #itemsCard table.items-table tr{
    display:grid;
    grid-template-columns:auto 1fr auto;
    gap:3px 10px;align-items:start;
    border:1px solid var(--border);border-radius:10px;
    padding:11px 12px;margin-bottom:8px;background:var(--card);
  }
  #itemsCard table.items-table td{
    display:block;border:0!important;padding:0!important;text-align:left!important;
  }

  /* the tick stays where a thumb expects it, top left */
  #itemsCard table.items-table td:nth-child(1){grid-column:1;grid-row:1;padding-top:2px!important}
  /* the name leads, and takes the room it needs */
  #itemsCard table.items-table td:nth-child(2){
    grid-column:2;grid-row:1;font-weight:600;font-size:14.5px;line-height:1.3;
  }
  /* ⭐ THE SELLING PRICE IS THE ONE FIGURE THAT MATTERS, so it is large and sits
     opposite the name where the eye lands. */
  #itemsCard table.items-table td:nth-child(8){
    grid-column:3;grid-row:1;text-align:right!important;
    font-size:16px!important;font-weight:700;font-family:var(--num);white-space:nowrap;
  }

  /* code, category, unit, buy and margin run together as one small grey line */
  #itemsCard table.items-table td:nth-child(3),
  #itemsCard table.items-table td:nth-child(5),
  #itemsCard table.items-table td:nth-child(6),
  #itemsCard table.items-table td:nth-child(7),
  #itemsCard table.items-table td:nth-child(9),
  #itemsCard table.items-table td:nth-child(10){
    grid-column:2 / -1;display:inline!important;
    font-size:12px!important;color:var(--muted);margin-right:9px!important;
  }
  /* ⚠ HIDDEN, NOT SHRUNK. Nobody picks up a phone to read an HSN code or to check
     whether a price is GST-inclusive. Both are one tap away on the item itself,
     and both are still on the desktop table. */
  #itemsCard table.items-table td:nth-child(4),
  #itemsCard table.items-table td:nth-child(11){display:none!important}

  /* the status chip sits with the small line rather than owning a row */
  #itemsCard table.items-table td:nth-child(12){
    grid-column:2 / -1;display:inline!important;margin-right:9px!important;
  }
  /* the buttons get their own row, right-aligned, full touch size */
  #itemsCard table.items-table td:nth-child(13){
    grid-column:1 / -1;margin-top:8px!important;
  }
  #itemsCard table.items-table td:nth-child(13) > div{justify-content:flex-end}

  #itemsCard table.items-table .empty-row{
    grid-column:1 / -1;text-align:center!important;color:var(--muted);padding:20px 0!important;
  }
  /* a grouped-style row spans everything - it is a heading, not an item */
  #itemsCard table.items-table td[colspan]{grid-column:1 / -1}

  /* ── THE FILTER BAR ──────────────────────────────────────────────────────
     ⭐ SEARCH FIRST, FULL WIDTH, because that is what a person opens the items
     screen to do. The four dropdowns below it go two across - one per row wastes
     four rows of screen before any item appears, and they are short labels. */
  #itSearch{grid-column:1 / -1!important;font-size:16px!important}
  /* ⚠ itPageSizeSelect, NOT itPerPage - I wrote the latter from the pattern and no
     such element exists. THIRTEENTH WRONG NAME FROM MEMORY THIS WEEK, and a CSS
     rule pointing at a wrong id is the quietest failure of all: nothing errors,
     the page just looks slightly wrong and nothing says why. */
  #itFilterCategory,#itFilterBrand,#itFilterPriceType,#itPageSizeSelect{
    font-size:14px!important;
  }
  /* ⛔⛔ THE WRAPPERS WERE THE PROBLEM, NOT THE FIELDS. He reported the filters
     "coming side by side which is overlapping", and he was right: each field sits
     in its own div carrying flex:2 and min-width:180px. I had cleared min-width on
     the INPUT but never on the DIV around it, so five wrappers each still demanded
     100-180px and squeezed together on a 380px screen.
     ⇒ THE LESSON: clearing a width on the child is useless while the parent still
     reserves the space. Look at what CONTAINS the thing, not only the thing.
     ⭐ Search takes the full row - it is what the screen is for. The four short
     dropdowns go two across, which reads cleanly and saves three rows. */
  #itemsCard > div[style*="display:flex"]{
    flex-wrap:wrap!important;gap:8px 8px!important;
  }
  #itemsCard > div[style*="display:flex"] > div{
    min-width:0!important;
    flex:1 1 calc(50% - 4px)!important;
  }
  /* the search wrapper is the one that spans */
  #itemsCard > div[style*="display:flex"] > div:has(> #itSearch){
    flex:1 1 100%!important;
  }
  /* labels shrink so the pair of dropdowns is not two lines of heading */
  #itemsCard > div[style*="display:flex"] > div > label{
    font-size:10.5px!important;margin-bottom:2px!important;
  }
  /* ⚠ AND THE CHIPS MUST NOT PUSH THE PAGE SIDEWAYS. They are removable filters,
     so there can be five of them, and a phone has room for two. */
  /* ⚠ itFilterChips, not itChips - same fault, checked and corrected. */
  #itFilterChips{flex-wrap:wrap!important}
}

/* ══════════ THE PURCHASE SCREEN ON A PHONE ══════════
   ⚠⚠ THIS ONE IS DIFFERENT FROM THE CART AND THE ITEMS LIST, and the difference
   decides the design. Those two show TEXT, so a card is simply a restack. A
   purchase line is SEVEN BOXES YOU TYPE INTO, and a card per line makes each row
   a tall form - ten items means scrolling through ten tall forms.
   ⇒ He chose this anyway, and he is right that the alternative (sideways
   scrolling) is not an app. So the job is to make the tall form GOOD: every box
   thumb-sized, every box labelled, and the short ones sharing a row.

   ⭐ LABELS COME FROM CSS ::before, not from new markup. Without the table header
   there is no way to tell Qty from Cost - and adding labels in the JS would mean
   the desktop table grew a second set of headings. */
@media(max-width:640px){

  #puPaneNew table.items-table,
  #puPaneNew table.items-table tbody{display:block;width:100%;min-width:0!important}
  #puPaneNew table.items-table{overflow:visible!important;border:0}
  #puPaneNew table.items-table thead{display:none}

  #puPaneNew table.items-table tr{
    display:grid;
    grid-template-columns:1fr 1fr 1fr;
    gap:8px;align-items:end;
    border:1px solid var(--border);border-radius:10px;
    padding:12px;margin-bottom:10px;background:var(--card);
  }
  #puPaneNew table.items-table td{
    display:block;border:0!important;padding:0!important;text-align:left!important;
    min-width:0;
  }
  /* every field fills its cell */
  #puPaneNew table.items-table td input,
  #puPaneNew table.items-table td select{
    width:100%!important;max-width:100%!important;min-width:0!important;
  }

  /* ⭐ THE LABEL, ADDED BY CSS. The header row is hidden, so each box says what it
     is. Small and grey, sitting just above the field. */
  #puPaneNew table.items-table td::before{
    display:block;font-size:10px;font-weight:700;letter-spacing:.04em;
    text-transform:uppercase;color:var(--muted);margin-bottom:3px;
  }

    /* ⛔⛔ I GOT THIS WRONG TWICE AND HE CAUGHT BOTH. First I labelled by the table
     header without checking; then I "corrected" it from a regex that matched only
     the cells written as literal '<td...' strings - and CELL 2 IS NOT ONE. It comes
     from puSizeCell(i, l), a function call on line 16 of puRender, and my pattern
     could not see it. On that wrong count of seven I also DELETED the "Size"
     heading from the desktop table, breaking a screen that had been correct.
     ⇒⇒ THE COMMENT INSIDE puRender SAID THE ANSWER ALL ALONG: "ONE cell per column,
     EIGHT in all: item, size, qty, cost, batch, expiry, amount, remove."
     ⇒ READ THE FUNCTION. A regex over generated markup finds only the cells that
     happen to be written the way the regex expects.
     ⭐ AND puSizeCell ALWAYS RETURNS EXACTLY ONE <td> - both of its branches do -
     so the count is eight on every row, and fixed positions are safe. That was
     worth checking: if some rows had seven cells and some eight, no nth-child
     scheme could work at all. */

  /* 1 Item - the whole width, it is the longest thing on the row */
  #puPaneNew table.items-table td:nth-child(1){grid-column:1 / -1}
  #puPaneNew table.items-table td:nth-child(1)::before{content:"Item"}
  /* 2 Size - the pack or the base unit, with the conversion beneath it */
  #puPaneNew table.items-table td:nth-child(2){grid-column:1 / -1}
  #puPaneNew table.items-table td:nth-child(2)::before{content:"Size"}
  /* 3 Qty (which also holds the "recd" box) · 4 Cost - side by side */
  #puPaneNew table.items-table td:nth-child(3){grid-column:1 / 3}
  #puPaneNew table.items-table td:nth-child(3)::before{content:"Qty / received"}
  #puPaneNew table.items-table td:nth-child(4){grid-column:3}
  #puPaneNew table.items-table td:nth-child(4)::before{content:"Cost \20B9"}
  /* 5 Batch · 6 Expiry */
  #puPaneNew table.items-table td:nth-child(5){grid-column:1 / 3}
  #puPaneNew table.items-table td:nth-child(5)::before{content:"Batch"}
  #puPaneNew table.items-table td:nth-child(6){grid-column:3}
  #puPaneNew table.items-table td:nth-child(6)::before{content:"Expiry"}
  /* 7 Amount - the figure that matters */
  #puPaneNew table.items-table td:nth-child(7){
    grid-column:1 / 3;text-align:right!important;align-self:center;
    font-size:17px;font-weight:700;font-family:var(--num);padding-top:4px!important;
  }
  #puPaneNew table.items-table td:nth-child(7)::before{content:"Amount";text-align:right}
  /* 8 remove */
  #puPaneNew table.items-table td:nth-child(8){
    grid-column:3;text-align:right!important;align-self:center;
  }
  #puPaneNew table.items-table td:nth-child(8)::before{content:none}

  /* ⚠ AND THE IN-TABLE NUMBER-BOX RULE FROM PHASE 4 MUST NOT APPLY HERE. That rule
     keeps quantity boxes narrow inside a real table row - correct on the counter,
     wrong here, where the row IS the form. */
  #puPaneNew table.items-table input[type=number],
  #puPaneNew table.items-table input[type=text]{
    width:100%!important;max-width:100%!important;
  }

  /* the totals strip below the lines stacks instead of splitting */
  #puPaneNew > div[style*="justify-content:space-between"]{
    flex-wrap:wrap!important;gap:10px!important;
  }
  #puAddRowBtn,#puPaneNew .btn-primary{width:100%!important;min-height:48px!important}
}

/* ═══ THE SKELETON ROW ══════════════════════════════════════
   Shown while a slow screen loads. Grey bars rather than faded real rows,
   because a faded row can still be misread as the answer - and they hold the
   table's height so nothing jumps when the data arrives. */
/* ⛔ THE FIRST VERSION FADED EVERY BAR AT THE SAME INSTANT, and his verdict was
   fair: it read as a broken table rather than a loading one. A gradient that
   TRAVELS across is read as activity by anyone who has used a modern app. */
.rpr-skel {
  height: 12px; border-radius: 4px;
  background: linear-gradient(90deg, var(--bg) 25%, var(--border) 37%, var(--bg) 63%);
  background-size: 200% 100%;
  animation: rpr-skel-sweep 1.6s linear infinite;
}
@keyframes rpr-skel-sweep { 0% { background-position: 200% 0 } 100% { background-position: -200% 0 } }

/* The spinner, the progress line and the sentence that says WHAT is happening.
   ⭐ THE SENTENCE IS THE VALUABLE HALF AND IT IS NOT ANIMATION AT ALL: nobody
   minds three seconds when they can see it is reading a million rows. The same
   three seconds unexplained feels broken - which was his actual complaint. */
.rpr-load-bar { position: relative; height: 3px; background: var(--card); overflow: hidden; }
.rpr-load-bar > i { position: absolute; top: 0; height: 3px; width: 35%;
  background: var(--accent); animation: rpr-load-run 1.1s ease-in-out infinite; }
@keyframes rpr-load-run { 0% { left: -35% } 100% { left: 100% } }
.rpr-spin { width: 15px; height: 15px; flex: none; border: 2px solid var(--border-strong);
  border-top-color: var(--accent); border-radius: 50%;
  animation: rpr-spin-turn .7s linear infinite; }
@keyframes rpr-spin-turn { to { transform: rotate(360deg) } }
.rpr-load-note { display: flex; align-items: flex-start; gap: 8px; padding: 9px 2px 3px; }

/* ═══ THE WAITING INDICATOR ════════════════════════════════════════════════
   [stated] his choice of the nine shapes shown on 30 Sep: rising bars. They suit a
   retail app - a till printing, stock moving - where a plain turning circle says
   nothing about the product.
   ⚠ ONE PLACE, used by rprLoading() in core.js and nowhere else. 145 places in the
   app wrote "Loading..." as bare text; a spinner written separately into each of them
   is 143 chances to drift.
   ⚠ THE BARS ARE CURRENT-COLOUR, so they take the colour of whatever box they sit in
   and work in both the light and the dark theme without a second rule. */
.rpr-load{display:flex;align-items:center;gap:10px;justify-content:center}
.rpr-load-bars{display:flex;gap:3px;align-items:center;height:16px;flex:none}
.rpr-load-bars i{display:block;width:3px;height:16px;border-radius:2px;
  background:var(--accent,#2f6fed);transform-origin:center;
  animation:rprLoadBar .9s ease-in-out infinite}
.rpr-load-bars i:nth-child(2){animation-delay:.12s}
.rpr-load-bars i:nth-child(3){animation-delay:.24s}
.rpr-load-bars i:nth-child(4){animation-delay:.36s}
@keyframes rprLoadBar{0%,100%{transform:scaleY(.35)}50%{transform:scaleY(1)}}
.rpr-load-txt{font-size:13px;color:var(--muted);text-align:left}
.rpr-load-sub{font-size:11px;color:var(--hint);margin-top:2px}
/* ⚠ RESPECTS THE SHOP'S OWN SETTING. A person who has asked their device to stop
   moving things gets a still bar, not a jumping one - and still knows it is waiting. */
@media (prefers-reduced-motion:reduce){
  .rpr-load-bars i{animation:none;transform:scaleY(.7);opacity:.6}
}


/* SIGNED OUT WHILE WORKING - js/session-expiry.js. The login box opens ON TOP
   of the current screen, which stays underneath untouched, so nothing typed
   is lost. */
body.rpr-relogin{overflow:hidden}
body.rpr-relogin #login-screen{position:fixed;inset:0;z-index:10000;min-height:0;background:rgba(15,23,42,.55)}
#msgBox .msg.info{background:#eff6ff;color:#1e3a8a;border:1px solid #bfdbfe;border-radius:8px;padding:10px 12px;font-size:13px;line-height:1.45}
