/* Khaas Hub — mobile-first, brand-styled, big tap targets */
:root{
  --charcoal:#1f4239; --gold:#D4AF37; --cream:#f9f8f4;
  --ink:#222; --muted:#666; --line:#e4e2da; --danger:#9c2a2a;
  --new:#8a6d3b; --ready:#1f4239; --dispatch:#2b5f8a; --deliver:#3a7a3a;

  /* One radius scale, one shadow, one focus ring.

     Before these existed, a card was 10px on one screen, 12px on the next, 14px
     on a third and 18px on the login box — not by decision, but because each
     screen was written on a different day. Nobody notices any single one of
     them; everybody notices the result, which is an app that looks assembled
     rather than designed. Change a value here and every screen moves together. */
  --r-card:14px;      /* anything that holds content */
  --r-ctl:10px;       /* anything you type in or press */
  --r-pill:999px;     /* badges and tabs */
  --surface:#fff;
  --surface-sunk:#fbfaf7;
  --shadow:0 1px 2px rgba(31,66,57,.05), 0 1px 3px rgba(31,66,57,.05);
  --shadow-up:0 6px 18px rgba(31,66,57,.10);
  --gap:12px;
}
*{box-sizing:border-box}
body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  background:var(--cream);color:var(--ink);font-size:17px;line-height:1.45}
a{color:var(--charcoal)}

/* One visible focus ring, everywhere.

   Several screens had their own (the search box had a gold outline, nothing
   else did), which meant that tabbing through the app the ring appeared and
   disappeared and you could not tell whether you had lost your place. It is
   :focus-visible, so it shows for the keyboard and not for a thumb. */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--gold);outline-offset:2px;border-radius:6px}

/* Money and counts line up in a column when the digits are the same width.
   Without this, "Rs. 1,450" and "Rs. 38,643" in a stack of figures wander. */
b,strong,.money-big b,.detail-row b,.exp-amt,.cust-paid,.home-card-n{
  font-variant-numeric:tabular-nums}

/* Top bar */
.topbar{background:var(--charcoal);color:#fff;position:sticky;top:0;z-index:10}

/* Phone first. The brand and the signed-in name share the top line; the menu
   sits underneath as one full-width row of equal buttons. Letting the links
   wrap around the brand produced a ragged three-line block on a phone. */
.topbar-inner{max-width:900px;margin:0 auto;padding:10px 14px;
  display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px}
.brand{order:1;display:flex;align-items:center;gap:8px;font-weight:700;font-size:18px;
  color:var(--gold);margin-right:auto;text-decoration:none;
  /* flex:none and nowrap: on a wide screen the top bar is a nowrap flex row,
     and the brand was being squeezed by the eight nav links until it broke
     across two lines as "Khaas / Hub" beside the logo. */
  flex:none;white-space:nowrap}
.brand img{width:26px;height:26px;border-radius:50%;display:block;background:#fff}
.who{order:2;white-space:nowrap}

/* 🔴 A GRID, NOT A FLEX ROW — because the flex row silently cut links off.

   It was `display:flex` with `flex:1` and `white-space:nowrap` on each link.
   That is fine for four links. This app now has eight, and eight nowrap links
   cannot fit across a phone: the row overflowed the screen and **Customers and
   Team were unreachable on a phone**, half-drawn at the right edge. Nothing
   said so — they were simply gone, on the device the app is mostly used on.

   Four fixed columns wrap to a second row instead, so every link is on screen
   and every target is the same thumb-sized rectangle. */
.mainnav{order:3;flex-basis:100%;display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.mainnav a{text-align:center;color:#fff;text-decoration:none;
  padding:10px 4px;border-radius:8px;font-size:14px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  background:rgba(255,255,255,.06)}
.mainnav a.active{background:rgba(255,255,255,.22);font-weight:600}
.mainnav a:active{background:rgba(255,255,255,.3)}

/* Roomier screens: back to a single line. */
@media (min-width:720px){
  .topbar-inner{flex-wrap:nowrap}
  .brand{margin-right:18px}
  .mainnav{order:2;flex-basis:auto;flex:1;display:flex;gap:4px}
  .mainnav a{flex:0 0 auto;text-align:left;padding:8px 12px;font-size:15px;background:none}
  .who{order:3}
}
.who{font-size:13px;color:rgba(255,255,255,.85)}
.who a{color:var(--gold)}

.container{max-width:900px;margin:0 auto;padding:16px 14px 60px}

/* Page head, and the type scale.

   Three sizes and no more: the page title, a section heading, and body. A
   fourth size always turns out to be somebody's idea of "slightly more
   important", which nobody else can see. */
.page-head,.detail-head{display:flex;align-items:center;justify-content:space-between;
  gap:12px;margin-bottom:18px;flex-wrap:wrap}
.page-head h1,.detail-head h1{font-size:23px;margin:0;letter-spacing:-.01em}
.section-h{font-size:17px;margin:26px 0 10px;color:var(--charcoal);letter-spacing:-.005em}
/* The first heading on a page should not push everything down twice. */
.section-h:first-child{margin-top:0}
.section-note{color:var(--muted);font-size:14px;line-height:1.5;margin:8px 0 0}
.back{display:inline-block;margin-bottom:12px;text-decoration:none;color:var(--muted);font-size:15px}
.back:hover{color:var(--charcoal)}

/* Every white panel in the app, wherever it was written. Collected here so
   that a card is a card — same corner, same edge, same lift off the page. */
.tile,.form,.detail-box,.item-card,.exp-row,.cust-row,.cust-order,.export-row,
.home-card,.due-row,.low-row,.money-big,.money-block,.wa-box,.filters,.stock-row,
.team-card,.note-card{box-shadow:var(--shadow)}

/* Buttons — big tap targets.

   Every button in the app is one of three things and now looks like it: the
   one action on the screen (filled charcoal), a second choice (outlined), or
   buying something (gold, which is the colour this app uses for "your move").
   They were drifting apart — some 46px tall, some 38, some with a border and
   some without — so a screen with two buttons looked like two different apps. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  border:1px solid transparent;border-radius:var(--r-ctl);padding:12px 18px;font-size:16px;
  font-weight:600;cursor:pointer;text-decoration:none;text-align:center;
  min-height:46px;line-height:1.3;transition:background-color .12s,box-shadow .12s}
.btn-primary{background:var(--charcoal);color:#fff;box-shadow:var(--shadow)}
.btn-primary:hover{background:#295448}
.btn-light,.btn-status{background:var(--surface);color:var(--charcoal);border-color:var(--line)}
.btn-light:hover,.btn-status:hover{background:var(--surface-sunk);border-color:#d5d2c7}
.btn-buy{background:var(--gold);color:#3d3009;padding:10px 16px;box-shadow:var(--shadow)}
.btn-buy:hover{background:#c9a531}
.btn:active{transform:translateY(1px)}
.btn-block{display:flex;width:100%;margin-top:8px}
/* Small, for a control that sits inside a row rather than under it. */
.btn-sm{min-height:38px;padding:8px 14px;font-size:15px}

/* Tiles (order list) */
.tiles{display:grid;grid-template-columns:1fr;gap:12px}
@media(min-width:640px){.tiles{grid-template-columns:1fr 1fr}}
.tile{display:block;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-card);
  padding:14px;text-decoration:none;color:var(--ink)}
.tile:active{background:#faf9f5}
.tile-urgent{border-color:var(--gold);border-width:2px}
.tile-top{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px}
.tile-order{font-weight:700;color:var(--charcoal)}
.tile-customer{font-size:18px;font-weight:600;margin-bottom:8px}
.tile-meta{display:flex;flex-wrap:wrap;gap:8px 16px;font-size:14px;color:var(--muted)}
.tile-meta span,.tile-date,.tile-progress{display:inline-flex;align-items:center;gap:6px}
/* Line icons, in the colour and at the size of the text they sit beside. */
.ico{width:1.05em;height:1.05em;flex:none;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;opacity:.65}

/* Badges */
.badge{display:inline-flex;align-items:center;font-size:12px;font-weight:700;padding:5px 11px;
  border-radius:var(--r-pill);color:#fff;white-space:nowrap;letter-spacing:.01em;line-height:1}
.badge-New{background:var(--new)}
.badge-ReadytoPack{background:var(--ready)}
.badge-Dispatched{background:var(--dispatch)}
.badge-Delivered{background:var(--deliver)}
.badge-Returned{background:var(--danger)}

/* Detail */
.detail-customer{font-size:18px;font-weight:600;margin-bottom:12px}
.detail-box{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-card);padding:4px 16px;margin-bottom:8px}
.detail-row{display:flex;justify-content:space-between;gap:12px;padding:9px 0;border-bottom:1px solid var(--line)}
.detail-row:last-child{border-bottom:none}
.detail-row span{color:var(--muted)}

/* Item cards — big, tappable */
.items-list{display:flex;flex-direction:column;gap:10px}
.item-card{display:flex;justify-content:space-between;align-items:flex-start;gap:14px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-card);padding:14px}
.item-done{background:#f2f6f2;border-color:#cfe0cf}
/* Bigger throughout. This is read one-handed, in daylight, in a market. */
.item-name{font-size:19px;font-weight:600}
.item-desc{font-size:15px;color:var(--muted);margin-top:2px}
.item-sub{display:flex;flex-wrap:wrap;gap:10px;margin-top:6px;font-size:15px}
.target{color:var(--muted)} .paid{color:var(--deliver);font-weight:600} .qty{color:var(--muted)}

/* Paid more than the target. Red on the number itself and said in words next to
   it, because colour alone is no use to anyone who cannot easily tell these two
   apart — and no use at all in bright sunlight. */
.paid-over{color:var(--danger)}
.over-note{color:var(--danger);font-weight:600}

/* ---- Couldn't find it -------------------------------------------------- */
.item-missing{background:#fbf6ee;border-color:#e2d3b4}
.missing-tag{color:var(--new);font-weight:700;font-size:15px}
.not-found-note{margin-top:6px;color:var(--new);font-style:italic}
/* "Couldn't find it" is a fold too, but a quiet one inside a row rather than a
   card of its own — so it borrows the drawn chevron and nothing else. */
.not-found-panel{margin-top:10px}
.not-found-panel summary{display:flex;align-items:center;gap:8px;cursor:pointer;
  color:var(--muted);font-size:14px;list-style:none;padding:6px 0}
.not-found-panel summary::-webkit-details-marker{display:none}
.not-found-panel summary::before{content:"";flex:none;width:7px;height:7px;
  border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);
  transform:rotate(-45deg);transition:transform .15s}
.not-found-panel[open] summary::before{transform:rotate(45deg)}
.not-found-panel form{display:flex;flex-direction:column;gap:6px;margin-top:6px}
.not-found-panel textarea{width:100%;min-width:180px;padding:9px;font-size:16px;
  border:1px solid var(--line);border-radius:8px;font-family:inherit;resize:vertical}
.btn-missing{background:var(--new);color:#fff;padding:10px 14px;font-size:15px}
.btn-found{background:var(--charcoal);color:#fff;padding:10px 14px;font-size:15px}

/* What one row is doing right now. Lives beside the button rather than at the
   top of the page, because on a long list the top is off-screen. */
.row-status{font-size:13px;color:var(--muted);margin-top:6px;max-width:220px}
.row-status-error{color:var(--danger);font-weight:600}

/* ---- Packing sheet ----------------------------------------------------- */
/* Read while holding a box. Everything here is bigger than the rest of the app
   on purpose, and the card message biggest of all, because it is copied out by
   hand and a misread word ends up written on a gift. */
.btn-pack{background:var(--charcoal);color:#fff;margin:14px 0 4px;text-align:center;
  text-decoration:none;padding:14px 18px;font-size:17px}
.pack-who{color:var(--muted);margin-bottom:14px}
.pack-hint{color:var(--muted);max-width:60ch;margin:0 0 10px}
.pack-list{list-style:none;padding:0;margin:0 0 16px;display:flex;flex-direction:column;gap:8px}
.pack-item{display:flex;gap:12px;align-items:flex-start;background:#fff;
  border:1px solid var(--line);border-radius:12px;padding:14px}
.pack-item-missing{background:#fbf6ee;border-color:#e2d3b4}
.pack-n{flex:0 0 28px;height:28px;border-radius:50%;background:var(--charcoal);color:#fff;
  display:flex;align-items:center;justify-content:center;font-weight:700;font-size:15px}
.pack-what{display:flex;flex-direction:column;gap:2px;font-size:18px}
.pack-what .item-desc{font-size:15px}
.pack-block{background:#fff;border:1px solid var(--line);border-radius:12px;
  padding:14px;margin-bottom:16px}
.pack-label{display:block;color:var(--muted);font-size:13px;margin-bottom:8px;
  text-transform:uppercase;letter-spacing:.04em}
.pack-text{font-size:17px}

/* pre-wrap on both: the line breaks someone typed into a card message or an
   address ARE the formatting. Collapsing them turns an address into one run-on
   line and a three-line message into a paragraph. */
.pack-card{font-size:21px;line-height:1.6;white-space:pre-wrap;
  border-left:3px solid var(--gold);padding-left:14px}
.pack-address{font-size:19px;line-height:1.6;white-space:pre-wrap;user-select:all}
.pack-cost{margin-bottom:24px}

/* ---- Payments ---------------------------------------------------------- */
.form-note{color:var(--muted);font-size:14px;margin:4px 0 10px;line-height:1.5}
.pay-list{display:flex;flex-direction:column;gap:8px;margin-bottom:14px}
.pay-row{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;
  background:#fff;border:1px solid var(--line);border-radius:10px;padding:12px 14px}
.pay-main{display:flex;flex-direction:column;gap:2px}
.pay-main b{font-size:18px}
.pay-method{font-size:15px}
.pay-meta{color:var(--muted);font-size:13px}
.pay-form{margin-bottom:8px}

/* ---- Margin ------------------------------------------------------------ */
.margin-box{background:#fff;border:1px solid var(--line);border-radius:12px;
  padding:14px;margin-bottom:18px}
/* A margin worked out before everything is in is a guess. It looks different so
   nobody quotes it as a figure. */
.margin-provisional{background:#fbf6ee;border-color:#e2d3b4}
.margin-row{display:flex;justify-content:space-between;gap:12px;padding:5px 0;font-size:16px}
.margin-total{border-top:1px solid var(--line);margin-top:6px;padding-top:10px;font-size:19px}
.margin-note{color:var(--muted);font-size:13px;margin-top:8px;line-height:1.5}

/* A checkbox and its words on one line, with the words tappable. */
.check-line{display:flex;align-items:center;gap:10px;margin:6px 0 12px;font-weight:400}
.check-line input{width:20px;height:20px}

/* Sending a gift short an item. Deliberately in the way: this is the one action
   that removes work from the shopper's screen with nothing left to find it by. */
.status-form{display:inline-block}
.short-warn{background:#fbf6ee;border:1px solid #e2d3b4;border-radius:10px;
  padding:12px 14px;margin-bottom:10px;max-width:46ch;text-align:left;font-size:15px;
  line-height:1.5}
.short-warn b{display:block;color:var(--danger);margin-bottom:4px}

/* ---- Invoice link ------------------------------------------------------ */
.invoice-box{background:#fff;border:1px solid var(--line);border-radius:12px;
  padding:14px;margin-bottom:18px}
.btn-invoice{background:var(--gold);color:var(--charcoal);text-decoration:none;
  display:inline-block;margin-bottom:12px}
/* Readonly and full width so the whole link can be selected on a phone.

   🔴 16px, not 14px. It is readonly, but readonly does not mean unfocusable:
   tapping it to select the link is exactly what this box is FOR, and Safari on
   iPhone zooms the page in on any focused field under 16px and then leaves it
   zoomed. So the one control whose whole purpose is "tap me" was the one that
   broke the page. Found by a test that walks this stylesheet looking for a
   typable field below 16px, not by anybody noticing. */
.invoice-url{width:100%;padding:11px 12px;font-size:16px;font-family:ui-monospace,monospace;
  min-height:46px;border:1px solid var(--line);border-radius:var(--r-ctl);
  background:var(--surface-sunk);color:var(--muted)}
/* The column with the price box and the Bought button.

   It was `flex-shrink:0` and nothing else, so its width came out of whatever
   the input happened to be — and on a narrow phone the item's name was squeezed
   into a two-word column beside it. A floor and a ceiling: never so narrow that
   the button wraps, never so wide that it takes the screen off the item. */
.item-action{flex:0 0 auto;min-width:150px;max-width:190px}
@media (max-width:420px){
  /* Below this the two columns cannot both be honest. The item wins the width
     and the action sits under it, full width — which also makes the Bought
     button a bigger target, in a market, one-handed. */
  .item-card{flex-direction:column;align-items:stretch}
  .item-action{min-width:0;max-width:none;width:100%}
  .price-in{width:100%}
  .item-action .btn{width:100%}
}
.buy-form{display:flex;flex-direction:column;gap:6px;align-items:stretch}
/* 17px, not 15px: iOS zooms the whole page in when a focused input is under
   16px, which throws the layout around every time he taps the box. */
.price-in{width:100%;padding:11px 12px;min-height:46px;border:1px solid var(--line);
  border-radius:var(--r-ctl);font-size:17px;background:var(--surface);color:var(--ink)}
.price-label{display:block;font-size:13px;color:var(--muted);margin-bottom:2px}
.bought-tag{color:var(--deliver);font-weight:700;font-size:15px}

/* A bought item with no price on record. Red, and in words, because the number
   is missing rather than zero - and only an older row can be in this state now
   that an empty price box is refused. */
.paid-missing{color:var(--danger);font-weight:700}

/* Correcting a recorded price. A <details> rather than a button that reveals a
   form, because the page carries no inline JavaScript and this needs none. */
/* "Fix price" and "Couldn't find it" are the two quiet folds that live inside a
   row rather than as a card of their own. Same drawn chevron as everything
   else — this one was still showing the browser's own triangle. */
.fix-price{margin-top:10px}
.fix-price summary{display:flex;align-items:center;gap:8px;cursor:pointer;
  color:var(--muted);font-size:14px;list-style:none;padding:6px 0}
.fix-price summary::-webkit-details-marker{display:none}
.fix-price summary::before{content:"";flex:none;width:7px;height:7px;
  border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);
  transform:rotate(-45deg);transition:transform .15s}
.fix-price[open] summary::before{transform:rotate(45deg)}
/* The status block sits directly under the summary box now, not at the foot of
   the page: pressing the next step is the commonest thing anyone does here. */
.status-steps{margin-top:4px}
.fix-price form{display:flex;flex-direction:column;gap:6px;margin-top:6px}
.btn-fix{background:var(--charcoal);color:#fff;padding:8px 12px;font-size:14px}

/* ---- Team screen ------------------------------------------------------- */
/* Deliberately plain. It is opened rarely, and when it is opened it is because
   something has gone wrong and the person is in a hurry. */
.team-intro{color:var(--muted);max-width:60ch;margin:0 0 16px}
.notice{background:#eaf3ec;border:1px solid #bcd7c1;color:#2c5c36;
        padding:10px 12px;border-radius:8px;margin-bottom:14px}
.team-list{display:flex;flex-direction:column;gap:10px}
.team-card{display:flex;justify-content:space-between;align-items:center;gap:12px;
           background:#fff;border:1px solid var(--line);border-radius:12px;padding:14px}
.team-card-locked{background:#fdf3f3;border-color:#e6c4c4}
.team-name{font-weight:700}
.team-role{font-weight:400;color:var(--muted);font-size:13px;margin-left:6px}
.team-sub{color:var(--muted);font-size:13px;margin-top:4px;
          display:flex;flex-wrap:wrap;gap:4px 12px}
.team-locked-tag{color:var(--danger)}
.team-you{color:var(--muted);font-size:13px}
.btn-lock{background:var(--surface);color:var(--danger);border:2px solid var(--danger);width:100%}
.btn-lock:hover{background:#fff5f5}
.btn-unlock{background:var(--charcoal);color:#fff;padding:10px 16px}

/* On a phone the card stacks so the button never gets squeezed to nothing. */
@media (max-width:480px){
  .team-card{flex-direction:column;align-items:stretch}
  .team-action .btn{width:100%}
}

/* Status actions */
.status-actions{margin-top:20px;display:flex;flex-wrap:wrap;gap:10px}
.status-cur{padding:12px 0;color:var(--muted);font-weight:600}

/* Forms */
.form{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-card);padding:16px;margin-bottom:16px}
.form label,fieldset label{display:block;font-size:14px;font-weight:600;color:var(--charcoal);
  margin:12px 0 5px}
.form input,.form select,.form textarea,fieldset input,fieldset select,fieldset textarea{
  width:100%;padding:12px;border:1px solid var(--line);border-radius:var(--r-ctl);font-size:16px;
  font-family:inherit;background:var(--surface);color:var(--ink);min-height:46px}
.form textarea,fieldset textarea{min-height:auto}
/* A placeholder is a hint, not content. It was the same colour as a real
   answer, so a filled field and an empty one looked alike at a glance. */
::placeholder{color:#9a968c;opacity:1}
fieldset{border:1px solid var(--line);border-radius:var(--r-card);padding:14px 16px 18px;
  margin:0 0 16px;background:var(--surface);box-shadow:var(--shadow)}
legend{font-weight:700;color:var(--charcoal);padding:0 8px;font-size:15px}
.or{text-align:center;color:var(--muted);font-size:13px;margin:12px 0 4px}
.item-row{border:1px dashed var(--line);border-radius:10px;padding:10px;margin-bottom:10px}
.item-row input{margin-bottom:6px}
.item-row-2{display:flex;gap:8px}
.item-row-2 input{margin-bottom:0}
.add-supply select{margin-bottom:4px}

/* Expenses */
.exp-total{background:var(--charcoal);color:#fff;padding:12px 16px;border-radius:10px;
           display:flex;flex-wrap:wrap;justify-content:space-between;gap:6px 20px;
           margin-bottom:12px;font-size:15px}
.exp-total b{color:var(--gold)}

/* A list that stops at a limit says so. Quiet grey, under the list, because it
   is context rather than a warning. */
.list-note{color:var(--muted);font-size:13px;margin-top:12px;line-height:1.5}
.exp-list{display:flex;flex-direction:column;gap:8px}
.exp-row{display:flex;justify-content:space-between;gap:12px;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-card);padding:13px 15px}
.exp-desc{color:var(--muted)} .exp-meta{font-size:13px;color:var(--muted);margin-top:3px}
.exp-amt{font-weight:700;color:var(--charcoal);white-space:nowrap}

/* Empty / alert */
.empty{text-align:center;color:var(--muted);padding:34px 18px;background:var(--surface);
  border:1px dashed var(--line);border-radius:var(--r-card);line-height:1.5}
.alert{background:#fff3f3;border:1px solid #f0caca;color:var(--danger);padding:13px 15px;
  border-radius:var(--r-ctl);margin-bottom:12px;font-weight:600}

/* Login */
/* Login screen — brand colour behind, a single clear card on top. */
.login-body{display:flex;align-items:center;justify-content:center;min-height:100vh;
  padding:24px 16px;background:var(--charcoal)}
.login-card{background:#fff;border-radius:18px;padding:30px 24px 26px;
  width:100%;max-width:380px;box-shadow:0 18px 40px rgba(0,0,0,.28)}
.login-head{text-align:center;margin-bottom:6px}
/* The business has a logo and the one screen everybody sees first did not use
   it. It is the only picture on the page, so it can be large and calm. */
.login-mark{width:72px;height:72px;border-radius:50%;display:block;margin:0 auto 12px;
  box-shadow:0 2px 10px rgba(31,66,57,.18)}
.login-title{color:var(--charcoal);text-align:center;margin:0;font-size:27px}
.login-title::after{content:"";display:block;width:44px;height:3px;background:var(--gold);
  border-radius:2px;margin:12px auto 0}
.login-sub{margin:12px 0 0;color:var(--muted);font-size:13px;text-align:center}
.login-card label{display:block;font-weight:600;margin:16px 0 6px;font-size:14px}
.login-card input{width:100%;padding:13px 14px;border:1px solid var(--line);
  border-radius:10px;font-size:16px}
.login-card input:focus{outline:none;border-color:var(--charcoal);
  box-shadow:0 0 0 3px rgba(31,66,57,.13)}
/* Show/hide button sits inside the password box */
.pw-field{position:relative}
.pw-field input{padding-right:78px}
.pw-toggle{position:absolute;top:50%;transform:translateY(-50%);right:5px;
  border:0;background:transparent;color:var(--charcoal);font-weight:600;
  font-size:13px;padding:11px 12px;border-radius:8px;cursor:pointer}
.pw-toggle:active{background:var(--cream)}
.login-submit{margin-top:22px}

/* Reference photos (item screens) */
.item-photos{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:10px}
.photo-thumb{position:relative;width:64px;height:64px;border-radius:8px;overflow:hidden;
  border:1px solid var(--line);background:#fff;flex:0 0 auto}
.photo-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.photo-del{position:absolute;top:2px;right:2px;width:22px;height:22px;border:0;border-radius:50%;
  background:rgba(0,0,0,.6);color:#fff;font-size:15px;line-height:1;cursor:pointer;padding:0}
.photo-del:disabled{opacity:.5}
/* Big tap target — this gets used one-handed at a market */
/* Wide enough to read as "add a picture here" rather than a stray dashed
   square in the corner of a form. */
.photo-add{display:flex;align-items:center;justify-content:center;gap:8px;
  min-width:120px;height:64px;padding:0 14px;
  border:1px dashed var(--charcoal);border-radius:8px;color:var(--charcoal);font-size:13px;
  text-align:center;cursor:pointer;background:#fff;flex:0 0 auto}
.photo-add:active{background:var(--cream)}
.photo-status{flex-basis:100%;font-size:13px;color:var(--muted);min-height:1em}
.photo-status-error{color:var(--danger)}

/* A photo whose file aged off disk 30 days after delivery. The record is still
   there, so the strip shows a quiet marker rather than a gap or a broken image. */
.photo-thumb-gone{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:2px;border-style:dashed;border-color:var(--line,#ddd);background:#fafafa;cursor:help}
.photo-gone-mark{font-size:18px;opacity:.45;line-height:1}
.photo-gone-text{font-size:9px;letter-spacing:.02em;color:var(--muted);text-transform:uppercase}
.photo-gone-note{flex-basis:100%;font-size:12px;color:var(--muted);margin-top:2px}

/* Photos being picked on the New Order form, before the order is saved */
.item-photos-new{margin-top:4px}
.photo-thumb-staged{border-style:dashed;border-color:var(--gold)}
.photo-thumb-staged img{width:100%;height:100%;object-fit:cover;display:block}
.save-status{margin-top:8px;font-size:14px;color:var(--muted);text-align:center;min-height:1em}

/* The single To Buy list (items from every active order) */
.buy-summary{color:var(--muted);font-size:14px;margin:-4px 0 12px}
.buy-for{font-size:13px;color:var(--muted);margin-bottom:4px;display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.buy-for a{font-weight:600;text-decoration:none}
.buy-for-supply{font-weight:600;color:var(--charcoal)}
.buy-date{color:var(--muted);display:inline-flex;align-items:center;gap:5px}
.buy-date-soon{color:var(--danger);font-weight:600}

/* Order progress: ✓ Ready to Pack → ✓ Dispatched → ○ Delivered */
.status-steps{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:18px 0 10px;
  font-size:14px;color:var(--muted)}
.step{white-space:nowrap}
.step-done{color:var(--ready);font-weight:600}
.step-arrow{color:var(--line)}
.status-undo{margin-top:10px;font-size:13px;color:var(--muted);display:flex;
  flex-wrap:wrap;align-items:center;gap:8px}

/* Search and filters on the order list.

   🔴 THIS WAS THE UGLIEST THING IN THE APP and it was a layout accident, not a
   choice. The status box, a bare word "Out", a date, the word "to" and a second
   date were five flex children of one wrapping row. On a phone they broke
   wherever they happened to run out of room: "Out" ended up on one line with
   its date, "to" fell onto the next with its own, the two dates were different
   widths, and the Search button sat alone against the left edge looking like it
   belonged to something else. Nothing was aligned with anything.

   It is a grid now, and every field carries a real label above it instead of a
   stray word beside it. One column on a phone, three across when there is room.
   The labels are also what a screen reader reads out, which "to" was not. */
.filters{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-card);
  padding:14px;margin-bottom:16px;display:grid;gap:12px}
.filters-q{width:100%;min-width:0;font-size:16px;padding:13px 14px;min-height:46px;
  border:1px solid var(--line);border-radius:var(--r-ctl);background:var(--surface-sunk);color:var(--ink)}
.filters-q:focus{background:var(--surface)}
/* The two dates share a line from the start: they are one question — "between
   these days" — and stacking them put the Search button below the fold on a
   phone, which is the one control on this form nobody should have to hunt for. */
.filters-grid{display:grid;grid-template-columns:1fr;gap:12px}
.filters-grid .filters-field:nth-child(2),
.filters-grid .filters-field:nth-child(3){grid-column:span 1}
@media (min-width:340px){
  .filters-grid{grid-template-columns:1fr 1fr}
  /* Scoped to .filters: on the order list the first field is Status, which
     wants the full width above the two dates. The Money screen reuses this
     grid for two dates and nothing else, and there the first field is one of
     the pair — so an unscoped rule pushed "From" onto its own line there. */
  .filters .filters-grid .filters-field:first-child{grid-column:1 / -1}
}
.filters-field{display:flex;flex-direction:column;gap:5px;min-width:0}
.filters-field label{font-size:13px;font-weight:600;color:var(--muted)}
.filters-field select,.filters-field input[type="date"]{
  width:100%;font-size:16px;padding:11px 12px;min-height:46px;
  border:1px solid var(--line);border-radius:var(--r-ctl);background:var(--surface);
  color:var(--ink);font-family:inherit;min-width:0}
.filters-actions{display:flex;gap:10px}
.filters-actions .btn{flex:1 1 auto}

/* Roomier: the three fields side by side, and the buttons stop stretching. */
@media (min-width:560px){
  .filters-grid{grid-template-columns:1fr 1fr 1fr}
  .filters .filters-grid .filters-field:first-child{grid-column:auto}
  .period-custom .filters-grid{grid-template-columns:1fr 1fr}
  .filters-actions{justify-content:flex-start}
  .filters-actions .btn{flex:0 0 auto;min-width:120px}
}
@media (min-width:860px){
  .filters{grid-template-columns:minmax(220px,1fr) auto auto;align-items:end}
  .filters-q{grid-row:1}
  .filters-grid{grid-template-columns:auto auto auto}
  .filters-actions{align-self:end}
}

/* Older / newer. Kept at the bottom, big enough to hit with a thumb, with the
   position spelled out between them so a long list never feels bottomless. */
.pager{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:16px}
.pager-where{color:var(--muted);font-size:14px;text-align:center}

@media (min-width:640px){
  .filters-q{flex:1 1 260px}
  .filters{flex-wrap:nowrap;align-items:center}
}

/* Stock.

   Read in a hurry, often one-handed, sometimes in a shop. So the count is the
   biggest thing on each row, the action is a full-size button rather than a
   link, and anything low is coloured before it is read — you should be able to
   tell there is a problem from across the room without parsing a list. */
.stock-list{display:flex;flex-direction:column;gap:8px}
.stock-row{background:#fff;border:1px solid var(--line);border-radius:12px;padding:12px 14px;
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px}
.stock-row-low{border-color:#e6c9a8;background:#fffaf2}
.stock-main{display:flex;align-items:baseline;gap:10px;flex:1 1 auto;min-width:0}
.stock-name{font-weight:600;overflow-wrap:anywhere}
.stock-count{font-size:20px;font-weight:700;white-space:nowrap}
.stock-low{color:var(--new)}
.stock-flag{display:inline-block;background:var(--new);color:#fff;border-radius:6px;
  padding:1px 7px;font-size:12px;font-weight:700;vertical-align:middle;letter-spacing:.02em}
.stock-actions,.stock-meta{display:flex;align-items:center;gap:12px;flex:0 0 auto}
.stock-meta{color:var(--muted);font-size:14px}
.stock-history{font-size:14px;color:var(--muted);text-decoration:underline;white-space:nowrap}
.stock-use{margin:0}
/* A button that cannot do anything must not look like one that can. */
.stock-use .btn[disabled]{opacity:.45;cursor:not-allowed}

.stock-add{background:#fff;border:1px solid var(--line);border-radius:12px;margin-bottom:16px}
.stock-add summary{padding:14px;font-weight:600;cursor:pointer}
.stock-add .form{padding:0 14px 14px}
.stock-headline{background:#fff;border:1px solid var(--line);border-radius:12px;
  padding:16px;margin-bottom:14px;font-size:18px}
.stock-headline b{font-size:30px;margin-right:6px}
.section-note{color:var(--muted);font-size:14px;margin:0 0 10px;line-height:1.5}

/* The ledger. Every line says how many, why, and who — because the count is
   the sum of these, and a total nobody can check is a total nobody believes. */
.move-list{display:flex;flex-direction:column;gap:6px}
.move-row{background:#fff;border:1px solid var(--line);border-radius:10px;padding:10px 12px;
  display:grid;grid-template-columns:auto 1fr;gap:2px 12px;align-items:baseline}
.move-delta{font-weight:700;font-size:17px;grid-row:span 2;align-self:center}
.move-in{color:var(--deliver)}
.move-out{color:var(--danger)}
.move-why{font-size:15px}
.move-who{color:var(--muted);font-size:13px}
.move-note{grid-column:2;color:var(--muted);font-size:13px;font-style:italic}
.stock-remove{margin-top:22px}

/* Something that came off the shelf rather than out of the market. Marked on
   the item itself, because "Bought" alone would have you looking for a receipt
   that does not exist. */
.from-stock-tag{display:inline-block;background:var(--dispatch);color:#fff;border-radius:6px;
  padding:2px 8px;font-size:12px;font-weight:700;letter-spacing:.02em;margin-left:6px}
.add-from-stock{background:#fff;border:1px solid var(--line);border-radius:12px;margin-top:12px}
.add-from-stock summary{padding:14px;font-weight:600;cursor:pointer}
.add-from-stock .form,.add-from-stock .section-note{padding:0 14px}
.add-from-stock .section-note{padding-bottom:14px}
.add-from-stock select{width:100%;font-size:16px;padding:12px;border:1px solid var(--line);
  border-radius:10px;background:#fff;color:var(--ink)}

/* The month, in money.

   Three numbers at the top because that is the whole question — in, out, and
   what is left — and everything under them exists to explain those three. The
   leftover is coloured, and red when it is negative, because that is the one
   figure somebody should be able to read from across the room. */
.period-tabs{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:10px}
.period-tab{padding:9px 14px;border:1px solid var(--line);border-radius:999px;background:#fff;
  color:var(--ink);text-decoration:none;font-size:15px}
.period-on{background:var(--charcoal);color:#fff;border-color:var(--charcoal)}
.period-custom{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:6px}
.period-custom label{display:flex;align-items:center;gap:6px;color:var(--muted);font-size:14px}
.period-custom input[type="date"]{font-size:16px;padding:9px 11px;border:1px solid var(--line);
  border-radius:10px;background:#fff;color:var(--ink)}

.money-head{display:flex;flex-wrap:wrap;gap:10px;margin:14px 0 18px}
.money-big{flex:1 1 150px;background:#fff;border:1px solid var(--line);border-radius:12px;padding:14px}
.money-big span{display:block;color:var(--muted);font-size:13px;margin-bottom:4px}
.money-big b{font-size:24px;display:block;line-height:1.2;overflow-wrap:anywhere}
.money-in b{color:var(--deliver)}
.money-out b{color:var(--new)}
.money-up{border-color:#bcd7c1;background:#f4faf5}
.money-up b{color:var(--deliver)}
.money-down{border-color:#f0caca;background:#fff5f5}
.money-down b{color:var(--danger)}

.money-block{background:#fff;border:1px solid var(--line);border-radius:12px;padding:6px 14px;margin-bottom:6px}
.money-line{display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  padding:11px 0;border-bottom:1px solid var(--line)}
.money-line:last-child{border-bottom:none}
.money-label{color:var(--ink);overflow-wrap:anywhere}
/* How many things are behind the figure. Small, because it explains the number
   rather than competing with it. */
.money-count{display:inline-block;background:var(--cream);border:1px solid var(--line);
  border-radius:999px;padding:0 7px;font-size:12px;color:var(--muted);margin-left:4px}
.money-total{font-weight:700;border-top:2px solid var(--line);margin-top:2px}
.money-aside{background:var(--cream)}

/* An order that is not happening.

   Stated plainly rather than hidden: a cancelled order is a real thing that
   happened with a real customer, not a mistake to tuck away. Grey rather than
   red — nothing went wrong, the sale just did not happen. */
.badge-Cancelled{background:var(--muted);color:#fff}
.cancelled-box{background:#f4f4f2;border:1px solid var(--line);border-radius:12px;padding:16px;margin-top:8px}
.cancelled-head{font-weight:700;margin-bottom:6px}
.cancelled-why{font-style:italic;color:var(--muted);margin-bottom:8px;overflow-wrap:anywhere}

/* Behind a fold, all three of them. None is an everyday action, and a button
   that cancels an order should not sit where a thumb lands by accident. */
.cancel-order,.change-charge,.add-item{background:#fff;border:1px solid var(--line);
  border-radius:12px;margin-top:12px}
.cancel-order summary,.change-charge summary,.add-item summary{padding:14px;font-weight:600;cursor:pointer}
.cancel-order .form,.add-item .form,.change-charge .form{padding:0 14px}
.cancel-order .section-note,.add-item .section-note,.change-charge .section-note{padding:0 14px 14px}
.cancel-order summary{color:var(--danger)}
.btn-remove-item{padding:8px 12px;font-size:14px;color:var(--muted)}

/* What happened to this order.

   A list, not a decorated track with dots and lines: the reason to open it is
   to find one moment, and ornament between the rows makes that slower. On a
   phone each row stacks — time, what, who — which is the order a person reads
   them in anyway. */
.note-add{display:flex;gap:8px;margin-bottom:12px}
.note-add input{flex:1 1 auto;min-width:0;font-size:16px;padding:12px 14px;
  border:1px solid var(--line);border-radius:10px;background:#fff;color:var(--ink)}
.timeline{background:#fff;border:1px solid var(--line);border-radius:12px;padding:4px 14px}
.tl-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 12px;
  padding:10px 0;border-bottom:1px solid var(--line)}
.tl-row:last-child{border-bottom:none}
.tl-when{color:var(--muted);font-size:13px;flex:0 0 auto;min-width:150px}
.tl-what{flex:1 1 200px;overflow-wrap:anywhere}
.tl-who{color:var(--muted);font-size:13px;flex:0 0 auto}
/* A note is somebody's own words, so it reads as a quote rather than as
   another thing the system did. */
.tl-note .tl-what{font-style:italic}
.tl-note .tl-what::before{content:"\201C"}
.tl-note .tl-what::after{content:"\201D"}
.tl-payment .tl-what,.tl-delivery .tl-what{color:var(--deliver)}
.tl-notfound .tl-what{color:var(--new)}
.tl-status .tl-what{font-weight:600}

/* Export. A list of files, each saying what is in it — because "Orders.csv"
   alone does not tell you whether it is one row per order or one per item, and
   that is the only thing worth knowing before downloading it. */
.export-list{display:flex;flex-direction:column;gap:8px;margin:14px 0}
.export-row{display:grid;grid-template-columns:1fr auto;gap:2px 12px;
  background:#fff;border:1px solid var(--line);border-radius:12px;
  padding:14px;text-decoration:none;color:var(--ink)}
.export-name{font-weight:600}
.export-note{grid-column:1;color:var(--muted);font-size:14px}
.export-go{grid-column:2;grid-row:1 / span 2;align-self:center;color:var(--charcoal);
  font-weight:600;white-space:nowrap}
.export-link{display:inline-block;padding:12px 0;font-weight:600}

/* Customers.

   A row is a person, and the thing you scan for is the name — so it leads, and
   everything else is quieter. On a phone the row stacks; the money, where it
   is shown at all, sits last because it is the least useful thing for finding
   somebody and the most sensitive thing on the screen. */
.cust-list{display:flex;flex-direction:column;gap:8px;margin-bottom:12px}
.cust-row{display:grid;grid-template-columns:1fr auto;gap:2px 12px;
  background:#fff;border:1px solid var(--line);border-radius:12px;
  padding:13px 14px;text-decoration:none;color:var(--ink)}
.cust-name{font-weight:600;overflow-wrap:anywhere}
.cust-num{color:var(--muted);font-weight:400;font-size:14px}
.cust-meta{grid-column:1;color:var(--muted);font-size:14px}
.cust-count{grid-column:1;color:var(--muted);font-size:13px}
/* 🔴 grid-column:2 — without it the money took column 1.

   The row says "name, meta, count, money" in that order, and the money carried
   `grid-row:1 / span 3` but no column. Auto-placement put it in the FIRST
   column, which shoved the name across to the right: every row on the Customers
   screen read "Rs. 0 ... Ayesha Khan" — money first, person second, on the one
   screen whose whole job is finding a person. The same mistake was on the
   Export list, where every row read "Download ... Orders". */
.cust-paid{grid-column:2;grid-row:1 / span 3;align-self:center;
  font-weight:700;white-space:nowrap;text-align:right}
.cust-tag{display:inline-block;background:var(--dispatch);color:#fff;border-radius:6px;
  padding:1px 7px;font-size:12px;font-weight:700;margin-left:6px}

.cust-order{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 12px;
  background:#fff;border:1px solid var(--line);border-radius:12px;
  padding:12px 14px;margin-bottom:8px;text-decoration:none;color:var(--ink)}
.cust-order-no{font-weight:600}
.cust-order-when,.cust-order-items{color:var(--muted);font-size:14px}
.cust-order-money{margin-left:auto;white-space:nowrap}
.check{display:flex;align-items:center;gap:8px;margin:10px 0}
.check input{width:20px;height:20px}

/* The message to send.

   A real textarea, not a preview, because the owner will want to add a line
   about the delivery or the occasion, and a message you cannot touch is one
   people retype somewhere else. Big enough to read the whole thing without
   scrolling on a phone. */
.wa-box{background:#fff;border:1px solid var(--line);border-radius:12px;padding:12px}
.wa-text{width:100%;font-size:16px;line-height:1.5;padding:12px;border:1px solid var(--line);
  border-radius:10px;background:var(--cream);color:var(--ink);
  font-family:inherit;resize:vertical}
.wa-actions{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-top:10px}

/* Home — the first screen.

   Cards, not a table. The three people who use this are usually holding the
   phone in one hand; a number wants to be large enough to read at arm's length
   and its target wants to be large enough to hit with a thumb. */
.brand{text-decoration:none}
.home-head{margin-bottom:14px}
.home-head h1{font-size:22px;margin:0}
.home-day{margin:2px 0 0;color:var(--muted);font-size:14px}

/* auto-fit, so two cards fill the row on a phone and five sit on one line on a
   laptop without a media query for each count. */
/* Work cards and stage cards are two different things, so they are two grids.
   In one grid the five of them came out 2 + 2 + 1, leaving a lonely half-width
   "Dispatched" on its own row looking like a mistake. */
.home-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}
.home-stages{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:10px}
.home-stages .home-card{padding:12px 10px}
.home-stages .home-card-n{font-size:24px}
.home-stages .home-card-label{font-size:13px}
@media (max-width:360px){.home-stages{grid-template-columns:1fr 1fr}}
.home-card{display:block;background:#fff;border:1px solid var(--line);border-radius:14px;
  padding:14px;text-decoration:none;color:var(--ink)}
.home-card-n{display:block;font-size:28px;line-height:1.1;font-weight:700;color:var(--charcoal)}
.home-card-label{display:block;font-size:14px;color:var(--muted);margin-top:2px}
.home-card-note{display:block;font-size:12px;color:var(--muted);margin-top:4px}
/* Gold is the colour this app already uses for "your move" — the Bought button
   and the urgent tile edge. Work to do gets the same signal. */
.home-card-do{border-color:var(--gold);border-width:2px}
.home-card-do .home-card-n{color:var(--charcoal)}
.home-card-warn{border-color:#f0caca;background:#fff5f5}
.home-card-warn .home-card-n{color:var(--danger)}
/* A stage with nothing in it still shows, greyed. It is the shape of the board;
   a missing row reads as a broken screen. */
.home-card-quiet{opacity:.6}
.home-card-quiet .home-card-n{color:var(--muted)}

.home-clear{background:#f4faf5;border:1px solid #bcd7c1;border-radius:14px;padding:18px;margin-bottom:6px}
.home-clear b{display:block;font-size:19px;color:var(--deliver)}
.home-clear span{display:block;color:var(--muted);font-size:15px;margin-top:4px}

.home-jump{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:28px}
.home-jump .btn:first-child:nth-last-child(3){grid-column:1 / -1}
@media (min-width:560px){.home-jump{grid-template-columns:repeat(3,1fr)}
  .home-jump .btn:first-child:nth-last-child(3){grid-column:auto}}
.home-jump .btn:not(.btn-primary){background:#fff;color:var(--charcoal);border:1px solid var(--line)}

/* Orders whose dispatch day has arrived */
.due-list{display:grid;gap:8px}
.due-row{display:grid;grid-template-columns:1fr;gap:2px;background:#fff;border:1px solid var(--line);
  border-left-width:4px;border-radius:12px;padding:12px;text-decoration:none;color:var(--ink)}
.due-today{border-left-color:var(--gold)}
.due-late{border-left-color:var(--danger);background:#fff5f5}
.due-when{font-size:14px;color:var(--muted)}
.due-flag{display:inline-block;margin-left:8px;font-size:12px;font-weight:700;text-transform:uppercase;
  letter-spacing:.04em;color:var(--danger)}
.due-today .due-flag{color:var(--new)}
.due-who{font-weight:600}
.due-what{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:4px}
.due-left{font-size:13px;color:var(--danger)}
.due-ok{color:var(--deliver)}

/* Stock at or below its low mark. Shared by the home screen and To Buy. */
.low-list{display:grid;gap:8px}
/* A grid rather than a wrapping flex row: with flex, a long name pushed the
   count onto the next line on one row and not the next, so the numbers in a
   stack of three never lined up with each other. */
.low-row{display:grid;grid-template-columns:1fr auto;gap:2px 12px;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--r-card);padding:13px 15px;
  text-decoration:none;color:var(--ink)}
.low-name{font-weight:600;min-width:0;overflow-wrap:anywhere}
.low-count{grid-column:2;grid-row:1;font-size:15px;color:var(--new);font-weight:700;
  white-space:nowrap;text-align:right}
/* Nothing left is a different thing from nearly nothing left. */
.low-out{color:var(--danger)}
.low-mark{grid-column:1 / -1;font-size:13px;color:var(--muted)}

/* ── Folds ────────────────────────────────────────────────────────────────

   Six screens use a <details> to keep an occasional action out of the way, and
   every one of them had written its own rules for it — or, on the Boxes screen,
   none at all, which is why that page was a bare list of browser triangles with
   no card around it. One look, defined once.

   The marker is a drawn chevron rather than the browser's own triangle, because
   Safari, Chrome and Firefox each draw a different shape at a different size,
   and three of the app's screens sat next to each other showing all three. */
.fold,.stock-add,.add-from-stock,.cancel-order,.change-charge,.add-item,.box-row,.note-add{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-card);
  box-shadow:var(--shadow);margin-bottom:10px;overflow:hidden}
.fold>summary,.stock-add>summary,.add-from-stock>summary,.cancel-order>summary,
.change-charge>summary,.add-item>summary,.box-row>summary,.note-add>summary{
  display:flex;align-items:center;gap:10px;padding:14px 15px;font-weight:600;
  cursor:pointer;list-style:none;min-height:50px}
.fold>summary::-webkit-details-marker,.stock-add>summary::-webkit-details-marker,
.add-from-stock>summary::-webkit-details-marker,.cancel-order>summary::-webkit-details-marker,
.change-charge>summary::-webkit-details-marker,.add-item>summary::-webkit-details-marker,
.box-row>summary::-webkit-details-marker,.note-add>summary::-webkit-details-marker{display:none}
.fold>summary::before,.stock-add>summary::before,.add-from-stock>summary::before,
.cancel-order>summary::before,.change-charge>summary::before,.add-item>summary::before,
.box-row>summary::before,.note-add>summary::before{
  content:"";flex:none;width:9px;height:9px;margin-right:2px;
  border-right:2px solid var(--charcoal);border-bottom:2px solid var(--charcoal);
  transform:rotate(-45deg);transition:transform .15s}
.fold[open]>summary::before,.stock-add[open]>summary::before,.add-from-stock[open]>summary::before,
.cancel-order[open]>summary::before,.change-charge[open]>summary::before,
.add-item[open]>summary::before,.box-row[open]>summary::before,.note-add[open]>summary::before{
  transform:rotate(45deg)}
.fold>summary:hover,.stock-add>summary:hover,.add-from-stock>summary:hover,
.cancel-order>summary:hover,.change-charge>summary:hover,.add-item>summary:hover,
.box-row>summary:hover,.note-add>summary:hover{background:var(--surface-sunk)}
/* A form inside a fold is already in a card; it must not draw a second one. */
.fold .form,.stock-add .form,.add-from-stock .form,.cancel-order .form,
.change-charge .form,.add-item .form,.box-row .form,.note-add .form{
  background:none;border:none;box-shadow:none;border-radius:0;padding:0 15px 14px;margin:0}
.box-row .section-note,.add-from-stock .section-note,.change-charge .section-note,
.add-item .section-note,.cancel-order .section-note{padding:0 15px 14px;margin:0}

/* The Boxes list: a name, what one costs, and how many gifts have used it. */
.box-list{display:grid;gap:10px}
.box-row>summary{display:grid;grid-template-columns:auto 1fr auto;gap:2px 12px;align-items:baseline}
.box-row>summary::before{align-self:center;grid-row:1 / span 2}
.box-name{font-weight:600;overflow-wrap:anywhere}
.box-cost{grid-column:3;text-align:right;font-weight:700;white-space:nowrap}
.box-used{grid-column:2 / -1;font-weight:400;font-size:13px;color:var(--muted)}
.box-tag{display:inline-block;background:var(--muted);color:#fff;border-radius:6px;
  padding:1px 7px;font-size:12px;font-weight:700;margin-left:6px}
.box-retired .box-name{color:var(--muted)}

/* ── A labelled pair of fields ────────────────────────────────────────────

   Two inputs side by side used to carry no labels at all — only placeholders.
   A placeholder disappears the moment there is a value in the box, so the Stock
   screen showed a field containing "pack" and another containing "2" with
   nothing anywhere to say which was the unit and which was the warn-at number.
   You had to clear the field to find out what it was for. */
.pair{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:4px}
.pair-f{display:flex;flex-direction:column;gap:5px;min-width:0}
.pair-f label,.form .pair-f label,fieldset .pair-f label{
  margin:0;font-size:13px;font-weight:600;color:var(--muted)}
.pair-f input{width:100%;min-width:0;margin:0}

/* Two dates and a button, on the Money screen, reusing the order filters. */
.period-custom{display:grid;gap:12px;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-card);box-shadow:var(--shadow);padding:14px;margin-bottom:14px}

/* Locking somebody out is rare and serious. Outlined rather than a solid red
   slab: still unmistakably the dangerous button, without two of them being the
   loudest thing in the whole app on a screen opened twice a year. */
.btn-danger{background:var(--surface);color:var(--danger);border:2px solid var(--danger)}
.btn-danger:hover{background:#fff5f5}

/* ── Small things that were being used and had never been written ─────────

   Found by listing every class the templates put on an element and comparing it
   with every class this file defines. `.muted` was the one that mattered: three
   screens use it to say "no price yet", "not priced", "no phone" — the phrases
   that stand in for a missing number — and with no rule behind it they were
   rendering in full-strength black, reading as firmly as a real answer. */
.muted{color:var(--muted)}

/* The left-hand side of an item card. Without min-width:0 a long item name
   cannot shrink inside a flex row, so it pushed the price box off the edge. */
.item-main{flex:1 1 auto;min-width:0}
.item-main .item-name{overflow-wrap:anywhere}

.cust-orders{display:grid;gap:8px}
.team-main{flex:1 1 auto;min-width:0}
/* The recount form owns the top of the stock page; it should not be tighter
   than the cards under it. */
.stock-correct{margin-bottom:12px}

/* ── The order page, as a list of folds ───────────────────────────────────

   Eleven sections, all open, all of them full forms — to record a payment you
   scrolled past the invoice box, the margin table and eight delivery fields.
   The page was mostly things you were not doing.

   Shut, with the answer on the closed row. The summary is the whole point: a
   column of headings you have to open one at a time to find anything would be
   worse than the wall it replaced. So a closed Payments row says what is paid
   and what is not, and Delivery says the courier and the tracking number. */
.panel{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-card);
  box-shadow:var(--shadow);margin-bottom:10px;overflow:hidden}
.panel>summary{display:grid;grid-template-columns:auto 1fr;gap:2px 10px;
  padding:14px 15px;cursor:pointer;list-style:none;align-items:baseline;min-height:54px}
.panel>summary::-webkit-details-marker{display:none}
.panel>summary::before{content:"";grid-row:1 / span 2;align-self:center;
  width:9px;height:9px;flex:none;
  border-right:2px solid var(--charcoal);border-bottom:2px solid var(--charcoal);
  transform:rotate(-45deg);transition:transform .15s}
.panel[open]>summary::before{transform:rotate(45deg)}
.panel>summary:hover{background:var(--surface-sunk)}
.panel-title{font-size:17px;font-weight:700;color:var(--charcoal)}
/* The answer, on the row you have not opened. */
.panel-sum{grid-column:2;font-size:14px;color:var(--muted);overflow-wrap:anywhere}
.panel-body{padding:2px 15px 16px;border-top:1px solid var(--line);margin-top:2px}
/* A form inside a panel is already in a card and must not draw a second one. */
.panel-body .form{background:none;border:none;box-shadow:none;border-radius:0;padding:0;margin:14px 0 0}
.panel-body>.items-list,.panel-body>.timeline,.panel-body>.pay-list{margin-top:12px}
.panel-body .section-h{margin-top:16px}

/* Something is waiting in here — money owed, items unbought, a negative
   margin. The same gold this app uses everywhere for "your move", and red only
   where the number itself is bad. */
.panel-do>summary{box-shadow:inset 4px 0 0 var(--gold)}
.panel-warn>summary{box-shadow:inset 4px 0 0 var(--danger)}
.panel-warn .panel-sum b{color:var(--danger)}

/* The one thing people get wrong about the Money screen, said beside the number
   that causes it rather than three screens further down. Cream rather than a
   red alert: it is not a warning, it is the meaning of the figure. */
.money-caveat{background:var(--surface-sunk);border:1px solid var(--line);
  border-left:4px solid var(--gold);border-radius:var(--r-card);
  padding:14px 16px;margin:0 0 18px;font-size:15px;line-height:1.55;color:var(--ink)}

/* The invoice, inside the message panel rather than beside it.

   They were two folds doing one job. The message already CONTAINS the invoice
   link, so a separate "Invoice — a link to send" panel directly above it was a
   second copy of the same thing, and the owner spotted it straight away: "why
   are the invoice and message to customer the same".

   Only two parts of it were not already in the message: looking at the invoice
   yourself before sending, and the bare link for when WhatsApp is not how you
   are sending it. Both are secondary to the message, and now look it. */
.wa-extra{margin-top:18px;padding-top:14px;border-top:1px solid var(--line)}
.wa-extra-row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:10px}
.wa-extra-row span{color:var(--muted);font-size:15px}
.wa-extra .section-note{margin-top:8px}
.wa-extra .price-label{margin-top:14px}
